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.
22 #include <dali-test-suite-utils.h>
23 #include <dali/public-api/signals/callback.h>
25 // Internal headers are allowed here
26 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/internal/event/events/actor-observer.h>
30 using ActorObserver = Internal::ActorObserver;
32 namespace TestCallback
34 Internal::Actor* disconnectedActor = nullptr;
36 void Function( Internal::Actor* actor )
38 disconnectedActor = actor;
45 disconnectedActor = nullptr;
48 } // namespace TestCallback
50 void utc_dali_internal_actor_observer_startup()
52 test_return_value = TET_UNDEF;
55 void utc_dali_internal_actor_observer_cleanup()
57 test_return_value = TET_PASS;
60 int UtcDaliActorObserverTests(void)
62 TestApplication application;
64 auto scene = application.GetScene();
65 auto actor = Actor::New();
66 auto& actorImpl = GetImplementation( actor );
68 // Ensure we're not observing anything at the start
69 ActorObserver actorObserver;
70 DALI_TEST_EQUALS( actorObserver.GetActor(), nullptr, TEST_LOCATION );
72 // Set the actor and ensure GetActor returns the correct pointer
73 actorObserver.SetActor( &actorImpl );
74 DALI_TEST_EQUALS( actorObserver.GetActor(), &actorImpl, TEST_LOCATION );
77 DALI_TEST_EQUALS( actorObserver.GetActor(), &actorImpl, TEST_LOCATION );
79 // Removing the actor from the scene should make it return null
80 scene.Remove( actor );
81 DALI_TEST_EQUALS( actorObserver.GetActor(), nullptr, TEST_LOCATION );
83 // Adding the actor back to the scene should mean it returning the actor again
85 DALI_TEST_EQUALS( actorObserver.GetActor(), &actorImpl, TEST_LOCATION );
87 // Resetting the actor should return nullptr
88 actorObserver.ResetActor();
89 DALI_TEST_EQUALS( actorObserver.GetActor(), nullptr, TEST_LOCATION );
91 // Set the actor again
92 actorObserver.SetActor( &actorImpl );
93 DALI_TEST_EQUALS( actorObserver.GetActor(), &actorImpl, TEST_LOCATION );
95 // Create another Actor and observe that (don't add it to the scene just yet)
97 auto actor2 = Actor::New();
98 auto& actor2Impl = GetImplementation( actor2 );
99 actorObserver.SetActor( &actor2Impl );
100 DALI_TEST_EQUALS( actorObserver.GetActor(), &actor2Impl, TEST_LOCATION );
103 // Actor destroyed now, should return nullptr
104 DALI_TEST_EQUALS( actorObserver.GetActor(), nullptr, TEST_LOCATION );
109 int UtcDaliActorObserverGracefulDeletion(void)
111 TestApplication application;
113 // Create an ActorObserver and observe an actor that outlives the observer...
114 // when the actor is destroyed, there should be no segmentation fault,
115 // i.e. the ActorObserver should unregister itself
119 // Scope lifetime of Actor
120 auto actor = Actor::New();
121 auto& actorImpl = GetImplementation( actor );
123 // Now scope the lifetime of ActorObserver
125 ActorObserver actorObserver;
126 actorObserver.SetActor( &actorImpl );
127 } // ActorObserver goes out of scope
128 } // Actor goes out of scope
130 // If we get here without a crash, then it's all good
131 DALI_TEST_CHECK( true );
135 tet_infoline( "ActorObserver did not clean up properly" );
136 DALI_TEST_CHECK( false );
142 int UtcDaliActorObserverMoveConstructorAndAssignmentEmpty(void)
144 TestApplication application;
146 // Copy empty observer
147 ActorObserver observer1;
148 ActorObserver observer2( std::move( observer1 ) );
149 DALI_TEST_EQUALS( observer1.GetActor(), nullptr, TEST_LOCATION );
150 DALI_TEST_EQUALS( observer2.GetActor(), nullptr, TEST_LOCATION );
152 // Assign empty observer
153 observer1 = std::move( observer2 );
154 DALI_TEST_EQUALS( observer1.GetActor(), nullptr, TEST_LOCATION );
155 DALI_TEST_EQUALS( observer2.GetActor(), nullptr, TEST_LOCATION );
157 // Ensure self assignment doesn't change anything
158 observer1 = std::move( observer1 );
159 observer2 = std::move( observer2 );
160 DALI_TEST_EQUALS( observer1.GetActor(), nullptr, TEST_LOCATION );
161 DALI_TEST_EQUALS( observer2.GetActor(), nullptr, TEST_LOCATION );
166 int UtcDaliActorObserverMoveConstructorAndAssignment(void)
168 TestApplication application;
170 // Ensure new observer is observing the correct actor
171 // Ensure previous observer is not observing anything any more
172 auto actor = Actor::New();
173 auto& actorImpl = GetImplementation( actor );
175 ActorObserver observer1;
176 observer1.SetActor( &actorImpl );
177 DALI_TEST_EQUALS( observer1.GetActor(), &actorImpl, TEST_LOCATION );
180 ActorObserver observer2( std::move( observer1 ) );
181 DALI_TEST_EQUALS( observer1.GetActor(), nullptr, TEST_LOCATION );
182 DALI_TEST_EQUALS( observer2.GetActor(), &actorImpl, TEST_LOCATION );
185 observer1 = std::move( observer2 );
186 DALI_TEST_EQUALS( observer1.GetActor(), &actorImpl, TEST_LOCATION );
187 DALI_TEST_EQUALS( observer2.GetActor(), nullptr, TEST_LOCATION );
190 observer1 = std::move( observer1 );
191 observer2 = std::move( observer2 );
192 DALI_TEST_EQUALS( observer1.GetActor(), &actorImpl, TEST_LOCATION );
193 DALI_TEST_EQUALS( observer2.GetActor(), nullptr, TEST_LOCATION );
198 int UtcDaliActorObserverEnsureRValueCleansUp(void)
200 TestApplication application;
202 // ActorObservers observe the actors
203 // When an actor observer is moved, we need to ensure that the r-value observer cleans up after itself
205 // Here we're testing that we're handling this correctly by scoping the lifetime of the observer and actor
209 // Scope lifetime of Actor
210 auto actor = Actor::New();
211 auto& actorImpl = GetImplementation( actor );
213 // Score lifetime of observers
215 ActorObserver observer1;
216 observer1.SetActor( &actorImpl );
217 ActorObserver observer2( std::move( observer1 ) );
218 } // Both observers die here
219 } // Actor goes out of scope
221 // If we get here without a crash, then it's all good
222 DALI_TEST_CHECK( true );
226 tet_infoline( "ActorObserver did not clean up properly" );
227 DALI_TEST_CHECK( false );
233 int UtcDaliActorObserverFunctionCallback(void)
235 TestApplication application;
237 // Test to ensure the passed in callback is called when the observed actor is disconnected
238 TestCallback::Reset();
240 auto scene = application.GetScene();
241 auto actor = Actor::New();
242 auto& actorImpl = GetImplementation( actor );
245 ActorObserver actorObserver( MakeCallback( &TestCallback::Function ) );
246 actorObserver.SetActor( &actorImpl );
247 DALI_TEST_EQUALS( actorObserver.GetActor(), &actorImpl, TEST_LOCATION );
248 DALI_TEST_EQUALS( TestCallback::disconnectedActor, nullptr, TEST_LOCATION );
250 // Remove Actor from scene
252 DALI_TEST_EQUALS( actorObserver.GetActor(), nullptr, TEST_LOCATION );
253 DALI_TEST_EQUALS( TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION );
258 int UtcDaliActorObserverFunctionCallbackEnsureNoDoubleDelete(void)
260 TestApplication application;
262 // When we move an observer, we need to make sure we pass the ownership of a connected callback
263 // to ensure no double deletion.
264 TestCallback::Reset();
268 auto scene = application.GetScene();
269 auto actor = Actor::New();
270 auto& actorImpl = GetImplementation( actor );
273 ActorObserver *observer1 = new ActorObserver( MakeCallback( &TestCallback::Function ) );
274 observer1->SetActor( &actorImpl );
276 // Move observer1 into a new observer
277 ActorObserver* observer2 = new ActorObserver( std::move( *observer1 ) );
279 // Remove actor from scene, function should be called only once
281 DALI_TEST_EQUALS( TestCallback::disconnectedActor, &actorImpl, TEST_LOCATION );
282 DALI_TEST_EQUALS( TestCallback::callCount, 1, TEST_LOCATION );
284 // Delete both observers here, only one of them should delete the callback
288 // If we get here without a crash, then the callback has NOT been double-freed
289 DALI_TEST_CHECK( true );
293 DALI_TEST_CHECK( false );
294 tet_infoline( "Callback double Freed" );