| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include <gtest/gtest.h> |
| #include <tvm/ffi/optional.h> |
| |
| #include "../src/runtime/hexagon/hexagon_buffer.h" |
| |
| using namespace tvm; |
| using namespace tvm::runtime; |
| using namespace tvm::runtime::hexagon; |
| using namespace tvm::ffi; |
| |
| TEST(HexagonBuffer, default_scope) { |
| ffi::Optional<ffi::String> scope; |
| HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_EQ(hb.GetStorageScope(), HexagonBuffer::StorageScope::kDDR); |
| } |
| |
| TEST(HexagonBuffer, ddr_scope) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_EQ(hb.GetStorageScope(), HexagonBuffer::StorageScope::kDDR); |
| } |
| |
| TEST(HexagonBuffer, vtcm_scope) { |
| ffi::Optional<ffi::String> scope(ffi::String("global.vtcm")); |
| HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_EQ(hb.GetStorageScope(), HexagonBuffer::StorageScope::kVTCM); |
| } |
| |
| TEST(HexagonBuffer, invalid_scope) { |
| ffi::Optional<ffi::String> scope(ffi::String("invalid")); |
| EXPECT_THROW(HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope), InternalError); |
| } |
| |
| TEST(HexagonBuffer, micro_copies_corresponding_regions) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 16); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 16); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 32); |
| EXPECT_EQ(micro_copies.size(), 2); |
| for (size_t i = 0; i < micro_copies.size(); i++) { |
| EXPECT_EQ(micro_copies[i].src, ptr(16 * i)); |
| EXPECT_EQ(micro_copies[i].dest, ptr(64 + 16 * i)); |
| EXPECT_EQ(micro_copies[i].num_bytes, 16); |
| } |
| } |
| |
| TEST(HexagonBuffer, micro_copies_src_bigger) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 16); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(72), ptr(80), ptr(88)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 8); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 32); |
| EXPECT_EQ(micro_copies.size(), 4); |
| for (size_t i = 0; i < micro_copies.size(); i++) { |
| EXPECT_EQ(micro_copies[i].src, ptr(8 * i)); |
| EXPECT_EQ(micro_copies[i].dest, ptr(64 + 8 * i)); |
| EXPECT_EQ(micro_copies[i].num_bytes, 8); |
| } |
| } |
| |
| TEST(HexagonBuffer, micro_copies_dest_bigger) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(8), ptr(16), ptr(24)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 8); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 16); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 32); |
| EXPECT_EQ(micro_copies.size(), 4); |
| for (size_t i = 0; i < micro_copies.size(); i++) { |
| EXPECT_EQ(micro_copies[i].src, ptr(8 * i)); |
| EXPECT_EQ(micro_copies[i].dest, ptr(64 + 8 * i)); |
| EXPECT_EQ(micro_copies[i].num_bytes, 8); |
| } |
| } |
| |
| TEST(HexagonBuffer, micro_copies_src_overlaps_dest_region) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 16); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(76)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 12); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 24); |
| EXPECT_EQ(micro_copies.size(), 3); |
| |
| // First region of source, first region of dest |
| EXPECT_EQ(micro_copies[0].src, ptr(0)); |
| EXPECT_EQ(micro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(micro_copies[0].num_bytes, 12); |
| |
| // First region of source, second region of dest |
| EXPECT_EQ(micro_copies[1].src, ptr(12)); |
| EXPECT_EQ(micro_copies[1].dest, ptr(76)); |
| EXPECT_EQ(micro_copies[1].num_bytes, 4); |
| |
| // Second region of source, second region of dest |
| EXPECT_EQ(micro_copies[2].src, ptr(16)); |
| EXPECT_EQ(micro_copies[2].dest, ptr(80)); |
| EXPECT_EQ(micro_copies[2].num_bytes, 8); |
| } |
| |
| TEST(HexagonBuffer, micro_copies_dest_overlaps_src_region) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(12)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 12); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 16); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 24); |
| EXPECT_EQ(micro_copies.size(), 3); |
| |
| // First region of source, first region of dest |
| EXPECT_EQ(micro_copies[0].src, ptr(0)); |
| EXPECT_EQ(micro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(micro_copies[0].num_bytes, 12); |
| |
| // Second region of source, first region of dest |
| EXPECT_EQ(micro_copies[1].src, ptr(12)); |
| EXPECT_EQ(micro_copies[1].dest, ptr(76)); |
| EXPECT_EQ(micro_copies[1].num_bytes, 4); |
| |
| // Second region of source, second region of dest |
| EXPECT_EQ(micro_copies[2].src, ptr(16)); |
| EXPECT_EQ(micro_copies[2].dest, ptr(80)); |
| EXPECT_EQ(micro_copies[2].num_bytes, 8); |
| } |
| |
| TEST(HexagonBuffer, micro_copies_discontiguous_regions) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| // Stride of 16, but only first 11 bytes in each region belong to |
| // this buffer. |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 11); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 13); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 16); |
| EXPECT_EQ(micro_copies.size(), 3); |
| |
| // First region of source, first region of dest |
| EXPECT_EQ(micro_copies[0].src, ptr(0)); |
| EXPECT_EQ(micro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(micro_copies[0].num_bytes, 11); |
| |
| // Second region of source, first region of dest |
| EXPECT_EQ(micro_copies[1].src, ptr(16)); |
| EXPECT_EQ(micro_copies[1].dest, ptr(75)); |
| EXPECT_EQ(micro_copies[1].num_bytes, 2); |
| |
| // Second region of source, second region of dest |
| EXPECT_EQ(micro_copies[2].src, ptr(18)); |
| EXPECT_EQ(micro_copies[2].dest, ptr(80)); |
| EXPECT_EQ(micro_copies[2].num_bytes, 3); |
| } |
| |
| TEST(HexagonBuffer, micro_copies_invalid_size) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| |
| { |
| BufferSet src(src_ptr.data(), 1, 16); |
| BufferSet dest(dest_ptr.data(), 2, 16); |
| EXPECT_THROW(BufferSet::MemoryCopies(dest, src, 24), InternalError); |
| } |
| |
| { |
| BufferSet src(src_ptr.data(), 2, 16); |
| BufferSet dest(dest_ptr.data(), 1, 16); |
| EXPECT_THROW(BufferSet::MemoryCopies(dest, src, 24), InternalError); |
| } |
| } |
| |
| TEST(HexagonBuffer, macro_copies_adjacent_corresponding_regions_merged) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 16); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 16); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 32); |
| auto macro_copies = MemoryCopy::MergeAdjacent(std::move(micro_copies)); |
| |
| ASSERT_EQ(macro_copies.size(), 1); |
| EXPECT_EQ(macro_copies[0].src, ptr(0)); |
| EXPECT_EQ(macro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(macro_copies[0].num_bytes, 32); |
| } |
| |
| TEST(HexagonBuffer, macro_copies_discontiguous_regions_not_merged) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(16)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 12); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 12); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 24); |
| auto macro_copies = MemoryCopy::MergeAdjacent(std::move(micro_copies)); |
| |
| ASSERT_EQ(macro_copies.size(), 2); |
| |
| EXPECT_EQ(macro_copies[0].src, ptr(0)); |
| EXPECT_EQ(macro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(macro_copies[0].num_bytes, 12); |
| |
| EXPECT_EQ(macro_copies[1].src, ptr(16)); |
| EXPECT_EQ(macro_copies[1].dest, ptr(80)); |
| EXPECT_EQ(macro_copies[1].num_bytes, 12); |
| } |
| |
| TEST(HexagonBuffer, macro_copies_overlapping_regions_merged) { |
| auto ptr = [](auto val) { return reinterpret_cast<void*>(val); }; |
| |
| std::vector<void*> src_ptr{ptr(0), ptr(12)}; |
| BufferSet src(src_ptr.data(), src_ptr.size(), 12); |
| |
| std::vector<void*> dest_ptr{ptr(64), ptr(80)}; |
| BufferSet dest(dest_ptr.data(), dest_ptr.size(), 16); |
| |
| auto micro_copies = BufferSet::MemoryCopies(dest, src, 24); |
| auto macro_copies = MemoryCopy::MergeAdjacent(std::move(micro_copies)); |
| |
| ASSERT_EQ(macro_copies.size(), 1); |
| EXPECT_EQ(macro_copies[0].src, ptr(0)); |
| EXPECT_EQ(macro_copies[0].dest, ptr(64)); |
| EXPECT_EQ(macro_copies[0].num_bytes, 24); |
| } |
| |
| TEST(HexagonBuffer, copy_from) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb.CopyFrom(data.data(), data.size()); |
| |
| uint8_t* ptr = static_cast<uint8_t*>(hb.GetPointer()); |
| for (size_t i = 0; i < data.size(); ++i) { |
| EXPECT_EQ(ptr[i], data[i]); |
| } |
| } |
| |
| TEST(HexagonBuffer, copy_from_invalid_size) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| |
| // HexagonBuffer too small |
| HexagonBuffer toosmall(4 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_THROW(toosmall.CopyFrom(data.data(), data.size()), InternalError); |
| } |
| |
| TEST(HexagonBuffer, copy_from_smaller_size) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| |
| // HexagonBuffer is big |
| HexagonBuffer big(16 /* nbytes */, 16 /* alignment */, scope); |
| EXPECT_NO_THROW(big.CopyFrom(data.data(), data.size())); |
| } |
| |
| TEST(HexagonBuffer, nd) { |
| ffi::Optional<ffi::String> def; |
| HexagonBuffer hb_default(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, def); |
| EXPECT_EQ(hb_default.GetStorageScope(), HexagonBuffer::StorageScope::kDDR); |
| |
| ffi::Optional<ffi::String> global(ffi::String("global")); |
| HexagonBuffer hb_global(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, global); |
| EXPECT_EQ(hb_global.GetStorageScope(), HexagonBuffer::StorageScope::kDDR); |
| |
| ffi::Optional<ffi::String> vtcm(ffi::String("global.vtcm")); |
| HexagonBuffer hb_vtcm(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, vtcm); |
| EXPECT_EQ(hb_vtcm.GetStorageScope(), HexagonBuffer::StorageScope::kVTCM); |
| |
| ffi::Optional<ffi::String> invalid(ffi::String("invalid")); |
| EXPECT_THROW(HexagonBuffer hb_invalid(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, invalid), |
| InternalError); |
| } |
| |
| TEST(HexagonBuffer, nd_copy_from) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, scope); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb.CopyFrom(data.data(), data.size()); |
| |
| uint8_t** ptr = static_cast<uint8_t**>(hb.GetPointer()); |
| EXPECT_EQ(ptr[0][0], data[0]); |
| EXPECT_EQ(ptr[0][1], data[1]); |
| EXPECT_EQ(ptr[0][2], data[2]); |
| EXPECT_EQ(ptr[0][3], data[3]); |
| EXPECT_EQ(ptr[1][0], data[4]); |
| EXPECT_EQ(ptr[1][1], data[5]); |
| EXPECT_EQ(ptr[1][2], data[6]); |
| EXPECT_EQ(ptr[1][3], data[7]); |
| } |
| |
| TEST(HexagonBuffer, 1d_copy_from_1d) { |
| ffi::Optional<ffi::String> global(ffi::String("global")); |
| HexagonBuffer from(8 /* nbytes */, 8 /* alignment */, global); |
| |
| ffi::Optional<ffi::String> vtcm(ffi::String("global.vtcm")); |
| HexagonBuffer to(8 /* nbytes */, 8 /* alignment */, vtcm); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| from.CopyFrom(data.data(), data.size()); |
| to.CopyFrom(from, 8); |
| |
| uint8_t* ptr = static_cast<uint8_t*>(to.GetPointer()); |
| for (size_t i = 0; i < data.size(); ++i) { |
| EXPECT_EQ(ptr[i], data[i]); |
| } |
| } |
| |
| TEST(HexagonBuffer, 2d_copy_from_1d) { |
| ffi::Optional<ffi::String> vtcm(ffi::String("global.vtcm")); |
| HexagonBuffer hb1d(8 /* nbytes */, 8 /* alignment */, vtcm); |
| |
| ffi::Optional<ffi::String> global(ffi::String("global")); |
| HexagonBuffer hb2d(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, global); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb1d.CopyFrom(data.data(), data.size()); |
| hb2d.CopyFrom(hb1d, 8); |
| |
| uint8_t** ptr = static_cast<uint8_t**>(hb2d.GetPointer()); |
| EXPECT_EQ(ptr[0][0], data[0]); |
| EXPECT_EQ(ptr[0][1], data[1]); |
| EXPECT_EQ(ptr[0][2], data[2]); |
| EXPECT_EQ(ptr[0][3], data[3]); |
| EXPECT_EQ(ptr[1][0], data[4]); |
| EXPECT_EQ(ptr[1][1], data[5]); |
| EXPECT_EQ(ptr[1][2], data[6]); |
| EXPECT_EQ(ptr[1][3], data[7]); |
| } |
| |
| TEST(HexagonBuffer, 1d_copy_from_2d) { |
| ffi::Optional<ffi::String> vtcm(ffi::String("global.vtcm")); |
| HexagonBuffer hb2d(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, vtcm); |
| |
| ffi::Optional<ffi::String> global(ffi::String("global.vtcm")); |
| HexagonBuffer hb1d(8 /* nbytes */, 8 /* alignment */, global); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb2d.CopyFrom(data.data(), data.size()); |
| hb1d.CopyFrom(hb2d, 8); |
| |
| uint8_t* ptr = static_cast<uint8_t*>(hb1d.GetPointer()); |
| for (size_t i = 0; i < data.size(); ++i) { |
| EXPECT_EQ(ptr[i], data[i]); |
| } |
| } |
| |
| TEST(HexagonBuffer, nd_copy_from_nd_invalid_size) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb1d(8 /* nbytes */, 8 /* alignment */, scope); |
| HexagonBuffer hb2d(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, scope); |
| |
| HexagonBuffer toosbig1d(16 /* nbytes */, 16 /* alignment */, scope); |
| EXPECT_THROW(hb1d.CopyFrom(toosbig1d, 16), InternalError); |
| EXPECT_THROW(hb2d.CopyFrom(toosbig1d, 16), InternalError); |
| |
| HexagonBuffer toobig2d(2 /* ndim */, 16 /* nbytes */, 16 /* alignment */, scope); |
| EXPECT_THROW(hb1d.CopyFrom(toobig2d, 32), InternalError); |
| EXPECT_THROW(hb2d.CopyFrom(toobig2d, 32), InternalError); |
| } |
| |
| TEST(HexagonBuffer, nd_copy_from_nd_smaller_size) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb1d(8 /* nbytes */, 8 /* alignment */, scope); |
| HexagonBuffer hb2d(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, scope); |
| |
| HexagonBuffer small1d(4 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_NO_THROW(hb1d.CopyFrom(small1d, 4)); |
| EXPECT_NO_THROW(hb2d.CopyFrom(small1d, 4)); |
| |
| HexagonBuffer small2d(2 /* ndim */, 2 /* nbytes */, 8 /* alignment */, scope); |
| EXPECT_NO_THROW(hb1d.CopyFrom(small2d, 4)); |
| EXPECT_NO_THROW(hb2d.CopyFrom(small2d, 4)); |
| } |
| |
| TEST(HexagonBuffer, md_copy_from_nd) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb3d(3 /* ndim */, 4 /* nbytes */, 8 /* alignment */, scope); |
| HexagonBuffer hb4d(4 /* ndim */, 3 /* nbytes */, 8 /* alignment */, scope); |
| |
| std::vector<uint8_t> data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; |
| |
| hb3d.CopyFrom(data.data(), data.size()); |
| hb4d.CopyFrom(hb3d, data.size()); |
| |
| uint8_t** hb3d_ptr = static_cast<uint8_t**>(hb3d.GetPointer()); |
| uint8_t** hb4d_ptr = static_cast<uint8_t**>(hb4d.GetPointer()); |
| for (size_t i = 0; i < 12; i++) { |
| EXPECT_EQ(hb3d_ptr[i / 4][i % 4], hb4d_ptr[i / 3][i % 3]); |
| } |
| } |
| |
| TEST(HexagonBuffer, copy_to) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb(8 /* nbytes */, 8 /* alignment */, scope); |
| |
| std::vector<uint8_t> data_in{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb.CopyFrom(data_in.data(), data_in.size()); |
| |
| std::vector<uint8_t> data_out{7, 6, 5, 4, 3, 2, 1, 0}; |
| hb.CopyTo(data_out.data(), data_out.size()); |
| |
| for (size_t i = 0; i < data_in.size(); ++i) { |
| EXPECT_EQ(data_in[i], data_out[i]); |
| } |
| } |
| |
| TEST(HexagonBuffer, nd_copy_to) { |
| ffi::Optional<ffi::String> scope(ffi::String("global")); |
| HexagonBuffer hb(2 /* ndim */, 4 /* nbytes */, 8 /* alignment */, scope); |
| |
| std::vector<uint8_t> data_in{0, 1, 2, 3, 4, 5, 6, 7}; |
| hb.CopyFrom(data_in.data(), data_in.size()); |
| |
| std::vector<uint8_t> data_out{7, 6, 5, 4, 3, 2, 1, 0}; |
| hb.CopyTo(data_out.data(), data_out.size()); |
| |
| for (size_t i = 0; i < data_in.size(); ++i) { |
| EXPECT_EQ(data_in[i], data_out[i]); |
| } |
| } |