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