Builder templated constant expansion
[platform/core/uifw/dali-toolkit.git] / automated-tests / TET / dali-test-suite / builder / utc-Dali-JsonParser.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <iostream>
18
19 #include <stdlib.h>
20 #include <tet_api.h>
21
22 #include <dali/public-api/dali-core.h>
23 #include <dali-toolkit/public-api/builder/json-parser.h>
24
25 #include <dali-toolkit-test-suite-utils.h>
26
27 using namespace Dali;
28 using namespace Dali::Toolkit;
29
30 static void Startup();
31 static void Cleanup();
32
33 extern "C" {
34   void (*tet_startup)() = Startup;
35   void (*tet_cleanup)() = Cleanup;
36 }
37
38 enum {
39   POSITIVE_TC_IDX = 0x01,
40   NEGATIVE_TC_IDX,
41 };
42
43 #define MAX_NUMBER_OF_TESTS 10000
44 extern "C" {
45   struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
46 }
47
48 TEST_FUNCTION( UtcDaliJsonParserMethod01, NEGATIVE_TC_IDX );
49 TEST_FUNCTION( UtcDaliJsonParserMethod02, NEGATIVE_TC_IDX );
50 TEST_FUNCTION( UtcDaliJsonParserMethod03, NEGATIVE_TC_IDX );
51 TEST_FUNCTION( UtcDaliJsonParserMethod04, NEGATIVE_TC_IDX );
52 TEST_FUNCTION( UtcDaliJsonParserMethod05, NEGATIVE_TC_IDX );
53 TEST_FUNCTION( UtcDaliJsonParserMethod06, NEGATIVE_TC_IDX );
54 TEST_FUNCTION( UtcDaliJsonParserMethod07, NEGATIVE_TC_IDX );
55 TEST_FUNCTION( UtcDaliJsonParserMethod08, NEGATIVE_TC_IDX );
56 TEST_FUNCTION( UtcDaliJsonParserMethod09, NEGATIVE_TC_IDX );
57 TEST_FUNCTION( UtcDaliJsonParserMethod10, NEGATIVE_TC_IDX );
58
59 // Called only once before first test is run.
60 static void Startup()
61 {
62 }
63
64 // Called only once after last test is run
65 static void Cleanup()
66 {
67 }
68
69 std::string ReplaceQuotes(const std::string &in_s)
70 {
71   std::string s(in_s);
72   // wrong as no embedded quote but had regex link problems
73   std::replace(s.begin(), s.end(), '\'', '"');
74   return s;
75 }
76
77
78 static void UtcDaliJsonParserMethod01()
79 {
80   ToolkitTestApplication application;
81
82   tet_infoline("JSON basic test");
83
84   std::string s1( ReplaceQuotes("\
85 {                                         \
86   'string':'value2',                      \
87   'integer':2,                            \
88   'float':2.0,                            \
89   'boolean':true,                         \
90   'nil':null,                             \
91   'array':[1,2,3],                        \
92   'object':{'key':'value'}                \
93 }                                         \
94 "));
95
96   JsonParser parser = JsonParser::New();
97
98   parser.Parse( s1 );
99
100   if(parser.ParseError())
101   {
102     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
103     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
104   }
105
106   DALI_TEST_CHECK(!parser.ParseError());
107
108   const TreeNode* root = parser.GetRoot();
109
110   DALI_TEST_CHECK(root);
111
112   DALI_TEST_CHECK(root->Size());
113
114   TreeNode::ConstIterator iter = root->CBegin();
115   DALI_TEST_CHECK(iter != root->CEnd());
116
117   const TreeNode* node = NULL;
118
119   node = &((*iter).second);
120   DALI_TEST_CHECK(node);
121   DALI_TEST_CHECK(node->GetType() == TreeNode::STRING);
122   DALI_TEST_CHECK(std::string((*iter).first) == std::string("string"));
123   DALI_TEST_CHECK(std::string(node->GetString()) == std::string("value2"));
124
125   ++iter;
126   DALI_TEST_CHECK(iter != root->CEnd());
127   node = &((*iter).second);
128   DALI_TEST_CHECK(node);
129   DALI_TEST_CHECK(node->GetType() == TreeNode::INTEGER);
130   DALI_TEST_CHECK(std::string((*iter).first) == std::string("integer"));
131   DALI_TEST_CHECK(node->GetInteger() == 2);
132
133   ++iter;
134   DALI_TEST_CHECK(iter != root->CEnd());
135   node = &((*iter).second);
136   DALI_TEST_CHECK(node);
137   DALI_TEST_CHECK(node->GetType() == TreeNode::FLOAT);
138   DALI_TEST_CHECK(std::string((*iter).first) == std::string("float"));
139   DALI_TEST_CHECK(node->GetFloat() == 2.0);
140
141   ++iter;
142   DALI_TEST_CHECK(iter != root->CEnd());
143   node = &((*iter).second);
144   DALI_TEST_CHECK(node);
145   DALI_TEST_CHECK(node->GetType() == TreeNode::BOOLEAN);
146   DALI_TEST_CHECK(std::string((*iter).first) == std::string("boolean"));
147   DALI_TEST_CHECK(node->GetBoolean());
148
149   ++iter;
150   DALI_TEST_CHECK(iter != root->CEnd());
151   node = &((*iter).second);
152   DALI_TEST_CHECK(node);
153   DALI_TEST_CHECK(node->GetType() == TreeNode::IS_NULL);
154   DALI_TEST_CHECK(std::string((*iter).first) == std::string("nil"));
155
156   ++iter;
157   DALI_TEST_CHECK(iter != root->CEnd());
158   node = &((*iter).second);
159   DALI_TEST_CHECK(node);
160   DALI_TEST_CHECK(node->GetType() == TreeNode::ARRAY);
161   DALI_TEST_CHECK(node->Size() == 3);
162   TreeNode::ConstIterator iterArray = node->CBegin();
163
164   DALI_TEST_CHECK(iterArray != node->CEnd());
165   DALI_TEST_CHECK( ((*iterArray).second).GetType() == TreeNode::INTEGER);
166   DALI_TEST_CHECK( (*iterArray).first == NULL );
167   DALI_TEST_CHECK( ((*iterArray).second).GetInteger() == 1);
168
169   ++iterArray;
170   DALI_TEST_CHECK(iterArray != node->CEnd());
171   DALI_TEST_CHECK( ((*iterArray).second).GetType() == TreeNode::INTEGER);
172   DALI_TEST_CHECK( (*iterArray).first == NULL );
173   DALI_TEST_CHECK( ((*iterArray).second).GetInteger() == 2);
174
175   ++iterArray;
176   DALI_TEST_CHECK(iterArray != node->CEnd());
177   DALI_TEST_CHECK( ((*iterArray).second).GetType() == TreeNode::INTEGER);
178   DALI_TEST_CHECK( (*iterArray).first == NULL );
179   DALI_TEST_CHECK( ((*iterArray).second).GetInteger() == 3);
180
181   ++iter;
182   DALI_TEST_CHECK(iter != root->CEnd());
183   node = &((*iter).second);
184   DALI_TEST_CHECK(node);
185   DALI_TEST_CHECK(node->GetType() == TreeNode::OBJECT);
186   DALI_TEST_CHECK(node->Size() == 1);
187
188   TreeNode::ConstIterator iterObject = node->CBegin();
189   DALI_TEST_CHECK(iterObject != node->CEnd());
190   DALI_TEST_CHECK( ((*iterObject).second).GetType() == TreeNode::STRING);
191   DALI_TEST_CHECK( std::string((*iterObject).first) == std::string("key" ));
192   DALI_TEST_CHECK( std::string(((*iterObject).second).GetString()) == std::string("value"));
193
194   tet_result(TET_PASS);
195 }
196
197 static void UtcDaliJsonParserMethod02()
198 {
199   ToolkitTestApplication application;
200
201   tet_infoline("JSON Comments");
202
203   std::string s1( ReplaceQuotes("         \
204 // some comments with empty line above  \n\
205 {                                         \
206   // inline comments                    \n\
207   'key':'value', // endline comments    \n\
208   // more inline comments               \n\
209   'key2':'value2'                         \
210 }                                         \
211 "));
212
213   JsonParser parser = JsonParser::New();
214
215   parser.Parse( s1 );
216
217   if(parser.ParseError())
218   {
219     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
220     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
221   }
222
223   DALI_TEST_CHECK(!parser.ParseError());
224
225   const TreeNode* root = parser.GetRoot();
226
227   DALI_TEST_CHECK(root);
228
229   DALI_TEST_CHECK(root->Size());
230
231   const TreeNode& node = (*root->CBegin()).second;
232
233   DALI_TEST_CHECK(node.GetType() == TreeNode::STRING);
234
235   DALI_TEST_CHECK(node.GetString() == std::string("value"));
236
237   DALI_TEST_CHECK((*root->CBegin()).first == std::string("key"));
238
239   tet_result(TET_PASS);
240 }
241
242
243 static void UtcDaliJsonParserMethod03()
244 {
245   ToolkitTestApplication application;
246
247   tet_infoline("JSON Empty line comment");
248
249   std::string s1( ReplaceQuotes(
250 "/*\n" \
251 "c comment\n" \
252 "*/"\
253 "// next empty line comment\n"\
254 "//\n"\
255 "{\n"\
256 "  'key':'value'\n"\
257 "}\n"\
258 ));
259
260   JsonParser parser = JsonParser::New();
261
262   parser.Parse( s1 );
263
264   if(parser.ParseError())
265   {
266     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
267     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
268   }
269
270   DALI_TEST_CHECK(!parser.ParseError());
271
272   const TreeNode* root = parser.GetRoot();
273
274   DALI_TEST_CHECK(root);
275
276   DALI_TEST_CHECK(root->Size());
277
278   const TreeNode& node = (*root->CBegin()).second;
279
280   DALI_TEST_CHECK(node.GetType() == TreeNode::STRING);
281
282   DALI_TEST_CHECK(node.GetString() == std::string("value"));
283
284   DALI_TEST_CHECK((*root->CBegin()).first == std::string("key"));
285
286   tet_result(TET_PASS);
287 }
288
289 static void UtcDaliJsonParserMethod04()
290 {
291   ToolkitTestApplication application;
292
293   tet_infoline("JSON Merge");
294
295   std::string s1( ReplaceQuotes("                                       \
296 {                                                                       \
297   'animations':                                                         \
298   {                                                                     \
299     'bump':                                                             \
300     {                                                                   \
301       'properties':                                                     \
302       [                                                                 \
303         {                                                               \
304           'actor':'bump-image',                                         \
305           'property':'uLightPosition',                                  \
306           'value':[0.8, 0.0, -1.5],                                     \
307           'alpha-function': 'BOUNCE',                                   \
308           'time-period': { 'duration': 2.5 }                            \
309         }                                                               \
310       ]                                                                 \
311     }                                                                   \
312   }                                                                     \
313 }                                                                       \
314 "));
315
316   std::string s2( ReplaceQuotes("                                       \
317 {                                                                       \
318   'animations':                                                         \
319   {                                                                     \
320     'bump':                                                             \
321     {                                                                   \
322       'duration': 5.0,                                                  \
323       'loop': true,                                                     \
324       'end-action':'DISCARD'                                            \
325     }                                                                   \
326   }                                                                     \
327 }                                                                       \
328 "));
329
330   JsonParser parser = JsonParser::New();
331
332   parser.Parse( s1 );
333
334   if(parser.ParseError())
335   {
336     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
337     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
338   }
339   DALI_TEST_CHECK(!parser.ParseError());
340
341   parser.Parse( s2 );
342
343   if(parser.ParseError())
344   {
345     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
346     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
347   }
348
349   DALI_TEST_CHECK(!parser.ParseError());
350
351   const TreeNode* root = parser.GetRoot();
352   DALI_TEST_CHECK(root);
353
354   const TreeNode *node = root->Find("bump");
355   DALI_TEST_CHECK(node);
356
357   DALI_TEST_CHECK(static_cast<int>(node->Size()) == 4);
358
359   DALI_TEST_CHECK( node->GetChild("duration") );
360   DALI_TEST_CHECK( node->GetChild("loop") );
361   DALI_TEST_CHECK( node->GetChild("properties") );
362
363
364   tet_result(TET_PASS);
365 }
366
367 static void UtcDaliJsonParserMethod05()
368 {
369   ToolkitTestApplication application;
370
371   tet_infoline("JSON Pack & Write");
372
373   std::string s1( ReplaceQuotes("                                       \
374 {                                                                       \
375   'animations':                                                         \
376   {                                                                     \
377     'bump':                                                             \
378     {                                                                   \
379       'properties':                                                     \
380       [                                                                 \
381         {                                                               \
382           'actor':'bump-image',                                         \
383           'property':'uLightPosition',                                  \
384           'value':[0.8, 0.0, -1.5],                                     \
385           'alpha-function': 'BOUNCE',                                   \
386           'time-period': { 'duration': 2.5 }                            \
387         }                                                               \
388       ]                                                                 \
389     }                                                                   \
390   }                                                                     \
391 }                                                                       \
392 "));
393
394   JsonParser parser = JsonParser::New();
395
396   parser.Parse( s1 );
397
398   if(parser.ParseError())
399   {
400     std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
401     std::cout << "   at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
402   }
403   DALI_TEST_CHECK(!parser.ParseError());
404
405   std::stringstream a;
406   parser.Write(a, 2);
407
408   parser.Pack();
409
410   std::stringstream b;
411   parser.Write(b, 2);
412
413   DALI_TEST_CHECK( a.str() == b.str() );
414
415   tet_result(TET_PASS);
416 }
417
418
419 static const int NUMBER_OK_TESTS = 36;
420 char *TEST_OK[NUMBER_OK_TESTS] = {
421   "{ 'hex': '\u0123\u4567\u89AB\uCDEF\uabcd\uef4A' }",
422   "{ 'special': '`1~!@#$%^&*()_+-={:[,]}|;.</>?' }",
423   "{ 'slash': '/ & \' }",
424   "{'object with 1 member':['array with 1 element']}",
425   "[{}, [], -42, true, false, null]",
426   "{ 'integer': 1234567890 }",
427   "{ 'integer': 1234567890 }",
428   "{ 'real': -9876.543210 }",
429   "{ 'e': 0.123456789e-12 }",
430   "{ 'E': 1.234567890E+34 }",
431   "{ '':  23456789012E66 }",
432   "{ 'zero': 0 }",
433   "{ 'one': 1 }",
434   "{ 'space': ' ' }",
435   "{ 'backslash': '\' }",
436   "{ 'controls': '\\b\\f\\n\\r\\t' }",
437   "{ 'alpha': 'abcdefghijklmnopqrstuvwyz' }",
438   "{ 'ALPHA': 'ABCDEFGHIJKLMNOPQRSTUVWYZ' }",
439   "{ 'digit': '0123456789' }",
440   "{ '0123456789': 'digit' }",
441   "{ 'true': true }",
442   "{ 'false': false }",
443   "{ 'null': null }",
444   "{ 'array':[  ] }",
445   "{ 'object':{  } }",
446   "{ 'address': '1 Communication Centre. South Street' }",
447   "{ 'url': 'http://www.JSON.org/' }",
448   "{ 'comment': '// /* <!-- --' }",
449   "{ '# -- --> */': ' ' }",
450   "{ ' s p a c e d ' :[1,2 , 3,4 , 5        ,          6           ,7        ]}",
451   "{ 'compact':[1,2,3,4,5,6,7]}",
452   "{ 'quotes': '&#34; \\u0022 %22 0x22 034 &#x22;' }",
453   "{ '\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:': 'A key can be any string'}",
454   "[ 0.5 ,98.6, 99.44,1066,1e1,0.1e1,1e-1,1e00,2e+00,2e-00, 'rosebud']",
455   "{'JSON Test Pattern pass3': { 'The outermost value': 'must be an object or array.', 'In this test': 'It is an object.' } }",
456   "[[[[[[[[[[[[[[[[[[['Not too deep']]]]]]]]]]]]]]]]]]]",
457 };
458
459
460 static void UtcDaliJsonParserMethod06()
461 {
462   ToolkitTestApplication application;
463
464   tet_infoline("JSON Parse Success");
465
466   JsonParser parser = JsonParser::New();
467
468   for(int i = 0; i < NUMBER_OK_TESTS; ++i)
469   {
470     parser = JsonParser::New();
471
472     parser.Parse( ReplaceQuotes(TEST_OK[i]) );
473
474     if(parser.ParseError())
475     {
476       tet_printf("Valid JSON parse test %d Failed", i);
477       tet_printf("%s", ReplaceQuotes(TEST_OK[i]).c_str());
478
479       tet_printf("JSON Error %d:%d: %s (%d)", parser.GetErrorLineNumber(), parser.GetErrorColumn(), parser.GetErrorDescription().c_str(), parser.GetErrorPosition());
480     }
481
482     DALI_TEST_CHECK(!parser.ParseError());
483   }
484
485   tet_result(TET_PASS);
486 }
487
488
489 static const int NUMBER_FAIL_TESTS = 32;
490 char *TEST_FAIL[] = {
491   "[' tab\t   character  \t in\t string   ']",
492   "['Extra close']]",
493   "['Colon instead of comma': false]",
494   "{'Numbers cannot have leading zeroes': 013}",
495   "['Bad value', truth]",
496   "['Illegal backslash escape: \017']",
497   "['Bad value', truth]['Illegal backslash escape: \017']",
498   "{'Comma instead if closing brace': true,",
499   "{'Double colon':: null}",
500   "{'Extra comma': true,}",
501   "['Unclosed array'",
502   "{'Illegal invocation': alert()}",
503   "{'Missing colon' null}",
504   "[0e]",
505   "{unquoted_key: 'keys must be quoted'}",
506   "'A JSON payload should be an object or array, not a string.'",
507   "[\naked]",
508   "{'Illegal expression': 1 + 2}",
509   "{'Extra value after close': true} 'misplaced quoted value'",
510   "[0e+]",
511   "[+23456789012E66]",
512   "['extra comma',]",
513   "['Comma after the close'],",
514   "['double extra comma',,]",
515   "['Illegal backslash escape: \x15']",
516   "['line\nbreak']",
517   "{'Comma instead of colon', null}",
518   "['mismatch'}",
519   "['line\nbreak']",
520   "[0e+-1]",
521   "{'Numbers cannot be hex': 0x14}",
522   "[   , '<-- missing value']",
523 };
524
525 static void UtcDaliJsonParserMethod07()
526 {
527   ToolkitTestApplication application;
528
529   tet_infoline("JSON Fail");
530
531   JsonParser parser = JsonParser::New();
532
533   for(int i = 0; i < NUMBER_FAIL_TESTS; ++i)
534   {
535     parser = JsonParser::New();
536
537     parser.Parse( ReplaceQuotes(TEST_FAIL[i]) );
538
539     if(!parser.ParseError())
540     {
541       tet_printf("Invalid JSON parse test %d Failed", i);
542       tet_printf("%s", ReplaceQuotes(TEST_FAIL[i]).c_str());
543       tet_printf("JSON Error %d:%d %s (%s)", parser.GetErrorLineNumber(), parser.GetErrorColumn(),
544                  parser.GetErrorDescription().c_str(), parser.GetErrorPosition());
545     }
546
547     DALI_TEST_CHECK(parser.ParseError());
548   }
549
550
551   parser = JsonParser::New();
552
553   parser.Parse( "['single quote']" );
554
555   if(!parser.ParseError())
556   {
557     tet_printf("['single quote']");
558   }
559
560   DALI_TEST_CHECK(parser.ParseError());
561
562   tet_result(TET_PASS);
563 }
564
565 static void UtcDaliJsonParserMethod08()
566 {
567   ToolkitTestApplication application;
568
569   tet_infoline("JSON error reporting");
570
571   std::string s1( ReplaceQuotes("\
572 {                                         \n\
573   'float':,],                             \n\
574 }                                         \n\
575 "));
576
577   JsonParser parser = JsonParser::New();
578
579   parser.Parse( s1 );
580
581   DALI_TEST_CHECK(parser.ParseError());
582
583   DALI_TEST_CHECK(1  == parser.GetErrorLineNumber());
584   DALI_TEST_CHECK(53 == parser.GetErrorPosition());
585   DALI_TEST_CHECK(11 == parser.GetErrorColumn());
586
587   tet_result(TET_PASS);
588 }
589
590 static void UtcDaliJsonParserMethod09()
591 {
592   ToolkitTestApplication application;
593
594   tet_infoline("JSON Pack()");
595
596   std::string s1( ReplaceQuotes("\
597 {                                         \
598   'string':'value2',                      \
599   'integer':2,                            \
600   'float':2.3,                            \
601   'boolean':true,                         \
602   'nil':null,                             \
603   'array':[1,2,3],                        \
604   'object':{'key':'value'}                \
605 }                                         \
606 "));
607
608   JsonParser parser = JsonParser::New();
609
610   parser.Parse( s1 );
611
612   std::stringstream ss1;
613   parser.Write(ss1, 2);
614
615   parser.Pack(); // Pack() moves strings
616
617   std::stringstream ss2;
618   parser.Write(ss2, 2);
619
620   DALI_TEST_CHECK(ss1.str() == ss2.str());
621
622   tet_result(TET_PASS);
623 }
624
625 static void UtcDaliJsonParserMethod10()
626 {
627   ToolkitTestApplication application;
628
629   tet_infoline("JSON basic test");
630
631   std::string s1( "" );
632
633   JsonParser parser = JsonParser::New();
634
635   parser.Parse( s1 );
636
637   DALI_TEST_CHECK(parser.ParseError());
638
639   tet_result(TET_PASS);
640 }