UFO: Alien Invasion
Loading...
Searching...
No Matches
test_generic.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "test_shared.h"
27#include "../common/common.h"
28#include "../common/sha1.h"
29#include "../common/sha2.h"
30#include "../common/http.h"
32#include "../shared/utf8.h"
33#include "../shared/shared.h"
34#include "../shared/parse.h"
38#include "../ports/system.h"
39
40class GenericTest: public ::testing::Test {
41protected:
42 static void SetUpTestCase() {
43 TEST_Init();
44 }
45
46 static void TearDownTestCase() {
49 }
50};
51
52static void STRHUNK_VisitorTestEntry (const char* string)
53{
54 ASSERT_STREQ(string, "Test");
55}
56
57static void STRHUNK_VisitorTestEntry2 (const char* string)
58{
59 ASSERT_STREQ(string, "T");
60}
61
62TEST_F(GenericTest, StringHunks)
63{
64 stringHunk_t* hunk = STRHUNK_Create(20);
65 ASSERT_TRUE(STRHUNK_Add(hunk, "Test"));
66 ASSERT_EQ(STRHUNK_Size(hunk), 1);
67 ASSERT_EQ(STRHUNK_GetFreeSpace(hunk), 15);
69 STRHUNK_Delete(&hunk);
70 ASSERT_TRUE(nullptr == hunk);
71
72 hunk = STRHUNK_Create(23);
73 ASSERT_TRUE(STRHUNK_Add(hunk, "Test"));
74 ASSERT_TRUE(STRHUNK_Add(hunk, "Test"));
75 ASSERT_TRUE(STRHUNK_Add(hunk, "Test"));
76 ASSERT_TRUE(STRHUNK_Add(hunk, "Test"));
77 ASSERT_EQ(STRHUNK_Size(hunk), 4);
78 ASSERT_EQ(STRHUNK_GetFreeSpace(hunk), 0);
80
81 STRHUNK_Reset(hunk);
82 ASSERT_EQ(STRHUNK_Size(hunk), 0);
83
84 STRHUNK_Delete(&hunk);
85 ASSERT_TRUE(nullptr == hunk);
86
87 hunk = STRHUNK_Create(5);
88 ASSERT_TRUE(STRHUNK_Add(hunk, "T"));
89 ASSERT_FALSE(STRHUNK_Add(hunk, "Test"));
90 /* the second string is ignored */
91 ASSERT_FALSE(STRHUNK_Add(hunk, "Test"));
92 ASSERT_EQ(STRHUNK_Size(hunk), 2);
94 STRHUNK_Delete(&hunk);
95}
96
98{
99 const constListEntry_t list[] = {
100 {"namespace::power", 1},
101 {"namespace::speed", 2},
102 {"namespace::accuracy", 3},
103 {"namespace::mind", 4},
104 {"namespace::close", 5},
105 {"namespace::heavy", 6},
106 {"namespace::assault", 7},
107 {"namespace::sniper", 8},
108 {"namespace::explosive", 9},
109 {"namespace::hp", 10},
110
111 {nullptr, -1}
112 };
113 const constListEntry_t list2[] = {
114 {"namespace2::soldier", 0},
115 {"namespace2::scientist", 1},
116 {"namespace2::worker", 2},
117 {"namespace2::pilot", 3},
118 {nullptr, -1}
119 };
120 int out;
121
122 Com_RegisterConstInt("namespace::variable", 1);
123 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable"));
124
125 Com_RegisterConstInt("namespace::variable", 1);
126 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable"));
127
128 Com_RegisterConstInt("namespace::variable2", 2);
129 Com_RegisterConstInt("namespace::variable3", 3);
130 Com_RegisterConstInt("namespace::variable4", 4);
131 Com_RegisterConstInt("namespace::variable5", 5);
132 Com_RegisterConstInt("namespace::variable6", 6);
133
134 Com_RegisterConstInt("namespace2::variable2", 10);
135
136 out = 0;
137 ASSERT_TRUE(Com_GetConstInt("namespace2::variable2", &out));
138 ASSERT_EQ(out, 10);
139 out = 0;
140 ASSERT_TRUE(Com_GetConstInt("namespace::variable2", &out));
141 ASSERT_EQ(out, 2);
142 out = 0;
143 ASSERT_TRUE(Com_GetConstInt("variable2", &out));
144 ASSERT_EQ(out, 10);
145
146 ASSERT_STREQ(Com_GetConstVariable("namespace", 2), "variable2");
147
148 ASSERT_TRUE(Com_UnregisterConstVariable("namespace2::variable2"));
149 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable2"));
150 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable3"));
151 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable4"));
152 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable5"));
153 ASSERT_TRUE(Com_UnregisterConstVariable("namespace::variable6"));
154
155 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable"));
156 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable2"));
157 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable3"));
158 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable4"));
159 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable5"));
160 ASSERT_TRUE(!Com_UnregisterConstVariable("namespace::variable6"));
161
163 out = 0;
164 ASSERT_TRUE(Com_GetConstInt("sniper", &out));
165 ASSERT_EQ(out, 8);
166
167 ASSERT_TRUE(Com_UnregisterConstList(list));
168 out = 0;
169 ASSERT_FALSE(Com_GetConstInt("sniper", &out));
170
172
174 ASSERT_TRUE(Com_UnregisterConstList(list));
175
176 out = 0;
177 ASSERT_TRUE(Com_GetConstInt("pilot", &out));
178 ASSERT_EQ(out, 3);
180}
181
182static int testListSorter (linkedList_t* entry1, linkedList_t* entry2, const void* userData)
183{
184 return strcmp((const char*)entry1->data, (const char*)entry2->data);
185}
186
187TEST_F(GenericTest, LinkedList)
188{
189 linkedList_t* list = nullptr, *list2;
190 const char* data = "SomeDataForTheLinkedList";
191 const size_t length = strlen(data);
192 linkedList_t* entry;
193 const linkedList_t* entry2;
194 const char* returnedData;
195
196 entry = LIST_Add(&list, data, length);
197 ASSERT_EQ(LIST_Count(list), 1);
198 ASSERT_TRUE(entry != nullptr);
199 returnedData = (const char*)LIST_GetByIdx(list, 0);
200 ASSERT_TRUE(returnedData != nullptr);
201 entry2 = LIST_ContainsString(list, returnedData);
202 ASSERT_TRUE(entry2 != nullptr);
203 ASSERT_EQ((const void*)entry2->data, (const void*)returnedData);
204 ASSERT_STREQ(static_cast<const char*>(entry2->data), returnedData);
205 LIST_RemoveEntry(&list, entry);
206 ASSERT_EQ(LIST_Count(list), 0);
207 ASSERT_EQ(LIST_Count(LIST_CopyStructure(list)), 0);
208 LIST_Add(&list, data, length);
209 list2 = LIST_CopyStructure(list);
210 ASSERT_EQ(LIST_Count(list2), 1);
211 LIST_Delete(&list2);
212 ASSERT_EQ(LIST_Count(list2), 0);
213 ASSERT_EQ(LIST_Count(list), 1);
214 LIST_Delete(&list);
215 ASSERT_TRUE(nullptr == LIST_GetRandom(list2));
216
217 LIST_AddString(&list, "test6");
218 LIST_AddString(&list, "test2");
219 LIST_AddString(&list, "test1");
220 LIST_AddString(&list, "test3");
221 LIST_AddString(&list, "test5");
222 LIST_AddString(&list, "test4");
223 LIST_AddString(&list, "test7");
224 ASSERT_EQ(LIST_Count(list), 7);
225 ASSERT_TRUE(nullptr != LIST_GetRandom(list));
226
227 LIST_Sort(&list, testListSorter, nullptr);
228 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 0)), "test1");
229 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 1)), "test2");
230 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 2)), "test3");
231 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 3)), "test4");
232 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 4)), "test5");
233 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 5)), "test6");
234 ASSERT_STREQ(static_cast<const char*>(LIST_GetByIdx(list, 6)), "test7");
235}
236
237TEST_F(GenericTest, LinkedListIterator)
238{
239 linkedList_t* list = nullptr;
240 int cnt;
241
242 LIST_AddString(&list, "test1");
243 LIST_AddString(&list, "test2");
244 LIST_AddString(&list, "test3");
245
246 cnt = 0;
247 LIST_Foreach(list, char, string) {
248 ASSERT_TRUE(nullptr != string);
249 cnt++;
250 }
251
252 LIST_Delete(&list);
253
254 ASSERT_EQ(cnt, 3);
255
256 list = nullptr;
257 LIST_Foreach(list, char, string) {
258 (void)string;
259 /* we should not be here, because the list is empty */
260 ASSERT_TRUE(false);
261 }
262}
263
264TEST_F(GenericTest, LinkedListIteratorRemove)
265{
266 linkedList_t* list = nullptr;
267
268 LIST_AddString(&list, "test1");
269 LIST_AddString(&list, "test2");
270 LIST_AddString(&list, "test3");
271
272 LIST_Foreach(list, char, string) {
273 Com_Printf("Found string: %s\n", string);
274 LIST_Remove(&list, string);
275 }
276
277 ASSERT_TRUE(LIST_IsEmpty(list));
278}
279
280TEST_F(GenericTest, PrependStringList)
281{
282 linkedList_t* list = nullptr;
283
284 LIST_PrependString(&list, "test2");
285 LIST_PrependString(&list, "test1");
286
287 ASSERT_STREQ((const char*)LIST_GetByIdx(list, 0), "test1");
288 ASSERT_STREQ((const char*)LIST_GetByIdx(list, 1), "test2");
289
290 LIST_Delete(&list);
291}
292
293TEST_F(GenericTest, LinkedListStringSort)
294{
295 linkedList_t* list = nullptr;
296
297 LIST_AddStringSorted(&list, "test2");
298 LIST_AddStringSorted(&list, "test1");
299 LIST_AddStringSorted(&list, "test3");
300
301 ASSERT_STREQ((const char*)LIST_GetByIdx(list, 0), "test1");
302
303 LIST_Delete(&list);
304}
305
306TEST_F(GenericTest, FileSystemBuildLists)
307{
308 const char* filename, *prev;
309 const char* wildcard = "ufos/**.ufo";
310 const int ufosCnt = FS_BuildFileList(wildcard);
311
312 ASSERT_TRUE(ufosCnt > 1);
313
314 prev = nullptr;
315 while ((filename = FS_NextFileFromFileList(wildcard)) != nullptr) {
316 if (prev != nullptr) {
317 ASSERT_EQ(Q_StringSort(prev, filename), -1);
318 }
319 prev = filename;
320 }
321
323}
324
325TEST_F(GenericTest, InfoStrings)
326{
327 char info[MAX_INFO_STRING] = "";
328
329 Info_SetValueForKey(info, sizeof(info), "name", "test");
330
331 ASSERT_STREQ(Info_ValueForKey(info, "name"), "test");
332 ASSERT_STREQ(Info_ValueForKey(info, "name2"), "");
333 Info_RemoveKey(info, "name");
334 ASSERT_STREQ(Info_ValueForKey(info, "name"), "");
335
336 Info_SetValueForKey(info, sizeof(info), "name", "\\invalid\\value");
337 ASSERT_STREQ(Info_ValueForKey(info, "name"), "");
338}
339
340TEST_F(GenericTest, TokenizeInfoStrings)
341{
342 Cvar_Get("password", "test", CVAR_USERINFO, nullptr);
343 char info[MAX_INFO_STRING];
344 const char* s = va(SV_CMD_CONNECT " %i \"%s\"\n", PROTOCOL_VERSION, Cvar_Userinfo(info, sizeof(info)));
345 Cmd_TokenizeString(s, false, false);
346 ASSERT_STREQ(Cmd_Argv(0), SV_CMD_CONNECT);
347 ASSERT_STREQ(Cmd_Argv(1), DOUBLEQUOTE(PROTOCOL_VERSION));
348 ASSERT_STREQ(Cmd_Argv(2), info);
349}
350
352{
353 Cvar_Get("testGeneric_cvar", "testGeneric_cvarValue", CVAR_NOSET, "No set");
354 Cvar_Set("testGeneric_cvar", "test");
355 ASSERT_STREQ(Cvar_GetString("testGeneric_cvar"), "testGeneric_cvarValue");
356}
357
358TEST_F(GenericTest, StringCopiers)
359{
360 const char src[] = "Командующий, я чрезвычайно рад доложить, что наш проект ОПЭВ был завершён успешно. Я прикрепил к письму "
361 "изображения и схемы прототипа лазерного оружия, в котором реализовано непрерывное волновое излучение достаточной "
362 "мощности в портативном корпусе. Практическое решение лежало не в тщетных попытках увеличения ёмкости аккумуляторной "
363 "батареи, а в использовании радикальных технологий миниатюризации с целью облегчения и уменьшения размеров существующих "
364 "лазеров с химической накачкой. Они использовались довольно долгое время, будучи частью экспериментальных военных "
365 "программ с конца XX века, но их применение всегда сталкивалось с множеством проблем. Модели химических лазеров с "
366 "реальными военными перспективами были слишком большими и громоздкими для использования в бою пехотой. До сих пор их "
367 "расположение было ограничено выбором между лазерными орудиями на сухопутном шасси и батареями морского базирования. "
368 "Боевое применение заключалось в основном для целей противоракетной обороны (ПРО). Тем не менее, теперь мы в ФАЛАНКС "
369 "создали компактное лазерное орудие. Вопреки своему малому размеру, оно полностью способно управлять фтор-дейтериевой "
370 "реакцией и её токсическими продуктами распада без опасности поражения личного состава. Разрешите мне дать вам краткое "
371 "описание принципа его работы. Внутри камеры сгорания этилен окисляется в пламени трифторида азота. В ходе этой реакции "
372 "выделяются свободные радикалы фтора, которые затем приводятся в контакт с газообразной смесью гелия и дейтерия. Дейтерий "
373 "вступает в реакцию с фтором, что приводит к образованию энергетически возбуждённых молекул фторида дейтерия. Они "
374 "подвергаются стимулированной эмиссии в оптическом резонаторе оружия, генерируя лазерный луч. Серия интеллектуальных "
375 "линз фокусирует и направляет луч в точку прицеливания, и даже вносит коррекцию, с учётом небольших перемещений стрелка "
376 "и/или цели. Излишки газообразного дейтерия направляются через сконструированную нами систему фильтров высокого давления, "
377 "которые задерживают все токсичные и радиоактивные молекулы перед выбросом отработанных паров в атмосферу. Фильтр требует "
378 "замены после каждой боевой операции, но разработанная нами система делает этот процесс простым и безболезненным. Если ";
379
380 long time;
381 const int copies = 10000;
382 char dest[8192];
383 int i;
384
385 Com_Printf("\n");
386 time = Sys_Milliseconds();
387 for (i = 0; i < copies; ++i) {
388 Q_strncpyz(dest, src, sizeof(dest));
389 }
390 time = Sys_Milliseconds() - time;
391 Com_Printf("%d copies with Q_strncpyz: %ld ms\n", copies, time);
392
393 time = Sys_Milliseconds();
394 for (i = 0; i < copies; ++i) {
395 UTF8_strncpyz(dest, src, sizeof(dest));
396 }
397 time = Sys_Milliseconds() - time;
398 Com_Printf("%d copies with UTF8_strncpyz: %ld ms\n", copies, time);
399
400 time = Sys_Milliseconds();
401 for (i = 0; i < copies; ++i) {
402 Com_sprintf(dest, sizeof(dest), "%s", src);
403 }
404 time = Sys_Milliseconds() - time;
405 Com_Printf("%d copies with Com_sprintf: %ld ms\n", copies, time);
406
407 const char* s = src;
408 int cnt = 0;
409 while (UTF8_next(&s) != -1) {
410 cnt++;
411 }
412 ASSERT_EQ(cnt, UTF8_strlen(src));
413
414 /* Com_sprintf */
415
416 /* empty string */
417 Com_sprintf(dest, 1, "aab%c%c", 0xd0, 0x80);
418 ASSERT_EQ(dest[0], '\0');
419
420 /* trimmed non utf8 */
421 Com_sprintf(dest, 4, "aab%c%c", 0xd0, 0x80);
422 ASSERT_EQ(dest[2], 'b');
423 ASSERT_EQ(dest[3], '\0');
424
425 /* trimmed utf8 char. */
426 Com_sprintf(dest, 5, "aab%c%c", 0xd0, 0x80);
427 ASSERT_EQ(dest[2], 'b');
428 ASSERT_EQ(dest[3], '\0');
429
430 /* untrimmed utf8 char. */
431 Com_sprintf(dest, 6, "aab%c%c", 0xd0, 0x80);
432 ASSERT_EQ((unsigned char) dest[3], 0xd0);
433 ASSERT_EQ((unsigned char) dest[4], 0x80);
434 ASSERT_EQ(dest[5], '\0');
435
436 /* 2 consecutive utf8 char. */
437 Com_sprintf(dest, 7, "aab\xD0\x80\xD0\x80");
438 ASSERT_NE(dest[3], '\0');
439 ASSERT_EQ(dest[5], '\0');
440
441 /* UTF8_strncpyz */
442
443 /* empty string */
444 UTF8_strncpyz(dest, "aab\xD0\x80", 1);
445 ASSERT_EQ(dest[0], '\0');
446
447 /* trimmed non utf8 */
448 UTF8_strncpyz(dest, "aab\xD0\x80", 4);
449 ASSERT_EQ(dest[2], 'b');
450 ASSERT_EQ(dest[3], '\0');
451
452 /* trimmed utf8 char. */
453 UTF8_strncpyz(dest, "aab\xD0\x80", 5);
454 ASSERT_EQ(dest[2], 'b');
455 ASSERT_EQ(dest[3], '\0');
456
457 /* untrimmed utf8 char. */
458 UTF8_strncpyz(dest, "aab\xD0\x80", 6);
459 ASSERT_EQ((unsigned char) dest[3], 0xd0);
460 ASSERT_EQ((unsigned char) dest[4], 0x80);
461 ASSERT_EQ(dest[5], '\0');
462
463 /* 2 consecutive utf8 char. */
464 UTF8_strncpyz(dest, "aab\xD0\x80\xD0\x80", 7);
465 ASSERT_NE(dest[3], '\0');
466 ASSERT_EQ(dest[5], '\0');
467}
468
469TEST_F(GenericTest, StringFunctions)
470{
471 char targetBuf[256];
472 char buf[16];
473 const size_t length = lengthof(targetBuf);
474
475 ASSERT_FALSE(Q_strreplace("ReplaceNothing", "###", "foobar", targetBuf, length));
476 ASSERT_TRUE(Q_strreplace("Replace###Something", "###", "foobar", targetBuf, length));
477 ASSERT_STREQ(targetBuf, "ReplacefoobarSomething");
478
479 ASSERT_TRUE(Q_strreplace("Replace#", "#", "foobar", targetBuf, length));
480 ASSERT_STREQ(targetBuf, "Replacefoobar");
481
482 ASSERT_TRUE(Q_strreplace("#Replace", "#", "foobar", targetBuf, length));
483 ASSERT_STREQ(targetBuf, "foobarReplace");
484
485 ASSERT_TRUE(Q_strreplace("#Replace#", "#", "foobar", targetBuf, length));
486 ASSERT_STREQ(targetBuf, "foobarReplace#");
487
488 ASSERT_FALSE(Q_strreplace("#ReplaceNothing#", "##", "foobar", targetBuf, length));
489
490 Q_strncpyz(buf, "foobar", sizeof(buf));
491 ASSERT_STREQ(Com_ConvertToASCII7(buf), "foobar");
492
493 buf[0] = '\177';
494 ASSERT_STREQ(Com_ConvertToASCII7(buf), ".oobar");
495
496 buf[5] = '\177';
497 ASSERT_STREQ(Com_ConvertToASCII7(buf), ".ooba.");
498
499
500 /* UTF8_char_offset_to_byte_offset */
501
502 Q_strncpyz(buf, "mn\xD0\x80opq\xD0\x81r", sizeof(buf));
503
504 ASSERT_EQ(UTF8_char_offset_to_byte_offset(buf, 4), 5);
505 ASSERT_EQ(UTF8_char_offset_to_byte_offset(buf, 0), 0);
506 ASSERT_EQ(UTF8_char_offset_to_byte_offset(buf, -1), 0);
507 ASSERT_EQ(UTF8_char_offset_to_byte_offset(buf, 999), 10);
508
509 /* UTF8_delete_char_at */
510
511 Q_strncpyz(buf, "mn\xD0\x80opq\xD0\x81r", sizeof(buf));
512
513 /* single-byte char before any multi-byte chars */
514 ASSERT_EQ(UTF8_delete_char_at(buf, 4), 1);
515 ASSERT_STREQ(buf, "mn\xD0\x80oq\xD0\x81r");
516
517 /* multi-byte char after a multi-byte char */
518 ASSERT_EQ(UTF8_delete_char_at(buf, 5), 2);
519 ASSERT_STREQ(buf, "mn\xD0\x80oqr");
520
521 /* negative index deletes first char */
522 ASSERT_EQ(UTF8_delete_char_at(buf, -1), 1);
523 ASSERT_STREQ(buf, "n\xD0\x80oqr");
524
525 /* too-high index deletes nothing */
526 ASSERT_EQ(UTF8_delete_char_at(buf, 999), 0);
527 ASSERT_STREQ(buf, "n\xD0\x80oqr");
528
529 /* UTF8_insert_char_at */
530
531 Q_strncpyz(buf, "m\xD0\x82opqr", sizeof(buf));
532
533 /* single-byte char before any multi-byte chars */
534 ASSERT_EQ(UTF8_insert_char_at(buf, sizeof(buf), 1, (int)'n'), 1);
535 ASSERT_STREQ(buf, "mn\xD0\x82opqr");
536
537 /* multi-byte char after a multi-byte char */
538 ASSERT_EQ(UTF8_insert_char_at(buf, sizeof(buf), 5, 0x0403), 2);
539 ASSERT_STREQ(buf, "mn\xD0\x82op\xD0\x83qr");
540
541 /* negative index inserts as first char */
542 ASSERT_EQ(UTF8_insert_char_at(buf, sizeof(buf), -1, 0x0404), 2);
543 ASSERT_STREQ(buf, "\xD0\x84mn\xD0\x82op\xD0\x83qr");
544
545 /* too-high index inserts as last char */
546 ASSERT_EQ(UTF8_insert_char_at(buf, sizeof(buf), 999, 0x0405), 2);
547 ASSERT_STREQ(buf, "\xD0\x84mn\xD0\x82op\xD0\x83qr\xD0\x85");
548
549 Q_strncpyz(buf, "mnopqr", sizeof(buf));
550
551 /* trigger buffer overrun protection using multi-byte char */
552 ASSERT_EQ(UTF8_insert_char_at(buf, 8, 0, 0x0405), 0);
553 ASSERT_STREQ(buf, "mnopqr");
554
555 /* trigger buffer overrun protection using single-byte char */
556 ASSERT_EQ(UTF8_insert_char_at(buf, 7, 0, (int)'o'), 0);
557 ASSERT_STREQ(buf, "mnopqr");
558
559 /* exactly fill the buffer using multi-byte char */
560 ASSERT_EQ(UTF8_insert_char_at(buf, 9, 1, 0x0406), 2);
561 ASSERT_STREQ(buf, "m\xD0\x86nopqr");
562
563 /* exactly fill the buffer using single-byte char */
564 ASSERT_EQ(UTF8_insert_char_at(buf, 10, 1, (int)'s'), 1);
565 ASSERT_STREQ(buf, "ms\xD0\x86nopqr");
566
567 char catBuf[32] = "";
568 Q_strcat(catBuf, sizeof(catBuf), "foo");
569 Q_strcat(catBuf, sizeof(catBuf), "bar");
570 ASSERT_STREQ(catBuf, "foobar");
571}
572
573TEST_F(GenericTest, HttpHelperFunctions)
574{
575 char scheme[6];
576 char server[512];
577 char uriPath[512];
578 int port;
579 const char* url;
580
581 url = "http://www.test.domain.com:123/someScript.cgi?parameter";
582 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
583 ASSERT_STREQ("http", scheme);
584 ASSERT_STREQ("www.test.domain.com", server);
585 ASSERT_EQ(port, 123);
586 ASSERT_STREQ("/someScript.cgi?parameter", uriPath);
587
588 url = "hTTpS://Www.TeST.domain.coM:123/someScript.cgi?parameter";
589 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
590 ASSERT_STREQ("https", scheme);
591 ASSERT_STREQ("www.test.domain.com", server);
592 ASSERT_EQ(port, 123);
593 ASSERT_STREQ("/someScript.cgi?parameter", uriPath);
594
595 url = "http://www.test.domain.com/someScript.cgi?parameter";
596 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
597 ASSERT_STREQ("http", scheme);
598 ASSERT_STREQ("www.test.domain.com", server);
599 ASSERT_EQ(80, port);
600 ASSERT_STREQ("/someScript.cgi?parameter", uriPath);
601
602 url = "http://www.test.domain.com";
603 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
604 ASSERT_STREQ("http", scheme);
605 ASSERT_STREQ("www.test.domain.com", server);
606 ASSERT_EQ(80, port);
607 ASSERT_STREQ("", uriPath);
608
609 url = "http://www.test.domain.com/";
610 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
611 ASSERT_STREQ("http", scheme);
612 ASSERT_STREQ("www.test.domain.com", server);
613 ASSERT_EQ(80, port);
614 ASSERT_STREQ("/", uriPath);
615
616 url = "http://ufoai.org/ufo/masterserver.php?query";
617 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
618 ASSERT_STREQ("http", scheme);
619 ASSERT_STREQ("ufoai.org", server);
620 ASSERT_EQ(80, port);
621 ASSERT_STREQ("/ufo/masterserver.php?query", uriPath);
622
623 url = "https://ufoai.org/ufo/masterserver.php?query";
624 ASSERT_TRUE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
625 ASSERT_STREQ("https", scheme);
626 ASSERT_STREQ("ufoai.org", server);
627 ASSERT_EQ(443, port);
628 ASSERT_STREQ("/ufo/masterserver.php?query", uriPath);
629
630 url = "https://ufoai.org:0/ufo/masterserver.php?query";
631 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
632 url = "https://ufoai.org:65536/ufo/masterserver.php?query";
633 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
634 url = "https://ufoai.org:80sas/ufo/masterserver.php?query";
635 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
636 url = "https://ufoai.org:000000080/ufo/masterserver.php?query";
637 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
638 url = "ftp://ufoai.org:0/ufo/masterserver.php?query";
639 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
640 url = "https:///ufo/masterserver.php?query";
641 ASSERT_FALSE(HTTP_ExtractComponents(url, scheme, sizeof(scheme), server, sizeof(server), uriPath, sizeof(uriPath), &port));
642}
643
645{
646 char ipServer[MAX_VAR];
647 ASSERT_TRUE(NET_ResolvNode("localhost", ipServer, sizeof(ipServer))) << "failed to resolve localhost";
648 ASSERT_STREQ("127.0.0.1", ipServer);
649}
650
651TEST_F(GenericTest, UnsignedIntToBinary)
652{
653 const char* buf = Com_UnsignedIntToBinary(3);
654 ASSERT_STREQ(buf, "00000000 00000000 00000000 00000011");
655
657 ASSERT_STREQ(buf, "00000000 00000000 00000000 11111111");
658
660 ASSERT_STREQ(buf, "00000000 00000001 00000000 00000000");
661
663 ASSERT_STREQ(buf, "00000000 00000000 11111111 11111111");
664
666 ASSERT_STREQ(buf, "00000010");
667
668 buf = Com_ByteToBinary(255);
669 ASSERT_STREQ(buf, "11111111");
670}
671
672TEST_F(GenericTest, StringCheckFunctions)
673{
674 const char* strNull = nullptr;
675 const char* strEmpty = "";
676 const char* strValid = "someString";
677 ASSERT_TRUE(Q_strnull(strNull));
678 ASSERT_TRUE(Q_strnull(strEmpty));
679 ASSERT_FALSE(Q_strnull(strValid));
680 ASSERT_TRUE(Q_strvalid(strValid));
681 ASSERT_FALSE(Q_strvalid(strEmpty));
682 ASSERT_FALSE(Q_strvalid(strNull));
683}
684
685TEST_F(GenericTest, EntitiesDef)
686{
687 byte* fileBuffer;
688
689 ASSERT_NE(-1, FS_LoadFile("ufos/entities.ufo", &fileBuffer)) << "Could not load ufos/entities.ufo.";
690 ASSERT_TRUE(fileBuffer != nullptr);
691
692 const char* buf = (const char*) fileBuffer;
693 ASSERT_EQ(ED_Parse(buf), ED_OK);
694
695 ASSERT_TRUE(numEntityDefs > 0);
696
697 bool worldSpawnFound = false;
698 for (int i = 0; i < numEntityDefs; i++) {
699 const entityDef_t* e = &entityDefs[i];
700
701 ASSERT_TRUE(nullptr != e);
702 if (Q_streq(e->classname, "worldspawn")) {
703 worldSpawnFound = true;
704
705 ASSERT_TRUE(e->numKeyDefs > 10);
706 for (int j = 0; j < e->numKeyDefs; j++) {
707 const entityKeyDef_t* keyDef = &e->keyDefs[j];
708 ASSERT_TRUE(nullptr != keyDef);
709 }
710 }
711 }
712
713 ASSERT_TRUE(worldSpawnFound);
714
715 FS_FreeFile(fileBuffer);
716 ED_Free();
717}
718
720{
721 {
722 const char* test = "invalid block";
723 const int length = Com_GetBlock(&test, nullptr);
724 ASSERT_EQ(length, -1);
725 }
726 {
727 const char* test = "{the block length }";
728 const char* buf = test;
729 const size_t expected = strlen(test) - 2;
730 const char* start = nullptr;
731 const int length = Com_GetBlock(&buf, &start);
732 ASSERT_EQ(length, expected);
733 ASSERT_EQ(strncmp(start, test + 1, length), 0) << start << " and " << (test + 1) << " should match on the first " << length << " characters";
734 }
735}
736
737TEST_F(GenericTest, ComFilePath)
738{
739 char buf[32];
740 Com_FilePath("/foo/bar/file.txt", buf, sizeof(buf));
741 ASSERT_STREQ(buf, "/foo/bar");
742
743 Com_FilePath("/foo/bar/a/little/bit/too/long/for/the/buffer/file.txt", buf, sizeof(buf));
744 ASSERT_STREQ(buf, "");
745}
746
748{
749 const char* md5 = Com_MD5File("media/DejaVuSans.ttf");
750 const char* expected = "c4adcbdd6ec636e0b19cd6aabe85e8fb";
751 Com_Printf("got: '%s', expected '%s'\n", md5, expected);
752 ASSERT_STREQ(md5, expected);
753}
754
756{
757 const char* in = "Test";
758 const char* expected = "0cbc6611f5540bd0809a388dc95a615b";
759 const char* md5 = Com_MD5Buffer((const byte*)in, strlen(in));
760 Com_Printf("got: '%s', expected '%s'\n", md5, expected);
761 ASSERT_STREQ(md5, expected);
762}
763
764TEST_F(GenericTest, SHA1Buffer)
765{
766 const char* in = "Test";
767 const char* expected = "640ab2bae07bedc4c163f679a746f7ab7fb5d1fa";
768 char digest[41];
769 Com_SHA1Buffer((const byte*)in, strlen(in), digest);
770 Com_Printf("got: '%s', expected '%s'\n", digest, expected);
771 ASSERT_STREQ(digest, expected);
772}
773
774TEST_F(GenericTest, SHA2Buffer)
775{
776 const char* in = "Test";
777 const char* expected = "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25";
778 byte digest[32];
779 Com_SHA2Csum((const byte*)in, strlen(in), digest);
780 char buf[65];
781 Com_SHA2ToHex(digest, buf);
782 Com_Printf("got: '%s', expected '%s'\n", buf, expected);
783 ASSERT_STREQ(buf, expected);
784}
785
789static int TEST_BEP (const char* id, const void* userdata)
790{
791 return Q_streq(id, "a") || Q_streq(id, "c");
792}
793
795{
796 ASSERT_TRUE(BEP_Evaluate("", TEST_BEP));
797 ASSERT_TRUE(BEP_Evaluate("a", TEST_BEP));
798 ASSERT_TRUE(BEP_Evaluate("c", TEST_BEP));
799 ASSERT_FALSE(BEP_Evaluate("d", TEST_BEP));
800 ASSERT_TRUE(BEP_Evaluate("a|b", TEST_BEP));
801 ASSERT_FALSE(BEP_Evaluate("a&b", TEST_BEP));
802 ASSERT_TRUE(BEP_Evaluate("a&(b|c)", TEST_BEP));
803 ASSERT_TRUE(BEP_Evaluate("a|(b&c)", TEST_BEP));
804 ASSERT_FALSE(BEP_Evaluate("b|(d&c)", TEST_BEP));
805 ASSERT_TRUE(BEP_Evaluate("b|(a&c)", TEST_BEP));
806 ASSERT_FALSE(BEP_Evaluate("a^c", TEST_BEP));
807 ASSERT_TRUE(BEP_Evaluate("a^d", TEST_BEP));
808 ASSERT_TRUE(BEP_Evaluate("!z", TEST_BEP));
809 ASSERT_FALSE(BEP_Evaluate("!!z", TEST_BEP));
810 ASSERT_FALSE(BEP_Evaluate("!a", TEST_BEP));
811}
bool BEP_Evaluate(const char *expr, BEPEvaluteCallback_t varFuncParam, const void *userdata)
linkedList_t * LIST_CopyStructure(linkedList_t *src)
CGAME_HARD_LINKED_FUNCTIONS linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
void LIST_Sort(linkedList_t **list, linkedListSort_t sorter, const void *userData)
Evaluates stuff like this expression.
static void TearDownTestCase()
static void SetUpTestCase()
const char * Cmd_Argv(int arg)
Returns a given argument.
Definition cmd.cpp:516
void Cmd_TokenizeString(const char *text, bool macroExpand, bool replaceWhitespaces)
Parses the given string into command line tokens.
Definition cmd.cpp:565
const char * Com_ByteToBinary(byte x)
Definition common.cpp:1022
cvar_t * port
Definition common.cpp:58
const char * Com_UnsignedIntToBinary(uint32_t x)
Definition common.cpp:1038
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
definitions common between client and server, but not game lib
#define PROTOCOL_VERSION
Definition common.h:134
const char * Com_MD5Buffer(const byte *buf, size_t len)
Compute the md5sum of the given buffer.
Definition md5.cpp:300
const char * Com_MD5File(const char *fn, int length=0)
Compute the md5sum of a given file.
Definition md5.cpp:257
const char * Cvar_Userinfo(char *info, size_t infoSize)
Returns an info string containing all the CVAR_USERINFO cvars.
Definition cvar.cpp:967
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition cvar.cpp:342
const char * Cvar_GetString(const char *varName)
Returns the value of cvar as string.
Definition cvar.cpp:210
#define CVAR_USERINFO
Definition cvar.h:41
#define CVAR_NOSET
Definition cvar.h:43
int numEntityDefs
int ED_Parse(const char *data_p)
void ED_Free(void)
entityDef_t entityDefs[ED_MAX_DEFS+1]
Handles definition of entities, parsing them from entities.ufo.
#define ED_OK
Definition entitiesdef.h:33
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
const char * FS_NextFileFromFileList(const char *files)
Returns the next file that is found in the virtual filesystem identified by the given file pattern.
Definition files.cpp:1081
int FS_BuildFileList(const char *fileList)
Build a filelist.
Definition files.cpp:962
bool HTTP_ExtractComponents(const char *url, char *scheme, size_t schemeLength, char *host, size_t hostLength, char *path, size_t pathLength, int *port)
Extract the servername, the port and the path part of the given url.
Definition http.cpp:38
const char * Info_ValueForKey(const char *s, const char *key)
Searches the string for the given key and returns the associated value, or an empty string.
void Info_SetValueForKey(char *s, const size_t size, const char *key, const char *value)
Adds a new entry into string with given value.
void Info_RemoveKey(char *s, const char *key)
Searches through s for key and remove is.
Info string handling.
#define MAX_INFO_STRING
Definition infostring.h:36
const char * filename
Definition ioapi.h:41
voidpf void * buf
Definition ioapi.h:42
void LIST_AddStringSorted(linkedList_t **listDest, const char *data)
Definition list.cpp:107
void LIST_AddString(linkedList_t **listDest, const char *data)
Adds an string to a new or to an already existing linked list. The string is copied here.
Definition list.cpp:139
void * LIST_GetRandom(linkedList_t *list)
Definition list.cpp:381
void LIST_Delete(linkedList_t **list)
Definition list.cpp:195
bool LIST_RemoveEntry(linkedList_t **list, linkedList_t *entry)
Removes one entry from the linked list.
Definition list.cpp:172
void * LIST_GetByIdx(linkedList_t *list, int index)
Get an entry of a linked list by its index in the list.
Definition list.cpp:362
int LIST_Count(const linkedList_t *list)
Definition list.cpp:344
bool LIST_Remove(linkedList_t **list, const void *data)
Definition list.cpp:213
bool LIST_IsEmpty(const linkedList_t *list)
Checks whether the given list is empty.
Definition list.cpp:335
const linkedList_t * LIST_ContainsString(const linkedList_t *list, const char *string)
Searches for the first occurrence of a given string.
Definition list.cpp:73
void LIST_PrependString(linkedList_t **listDest, const char *data)
Adds a string as first entry to a linked list.
Definition list.cpp:127
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it's safe to delete the returned entry from the list while looping over ...
Definition list.h:41
void NET_Shutdown(void)
Definition net.cpp:337
bool NET_ResolvNode(const char *node, char *buf, size_t bufLength)
Definition net.cpp:1229
int Com_GetBlock(const char **text, const char **start)
Get the start and end point of a block in the given text.
Definition parse.cpp:272
Shared parsing functions.
#define SV_CMD_CONNECT
Definition q_shared.h:588
QGL_EXTERN void(APIENTRY *qglActiveTexture)(GLenum texture)
QGL_EXTERN GLenum GLuint * dest
Definition r_gl.h:101
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLint i
Definition r_gl.h:113
void Com_RegisterConstInt(const char *name, int value)
Register mappings between script strings and enum values for values of the type V_INT.
Definition scripts.cpp:198
bool Com_UnregisterConstList(const constListEntry_t constList[])
Unregisters a list of string aliases.
Definition scripts.cpp:237
bool Com_UnregisterConstVariable(const char *name)
Removes a registered constant from the script mapping hash table.
Definition scripts.cpp:147
bool Com_GetConstInt(const char *name, int *value)
Searches whether a given value was registered as a string to int mapping.
Definition scripts.cpp:74
const char * Com_GetConstVariable(const char *space, int value)
Searches the mapping variable for a given integer value and a namespace.
Definition scripts.cpp:122
void Com_RegisterConstList(const constListEntry_t constList[])
Registers a list of string aliases.
Definition scripts.cpp:253
bool Com_SHA1Buffer(const unsigned char *buf, unsigned int len, char digest[41])
Definition sha1.cpp:358
void Com_SHA2ToHex(const byte digest[32], char final[65])
Definition sha2.cpp:301
void Com_SHA2Csum(const byte *buf, uint32_t buflen, byte digest[32])
Output SHA-256(buf).
Definition sha2.cpp:292
#define Q_strvalid(string)
Definition shared.h:141
#define Q_streq(a, b)
Definition shared.h:136
bool Q_strnull(const char *string)
Definition shared.h:138
#define DOUBLEQUOTE(x)
Definition shared.h:90
#define MAX_VAR
Definition shared.h:36
#define lengthof(x)
Definition shared.h:105
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
int Q_StringSort(const void *string1, const void *string2)
Compare two strings.
Definition shared.cpp:385
void Com_FilePath(const char *in, char *out, size_t size)
Returns the path up to, but not including the last /.
Definition shared.cpp:319
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
char * Com_ConvertToASCII7(char *s)
Remove high character values and only keep ascii. This can be used to print utf-8 characters to the c...
Definition shared.cpp:82
bool Q_strreplace(const char *source, const char *pattern, const char *replace, char *dest, size_t destsize)
Replaces the first occurence of the given pattern in the source string with the given replace string.
Definition shared.cpp:596
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
bool STRHUNK_Add(stringHunk_t *hunk, const char *string)
stringHunk_t * STRHUNK_Create(size_t size)
void STRHUNK_Delete(stringHunk_t **hunk)
void STRHUNK_Visit(stringHunk_t *hunk, stringHunkVisitor_t visitor)
size_t STRHUNK_GetFreeSpace(const stringHunk_t *hunk)
int STRHUNK_Size(const stringHunk_t *hunk)
void STRHUNK_Reset(stringHunk_t *hunk)
Header for string hunk management.
list of script aliases to register
Definition scripts.h:231
char * classname
Definition entitiesdef.h:74
entityKeyDef_t * keyDefs
Definition entitiesdef.h:75
void * data
Definition list.h:31
System specific stuff.
int Sys_Milliseconds(void)
static int testListSorter(linkedList_t *entry1, linkedList_t *entry2, const void *userData)
static void STRHUNK_VisitorTestEntry2(const char *string)
static void STRHUNK_VisitorTestEntry(const char *string)
TEST_F(GenericTest, StringHunks)
static int TEST_BEP(const char *id, const void *userdata)
The string 'a' and 'c' evaluates to true - everything else to false.
void TEST_Shutdown(void)
void TEST_Init(void)
int UTF8_delete_char_at(char *s, int pos)
Delete a whole (possibly multibyte) character from a string.
Definition utf8.cpp:35
int UTF8_insert_char_at(char *s, int n, int pos, int c)
Insert a (possibly multibyte) UTF-8 character into a string.
Definition utf8.cpp:63
size_t UTF8_strlen(const char *str)
Count the number of character (not the number of bytes) of a zero termination string.
Definition utf8.cpp:207
int UTF8_next(const char **str)
Get the next utf-8 character from the given string.
Definition utf8.cpp:132
char * UTF8_strncpyz(char *dest, const char *src, size_t limit)
UTF8 capable string copy function.
Definition utf8.cpp:247
int UTF8_char_offset_to_byte_offset(char *str, int pos)
Convert UTF-8 character offset to a byte offset in the given string.
Definition utf8.cpp:227