2 * Copyright (c) 2020 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-test-suite-utils.h>
19 #include <dali/public-api/signals/callback.h>
24 // Internal headers are allowed here
25 #include <dali/internal/event/actors/actor-impl.h>
26 #include <dali/internal/event/events/actor-observer.h>
29 using ActorObserver = Internal::ActorObserver;
31 namespace TestCallback
33 Internal::Actor* disconnectedActor = nullptr;
35 void Function(Internal::Actor* actor)
37 disconnectedActor = actor;
44 disconnectedActor = nullptr;
47 } // namespace TestCallback
49 void utc_dali_internal_actor_observer_startup()
51 test_return_value = TET_UNDEF;
54 void utc_dali_internal_actor_observer_cleanup()
56 test_return_value = TET_PASS;
59 int UtcDaliActorObserverTests(void)
61 TestApplication application;
63 auto scene = application.GetScene();
64 auto actor = Actor::New();
65 auto& actorImpl = GetImplementation(actor);
67 // Ensure we're not observing anything at the start
68 ActorObserver actorObserver;
69 DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
71 // Set the actor and ensure GetActor returns the correct pointer
72 actorObserver.SetActor(&actorImpl);
73 DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
76 DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
78 // Removing the actor from the scene should make it return null
80 DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
82 // Adding the actor back to the scene should mean it returning the actor again
84 DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
86 // Resetting the actor should return nullptr
87 actorObserver.ResetActor();
88 DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
90 // Set the actor again
91 actorObserver.SetActor(&actorImpl);
92 DALI_TEST_EQUALS(actorObserver.GetActor(), &actorImpl, TEST_LOCATION);
94 // Create another Actor and observe that (don't add it to the scene just yet)
96 auto actor2 = Actor::New();
97 auto& actor2Impl = GetImplementation(actor2);
98 actorObserver.SetActor(&actor2Impl);
99 DALI_TEST_EQUALS(actorObserver.GetActor(), &actor2Impl, TEST_LOCATION);
102 // Actor destroyed now, should return nullptr
103 DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
108 int UtcDaliActorObserverGracefulDeletion(void)
110 TestApplication application;
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
118 // Scope lifetime of Actor
119 auto actor = Actor::New();
120 auto& actorImpl = GetImplementation(actor);
122 // Now scope the lifetime of ActorObserver
124 ActorObserver actorObserver;
125 actorObserver.SetActor(&actorImpl);
126 } // ActorObserver goes out of scope
127 } // Actor goes out of scope
129 // If we get here without a crash, then it's all good
130 DALI_TEST_CHECK(true);
134 tet_infoline("ActorObserver did not clean up properly");
135 DALI_TEST_CHECK(false);
141 int UtcDaliActorObserverMoveConstructorAndAssignmentEmpty(void)
143 TestApplication application;
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);
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);
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);
165 int UtcDaliActorObserverMoveConstructorAndAssignment(void)
167 TestApplication application;
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);
174 ActorObserver observer1;
175 observer1.SetActor(&actorImpl);
176 DALI_TEST_EQUALS(observer1.GetActor(), &actorImpl, TEST_LOCATION);
179 ActorObserver observer2(std::move(observer1));
180 DALI_TEST_EQUALS(observer1.GetActor(), nullptr, TEST_LOCATION);
181 DALI_TEST_EQUALS(observer2.GetActor(), &actorImpl, TEST_LOCATION);
184 observer1 = std::move(observer2);
185 DALI_TEST_EQUALS(observer1.GetActor(), &actorImpl, TEST_LOCATION);
186 DALI_TEST_EQUALS(observer2.GetActor(), nullptr, TEST_LOCATION);
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);
197 int UtcDaliActorObserverEnsureRValueCleansUp(void)
199 TestApplication application;
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
204 // Here we're testing that we're handling this correctly by scoping the lifetime of the observer and actor
208 // Scope lifetime of Actor
209 auto actor = Actor::New();
210 auto& actorImpl = GetImplementation(actor);
212 // Score lifetime of observers
214 ActorObserver observer1;
215 observer1.SetActor(&actorImpl);
216 ActorObserver observer2(std::move(observer1));
217 } // Both observers die here
218 } // Actor goes out of scope
220 // If we get here without a crash, then it's all good
221 DALI_TEST_CHECK(true);
225 tet_infoline("ActorObserver did not clean up properly");
226 DALI_TEST_CHECK(false);
232 int UtcDaliActorObserverFunctionCallback(void)
234 TestApplication application;
236 // Test to ensure the passed in callback is called when the observed actor is disconnected
237 TestCallback::Reset();
239 auto scene = application.GetScene();
240 auto actor = Actor::New();
241 auto& actorImpl = GetImplementation(actor);
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);
249 // Remove Actor from scene
251 DALI_TEST_EQUALS(actorObserver.GetActor(), nullptr, TEST_LOCATION);
252 DALI_TEST_EQUALS(TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION);
257 int UtcDaliActorObserverFunctionCallbackEnsureNoDoubleDelete(void)
259 TestApplication application;
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();
267 auto scene = application.GetScene();
268 auto actor = Actor::New();
269 auto& actorImpl = GetImplementation(actor);
272 ActorObserver* observer1 = new ActorObserver(MakeCallback(&TestCallback::Function));
273 observer1->SetActor(&actorImpl);
275 // Move observer1 into a new observer
276 ActorObserver* observer2 = new ActorObserver(std::move(*observer1));
278 // Remove actor from scene, function should be called only once
280 DALI_TEST_EQUALS(TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION);
281 DALI_TEST_EQUALS(TestCallback::callCount, 1, TEST_LOCATION);
283 // Delete both observers here, only one of them should delete the callback
287 // If we get here without a crash, then the callback has NOT been double-freed
288 DALI_TEST_CHECK(true);
292 DALI_TEST_CHECK(false);
293 tet_infoline("Callback double Freed");