xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp (revision 1834a310d060d55748ca38d4ae0482864c2047d8)
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