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