|  | 
|  | 1 | +/* | 
|  | 2 | + * Copyright (c) Meta Platforms, Inc. and affiliates. | 
|  | 3 | + * All rights reserved. | 
|  | 4 | + * | 
|  | 5 | + * This source code is licensed under the BSD-style license found in the | 
|  | 6 | + * LICENSE file in the root directory of this source tree. | 
|  | 7 | + */ | 
|  | 8 | + | 
|  | 9 | +#include <executorch/extension/flat_tensor/serialize/flat_tensor_header.h> | 
|  | 10 | + | 
|  | 11 | +#include <gtest/gtest.h> | 
|  | 12 | + | 
|  | 13 | +#include <executorch/runtime/core/result.h> | 
|  | 14 | +#include <executorch/runtime/platform/runtime.h> | 
|  | 15 | + | 
|  | 16 | +using namespace ::testing; | 
|  | 17 | +using executorch::extension::FlatTensorHeader; | 
|  | 18 | +using executorch::runtime::Error; | 
|  | 19 | +using executorch::runtime::Result; | 
|  | 20 | + | 
|  | 21 | +class FlatTensorHeaderTest : public ::testing::Test { | 
|  | 22 | + protected: | 
|  | 23 | +  void SetUp() override { | 
|  | 24 | +    // Since these tests cause ET_LOG to be called, the PAL must be initialized | 
|  | 25 | +    // first. | 
|  | 26 | +    executorch::runtime::runtime_init(); | 
|  | 27 | +  } | 
|  | 28 | +}; | 
|  | 29 | + | 
|  | 30 | +/** | 
|  | 31 | + * An example, valid flat_tensor header. | 
|  | 32 | + * | 
|  | 33 | + * This data is intentionally fragile. If the header layout or magic changes, | 
|  | 34 | + * this test data must change too. The layout of the header is a contract, not | 
|  | 35 | + * an implementation detail. | 
|  | 36 | + */ | 
|  | 37 | +// clang-format off | 
|  | 38 | +// @lint-ignore CLANGTIDY facebook-hte-CArray | 
|  | 39 | +constexpr char kExampleHeaderData[] = { | 
|  | 40 | +  // Magic bytes | 
|  | 41 | +  'F', 'H', '0', '1', | 
|  | 42 | +  // uint32_t header size (little endian) | 
|  | 43 | +  0x28, 0x00, 0x00, 0x00, | 
|  | 44 | +  // uint64_t flatbuffer_offset | 
|  | 45 | +  0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01, | 
|  | 46 | +  // uint64_t flatbuffer_size | 
|  | 47 | +  0x72, 0x62, 0x52, 0x42, 0x32, 0x22, 0x12, 0x02, | 
|  | 48 | +  // uint64_t segment_base_offset | 
|  | 49 | +  0x73, 0x63, 0x53, 0x43, 0x33, 0x23, 0x13, 0x03, | 
|  | 50 | +  // uint64_t segment_data_size | 
|  | 51 | +  0x74, 0x64, 0x54, 0x44, 0x34, 0x24, 0x14, 0x04, | 
|  | 52 | +}; | 
|  | 53 | + | 
|  | 54 | +constexpr uint64_t kExampleFlatbufferOffset = 0x0111213141516171; | 
|  | 55 | +constexpr uint64_t kExampleFlatbufferSize = 0x0212223242526272; | 
|  | 56 | +constexpr uint64_t kExampleSegmentBaseOffset = 0x0313233343536373;  | 
|  | 57 | +constexpr uint64_t kExampleSegmentDataSize = 0x0414243444546474; | 
|  | 58 | + | 
|  | 59 | +/** | 
|  | 60 | + * Returns fake serialized FlatTensor data that contains kExampleHeaderData at | 
|  | 61 | + * the expected offset. | 
|  | 62 | + */ | 
|  | 63 | +std::vector<uint8_t> CreateExampleFlatTensorHeader() { | 
|  | 64 | +  // Allocate memory representing the FlatTensor header. | 
|  | 65 | +  std::vector<uint8_t> ret(FlatTensorHeader::kNumHeadBytes); | 
|  | 66 | +  // Write non-zeros into it to make it more obvious if we read outside the | 
|  | 67 | +  // header. | 
|  | 68 | +  memset(ret.data(), 0x55, ret.size()); | 
|  | 69 | +  // Copy the example header into the right offset. | 
|  | 70 | +  memcpy( | 
|  | 71 | +      ret.data(), | 
|  | 72 | +      kExampleHeaderData, | 
|  | 73 | +      sizeof(kExampleHeaderData)); | 
|  | 74 | +  return ret; | 
|  | 75 | +} | 
|  | 76 | + | 
|  | 77 | +TEST_F(FlatTensorHeaderTest, ValidHeaderParsesCorrectly) { | 
|  | 78 | +  std::vector<uint8_t> flat_tensor = CreateExampleFlatTensorHeader(); | 
|  | 79 | + | 
|  | 80 | +  Result<FlatTensorHeader> header = FlatTensorHeader::Parse(flat_tensor.data(), flat_tensor.size()); | 
|  | 81 | + | 
|  | 82 | +  // The header should be present. | 
|  | 83 | +  ASSERT_EQ(header.error(), Error::Ok);   | 
|  | 84 | + | 
|  | 85 | +  // Since each byte of these fields is unique, success demonstrates that the | 
|  | 86 | +  // endian-to-int conversion is correct and looks at the expected bytes of the | 
|  | 87 | +  // header. | 
|  | 88 | +  EXPECT_EQ(header->flatbuffer_offset, kExampleFlatbufferOffset); | 
|  | 89 | +  EXPECT_EQ(header->flatbuffer_size, kExampleFlatbufferSize); | 
|  | 90 | +  EXPECT_EQ(header->segment_base_offset, kExampleSegmentBaseOffset); | 
|  | 91 | +  EXPECT_EQ(header->segment_data_size, kExampleSegmentDataSize); | 
|  | 92 | +} | 
0 commit comments