1 //===-------- SimplePackedSerializationTest.cpp - Test SPS scheme ---------===// 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 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" 10 #include "gtest/gtest.h" 11 12 using namespace llvm; 13 using namespace llvm::orc::shared; 14 15 TEST(SimplePackedSerializationTest, SPSOutputBuffer) { 16 constexpr unsigned NumBytes = 8; 17 char Buffer[NumBytes]; 18 char Zero = 0; 19 SPSOutputBuffer OB(Buffer, NumBytes); 20 21 // Expect that we can write NumBytes of content. 22 for (unsigned I = 0; I != NumBytes; ++I) { 23 char C = I; 24 EXPECT_TRUE(OB.write(&C, 1)); 25 } 26 27 // Expect an error when we attempt to write an extra byte. 28 EXPECT_FALSE(OB.write(&Zero, 1)); 29 30 // Check that the buffer contains the expected content. 31 for (unsigned I = 0; I != NumBytes; ++I) 32 EXPECT_EQ(Buffer[I], (char)I); 33 } 34 35 TEST(SimplePackedSerializationTest, SPSInputBuffer) { 36 char Buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; 37 SPSInputBuffer IB(Buffer, sizeof(Buffer)); 38 39 char C; 40 for (unsigned I = 0; I != sizeof(Buffer); ++I) { 41 EXPECT_TRUE(IB.read(&C, 1)); 42 EXPECT_EQ(C, (char)I); 43 } 44 45 EXPECT_FALSE(IB.read(&C, 1)); 46 } 47 48 template <typename SPSTagT, typename T> 49 static void spsSerializationRoundTrip(const T &Value) { 50 using BST = SPSSerializationTraits<SPSTagT, T>; 51 52 size_t Size = BST::size(Value); 53 auto Buffer = std::make_unique<char[]>(Size); 54 SPSOutputBuffer OB(Buffer.get(), Size); 55 56 EXPECT_TRUE(BST::serialize(OB, Value)); 57 58 SPSInputBuffer IB(Buffer.get(), Size); 59 60 T DSValue; 61 EXPECT_TRUE(BST::deserialize(IB, DSValue)); 62 63 EXPECT_EQ(Value, DSValue) 64 << "Incorrect value after serialization/deserialization round-trip"; 65 } 66 67 template <typename T> static void testFixedIntegralTypeSerialization() { 68 spsSerializationRoundTrip<T, T>(0); 69 spsSerializationRoundTrip<T, T>(static_cast<T>(1)); 70 if (std::is_signed_v<T>) { 71 spsSerializationRoundTrip<T, T>(static_cast<T>(-1)); 72 spsSerializationRoundTrip<T, T>(std::numeric_limits<T>::min()); 73 } 74 spsSerializationRoundTrip<T, T>(std::numeric_limits<T>::max()); 75 } 76 77 TEST(SimplePackedSerializationTest, BoolSerialization) { 78 spsSerializationRoundTrip<bool, bool>(true); 79 spsSerializationRoundTrip<bool, bool>(false); 80 } 81 82 TEST(SimplePackedSerializationTest, CharSerialization) { 83 spsSerializationRoundTrip<char, char>((char)0x00); 84 spsSerializationRoundTrip<char, char>((char)0xAA); 85 spsSerializationRoundTrip<char, char>((char)0xFF); 86 } 87 88 TEST(SimplePackedSerializationTest, Int8Serialization) { 89 testFixedIntegralTypeSerialization<int8_t>(); 90 } 91 92 TEST(SimplePackedSerializationTest, UInt8Serialization) { 93 testFixedIntegralTypeSerialization<uint8_t>(); 94 } 95 96 TEST(SimplePackedSerializationTest, Int16Serialization) { 97 testFixedIntegralTypeSerialization<int16_t>(); 98 } 99 100 TEST(SimplePackedSerializationTest, UInt16Serialization) { 101 testFixedIntegralTypeSerialization<uint16_t>(); 102 } 103 104 TEST(SimplePackedSerializationTest, Int32Serialization) { 105 testFixedIntegralTypeSerialization<int32_t>(); 106 } 107 108 TEST(SimplePackedSerializationTest, UInt32Serialization) { 109 testFixedIntegralTypeSerialization<uint32_t>(); 110 } 111 112 TEST(SimplePackedSerializationTest, Int64Serialization) { 113 testFixedIntegralTypeSerialization<int64_t>(); 114 } 115 116 TEST(SimplePackedSerializationTest, UInt64Serialization) { 117 testFixedIntegralTypeSerialization<uint64_t>(); 118 } 119 120 TEST(SimplePackedSerializationTest, SequenceSerialization) { 121 std::vector<int32_t> V({1, 2, -47, 139}); 122 spsSerializationRoundTrip<SPSSequence<int32_t>>(V); 123 } 124 125 TEST(SimplePackedSerializationTest, StringViewCharSequenceSerialization) { 126 const char *HW = "Hello, world!"; 127 spsSerializationRoundTrip<SPSString>(StringRef(HW)); 128 } 129 130 TEST(SimplePackedSerializationTest, StdTupleSerialization) { 131 std::tuple<int32_t, std::string, bool> P(42, "foo", true); 132 spsSerializationRoundTrip<SPSTuple<int32_t, SPSString, bool>>(P); 133 } 134 135 TEST(SimplePackedSerializationTest, StdPairSerialization) { 136 std::pair<int32_t, std::string> P(42, "foo"); 137 spsSerializationRoundTrip<SPSTuple<int32_t, SPSString>>(P); 138 } 139 140 TEST(SimplePackedSerializationTest, ArgListSerialization) { 141 using BAL = SPSArgList<bool, int32_t, SPSString>; 142 143 bool Arg1 = true; 144 int32_t Arg2 = 42; 145 std::string Arg3 = "foo"; 146 147 size_t Size = BAL::size(Arg1, Arg2, Arg3); 148 auto Buffer = std::make_unique<char[]>(Size); 149 SPSOutputBuffer OB(Buffer.get(), Size); 150 151 EXPECT_TRUE(BAL::serialize(OB, Arg1, Arg2, Arg3)); 152 153 SPSInputBuffer IB(Buffer.get(), Size); 154 155 bool ArgOut1; 156 int32_t ArgOut2; 157 std::string ArgOut3; 158 159 EXPECT_TRUE(BAL::deserialize(IB, ArgOut1, ArgOut2, ArgOut3)); 160 161 EXPECT_EQ(Arg1, ArgOut1); 162 EXPECT_EQ(Arg2, ArgOut2); 163 EXPECT_EQ(Arg3, ArgOut3); 164 } 165 166 TEST(SimplePackedSerialization, StringMap) { 167 StringMap<int32_t> M({{"A", 1}, {"B", 2}}); 168 spsSerializationRoundTrip<SPSSequence<SPSTuple<SPSString, int32_t>>>(M); 169 } 170 171 TEST(SimplePackedSerializationTest, ArrayRef) { 172 constexpr unsigned BufferSize = 6 + 8; // "hello\0" + sizeof(uint64_t) 173 ArrayRef<char> HelloOut = "hello"; 174 char Buffer[BufferSize]; 175 memset(Buffer, 0, BufferSize); 176 177 SPSOutputBuffer OB(Buffer, BufferSize); 178 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, HelloOut)); 179 180 ArrayRef<char> HelloIn; 181 SPSInputBuffer IB(Buffer, BufferSize); 182 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, HelloIn)); 183 184 // Output should be copied to buffer. 185 EXPECT_NE(HelloOut.data(), Buffer); 186 187 // Input should reference buffer. 188 EXPECT_LT(HelloIn.data() - Buffer, BufferSize); 189 } 190 191 TEST(SimplePackedSerializationTest, ArrayRefEmpty) { 192 // Make sure that empty ArrayRefs serialize and deserialize as expected. 193 // Empty ArrayRefs should not succeed even when the data field is null, and 194 // should deserialize to a default-constructed ArrayRef, not a pointer into 195 // the stream. 196 constexpr unsigned BufferSize = sizeof(uint64_t); 197 char Buffer[BufferSize]; 198 memset(Buffer, 0, BufferSize); 199 200 ArrayRef<char> AOut; 201 SPSOutputBuffer OB(Buffer, BufferSize); 202 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, AOut)); 203 204 ArrayRef<char> AIn; 205 SPSInputBuffer IB(Buffer, BufferSize); 206 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, AIn)); 207 208 EXPECT_EQ(AIn.data(), nullptr); 209 EXPECT_EQ(AIn.size(), 0U); 210 } 211 212 TEST(SimplePackedSerializationTest, StringRefEmpty) { 213 // Make sure that empty StringRefs serialize and deserialize as expected. 214 // Empty StringRefs should not succeed even when the data field is null, and 215 // should deserialize to a default-constructed StringRef, not a pointer into 216 // the stream. 217 constexpr unsigned BufferSize = sizeof(uint64_t); 218 char Buffer[BufferSize]; 219 memset(Buffer, 0, BufferSize); 220 221 StringRef SROut; 222 SPSOutputBuffer OB(Buffer, BufferSize); 223 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, SROut)); 224 225 StringRef SRIn; 226 SPSInputBuffer IB(Buffer, BufferSize); 227 EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, SRIn)); 228 229 EXPECT_EQ(SRIn.data(), nullptr); 230 EXPECT_EQ(SRIn.size(), 0U); 231 } 232