1#include "test.h"
2
3#include <base/mem.h>
4#include <base/str.h>
5
6#include <engine/shared/packer.h>
7
8#include <gtest/gtest.h>
9
10// pExpected is NULL if an error is expected
11static void ExpectAddString5(const char *pString, int Limit, bool AllowTruncation, const char *pExpected)
12{
13 static char ZEROS[CPacker::PACKER_BUFFER_SIZE] = {0};
14 static const int OFFSET = CPacker::PACKER_BUFFER_SIZE - 5;
15 CPacker Packer;
16 Packer.Reset();
17 Packer.AddRaw(pData: ZEROS, Size: OFFSET);
18 Packer.AddString(pStr: pString, Limit, AllowTruncation);
19
20 EXPECT_EQ(pExpected == 0, Packer.Error()) << "for String='" << pString << "', Limit='" << Limit << "', AllowTruncation='" << AllowTruncation << "'";
21 if(pExpected)
22 {
23 // Include null termination.
24 int ExpectedLength = str_length(str: pExpected) + 1;
25 EXPECT_EQ(ExpectedLength, Packer.Size() - OFFSET) << "for String='" << pString << "', Limit='" << Limit << "', AllowTruncation='" << AllowTruncation << "'";
26 if(ExpectedLength == Packer.Size() - OFFSET)
27 {
28 EXPECT_STREQ(pExpected, (const char *)Packer.Data() + OFFSET) << "for String='" << pString << "', Limit='" << Limit << "', AllowTruncation='" << AllowTruncation << "'";
29 }
30 }
31}
32
33static void ExpectAddInt(int Input, int Expected)
34{
35 CPacker Packer;
36 Packer.Reset();
37 Packer.AddInt(i: Input);
38 EXPECT_EQ(Packer.Error(), false);
39 ASSERT_EQ(Packer.Size(), 1);
40 EXPECT_EQ(Packer.Data()[0], Expected);
41}
42
43static void ExpectAddExtendedInt(int Input, unsigned char *pExpected, int Size)
44{
45 CPacker Packer;
46 Packer.Reset();
47 Packer.AddInt(i: Input);
48 EXPECT_EQ(Packer.Error(), false);
49 ASSERT_EQ(Packer.Size(), Size);
50 EXPECT_EQ(mem_comp(Packer.Data(), pExpected, Size), 0);
51}
52
53TEST(Packer, AddInt)
54{
55 ExpectAddInt(Input: 1, Expected: 0b0000'0001);
56 ExpectAddInt(Input: 2, Expected: 0b0000'0010);
57 // ^^^ ^
58 // ||\ /
59 // Not extended| \ /
60 // | \ /
61 // |00'0010 => 2
62 // |
63 // Positive
64
65 // there is no -0 so 00 0000
66 // plus the negative bit is -1
67 ExpectAddInt(Input: -1, Expected: 0b0100'0000);
68 // ^^^ ^
69 // ||\ /
70 // Not extended| \ /
71 // | \ /
72 // |00'0000 => 0
73 // |
74 // Negative
75 ExpectAddInt(Input: -2, Expected: 0b0100'0001);
76
77 // 0-63 packed ints
78 // are represented the same way
79 // C++ represents ints
80 // All other numbers differ due to packing shinanigans
81 for(int i = 0; i < 63; i++)
82 ExpectAddInt(Input: i, Expected: i);
83}
84
85TEST(Packer, AddExtendedInt)
86{
87 unsigned char pExpected64[] = {
88 0b1000'0000, 0b0000'0001};
89 ExpectAddExtendedInt(Input: 64, pExpected: pExpected64, Size: 2);
90 unsigned char pExpected65[] = {
91 0b1000'0001, 0b0000'0001
92 /*^^^ ^ ^^ ^
93 ||\ / | \ /
94 || \ / | \ /
95 || \ / Not \/
96 || \ Extended /
97 || \ /
98 || \ /
99 || \ /
100 || \ /
101 || \ /
102 || X
103 || / \
104 || / \
105 || / \
106 || / \
107 || 000'0001 00'0001 => 1000001 => 65
108 ||
109 |0 Not negative
110 |
111 1 Extended (one more byte following)
112 */
113 };
114 ExpectAddExtendedInt(Input: 65, pExpected: pExpected65, Size: 2);
115
116 unsigned char pExpected66[] = {
117 0b1000'0010, 0b0000'0001
118 /*^^^ ^ ^^ ^
119 ||\ / | \ /
120 || \ / | \ /
121 || \ / Not \/
122 || \ Extended /
123 || \ /
124 || \ /
125 || \ /
126 || \ /
127 || \ /
128 || X
129 || / \
130 || / \
131 || / \
132 || / \
133 || 000'0001 00'0010 => 1000010 => 66
134 ||
135 |0 Not negative
136 |
137 1 Extended (one more byte following)
138 */
139 };
140 ExpectAddExtendedInt(Input: 66, pExpected: pExpected66, Size: 2);
141
142 // there is no -0 so all negative numbers
143 // are one smaller
144 // So 64 + negative bit is -65
145 unsigned char pExpectedNegative65[] = {
146 0b1100'0000, 0b0000'0001
147 /*^^^ ^ ^^ ^
148 ||\ / | \ /
149 || \ / | \ /
150 || \ / Not \/
151 || \ Extended /
152 || \ /
153 || \ /
154 || \ /
155 || \ /
156 || \ /
157 || X
158 || / \
159 || / \
160 || / \
161 || / \
162 || 000'0001 00'0000 => 1000000 => 64
163 ||
164 |1 Negative
165 |
166 1 Extended (one more byte following)
167 */
168 };
169 ExpectAddExtendedInt(Input: -65, pExpected: pExpectedNegative65, Size: 2);
170
171 unsigned char pExpectedNegative66[] = {
172 0b1100'0001, 0b0000'0001
173 /*^^^ ^ ^^ ^
174 ||\ / | \ /
175 || \ / | \ /
176 || \ / Not \/
177 || \ Extended /
178 || \ /
179 || \ /
180 || \ /
181 || \ /
182 || \ /
183 || X
184 || / \
185 || / \
186 || / \
187 || / \
188 || 000'0001 00'0001 => 1000001 => 65
189 ||
190 |1 Negative
191 |
192 1 Extended (one more byte following)
193 */
194 };
195 ExpectAddExtendedInt(Input: -66, pExpected: pExpectedNegative66, Size: 2);
196
197 unsigned char pExpectedNegative67[] = {
198 0b1100'0010, 0b0000'0001};
199 ExpectAddExtendedInt(Input: -67, pExpected: pExpectedNegative67, Size: 2);
200 unsigned char pExpectedNegative68[] = {
201 0b1100'0011, 0b0000'0001};
202 ExpectAddExtendedInt(Input: -68, pExpected: pExpectedNegative68, Size: 2);
203 unsigned char pExpectedNegative69[] = {
204 0b1100'0100, 0b0000'0001};
205 ExpectAddExtendedInt(Input: -69, pExpected: pExpectedNegative69, Size: 2);
206 unsigned char pExpectedNegative70[] = {
207 0b1100'0101, 0b0000'0001};
208 ExpectAddExtendedInt(Input: -70, pExpected: pExpectedNegative70, Size: 2);
209}
210
211TEST(Packer, AddString)
212{
213 ExpectAddString5(pString: "", Limit: 0, AllowTruncation: true, pExpected: "");
214 ExpectAddString5(pString: "a", Limit: 0, AllowTruncation: true, pExpected: "a");
215 ExpectAddString5(pString: "abcd", Limit: 0, AllowTruncation: true, pExpected: "abcd");
216 ExpectAddString5(pString: "abcde", Limit: 0, AllowTruncation: true, pExpected: nullptr);
217}
218
219TEST(Packer, AddStringLimit)
220{
221 ExpectAddString5(pString: "", Limit: 1, AllowTruncation: true, pExpected: "");
222 ExpectAddString5(pString: "a", Limit: 1, AllowTruncation: true, pExpected: "a");
223 ExpectAddString5(pString: "aa", Limit: 1, AllowTruncation: true, pExpected: "a");
224 ExpectAddString5(pString: "ä", Limit: 1, AllowTruncation: true, pExpected: "");
225
226 ExpectAddString5(pString: "", Limit: 10, AllowTruncation: true, pExpected: "");
227 ExpectAddString5(pString: "a", Limit: 10, AllowTruncation: true, pExpected: "a");
228 ExpectAddString5(pString: "abcd", Limit: 10, AllowTruncation: true, pExpected: "abcd");
229 ExpectAddString5(pString: "abcde", Limit: 10, AllowTruncation: true, pExpected: nullptr);
230
231 ExpectAddString5(pString: "äöü", Limit: 4, AllowTruncation: true, pExpected: "äö");
232 ExpectAddString5(pString: "äöü", Limit: 5, AllowTruncation: true, pExpected: "äö");
233 ExpectAddString5(pString: "äöü", Limit: 6, AllowTruncation: true, pExpected: nullptr);
234
235 ExpectAddString5(pString: "", Limit: 1, AllowTruncation: false, pExpected: "");
236 ExpectAddString5(pString: "a", Limit: 1, AllowTruncation: false, pExpected: "a");
237 ExpectAddString5(pString: "aa", Limit: 1, AllowTruncation: false, pExpected: nullptr);
238 ExpectAddString5(pString: "ä", Limit: 1, AllowTruncation: false, pExpected: nullptr);
239
240 ExpectAddString5(pString: "", Limit: 10, AllowTruncation: false, pExpected: "");
241 ExpectAddString5(pString: "a", Limit: 10, AllowTruncation: false, pExpected: "a");
242 ExpectAddString5(pString: "abcd", Limit: 10, AllowTruncation: false, pExpected: "abcd");
243 ExpectAddString5(pString: "abcde", Limit: 10, AllowTruncation: false, pExpected: nullptr);
244
245 ExpectAddString5(pString: "äöü", Limit: 4, AllowTruncation: false, pExpected: nullptr);
246 ExpectAddString5(pString: "äöü", Limit: 5, AllowTruncation: false, pExpected: nullptr);
247 ExpectAddString5(pString: "äöü", Limit: 6, AllowTruncation: false, pExpected: nullptr);
248}
249
250TEST(Packer, AddStringBroken)
251{
252 ExpectAddString5(pString: "\x80", Limit: 0, AllowTruncation: true, pExpected: "�");
253 ExpectAddString5(pString: "\x80\x80", Limit: 0, AllowTruncation: true, pExpected: nullptr);
254 ExpectAddString5(pString: "a\x80", Limit: 0, AllowTruncation: true, pExpected: "a�");
255 ExpectAddString5(pString: "\x80"
256 "a",
257 Limit: 0, AllowTruncation: true, pExpected: "�a");
258
259 ExpectAddString5(pString: "\x80", Limit: 1, AllowTruncation: true, pExpected: "");
260 ExpectAddString5(pString: "\x80", Limit: 3, AllowTruncation: true, pExpected: "�");
261 ExpectAddString5(pString: "\x80\x80", Limit: 3, AllowTruncation: true, pExpected: "�");
262 ExpectAddString5(pString: "\x80\x80", Limit: 5, AllowTruncation: true, pExpected: "�");
263 ExpectAddString5(pString: "\x80\x80", Limit: 6, AllowTruncation: true, pExpected: nullptr);
264
265 ExpectAddString5(pString: "\x80", Limit: 1, AllowTruncation: false, pExpected: nullptr);
266 ExpectAddString5(pString: "\x80", Limit: 3, AllowTruncation: false, pExpected: "�");
267 ExpectAddString5(pString: "\x80\x80", Limit: 3, AllowTruncation: false, pExpected: nullptr);
268 ExpectAddString5(pString: "\x80\x80", Limit: 5, AllowTruncation: false, pExpected: nullptr);
269 ExpectAddString5(pString: "\x80\x80", Limit: 6, AllowTruncation: false, pExpected: nullptr);
270}
271
272TEST(Packer, Error1)
273{
274 char aData[CPacker::PACKER_BUFFER_SIZE];
275 mem_zero(block: aData, size: sizeof(aData));
276
277 CPacker Packer;
278 Packer.Reset();
279 EXPECT_EQ(Packer.Error(), false);
280 Packer.AddRaw(pData: aData, Size: sizeof(aData) - 1);
281 EXPECT_EQ(Packer.Error(), false);
282 EXPECT_EQ(Packer.Size(), sizeof(aData) - 1);
283 Packer.AddInt(i: 1);
284 EXPECT_EQ(Packer.Error(), false);
285 EXPECT_EQ(Packer.Size(), sizeof(aData));
286 Packer.AddInt(i: 2);
287 EXPECT_EQ(Packer.Error(), true);
288 Packer.AddInt(i: 3);
289 EXPECT_EQ(Packer.Error(), true);
290}
291
292TEST(Packer, Error2)
293{
294 char aData[CPacker::PACKER_BUFFER_SIZE];
295 mem_zero(block: aData, size: sizeof(aData));
296
297 CPacker Packer;
298 Packer.Reset();
299 EXPECT_EQ(Packer.Error(), false);
300 Packer.AddRaw(pData: aData, Size: sizeof(aData) - 1);
301 EXPECT_EQ(Packer.Error(), false);
302 EXPECT_EQ(Packer.Size(), sizeof(aData) - 1);
303 Packer.AddRaw(pData: aData, Size: 1);
304 EXPECT_EQ(Packer.Error(), false);
305 EXPECT_EQ(Packer.Size(), sizeof(aData));
306 Packer.AddRaw(pData: aData, Size: 1);
307 EXPECT_EQ(Packer.Error(), true);
308 Packer.AddRaw(pData: aData, Size: 1);
309 EXPECT_EQ(Packer.Error(), true);
310}
311
312TEST(Packer, Error3)
313{
314 char aData[CPacker::PACKER_BUFFER_SIZE];
315 mem_zero(block: aData, size: sizeof(aData));
316
317 CPacker Packer;
318 Packer.Reset();
319 EXPECT_EQ(Packer.Error(), false);
320 Packer.AddRaw(pData: aData, Size: sizeof(aData) - 5);
321 EXPECT_EQ(Packer.Error(), false);
322 EXPECT_EQ(Packer.Size(), sizeof(aData) - 5);
323 Packer.AddString(pStr: "test");
324 EXPECT_EQ(Packer.Error(), false);
325 EXPECT_EQ(Packer.Size(), sizeof(aData));
326 Packer.AddString(pStr: "test");
327 EXPECT_EQ(Packer.Error(), true);
328 Packer.AddString(pStr: "test");
329 EXPECT_EQ(Packer.Error(), true);
330}
331