Change dali-scene-loader to dali-scene3d
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d / utc-Dali-SceneDefinition.cpp
1 /*
2  * Copyright (c) 2020 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 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
20
21 #include "dali-scene3d/public-api/loader/scene-definition.h"
22 #include "dali-scene3d/public-api/loader/utils.h"
23 #include <dali-test-suite-utils.h>
24
25 using namespace Dali;
26 using namespace Dali::Scene3D::Loader;
27
28 int UtcDaliSceneDefinitionAddNode(void)
29 {
30   SceneDefinition sceneDef;
31
32   DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 0u);
33   auto node = new NodeDefinition();
34   node->mName = "First";
35
36   auto result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ node });
37   DALI_TEST_EQUAL(result, node);
38   DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 1u);
39   DALI_TEST_EQUAL(sceneDef.GetNode(0), node);
40   DALI_TEST_EQUAL(sceneDef.FindNode(node->mName), node);
41
42   auto node2 = new NodeDefinition();
43   node2->mName = node->mName;
44   result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ node2 });
45   DALI_TEST_EQUAL(result, static_cast<NodeDefinition*>(nullptr)); // failed
46   DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 1u); // still
47   DALI_TEST_EQUAL(sceneDef.GetNode(0), node); // still
48   DALI_TEST_EQUAL(sceneDef.FindNode(node->mName), node); // still
49
50   auto child = new NodeDefinition();
51   child->mName = "Second";
52   child->mParentIdx = 0;
53
54   DALI_TEST_CHECK(node->mChildren.empty()); // these are hooked up by AddNode, base on parent idx.
55
56   result = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ child });
57   DALI_TEST_EQUAL(result, child);
58   DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 2u);
59   DALI_TEST_EQUAL(sceneDef.GetNode(1), child);
60   DALI_TEST_EQUAL(sceneDef.FindNode(child->mName), child);
61
62   DALI_TEST_EQUAL(node->mChildren[0], 1u); // these are hooked up by AddNode, base on parent idx.
63
64   END_TEST;
65 }
66
67 int UtcDaliSceneDefinitionAddRootsFail(void)
68 {
69   SceneDefinition sceneDef;
70
71   DALI_TEST_ASSERTION(sceneDef.AddRootNode(0), "index out of bounds");
72   DALI_TEST_CHECK(sceneDef.GetRoots().empty());
73   DALI_TEST_EQUAL(sceneDef.GetNodeCount(), 0u);
74
75   END_TEST;
76 }
77
78 namespace
79 {
80
81 struct TestContext
82 {
83   SceneDefinition sceneDef;
84   NodeDefinition* root;
85   NodeDefinition* childA;
86   NodeDefinition* childB;
87
88   TestContext()
89   : sceneDef{},
90     root{ new NodeDefinition{ "Root" }},
91     childA{ new NodeDefinition{ "A" }},
92     childB{ new NodeDefinition{ "B" }}
93   {
94     childA->mParentIdx = 0;
95     childB->mParentIdx = 0;
96
97     root = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ root });
98     childA = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ childA });
99     childB = sceneDef.AddNode(std::unique_ptr<NodeDefinition>{ childB });
100   }
101 };
102
103 enum Event
104 {
105   DEFAULT = -1,
106   START,
107   FINISH
108 };
109
110 struct NodeVisitor : NodeDefinition::IVisitor
111 {
112   struct Visit
113   {
114     Event event;
115     NodeDefinition* node;
116
117     bool operator==(const Visit& other) const
118     {
119       return event == other.event && node == other.node;
120     }
121   };
122
123   void Start(NodeDefinition& n) override
124   {
125     visits.push_back({ START, &n });
126   }
127
128   void Finish(NodeDefinition& n) override
129   {
130     visits.push_back({ FINISH, &n });
131   }
132
133   std::vector<Visit> visits;
134 };
135
136 struct ConstNodeVisitor : NodeDefinition::IConstVisitor
137 {
138   struct Visit
139   {
140     Event  event;
141     const NodeDefinition* node;
142
143     bool operator==(const Visit& other) const
144     {
145       return event == other.event && node == other.node;
146     }
147   };
148
149   void Start(const NodeDefinition& n) override
150   {
151     visits.push_back({ START, &n });
152   }
153
154   void Finish(const NodeDefinition& n) override
155   {
156     visits.push_back({ FINISH, &n });
157   }
158
159   std::vector<Visit> visits;
160 };
161
162 }
163
164 int UtcDaliSceneDefinitionAddRemoveRootNode(void)
165 {
166   TestContext ctx;
167
168   DALI_TEST_EQUAL(ctx.sceneDef.AddRootNode(0), 0);
169   DALI_TEST_EQUAL(ctx.sceneDef.GetRoots().size(), 1u);
170   DALI_TEST_EQUAL(ctx.sceneDef.GetRoots()[0], 0);
171
172   ctx.sceneDef.RemoveRootNode(0);
173   DALI_TEST_EQUAL(ctx.sceneDef.GetRoots().size(), 0);
174
175   DALI_TEST_EQUAL(ctx.sceneDef.GetNodeCount(), 3u);
176
177   END_TEST;
178 }
179
180 int UtcDaliSceneDefinitionVisit(void)
181 {
182   TestContext ctx;
183
184   NodeVisitor visitor;
185   ctx.sceneDef.Visit(0, Customization::Choices{}, visitor);
186
187   const NodeVisitor::Visit expected[] {
188     { START, ctx.root },
189     { START, ctx.childA },
190     { FINISH, ctx.childA },
191     { START, ctx.childB },
192     { FINISH, ctx.childB },
193     { FINISH, ctx.root },
194   };
195   DALI_TEST_CHECK(std::equal(visitor.visits.begin(), visitor.visits.end(), expected));
196
197   END_TEST;
198 };
199
200 int UtcDaliSceneDefinitionConstVisit(void)
201 {
202   TestContext ctx;
203
204   ConstNodeVisitor visitor;
205   ctx.sceneDef.Visit(0, Customization::Choices{}, visitor);
206
207   const ConstNodeVisitor::Visit expected[] {
208     { START, ctx.root },
209     { START, ctx.childA },
210     { FINISH, ctx.childA },
211     { START, ctx.childB },
212     { FINISH, ctx.childB },
213     { FINISH, ctx.root },
214   };
215   DALI_TEST_CHECK(std::equal(visitor.visits.begin(), visitor.visits.end(), expected));
216
217   END_TEST;
218 };
219
220 int UtcDaliSceneDefinitionVisitCustomized(void)
221 {
222   TestContext ctx;
223
224   ctx.root->mCustomization.reset(new NodeDefinition::CustomizationDefinition{ "A/B" });
225
226   const NodeVisitor::Visit expected[] {
227     { START, ctx.root },
228     { START, ctx.childB },
229     { FINISH, ctx.childB },
230     { FINISH, ctx.root },
231   };
232
233   Customization::Choices choices;
234   for (auto i : { 1, 2 })
235   {
236     choices.Set("A/B", i);
237
238     NodeVisitor visitor;
239     ctx.sceneDef.Visit(0, choices, visitor);
240
241     DALI_TEST_CHECK(std::equal(visitor.visits.begin(), visitor.visits.end(), std::begin(expected)));
242   }
243
244   END_TEST;
245 };
246
247 int UtcDaliSceneDefinitionConstVisitCustomized(void)
248 {
249   TestContext ctx;
250
251   ctx.root->mCustomization.reset(new NodeDefinition::CustomizationDefinition{ "A/B" });
252
253   const ConstNodeVisitor::Visit expected[] {
254     { START, ctx.root },
255     { START, ctx.childB },
256     { FINISH, ctx.childB },
257     { FINISH, ctx.root },
258   };
259
260   Customization::Choices choices;
261   for (auto i : { 1, 2 })
262   {
263     choices.Set("A/B", i);
264
265     ConstNodeVisitor visitor;
266     ctx.sceneDef.Visit(0, choices, visitor);
267
268     DALI_TEST_CHECK(std::equal(visitor.visits.begin(), visitor.visits.end(), std::begin(expected)));
269   }
270
271   END_TEST;
272 };
273
274 int UtcDaliSceneDefinitionGetCustomizationOptions(void)
275 {
276   TestContext ctx;
277
278   ctx.sceneDef.AddRootNode(0); // GetCustomizationOptions requires this.
279
280   ctx.root->mCustomization.reset(new NodeDefinition::CustomizationDefinition{ "A/B" });
281   ctx.childA->mCustomization.reset(new NodeDefinition::CustomizationDefinition{ "hello" });
282   ctx.childB->mCustomization.reset(new NodeDefinition::CustomizationDefinition{ "goodbye" });
283
284   Customization::Choices choices;
285   Customization::Map options;
286   ctx.sceneDef.GetCustomizationOptions(choices, options, &choices);
287
288   DALI_TEST_EQUAL(choices.Size(), 2u);
289   DALI_TEST_EQUAL(options.Size(), 2u);
290
291   struct TestOption
292   {
293     std::string name;
294     Customization customization;
295     Customization::OptionType choice;
296   };
297
298   std::vector<TestOption> testOptions {
299     { "A/B", { 2, { "Root" } }, 0 },
300     { "hello", { 0, { "A" } }, 0 },
301   };
302   for (auto& testOption: testOptions)
303   {
304     auto iFind = choices.Get(testOption.name);
305     DALI_TEST_EQUAL(iFind, testOption.choice);
306
307     auto iFindOption = options.Get(testOption.name);
308     DALI_TEST_CHECK(iFindOption != nullptr);
309     DALI_TEST_EQUAL(iFindOption->numOptions, testOption.customization.numOptions);
310     DALI_TEST_EQUAL(iFindOption->nodes.size(), testOption.customization.nodes.size());
311     DALI_TEST_CHECK(std::equal(iFindOption->nodes.begin(), iFindOption->nodes.end(),
312       testOption.customization.nodes.begin()));
313   }
314
315   choices.Clear();
316   choices.Set("A/B", 1);
317   *options.Get("A/B") = {};
318
319   testOptions[0].choice = 1;
320   testOptions[1].name = "goodbye";
321   testOptions[1].customization.nodes[0] = "B";
322
323   ctx.sceneDef.GetCustomizationOptions(choices, options, &choices);
324
325   DALI_TEST_EQUAL(choices.Size(), 2u);
326   DALI_TEST_EQUAL(options.Size(), 3u);
327
328   for (auto& testOption: testOptions)
329   {
330     auto iFind = choices.Get(testOption.name);
331     DALI_TEST_EQUAL(iFind, testOption.choice);
332
333     auto iFindOption = options.Get(testOption.name);
334     DALI_TEST_CHECK(iFindOption != nullptr);
335     DALI_TEST_EQUAL(iFindOption->numOptions, testOption.customization.numOptions);
336     DALI_TEST_EQUAL(iFindOption->nodes.size(), testOption.customization.nodes.size());
337     DALI_TEST_CHECK(std::equal(iFindOption->nodes.begin(), iFindOption->nodes.end(),
338       testOption.customization.nodes.begin()));
339   }
340
341   END_TEST;
342 }
343
344 int UtcDaliSceneDefinitionFindNode(void)
345 {
346   TestContext ctx;
347
348   Index result = INVALID_INDEX;
349   for (auto n: { ctx.root, ctx.childA, ctx.childB })
350   {
351     ctx.sceneDef.FindNode(n->mName, &result);
352     DALI_TEST_CHECK(result != INVALID_INDEX);
353     DALI_TEST_EQUAL(ctx.sceneDef.GetNode(result), n);
354   }
355
356   END_TEST;
357 }
358
359 int UtcDaliSceneDefinitionConstFindNode(void)
360 {
361   TestContext ctx;
362
363   Index result = INVALID_INDEX;
364   for (auto n: { ctx.root, ctx.childA, ctx.childB })
365   {
366     const_cast<const TestContext&>(ctx).sceneDef.FindNode(n->mName, &result);
367     DALI_TEST_CHECK(result != INVALID_INDEX);
368     DALI_TEST_EQUAL(ctx.sceneDef.GetNode(result), n);
369   }
370
371   END_TEST;
372 }
373
374 int UtcDaliSceneDefinitionFindNodeIndex(void)
375 {
376   TestContext ctx;
377
378   Index result = INVALID_INDEX;
379   for (auto n: { ctx.root, ctx.childA, ctx.childB })
380   {
381     result = ctx.sceneDef.FindNodeIndex(*n);
382     DALI_TEST_CHECK(result != INVALID_INDEX);
383     DALI_TEST_EQUAL(ctx.sceneDef.GetNode(result), n);
384   }
385
386   END_TEST;
387 }
388
389 int UtcDaliSceneDefinitionFindNodes(void)
390 {
391   TestContext ctx;
392
393   std::vector<NodeDefinition*> nodes;
394   auto nodeConsumer = [&nodes](NodeDefinition& nd) {
395     nodes.push_back(&nd);
396   };
397
398   auto nodePredicate = [](const NodeDefinition& nd) {
399     return nd.mName.length() == 1;
400   };
401
402   ctx.sceneDef.FindNodes(nodePredicate, nodeConsumer, 1);
403   DALI_TEST_EQUAL(nodes.size(), 1);
404   DALI_TEST_EQUAL(nodes[0]->mName, "A");
405   DALI_TEST_EQUAL(nodes[0], ctx.childA);
406
407   nodes.clear();
408   ctx.sceneDef.FindNodes(nodePredicate, nodeConsumer);
409
410   DALI_TEST_EQUAL(nodes.size(), 2);
411   DALI_TEST_EQUAL(nodes[0]->mName, "A");
412   DALI_TEST_EQUAL(nodes[0], ctx.childA);
413   DALI_TEST_EQUAL(nodes[1]->mName, "B");
414   DALI_TEST_EQUAL(nodes[1], ctx.childB);
415
416   END_TEST;
417 }
418
419 int UtcDaliSceneDefinitionRemoveNode(void)
420 {
421   TestContext ctx;
422   DALI_TEST_EQUAL(ctx.sceneDef.RemoveNode("doesn't exist"), false);
423
424   // pre-removing A
425   DALI_TEST_EQUAL(ctx.sceneDef.GetNodeCount(), 3u);
426   DALI_TEST_EQUAL(ctx.root->mChildren.size(), 2u);
427
428   Index result;
429   DALI_TEST_EQUAL(ctx.sceneDef.FindNode("B", &result), ctx.childB);
430   DALI_TEST_EQUAL(result, 2);
431
432   DALI_TEST_EQUAL(ctx.sceneDef.RemoveNode("A"), true);
433
434   // post-removing A
435   DALI_TEST_EQUAL(ctx.sceneDef.GetNodeCount(), 2u);
436
437   result = 12345;
438   DALI_TEST_EQUAL(ctx.sceneDef.FindNode("A", &result), static_cast<NodeDefinition*>(nullptr));
439   DALI_TEST_EQUAL(result, 12345); // doesn't change
440
441   DALI_TEST_EQUAL(ctx.sceneDef.FindNode("B", &result), ctx.childB);
442   DALI_TEST_EQUAL(result, 1); // dropped
443
444   DALI_TEST_EQUAL(ctx.root->mChildren.size(), 1u);
445   DALI_TEST_EQUAL(ctx.root->mChildren[0], 1u);
446
447   // removing root
448   DALI_TEST_EQUAL(ctx.sceneDef.RemoveNode("Root"), true);
449   DALI_TEST_EQUAL(ctx.sceneDef.GetNodeCount(), 0);
450
451   END_TEST;
452 }
453
454 int UtcDaliSceneDefinitionReparentNode(void)
455 {
456   TestContext ctx;
457
458   ctx.sceneDef.ReparentNode("B", "A", 0);
459
460   DALI_TEST_EQUAL(ctx.childB->mParentIdx, ctx.sceneDef.FindNodeIndex(*ctx.childA));
461   DALI_TEST_EQUAL(ctx.childA->mChildren.size(), 1u);
462   DALI_TEST_EQUAL(ctx.childA->mChildren[0], ctx.sceneDef.FindNodeIndex(*ctx.childB));
463
464   END_TEST;
465 }
466