2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali-toolkit-test-suite-utils.h>
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/builder/json-parser.h>
25 using namespace Dali::Toolkit;
27 void utc_json_parser_startup(void)
29 test_return_value = TET_UNDEF;
32 void utc_json_parser_cleanup(void)
34 test_return_value = TET_PASS;
39 std::string ReplaceQuotes(const std::string& in_s)
42 // wrong as no embedded quote but had regex link problems
43 std::replace(s.begin(), s.end(), '\'', '"');
47 void CompareTrees(const TreeNode& a, const TreeNode& b)
49 DALI_TEST_CHECK(a.GetType() == b.GetType());
51 DALI_TEST_CHECK(a.Size() == b.Size());
55 DALI_TEST_CHECK(std::string(a.GetName()) == std::string(b.GetName()));
58 DALI_TEST_CHECK(a.HasSubstitution() == b.HasSubstitution());
62 case TreeNode::OBJECT:
65 for(TreeNode::ConstIterator aiter = a.CBegin(), biter = b.CBegin();
66 aiter != a.CEnd() && biter != b.CEnd();
69 CompareTrees((*aiter).second, (*biter).second);
73 case TreeNode::STRING:
75 DALI_TEST_CHECK(std::string(a.GetString()) == std::string(b.GetString()));
80 DALI_TEST_CHECK(a.GetFloat() == b.GetFloat());
83 case TreeNode::INTEGER:
85 DALI_TEST_CHECK(a.GetInteger() == b.GetInteger());
88 case TreeNode::BOOLEAN:
90 DALI_TEST_CHECK(a.GetBoolean() == b.GetBoolean());
102 int UtcDaliJsonParserMethod01(void)
104 ToolkitTestApplication application;
106 tet_infoline("JSON basic test");
108 std::string s1(ReplaceQuotes(
116 'object':{'key':'value'} \
119 JsonParser parser = JsonParser::New();
123 if(parser.ParseError())
125 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
126 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
129 DALI_TEST_CHECK(!parser.ParseError());
131 const TreeNode* root = parser.GetRoot();
133 DALI_TEST_CHECK(root);
135 DALI_TEST_CHECK(root->Size());
137 TreeNode::ConstIterator iter = root->CBegin();
138 DALI_TEST_CHECK(iter != root->CEnd());
140 const TreeNode* node = NULL;
142 node = &((*iter).second);
143 DALI_TEST_CHECK(node);
144 DALI_TEST_CHECK(node->GetType() == TreeNode::STRING);
145 DALI_TEST_CHECK(std::string((*iter).first) == std::string("string"));
146 DALI_TEST_CHECK(std::string(node->GetString()) == std::string("value2"));
149 DALI_TEST_CHECK(iter != root->CEnd());
150 node = &((*iter).second);
151 DALI_TEST_CHECK(node);
152 DALI_TEST_CHECK(node->GetType() == TreeNode::INTEGER);
153 DALI_TEST_CHECK(std::string((*iter).first) == std::string("integer"));
154 DALI_TEST_CHECK(node->GetInteger() == 2);
157 DALI_TEST_CHECK(iter != root->CEnd());
158 node = &((*iter).second);
159 DALI_TEST_CHECK(node);
160 DALI_TEST_CHECK(node->GetType() == TreeNode::FLOAT);
161 DALI_TEST_CHECK(std::string((*iter).first) == std::string("float"));
162 DALI_TEST_CHECK(node->GetFloat() == 2.0);
165 DALI_TEST_CHECK(iter != root->CEnd());
166 node = &((*iter).second);
167 DALI_TEST_CHECK(node);
168 DALI_TEST_CHECK(node->GetType() == TreeNode::BOOLEAN);
169 DALI_TEST_CHECK(std::string((*iter).first) == std::string("boolean"));
170 DALI_TEST_CHECK(node->GetBoolean());
173 DALI_TEST_CHECK(iter != root->CEnd());
174 node = &((*iter).second);
175 DALI_TEST_CHECK(node);
176 DALI_TEST_CHECK(node->GetType() == TreeNode::IS_NULL);
177 DALI_TEST_CHECK(std::string((*iter).first) == std::string("nil"));
180 DALI_TEST_CHECK(iter != root->CEnd());
181 node = &((*iter).second);
182 DALI_TEST_CHECK(node);
183 DALI_TEST_CHECK(node->GetType() == TreeNode::ARRAY);
184 DALI_TEST_CHECK(node->Size() == 3);
185 TreeNode::ConstIterator iterArray = node->CBegin();
187 DALI_TEST_CHECK(iterArray != node->CEnd());
188 DALI_TEST_CHECK(((*iterArray).second).GetType() == TreeNode::INTEGER);
189 DALI_TEST_CHECK((*iterArray).first == NULL);
190 DALI_TEST_CHECK(((*iterArray).second).GetInteger() == 1);
193 DALI_TEST_CHECK(iterArray != node->CEnd());
194 DALI_TEST_CHECK(((*iterArray).second).GetType() == TreeNode::INTEGER);
195 DALI_TEST_CHECK((*iterArray).first == NULL);
196 DALI_TEST_CHECK(((*iterArray).second).GetInteger() == 2);
199 DALI_TEST_CHECK(iterArray != node->CEnd());
200 DALI_TEST_CHECK(((*iterArray).second).GetType() == TreeNode::INTEGER);
201 DALI_TEST_CHECK((*iterArray).first == NULL);
202 DALI_TEST_CHECK(((*iterArray).second).GetInteger() == 3);
205 DALI_TEST_CHECK(iter != root->CEnd());
206 node = &((*iter).second);
207 DALI_TEST_CHECK(node);
208 DALI_TEST_CHECK(node->GetType() == TreeNode::OBJECT);
209 DALI_TEST_CHECK(node->Size() == 1);
211 TreeNode::ConstIterator iterObject = node->CBegin();
212 DALI_TEST_CHECK(iterObject != node->CEnd());
213 DALI_TEST_CHECK(((*iterObject).second).GetType() == TreeNode::STRING);
214 DALI_TEST_CHECK(std::string((*iterObject).first) == std::string("key"));
215 DALI_TEST_CHECK(std::string(((*iterObject).second).GetString()) == std::string("value"));
218 DALI_TEST_CHECK(!(iter != root->CEnd()));
220 ++iter; // Go past the end
222 iter++; // Use the other operator using the post increment operator
224 tet_result(TET_PASS);
228 int UtcDaliJsonParserMethod02(void)
230 ToolkitTestApplication application;
232 tet_infoline("JSON Comments");
234 std::string s1(ReplaceQuotes(
236 // some comments with empty line above \n\
238 // inline comments \n\
239 'key':'value', // endline comments \n\
240 // more inline comments \n\
245 JsonParser parser = JsonParser::New();
249 if(parser.ParseError())
251 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
252 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
255 DALI_TEST_CHECK(!parser.ParseError());
257 const TreeNode* root = parser.GetRoot();
259 DALI_TEST_CHECK(root);
261 DALI_TEST_CHECK(root->Size());
263 const TreeNode& node = (*root->CBegin()).second;
265 DALI_TEST_CHECK(node.GetType() == TreeNode::STRING);
267 DALI_TEST_CHECK(node.GetString() == std::string("value"));
269 DALI_TEST_CHECK((*root->CBegin()).first == std::string("key"));
271 tet_result(TET_PASS);
275 int UtcDaliJsonParserMethod03(void)
277 ToolkitTestApplication application;
279 tet_infoline("JSON Empty line comment");
281 std::string s1(ReplaceQuotes(
285 "// next empty line comment\n"
291 JsonParser parser = JsonParser::New();
295 if(parser.ParseError())
297 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
298 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
301 DALI_TEST_CHECK(!parser.ParseError());
303 const TreeNode* root = parser.GetRoot();
305 DALI_TEST_CHECK(root);
307 DALI_TEST_CHECK(root->Size());
309 const TreeNode& node = (*root->CBegin()).second;
311 DALI_TEST_CHECK(node.GetType() == TreeNode::STRING);
313 DALI_TEST_CHECK(node.GetString() == std::string("value"));
315 DALI_TEST_CHECK((*root->CBegin()).first == std::string("key"));
317 tet_result(TET_PASS);
321 int UtcDaliJsonParserMethod04(void)
323 ToolkitTestApplication application;
325 tet_infoline("JSON Merge");
327 std::string s1(ReplaceQuotes(
337 'actor':'bump-image', \
338 'property':'uLightPosition', \
339 'value':[0.8, 0.0, -1.5], \
340 'alphaFunction': 'BOUNCE', \
341 'timePeriod': { 'duration': 2.5 } \
349 std::string s2(ReplaceQuotes(
358 'endAction':'DISCARD' \
364 JsonParser parser = JsonParser::New();
368 if(parser.ParseError())
370 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
371 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
373 DALI_TEST_CHECK(!parser.ParseError());
377 if(parser.ParseError())
379 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
380 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
383 DALI_TEST_CHECK(!parser.ParseError());
385 const TreeNode* root = parser.GetRoot();
386 DALI_TEST_CHECK(root);
388 const TreeNode* node = root->Find("bump");
389 DALI_TEST_CHECK(node);
391 DALI_TEST_CHECK(static_cast<int>(node->Size()) == 4);
393 DALI_TEST_CHECK(node->GetChild("duration"));
394 DALI_TEST_CHECK(node->GetChild("loop"));
395 DALI_TEST_CHECK(node->GetChild("properties"));
397 tet_result(TET_PASS);
401 int UtcDaliJsonParserMethod05(void)
403 ToolkitTestApplication application;
405 tet_infoline("JSON Pack & Write");
407 std::string s1(ReplaceQuotes(
417 'actor':'bump-image', \
418 'property':'uLightPosition', \
419 'value':[0.8, 0.0, -1.5], \
420 'alphaFunction': 'BOUNCE', \
421 'timePeriod': { 'duration': 2.5 } \
429 JsonParser parser = JsonParser::New();
433 if(parser.ParseError())
435 std::cout << "Error: " << parser.GetErrorDescription() << std::endl;
436 std::cout << " at: " << parser.GetErrorLineNumber() << "(" << parser.GetErrorPosition() << ")" << std::endl;
438 DALI_TEST_CHECK(!parser.ParseError());
448 DALI_TEST_CHECK(a.str() == b.str());
450 tet_result(TET_PASS);
456 static const int NUMBER_OK_TESTS = 36;
457 const char* TEST_OK[NUMBER_OK_TESTS] = {
458 "{ 'hex': '\u0123\u4567\u89AB\uCDEF\uabcd\uef4A' }",
459 "{ 'special': '`1~!@#$%^&*()_+-={:[,]}|;.</>?' }",
460 "{ 'slash': '/ & \' }",
461 "{'object with 1 member':['array with 1 element']}",
462 "[{}, [], -42, true, false, null]",
463 "{ 'integer': 1234567890 }",
464 "{ 'integer': 1234567890 }",
465 "{ 'real': -9876.543210 }",
466 "{ 'e': 0.123456789e-12 }",
467 "{ 'E': 1.234567890E+34 }",
468 "{ '': 23456789012E66 }",
472 "{ 'backslash': '\' }",
473 "{ 'controls': '\\b\\f\\n\\r\\t' }",
474 "{ 'alpha': 'abcdefghijklmnopqrstuvwyz' }",
475 "{ 'ALPHA': 'ABCDEFGHIJKLMNOPQRSTUVWYZ' }",
476 "{ 'digit': '0123456789' }",
477 "{ '0123456789': 'digit' }",
479 "{ 'false': false }",
483 "{ 'address': '1 Communication Centre. South Street' }",
484 "{ 'url': 'http://www.JSON.org/' }",
485 "{ 'comment': '// /* <!-- --' }",
486 "{ '# -- --> */': ' ' }",
487 "{ ' s p a c e d ' :[1,2 , 3,4 , 5 , 6 ,7 ]}",
488 "{ 'compact':[1,2,3,4,5,6,7]}",
489 "{ 'quotes': '" \\u0022 %22 0x22 034 "' }",
490 "{ '\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:': 'A key can be any string'}",
491 "[ 0.5 ,98.6, 99.44,1066,1e1,0.1e1,1e-1,1e00,2e+00,2e-00, 'rosebud']",
492 "{'JSON Test Pattern pass3': { 'The outermost value': 'must be an object or array.', 'In this test': 'It is an object.' } }",
493 "[[[[[[[[[[[[[[[[[[['Not too deep']]]]]]]]]]]]]]]]]]]",
497 int UtcDaliJsonParserMethod06(void)
499 ToolkitTestApplication application;
501 tet_infoline("JSON Parse Success");
503 JsonParser parser = JsonParser::New();
505 for(int i = 0; i < NUMBER_OK_TESTS; ++i)
507 parser = JsonParser::New();
509 parser.Parse(ReplaceQuotes(TEST_OK[i]));
511 if(parser.ParseError())
513 tet_printf("Valid JSON parse test %d Failed", i);
514 tet_printf("%s", ReplaceQuotes(TEST_OK[i]).c_str());
516 tet_printf("JSON Error %d:%d: %s (%d)", parser.GetErrorLineNumber(), parser.GetErrorColumn(), parser.GetErrorDescription().c_str(), parser.GetErrorPosition());
519 DALI_TEST_CHECK(!parser.ParseError());
522 tet_result(TET_PASS);
528 static const int NUMBER_FAIL_TESTS = 34;
529 const char* TEST_FAIL[] = {
530 "[' tab\t character \t in\t string ']",
532 "['Colon instead of comma': false]",
533 "{'Numbers cannot have leading zeroes': 013}",
534 "['Bad value', truth]",
535 "['Illegal backslash escape: \017']",
536 "['Bad value', truth]['Illegal backslash escape: \017']",
537 "{'Comma instead if closing brace': true,",
538 "{'Double colon':: null}",
539 "{'Extra comma': true,}",
541 "{'Illegal invocation': alert()}",
542 "{'Missing colon' null}",
544 "{unquoted_key: 'keys must be quoted'}",
545 "'A JSON payload should be an object or array, not a string.'",
547 "{'Illegal expression': 1 + 2}",
548 "{'Extra value after close': true} 'misplaced quoted value'",
552 "['Comma after the close'],",
553 "['double extra comma',,]",
554 "['Illegal backslash escape: \x15']",
556 "{'Comma instead of colon', null}",
560 "{'Numbers cannot be hex': 0x14}",
561 "[ , '<-- missing value']",
562 "[{'no comma':1} {'b:2}]",
563 "{'extra comma':1,}",
567 int UtcDaliJsonParserMethod07(void)
569 ToolkitTestApplication application;
571 tet_infoline("JSON Fail");
573 JsonParser parser = JsonParser::New();
575 for(int i = 0; i < NUMBER_FAIL_TESTS; ++i)
577 parser = JsonParser::New();
579 parser.Parse(ReplaceQuotes(TEST_FAIL[i]));
581 if(!parser.ParseError())
583 tet_printf("Invalid JSON parse test %d Failed", i);
584 tet_printf("%s", ReplaceQuotes(TEST_FAIL[i]).c_str());
585 tet_printf("JSON Error %d:%d %s (%s)", parser.GetErrorLineNumber(), parser.GetErrorColumn(), parser.GetErrorDescription().c_str(), parser.GetErrorPosition());
588 DALI_TEST_CHECK(parser.ParseError());
591 parser = JsonParser::New();
593 parser.Parse("['single quote']");
595 if(!parser.ParseError())
597 tet_printf("['single quote']");
600 DALI_TEST_CHECK(parser.ParseError());
602 tet_result(TET_PASS);
606 int UtcDaliJsonParserMethod08(void)
608 ToolkitTestApplication application;
610 tet_infoline("JSON error reporting");
612 std::string s1(ReplaceQuotes(
619 JsonParser parser = JsonParser::New();
623 DALI_TEST_CHECK(parser.ParseError());
625 DALI_TEST_CHECK(1 == parser.GetErrorLineNumber());
626 DALI_TEST_CHECK(53 == parser.GetErrorPosition());
627 DALI_TEST_CHECK(11 == parser.GetErrorColumn());
628 DALI_TEST_CHECK("Missing Value" == parser.GetErrorDescription());
630 tet_result(TET_PASS);
634 int UtcDaliJsonParserMethod09(void)
636 ToolkitTestApplication application;
638 tet_infoline("JSON Pack()");
640 std::string s1(ReplaceQuotes(
649 'object':{'key':'value'} \
653 JsonParser parser = JsonParser::New();
657 std::stringstream ss1;
658 parser.Write(ss1, 2);
660 parser.Pack(); // Pack() moves strings
662 std::stringstream ss2;
663 parser.Write(ss2, 2);
665 DALI_TEST_CHECK(ss1.str() == ss2.str());
667 tet_result(TET_PASS);
671 int UtcDaliJsonParserMethod10(void)
673 ToolkitTestApplication application;
675 tet_infoline("JSON empty data");
679 JsonParser parser = JsonParser::New();
683 DALI_TEST_CHECK(parser.ParseError());
685 tet_result(TET_PASS);
689 int UtcDaliJsonParserMethod11(void)
691 ToolkitTestApplication application;
692 tet_infoline("JSON tree copy");
694 std::string s1(ReplaceQuotes(
704 'actor':'bump-image', \
705 'property':'uLightPosition', \
706 'value':[0.8, 0.0, -1.5], \
707 'alphaFunction': 'BOUNCE', \
708 'timePeriod': { 'duration': 2.5 } \
716 JsonParser parser = JsonParser::New();
720 JsonParser parser2 = JsonParser::New(*parser.GetRoot());
722 DALI_TEST_CHECK(parser.GetRoot());
723 DALI_TEST_CHECK(parser2.GetRoot());
725 CompareTrees(*parser.GetRoot(), *parser2.GetRoot());
727 tet_result(TET_PASS);
731 int UtcDaliJsonParserMerge1(void)
733 ToolkitTestApplication application;
734 tet_infoline("JSON tree merge");
736 std::string s1(ReplaceQuotes(
743 'backgroundColor':[0.8, 0.0, 1.0, 1.0], \
744 'foregroundColor':[1, 1, 1, 1] \
750 JsonParser parser = JsonParser::New();
751 JsonParser testParser = JsonParser::New();
753 testParser.Parse(s1);
756 parser.Parse(s1); // Merge the tree into itself. The value array should not grow.
758 DALI_TEST_CHECK(parser.GetRoot());
760 CompareTrees(*parser.GetRoot(), *testParser.GetRoot());
765 int UtcDaliJsonParserDownCast(void)
767 BaseHandle handle = JsonParser::New();
768 JsonParser parser = JsonParser::DownCast(handle);
769 DALI_TEST_CHECK(parser);
773 int UtcDaliJsonParserTreeNodeCount(void)
775 std::string s1(ReplaceQuotes(
782 'backgroundColor':[0.8, 0.0, 1.0, 1.0], \
783 'foregroundColor':[1, 1, 1, 1] \
789 JsonParser parser = JsonParser::New();
792 const TreeNode* treeNode = parser.GetRoot();
793 DALI_TEST_EQUALS(1, treeNode->Count("styles"), TEST_LOCATION);
794 DALI_TEST_EQUALS(0, treeNode->Count("random"), TEST_LOCATION);
799 int UtcDaliJsonParserTreeNodeFind(void)
801 std::string s1(ReplaceQuotes(
810 'object':{'key':'value'} \
814 JsonParser parser = JsonParser::New();
817 const TreeNode* treeNode = parser.GetRoot();
818 const TreeNode* childNode = treeNode->Find("string");
819 DALI_TEST_CHECK(childNode);
820 const TreeNode* sameNode = childNode->Find("string");
821 DALI_TEST_EQUALS(sameNode, childNode, TEST_LOCATION);