1 /**
2  * @file
3  * @brief Test cases for code about shared parser
4  */
5 
6 /*
7 Copyright (C) 2002-2013 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 */
25 
26 #include "test_shared.h"
27 #include "test_parser.h"
28 #include "../shared/ufotypes.h"
29 #include "../shared/parse.h"
30 
31 /**
32  * The suite initialization function.
33  * Returns zero on success, non-zero otherwise.
34  */
UFO_InitSuiteParser(void)35 static int UFO_InitSuiteParser (void)
36 {
37 	TEST_Init();
38 	return 0;
39 }
40 
41 /**
42  * The suite cleanup function.
43  * Returns zero on success, non-zero otherwise.
44  */
UFO_CleanSuiteParser(void)45 static int UFO_CleanSuiteParser (void)
46 {
47 	TEST_Shutdown();
48 	return 0;
49 }
50 
51 /**
52  * @brief unittest around default use of parser
53  */
testParser(void)54 static void testParser (void)
55 {
56 	const char* string = "aa \t\n {\"bbb(bbb bbb)bbb {\"{a}\n/* foooo { } \n { } */\n// fooooo\naaaa";
57 	const char* cursor = string;
58 	const char* token;
59 
60 	token = Com_Parse(&cursor);
61 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
62 	CU_ASSERT_STRING_EQUAL(token, "aa");
63 
64 	token = Com_Parse(&cursor);
65 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
66 	CU_ASSERT_STRING_EQUAL(token, "{");
67 
68 	token = Com_Parse(&cursor);
69 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
70 	CU_ASSERT_STRING_EQUAL(token, "bbb(bbb bbb)bbb {");
71 
72 	token = Com_Parse(&cursor);
73 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
74 	CU_ASSERT_STRING_EQUAL(token, "{");
75 
76 	token = Com_Parse(&cursor);
77 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
78 	CU_ASSERT_STRING_EQUAL(token, "a");
79 
80 	token = Com_Parse(&cursor);
81 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
82 	CU_ASSERT_STRING_EQUAL(token, "}");
83 
84 	token = Com_Parse(&cursor);
85 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
86 	CU_ASSERT_STRING_EQUAL(token, "aaaa");
87 
88 	token = Com_Parse(&cursor);
89 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_EOF);
90 	CU_ASSERT_STRING_EQUAL(token, "\0");
91 }
92 
93 /**
94  * @brief unittest to check back slash entity conversion
95  */
testParserWithEntity(void)96 static void testParserWithEntity (void)
97 {
98 	const char* string = "\n\taaaa \"  \\n  \\t  \\\"  \"";
99 	const char* cursor = string;
100 	const char* token;
101 
102 	token = Com_Parse(&cursor);
103 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
104 	CU_ASSERT_STRING_EQUAL(token, "aaaa");
105 
106 	token = Com_Parse(&cursor);
107 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
108 	CU_ASSERT_STRING_EQUAL(token, "  \n  \t  \"  ");
109 }
110 
111 /**
112  * @brief unittest around default use of parser
113  */
testParserWithUnParse(void)114 static void testParserWithUnParse (void)
115 {
116 	const char* string = "aaaaa\n\tbbbbb \"ccccc\"";
117 	const char* cursor = string;
118 	const char* token;
119 
120 	token = Com_Parse(&cursor);
121 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
122 	CU_ASSERT_STRING_EQUAL(token, "aaaaa");
123 
124 	Com_UnParseLastToken();
125 
126 	token = Com_Parse(&cursor);
127 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
128 	CU_ASSERT_STRING_EQUAL(token, "aaaaa");
129 
130 	Com_UnParseLastToken();
131 
132 	token = Com_Parse(&cursor);
133 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
134 	CU_ASSERT_STRING_EQUAL(token, "aaaaa");
135 
136 	token = Com_Parse(&cursor);
137 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
138 	CU_ASSERT_STRING_EQUAL(token, "bbbbb");
139 
140 	Com_UnParseLastToken();
141 
142 	token = Com_Parse(&cursor);
143 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
144 	CU_ASSERT_STRING_EQUAL(token, "bbbbb");
145 
146 	Com_UnParseLastToken();
147 
148 	token = Com_Parse(&cursor);
149 	CU_ASSERT_NOT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
150 	CU_ASSERT_STRING_EQUAL(token, "bbbbb");
151 
152 	token = Com_Parse(&cursor);
153 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
154 	CU_ASSERT_STRING_EQUAL(token, "ccccc");
155 
156 	Com_UnParseLastToken();
157 
158 	token = Com_Parse(&cursor);
159 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
160 	CU_ASSERT_STRING_EQUAL(token, "ccccc");
161 
162 	Com_UnParseLastToken();
163 
164 	token = Com_Parse(&cursor);
165 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
166 	CU_ASSERT_STRING_EQUAL(token, "ccccc");
167 }
168 
169 /**
170  * @brief unittest around default use of parser
171  */
testParserWithFunctionScriptToken(void)172 static void testParserWithFunctionScriptToken (void)
173 {
174 	const char* string = "aa \t\n aa,({\"bbb(bbb bbb)bbb {\"{a}\n/* foooo { } \n { } */\n// fooooo\naaaa)";
175 	const char* cursor = string;
176 	const char* token;
177 
178 	token = Com_Parse(&cursor);
179 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_WORD);
180 	CU_ASSERT_STRING_EQUAL(token, "aa");
181 
182 	token = Com_Parse(&cursor);
183 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_WORD);
184 	CU_ASSERT_STRING_EQUAL(token, "aa");
185 
186 	token = Com_Parse(&cursor);
187 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_COMMA);
188 	CU_ASSERT_STRING_EQUAL(token, ",");
189 
190 	token = Com_Parse(&cursor);
191 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_BEGIN_LIST);
192 	CU_ASSERT_STRING_EQUAL(token, "(");
193 
194 	token = Com_Parse(&cursor);
195 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_BEGIN_BLOCK);
196 	CU_ASSERT_STRING_EQUAL(token, "{");
197 
198 	token = Com_Parse(&cursor);
199 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_QUOTED_WORD);
200 	CU_ASSERT_STRING_EQUAL(token, "bbb(bbb bbb)bbb {");
201 
202 	token = Com_Parse(&cursor);
203 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_BEGIN_BLOCK);
204 	CU_ASSERT_STRING_EQUAL(token, "{");
205 
206 	token = Com_Parse(&cursor);
207 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_WORD);
208 	CU_ASSERT_STRING_EQUAL(token, "a");
209 
210 	token = Com_Parse(&cursor);
211 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_END_BLOCK);
212 	CU_ASSERT_STRING_EQUAL(token, "}");
213 
214 	token = Com_Parse(&cursor);
215 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_WORD);
216 	CU_ASSERT_STRING_EQUAL(token, "aaaa");
217 
218 	token = Com_Parse(&cursor);
219 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_END_LIST);
220 	CU_ASSERT_STRING_EQUAL(token, ")");
221 
222 	token = Com_Parse(&cursor);
223 	CU_ASSERT_EQUAL(Com_GetType(&cursor), TT_EOF);
224 	CU_ASSERT_STRING_EQUAL(token, "\0");
225 }
226 
227 /**
228  * @brief unittest around common type
229  */
testParserCommonType(void)230 static void testParserCommonType (void)
231 {
232 	int ivalue;
233 	bool bvalue;
234 	float fvalue;
235 	align_t align;
236 	blend_t blend;
237 	style_t style;
238 	fade_t fade;
239 	size_t bytes;
240 	int result;
241 
242 	/* boolean */
243 
244 	bytes = 0;
245 	result = Com_ParseValue (&bvalue, "true", V_BOOL, 0, sizeof(bool), &bytes);
246 	CU_ASSERT_EQUAL(result, RESULT_OK);
247 	CU_ASSERT_EQUAL(bvalue, 1);
248 	CU_ASSERT_EQUAL(bytes, sizeof(bool));
249 
250 	bytes = 0;
251 	result = Com_ParseValue (&bvalue, "false", V_BOOL, 0, sizeof(bool), &bytes);
252 	CU_ASSERT_EQUAL(result, RESULT_OK);
253 	CU_ASSERT_EQUAL(bvalue, 0);
254 	CU_ASSERT_EQUAL(bytes, sizeof(bool));
255 
256 	bytes = 0;
257 	result = Com_ParseValue (&bvalue, "foo", V_BOOL, 0, sizeof(int), &bytes);
258 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
259 	CU_ASSERT_EQUAL(bytes, 0);
260 
261 	/* int */
262 
263 	bytes = 0;
264 	result = Com_ParseValue (&ivalue, "10", V_INT, 0, sizeof(int), &bytes);
265 	CU_ASSERT_EQUAL(result, RESULT_OK);
266 	CU_ASSERT_EQUAL(ivalue, 10);
267 	CU_ASSERT_EQUAL(bytes, sizeof(int));
268 
269 	bytes = 0;
270 	result = Com_ParseValue (&ivalue, "abc", V_INT, 0, sizeof(int), &bytes);
271 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
272 	CU_ASSERT_EQUAL(bytes, 0);
273 
274 	/* float */
275 
276 	bytes = 0;
277 	result = Com_ParseValue (&fvalue, "1.1", V_FLOAT, 0, sizeof(float), &bytes);
278 	CU_ASSERT_EQUAL(result, RESULT_OK);
279 	CU_ASSERT_EQUAL(fvalue, 1.1f);
280 	CU_ASSERT_EQUAL(bytes, sizeof(float));
281 
282 	bytes = 0;
283 	result = Com_ParseValue (&fvalue, "9.8", V_FLOAT, 0, sizeof(float), &bytes);
284 	CU_ASSERT_EQUAL(result, RESULT_OK);
285 	CU_ASSERT_EQUAL(fvalue, 9.8f);
286 	CU_ASSERT_EQUAL(bytes, sizeof(float));
287 
288 	bytes = 0;
289 	result = Com_ParseValue (&fvalue, "abc", V_FLOAT, 0, sizeof(float), &bytes);
290 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
291 	CU_ASSERT_EQUAL(bytes, 0);
292 
293 	/** @todo V_POS */
294 	/** @todo V_VECTOR */
295 	/** @todo V_COLOR */
296 	/** @todo V_STRING */
297 	/** @todo V_TRANSLATION_STRING */
298 	/** @todo V_LONGSTRING */
299 
300 	/* align */
301 
302 	bytes = 0;
303 	result = Com_ParseValue (&align, "cc", V_ALIGN, 0, sizeof(align_t), &bytes);
304 	CU_ASSERT_EQUAL(result, RESULT_OK);
305 	CU_ASSERT_EQUAL(align, ALIGN_CC);
306 	CU_ASSERT_EQUAL(bytes, sizeof(align_t));
307 
308 	bytes = 0;
309 	result = Com_ParseValue (&align, "abc", V_ALIGN, 0, sizeof(align_t), &bytes);
310 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
311 	CU_ASSERT_EQUAL(bytes, 0);
312 
313 	/* blend */
314 
315 	bytes = 0;
316 	result = Com_ParseValue (&blend, "blend", V_BLEND, 0, sizeof(blend_t), &bytes);
317 	CU_ASSERT_EQUAL(result, RESULT_OK);
318 	CU_ASSERT_EQUAL(blend, BLEND_BLEND);
319 	CU_ASSERT_EQUAL(bytes, sizeof(blend_t));
320 
321 	bytes = 0;
322 	result = Com_ParseValue (&blend, "abc", V_BLEND, 0, sizeof(blend_t), &bytes);
323 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
324 	CU_ASSERT_EQUAL(bytes, 0);
325 
326 	/* style */
327 
328 	bytes = 0;
329 	result = Com_ParseValue (&style, "rotated", V_STYLE, 0, sizeof(style_t), &bytes);
330 	CU_ASSERT_EQUAL(result, RESULT_OK);
331 	CU_ASSERT_EQUAL(style, STYLE_ROTATED);
332 	CU_ASSERT_EQUAL(bytes, sizeof(style_t));
333 
334 	bytes = 0;
335 	result = Com_ParseValue (&style, "abc", V_STYLE, 0, sizeof(style_t), &bytes);
336 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
337 	CU_ASSERT_EQUAL(bytes, 0);
338 
339 	/* fade */
340 
341 	bytes = 0;
342 	result = Com_ParseValue (&fade, "sin", V_FADE, 0, sizeof(fade_t), &bytes);
343 	CU_ASSERT_EQUAL(result, RESULT_OK);
344 	CU_ASSERT_EQUAL(fade, FADE_SIN);
345 	CU_ASSERT_EQUAL(bytes, sizeof(fade_t));
346 
347 	bytes = 0;
348 	result = Com_ParseValue (&fade, "abc", V_FADE, 0, sizeof(fade_t), &bytes);
349 	CU_ASSERT_EQUAL(result, RESULT_ERROR);
350 	CU_ASSERT_EQUAL(bytes, 0);
351 
352 }
353 
354 /**
355  * @brief unittest to check well formed list
356  */
testParserListOk(void)357 static void testParserListOk (void)
358 {
359 	const char* string = " (  aaa \n \"bbb\" \t ccc \n \n ) ";
360 	const char* cursor = string;
361 	linkedList_t* list;
362 
363 	if (!Com_ParseList(&cursor, &list)) {
364 		CU_FAIL_FATAL("List parsing failed");
365 	}
366 
367 	CU_ASSERT_EQUAL_FATAL(LIST_Count(list), 3);
368 
369 	CU_ASSERT_STRING_EQUAL(list->data, "aaa");
370 	CU_ASSERT_STRING_EQUAL(list->next->data, "bbb");
371 	CU_ASSERT_STRING_EQUAL(list->next->next->data, "ccc");
372 
373 	LIST_Delete(&list);
374 }
375 
376 
377 /**
378  * @brief unittest to check well formed empty list
379  */
testParserListOkEmpty(void)380 static void testParserListOkEmpty (void)
381 {
382 	const char* string = " (  \n ) ()";
383 	const char* cursor = string;
384 	linkedList_t* list;
385 
386 	if (!Com_ParseList(&cursor, &list)) {
387 		CU_FAIL_FATAL("List parsing failed");
388 	}
389 
390 	CU_ASSERT_EQUAL_FATAL(LIST_Count(list), 0);
391 
392 	if (!Com_ParseList(&cursor, &list)) {
393 		CU_FAIL_FATAL("List parsing failed");
394 	}
395 
396 	CU_ASSERT_EQUAL_FATAL(LIST_Count(list), 0);
397 }
398 
399 /**
400  * @brief unittest to check wrong list with EOF
401  */
testParserListKoEOF(void)402 static void testParserListKoEOF (void)
403 {
404 	const char* string = " (  aaa \n bbb \t ccc \n \n";
405 	const char* cursor = string;
406 	linkedList_t* list;
407 
408 	if (Com_ParseList(&cursor, &list)) {
409 		CU_FAIL_FATAL("List parsing succeed, which is wrong");
410 	}
411 }
412 
413 /**
414  * @brief unittest to check wrong list with unexpected token
415  */
testParserListKoWrongToken(void)416 static void testParserListKoWrongToken (void)
417 {
418 	const char* string = " (  aaa \n bbb \t ccc \n \n } ";
419 	const char* cursor = string;
420 
421 	linkedList_t* list;
422 	if (Com_ParseList(&cursor, &list)) {
423 		CU_FAIL_FATAL("List parsing succeed, which is wrong");
424 	}
425 }
426 
427 /**
428  * @brief unittest to check wrong list which contains another sublist
429  */
testParserListKoNewList(void)430 static void testParserListKoNewList (void)
431 {
432 	const char* string = " (  aaa \n bbb \t ccc \n \n ( ";
433 	const char* cursor = string;
434 	linkedList_t* list;
435 
436 	if (Com_ParseList(&cursor, &list)) {
437 		CU_FAIL_FATAL("List parsing succeed, which is wrong");
438 	}
439 }
440 
UFO_AddParserTests(void)441 int UFO_AddParserTests (void)
442 {
443 	/* add a suite to the registry */
444 	CU_pSuite ParserSuite = CU_add_suite("ParserTests", UFO_InitSuiteParser, UFO_CleanSuiteParser);
445 
446 	if (ParserSuite == nullptr)
447 		return CU_get_error();
448 
449 	/* add the tests to the suite */
450 #if PARSER_XX > 0
451 	if (CU_ADD_TEST(ParserSuite, testParserXX) == nullptr)
452 		return CU_get_error();
453 #else
454 	if (CU_ADD_TEST(ParserSuite, testParser) == nullptr)
455 		return CU_get_error();
456 	if (CU_ADD_TEST(ParserSuite, testParserWithFunctionScriptToken) == nullptr)
457 		return CU_get_error();
458 	if (CU_ADD_TEST(ParserSuite, testParserWithUnParse) == nullptr)
459 		return CU_get_error();
460 	if (CU_ADD_TEST(ParserSuite, testParserWithEntity) == nullptr)
461 		return CU_get_error();
462 	if (CU_ADD_TEST(ParserSuite, testParserCommonType) == nullptr)
463 		return CU_get_error();
464 
465 	if (CU_ADD_TEST(ParserSuite, testParserListOk) == nullptr)
466 		return CU_get_error();
467 	if (CU_ADD_TEST(ParserSuite, testParserListOkEmpty) == nullptr)
468 		return CU_get_error();
469 	if (CU_ADD_TEST(ParserSuite, testParserListKoEOF) == nullptr)
470 		return CU_get_error();
471 	if (CU_ADD_TEST(ParserSuite, testParserListKoWrongToken) == nullptr)
472 		return CU_get_error();
473 	if (CU_ADD_TEST(ParserSuite, testParserListKoNewList) == nullptr)
474 		return CU_get_error();
475 #endif
476 	return CUE_SUCCESS;
477 }
478