Fix SVACE error in render-manager.cpp
[platform/core/uifw/dali-core.git] / automated-tests / src / dali-internal / utc-Dali-Internal-ActorObserver.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 #include <dali-test-suite-utils.h>
19 #include <dali/public-api/signals/callback.h>
20 #include <stdlib.h>
21
22 #include <iostream>
23
24 // Internal headers are allowed here
25 #include <dali/internal/event/actors/actor-impl.h>
26 #include <dali/internal/event/events/actor-observer.h>
27
28 using namespace Dali;
29 using ActorObserver = Internal::ActorObserver;
30
31 namespace TestCallback
32 {
33 Internal::Actor* disconnectedActor = nullptr;
34 int              callCount         = 0;
35 void             Function(Internal::Actor* actor)
36 {
37   disconnectedActor = actor;
38   ++callCount;
39 }
40
41 void Reset()
42 {
43   callCount         = 0;
44   disconnectedActor = nullptr;
45 }
46
47 } // namespace TestCallback
48
49 void utc_dali_internal_actor_observer_startup()
50 {
51   test_return_value = TET_UNDEF;
52 }
53
54 void utc_dali_internal_actor_observer_cleanup()
55 {
56   test_return_value = TET_PASS;
57 }
58
59 int UtcDaliActorObserverTests(void)
60 {
61   TestApplication application;
62
63   auto  scene     = application.GetScene();
64   auto  actor     = Actor::New();
65   auto& actorImpl = GetImplementation(actor);
66
67   // Ensure we're not observing anything at the start
68   ActorObserver actorObserver;
69   DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
70
71   // Set the actor and ensure GetActor returns the correct pointer
72   actorObserver.SetActor(&actorImpl);
73   DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
74
75   scene.Add(actor);
76   DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
77
78   // Removing the actor from the scene should make it return null
79   scene.Remove(actor);
80   DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
81
82   // Adding the actor back to the scene should mean it returning the actor again
83   scene.Add(actor);
84   DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
85
86   // Resetting the actor should return nullptr
87   actorObserver.ResetActor();
88   DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
89
90   // Set the actor again
91   actorObserver.SetActor(&actorImpl);
92   DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
93
94   // Create another Actor and observe that (don't add it to the scene just yet)
95   {
96     auto  actor2     = Actor::New();
97     auto& actor2Impl = GetImplementation(actor2);
98     actorObserver.SetActor(&actor2Impl);
99     DALI_TEST_EQUALS(actorObserver.GetActor(), &actor2Impl, TEST_LOCATION);
100   }
101
102   // Actor destroyed now, should return nullptr
103   DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
104
105   END_TEST;
106 }
107
108 int UtcDaliActorObserverGracefulDeletion(void)
109 {
110   TestApplication application;
111
112   // Create an ActorObserver and observe an actor that outlives the observer...
113   // when the actor is destroyed, there should be no segmentation fault,
114   // i.e. the ActorObserver should unregister itself
115   try
116   {
117     {
118       // Scope lifetime of Actor
119       auto  actor     = Actor::New();
120       auto& actorImpl = GetImplementation(actor);
121
122       // Now scope the lifetime of ActorObserver
123       {
124         ActorObserver actorObserver;
125         actorObserver.SetActor(&actorImpl);
126       } // ActorObserver goes out of scope
127     }   // Actor goes out of scope
128
129     // If we get here without a crash, then it's all good
130     DALI_TEST_CHECK(true);
131   }
132   catch(...)
133   {
134     tet_infoline("ActorObserver did not clean up properly");
135     DALI_TEST_CHECK(false);
136   }
137
138   END_TEST;
139 }
140
141 int UtcDaliActorObserverMoveConstructorAndAssignmentEmpty(void)
142 {
143   TestApplication application;
144
145   // Copy empty observer
146   ActorObserver observer1;
147   ActorObserver observer2(std::move(observer1));
148   DALI_TEST_EQUALS(observer1.GetActor(), nullptr, TEST_LOCATION);
149   DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
150
151   // Assign empty observer
152   observer1 = std::move(observer2);
153   DALI_TEST_EQUALS(observer1.GetActor(), nullptr, TEST_LOCATION);
154   DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
155
156   // Ensure self assignment doesn't change anything
157   observer1 = std::move(observer1);
158   observer2 = std::move(observer2);
159   DALI_TEST_EQUALS(observer1.GetActor(), nullptr, TEST_LOCATION);
160   DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
161
162   END_TEST;
163 }
164
165 int UtcDaliActorObserverMoveConstructorAndAssignment(void)
166 {
167   TestApplication application;
168
169   // Ensure new observer is observing the correct actor
170   // Ensure previous observer is not observing anything any more
171   auto  actor     = Actor::New();
172   auto& actorImpl = GetImplementation(actor);
173
174   ActorObserver observer1;
175   observer1.SetActor(&actorImpl);
176   DALI_TEST_EQUALS(observer1.GetActor(), &actorImpl, TEST_LOCATION);
177
178   // Move constructor
179   ActorObserver observer2(std::move(observer1));
180   DALI_TEST_EQUALS(observer1.GetActor(), nullptr, TEST_LOCATION);
181   DALI_TEST_EQUALS(observer2.GetActor(), &actorImpl, TEST_LOCATION);
182
183   // Move assignment
184   observer1 = std::move(observer2);
185   DALI_TEST_EQUALS(observer1.GetActor(), &actorImpl, TEST_LOCATION);
186   DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
187
188   // Self assignment
189   observer1 = std::move(observer1);
190   observer2 = std::move(observer2);
191   DALI_TEST_EQUALS(observer1.GetActor(), &actorImpl, TEST_LOCATION);
192   DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
193
194   END_TEST;
195 }
196
197 int UtcDaliActorObserverEnsureRValueCleansUp(void)
198 {
199   TestApplication application;
200
201   // ActorObservers observe the actors
202   // When an actor observer is moved, we need to ensure that the r-value observer cleans up after itself
203
204   // Here we're testing that we're handling this correctly by scoping the lifetime of the observer and actor
205   try
206   {
207     {
208       // Scope lifetime of Actor
209       auto  actor     = Actor::New();
210       auto& actorImpl = GetImplementation(actor);
211
212       // Score lifetime of observers
213       {
214         ActorObserver observer1;
215         observer1.SetActor(&actorImpl);
216         ActorObserver observer2(std::move(observer1));
217       } // Both observers die here
218     }   // Actor goes out of scope
219
220     // If we get here without a crash, then it's all good
221     DALI_TEST_CHECK(true);
222   }
223   catch(...)
224   {
225     tet_infoline("ActorObserver did not clean up properly");
226     DALI_TEST_CHECK(false);
227   }
228
229   END_TEST;
230 }
231
232 int UtcDaliActorObserverFunctionCallback(void)
233 {
234   TestApplication application;
235
236   // Test to ensure the passed in callback is called when the observed actor is disconnected
237   TestCallback::Reset();
238
239   auto  scene     = application.GetScene();
240   auto  actor     = Actor::New();
241   auto& actorImpl = GetImplementation(actor);
242   scene.Add(actor);
243
244   ActorObserver actorObserver(MakeCallback(&TestCallback::Function));
245   actorObserver.SetActor(&actorImpl);
246   DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
247   DALI_TEST_EQUALS(TestCallback::disconnectedActor, nullptr, TEST_LOCATION);
248
249   // Remove Actor from scene
250   actor.Unparent();
251   DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
252   DALI_TEST_EQUALS(TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION);
253
254   END_TEST;
255 }
256
257 int UtcDaliActorObserverFunctionCallbackEnsureNoDoubleDelete(void)
258 {
259   TestApplication application;
260
261   // When we move an observer, we need to make sure we pass the ownership of a connected callback
262   // to ensure no double deletion.
263   TestCallback::Reset();
264
265   try
266   {
267     auto  scene     = application.GetScene();
268     auto  actor     = Actor::New();
269     auto& actorImpl = GetImplementation(actor);
270     scene.Add(actor);
271
272     ActorObserver* observer1 = new ActorObserver(MakeCallback(&TestCallback::Function));
273     observer1->SetActor(&actorImpl);
274
275     // Move observer1 into a new observer
276     ActorObserver* observer2 = new ActorObserver(std::move(*observer1));
277
278     // Remove actor from scene, function should be called only once
279     actor.Unparent();
280     DALI_TEST_EQUALS(TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION);
281     DALI_TEST_EQUALS(TestCallback::callCount, 1, TEST_LOCATION);
282
283     // Delete both observers here, only one of them should delete the callback
284     delete observer1;
285     delete observer2;
286
287     // If we get here without a crash, then the callback has NOT been double-freed
288     DALI_TEST_CHECK(true);
289   }
290   catch(...)
291   {
292     DALI_TEST_CHECK(false);
293     tet_infoline("Callback double Freed");
294   }
295
296   END_TEST;
297 }