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