Add UserInteractionEnabled property on actor for controlling user interaction.
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-ConditionalWait.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/devel-api/threading/conditional-wait.h>
20 #include <dali/devel-api/threading/thread.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23
24 #include <iostream>
25 #include <type_traits>
26
27 using Dali::ConditionalWait;
28 using Dali::Thread;
29
30 namespace // for local variables to avoid name clashes
31 {
32 volatile int  gGlobalValue      = 0;
33 volatile bool gWorkerThreadWait = true;
34 enum ThreadState
35 {
36   INIT,
37   RUN,
38   TERMINATE
39 } volatile gWorkerThreadState = INIT;
40 ConditionalWait* volatile gConditionalWait; // volatile pointer to a ConditionalWait object
41
42 class WorkerThreadNotify : public Thread
43 {
44   virtual void Run()
45   {
46     gGlobalValue = -1;
47     while(gWorkerThreadWait) // wait till we can exit
48     {
49       gWorkerThreadState = RUN;
50       usleep(1); // 1 microseconds
51     }
52     usleep(200); // give other thread time to get to Wait
53     gGlobalValue = 1;
54     gConditionalWait->Notify();
55     gWorkerThreadState = TERMINATE;
56   }
57 };
58
59 volatile int gNotifyCount = 0;
60 class WorkerThreadNotifyN : public Thread
61 {
62   virtual void Run()
63   {
64     while(gNotifyCount > 0)
65     {
66       gConditionalWait->Notify();
67       usleep(10); // 10 microseconds between each notify
68     }
69   }
70 };
71
72 class WorkerThreadWaitN : public Thread
73 {
74   virtual void Run()
75   {
76     gConditionalWait->Wait();
77   }
78 };
79
80 } // namespace
81
82 int UtcConditionalWait1P(void)
83 {
84   tet_infoline("Testing ConditionalWait - scenario:  wait - notify with 2 threads");
85
86   WorkerThreadNotify thread1;
87   // initialize values
88   gConditionalWait  = new ConditionalWait();
89   gWorkerThreadWait = true;
90   DALI_TEST_EQUALS(INIT, gWorkerThreadState, TEST_LOCATION);
91   DALI_TEST_EQUALS(0, gGlobalValue, TEST_LOCATION);
92
93   thread1.Start();
94   // wait till the thread is in run state
95   while(RUN != gWorkerThreadState)
96   {
97     usleep(1); // 1 microsecond
98   }
99   // let worker continue and finish
100   gWorkerThreadWait = false;
101   gConditionalWait->Wait();
102   DALI_TEST_EQUALS(1, gGlobalValue, TEST_LOCATION);
103   DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
104
105   // wait till the thread is terminated state
106   while(TERMINATE != gWorkerThreadState)
107   {
108     usleep(1); // 1 microsecond
109   }
110
111   thread1.Join();
112
113   delete gConditionalWait;
114   END_TEST;
115 }
116
117 int UtcConditionalWait2P(void)
118 {
119   tet_infoline("Testing ConditionalWait - scenario: notify without wait");
120
121   ConditionalWait wait;
122   DALI_TEST_EQUALS(0u, wait.GetWaitCount(), TEST_LOCATION);
123   wait.Notify();
124   DALI_TEST_EQUALS(0u, wait.GetWaitCount(), TEST_LOCATION);
125
126   END_TEST;
127 }
128
129 int UtcConditionalWait3P(void)
130 {
131   tet_infoline("Testing ConditionalWait - scenario: wait - notify N times 2 threads");
132
133   // initialize values
134   gConditionalWait = new ConditionalWait();
135   gNotifyCount     = 100;
136
137   WorkerThreadNotifyN thread1;
138   thread1.Start();
139
140   while(gNotifyCount > 0)
141   {
142     gConditionalWait->Wait();
143     --gNotifyCount;
144     DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
145     usleep(10); // 10 microseconds between each notify
146   }
147   DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
148
149   thread1.Join();
150
151   delete gConditionalWait;
152   END_TEST;
153 }
154
155 int UtcConditionalWait4P(void)
156 {
157   tet_infoline("Testing ConditionalWait - scenario:  wait - notify N times from 3 threads");
158
159   // initialize values
160   gConditionalWait = new ConditionalWait();
161   gNotifyCount     = 100;
162
163   WorkerThreadNotifyN thread1;
164   thread1.Start();
165   WorkerThreadNotifyN thread2;
166   thread2.Start();
167   WorkerThreadNotifyN thread3;
168   thread3.Start();
169
170   while(gNotifyCount > 0)
171   {
172     gConditionalWait->Wait();
173     --gNotifyCount;
174     DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
175     usleep(10); // 10 microseconds between each notify
176   }
177
178   thread1.Join();
179   thread2.Join();
180   thread3.Join();
181
182   delete gConditionalWait;
183   END_TEST;
184 }
185
186 int UtcConditionalWait5P(void)
187 {
188   tet_infoline("Testing ConditionalWait - scenario:  4 threads wait - notify once from 1 thread");
189
190   // initialize values
191   gConditionalWait = new ConditionalWait();
192
193   WorkerThreadWaitN thread1;
194   thread1.Start();
195   WorkerThreadWaitN thread2;
196   thread2.Start();
197   WorkerThreadWaitN thread3;
198   thread3.Start();
199   WorkerThreadWaitN thread4;
200   thread4.Start();
201   // wait till all child threads are waiting
202   while(gConditionalWait->GetWaitCount() < 4)
203   {
204   }
205
206   // notify once, it will resume all threads
207   gConditionalWait->Notify();
208
209   thread1.Join();
210   thread2.Join();
211   thread3.Join();
212   thread4.Join();
213
214   DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
215
216   delete gConditionalWait;
217   END_TEST;
218 }
219
220 int UtcConditionalWait6P(void)
221 {
222   tet_infoline("Testing ConditionalWait - scenario:  4 threads wait - notify once from 1 thread");
223
224   // initialize values
225   gConditionalWait = new ConditionalWait();
226
227   WorkerThreadWaitN thread1;
228   thread1.Start();
229   WorkerThreadWaitN thread2;
230   thread2.Start();
231   WorkerThreadWaitN thread3;
232   thread3.Start();
233   WorkerThreadWaitN thread4;
234   thread4.Start();
235   // wait till all child threads are waiting
236   while(gConditionalWait->GetWaitCount() < 4)
237   {
238   }
239
240   // notify once but with a scoped lock, it will resume all threads
241   {
242     ConditionalWait::ScopedLock lock(*gConditionalWait);
243     gConditionalWait->Notify(lock);
244   }
245
246   thread1.Join();
247   thread2.Join();
248   thread3.Join();
249   thread4.Join();
250
251   DALI_TEST_EQUALS(0u, gConditionalWait->GetWaitCount(), TEST_LOCATION);
252
253   delete gConditionalWait;
254   END_TEST;
255 }
256
257 int UtcConditionalWaitNonCopyable(void)
258 {
259   // we want to make sure that ConditionalWait is not copyable (its copy constructor is not defined)
260   // this test will stop compiling if ConditionalWait has compiler generated copy constructor
261   static_assert(!__has_trivial_copy(ConditionalWait), "ConditionalWait should NOT be copyable");
262
263   DALI_TEST_CHECK(true);
264   END_TEST;
265 }