| 1 | //===-- simple_packed_serialization_test.cpp ------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file is a part of the ORC runtime. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "simple_packed_serialization.h" |
| 14 | #include "simple_packed_serialization_utils.h" |
| 15 | #include "gtest/gtest.h" |
| 16 | |
| 17 | using namespace orc_rt; |
| 18 | |
| 19 | TEST(SimplePackedSerializationTest, SPSOutputBuffer) { |
| 20 | constexpr unsigned NumBytes = 8; |
| 21 | char Buffer[NumBytes]; |
| 22 | char Zero = 0; |
| 23 | SPSOutputBuffer OB(Buffer, NumBytes); |
| 24 | |
| 25 | // Expect that we can write NumBytes of content. |
| 26 | for (unsigned I = 0; I != NumBytes; ++I) { |
| 27 | char C = I; |
| 28 | EXPECT_TRUE(OB.write(Data: &C, Size: 1)); |
| 29 | } |
| 30 | |
| 31 | // Expect an error when we attempt to write an extra byte. |
| 32 | EXPECT_FALSE(OB.write(Data: &Zero, Size: 1)); |
| 33 | |
| 34 | // Check that the buffer contains the expected content. |
| 35 | for (unsigned I = 0; I != NumBytes; ++I) |
| 36 | EXPECT_EQ(Buffer[I], (char)I); |
| 37 | } |
| 38 | |
| 39 | TEST(SimplePackedSerializationTest, SPSInputBuffer) { |
| 40 | char Buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; |
| 41 | SPSInputBuffer IB(Buffer, sizeof(Buffer)); |
| 42 | |
| 43 | char C; |
| 44 | for (unsigned I = 0; I != sizeof(Buffer); ++I) { |
| 45 | EXPECT_TRUE(IB.read(Data: &C, Size: 1)); |
| 46 | EXPECT_EQ(C, (char)I); |
| 47 | } |
| 48 | |
| 49 | EXPECT_FALSE(IB.read(Data: &C, Size: 1)); |
| 50 | } |
| 51 | |
| 52 | template <typename T> static void testFixedIntegralTypeSerialization() { |
| 53 | blobSerializationRoundTrip<T, T>(0); |
| 54 | blobSerializationRoundTrip<T, T>(static_cast<T>(1)); |
| 55 | if (std::is_signed<T>::value) { |
| 56 | blobSerializationRoundTrip<T, T>(static_cast<T>(-1)); |
| 57 | blobSerializationRoundTrip<T, T>(std::numeric_limits<T>::min()); |
| 58 | } |
| 59 | blobSerializationRoundTrip<T, T>(std::numeric_limits<T>::max()); |
| 60 | } |
| 61 | |
| 62 | TEST(SimplePackedSerializationTest, BoolSerialization) { |
| 63 | blobSerializationRoundTrip<bool, bool>(Value: true); |
| 64 | blobSerializationRoundTrip<bool, bool>(Value: false); |
| 65 | } |
| 66 | |
| 67 | TEST(SimplePackedSerializationTest, CharSerialization) { |
| 68 | blobSerializationRoundTrip<char, char>(Value: (char)0x00); |
| 69 | blobSerializationRoundTrip<char, char>(Value: (char)0xAA); |
| 70 | blobSerializationRoundTrip<char, char>(Value: (char)0xFF); |
| 71 | } |
| 72 | |
| 73 | TEST(SimplePackedSerializationTest, Int8Serialization) { |
| 74 | testFixedIntegralTypeSerialization<int8_t>(); |
| 75 | } |
| 76 | |
| 77 | TEST(SimplePackedSerializationTest, UInt8Serialization) { |
| 78 | testFixedIntegralTypeSerialization<uint8_t>(); |
| 79 | } |
| 80 | |
| 81 | TEST(SimplePackedSerializationTest, Int16Serialization) { |
| 82 | testFixedIntegralTypeSerialization<int16_t>(); |
| 83 | } |
| 84 | |
| 85 | TEST(SimplePackedSerializationTest, UInt16Serialization) { |
| 86 | testFixedIntegralTypeSerialization<uint16_t>(); |
| 87 | } |
| 88 | |
| 89 | TEST(SimplePackedSerializationTest, Int32Serialization) { |
| 90 | testFixedIntegralTypeSerialization<int32_t>(); |
| 91 | } |
| 92 | |
| 93 | TEST(SimplePackedSerializationTest, UInt32Serialization) { |
| 94 | testFixedIntegralTypeSerialization<uint32_t>(); |
| 95 | } |
| 96 | |
| 97 | TEST(SimplePackedSerializationTest, Int64Serialization) { |
| 98 | testFixedIntegralTypeSerialization<int64_t>(); |
| 99 | } |
| 100 | |
| 101 | TEST(SimplePackedSerializationTest, UInt64Serialization) { |
| 102 | testFixedIntegralTypeSerialization<uint64_t>(); |
| 103 | } |
| 104 | |
| 105 | TEST(SimplePackedSerializationTest, SequenceSerialization) { |
| 106 | std::vector<int32_t> V({1, 2, -47, 139}); |
| 107 | blobSerializationRoundTrip<SPSSequence<int32_t>, std::vector<int32_t>>(Value: V); |
| 108 | } |
| 109 | |
| 110 | TEST(SimplePackedSerializationTest, StringViewCharSequenceSerialization) { |
| 111 | const char *HW = "Hello, world!" ; |
| 112 | blobSerializationRoundTrip<SPSString, std::string_view>(Value: std::string_view(HW)); |
| 113 | } |
| 114 | |
| 115 | TEST(SimplePackedSerializationTest, SpanSerialization) { |
| 116 | const char Data[] = {3, 2, 1, 0, 1, 2, 3}; // Span should handle nulls. |
| 117 | span<const char> OutS(Data, sizeof(Data)); |
| 118 | |
| 119 | size_t Size = SPSArgList<SPSSequence<char>>::size(Arg: OutS); |
| 120 | auto Buffer = std::make_unique<char[]>(num: Size); |
| 121 | SPSOutputBuffer OB(Buffer.get(), Size); |
| 122 | |
| 123 | EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, Arg: OutS)); |
| 124 | |
| 125 | SPSInputBuffer IB(Buffer.get(), Size); |
| 126 | |
| 127 | span<const char> InS; |
| 128 | |
| 129 | EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, Arg&: InS)); |
| 130 | |
| 131 | // Check that the serialized and deserialized values match. |
| 132 | EXPECT_EQ(InS.size(), OutS.size()); |
| 133 | EXPECT_EQ(memcmp(s1: OutS.data(), s2: InS.data(), n: InS.size()), 0); |
| 134 | |
| 135 | // Check that the span points directly to the input buffer. |
| 136 | EXPECT_EQ(InS.data(), Buffer.get() + sizeof(uint64_t)); |
| 137 | } |
| 138 | |
| 139 | TEST(SimplePackedSerializationTest, StdTupleSerialization) { |
| 140 | std::tuple<int32_t, std::string, bool> P(42, "foo" , true); |
| 141 | blobSerializationRoundTrip<SPSTuple<int32_t, SPSString, bool>>(Value: P); |
| 142 | } |
| 143 | |
| 144 | TEST(SimplePackedSerializationTest, StdPairSerialization) { |
| 145 | std::pair<int32_t, std::string> P(42, "foo" ); |
| 146 | blobSerializationRoundTrip<SPSTuple<int32_t, SPSString>, |
| 147 | std::pair<int32_t, std::string>>(Value: P); |
| 148 | } |
| 149 | |
| 150 | TEST(SimplePackedSerializationTest, StdOptionalNoValueSerialization) { |
| 151 | std::optional<int64_t> NoValue; |
| 152 | blobSerializationRoundTrip<SPSOptional<int64_t>>(Value: NoValue); |
| 153 | } |
| 154 | |
| 155 | TEST(SimplePackedSerializationTest, StdOptionalValueSerialization) { |
| 156 | std::optional<int64_t> Value(42); |
| 157 | blobSerializationRoundTrip<SPSOptional<int64_t>>(Value); |
| 158 | } |
| 159 | |
| 160 | TEST(SimplePackedSerializationTest, ArgListSerialization) { |
| 161 | using BAL = SPSArgList<bool, int32_t, SPSString>; |
| 162 | |
| 163 | bool Arg1 = true; |
| 164 | int32_t Arg2 = 42; |
| 165 | std::string Arg3 = "foo" ; |
| 166 | |
| 167 | size_t Size = BAL::size(Arg: Arg1, Args: Arg2, Args: Arg3); |
| 168 | auto Buffer = std::make_unique<char[]>(num: Size); |
| 169 | SPSOutputBuffer OB(Buffer.get(), Size); |
| 170 | |
| 171 | EXPECT_TRUE(BAL::serialize(OB, Arg: Arg1, Args: Arg2, Args: Arg3)); |
| 172 | |
| 173 | SPSInputBuffer IB(Buffer.get(), Size); |
| 174 | |
| 175 | bool ArgOut1; |
| 176 | int32_t ArgOut2; |
| 177 | std::string ArgOut3; |
| 178 | |
| 179 | EXPECT_TRUE(BAL::deserialize(IB, Arg&: ArgOut1, Args&: ArgOut2, Args&: ArgOut3)); |
| 180 | |
| 181 | EXPECT_EQ(Arg1, ArgOut1); |
| 182 | EXPECT_EQ(Arg2, ArgOut2); |
| 183 | EXPECT_EQ(Arg3, ArgOut3); |
| 184 | } |
| 185 | |