b8de978d83bf55ae51ea506231293de72407d08a
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / dali-test-suite-utils.h
1 #ifndef DALI_TEST_SUITE_UTILS_H
2 #define DALI_TEST_SUITE_UTILS_H
3
4 /*
5  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <cstdarg>
23 #include <cstdio>
24 #include <cstring>
25 #include <iostream>
26 #include <string>
27
28 // INTERNAL INCLUDES
29 #include <dali/public-api/dali-core.h>
30 #include <test-compare-types.h>
31
32 extern "C"
33 {
34   void tet_infoline(const char* str);
35   void tet_printf(const char* format, ...);
36 }
37
38 #include "test-actor-utils.h"
39 #include "test-application.h"
40 #include "test-gesture-generator.h"
41
42 using namespace Dali;
43
44 #define STRINGIZE_I(text) #text
45 #define STRINGIZE(text) STRINGIZE_I(text)
46
47 /**
48  * Inspired by https://stackoverflow.com/questions/1706346/file-macro-manipulation-handling-at-compile-time
49  * answer by Chetan Reddy
50  */
51 constexpr int32_t basenameIndex(const char* const path, const int32_t index = 0, const int32_t slashIndex = -1)
52 {
53   return path[index]
54            ? (path[index] == '/'
55                 ? basenameIndex(path, index + 1, index)
56                 : basenameIndex(path, index + 1, slashIndex))
57            : (slashIndex + 1);
58 }
59
60 #define __FILELINE__ ({ static const int32_t basenameIdx = basenameIndex( __FILE__ ); \
61                          static_assert (basenameIdx >= 0, "compile-time basename" );   \
62                          __FILE__ ":" STRINGIZE(__LINE__) + basenameIdx ; })
63
64 #define TEST_LOCATION __FILELINE__
65 #define TEST_INNER_LOCATION(x) (std::string(x) + " (" + STRINGIZE(__LINE__) + ")").c_str()
66
67 #define TET_UNDEF 2
68 #define TET_FAIL 1
69 #define TET_PASS 0
70
71 extern int32_t test_return_value;
72
73 void tet_result(int32_t value);
74
75 #define END_TEST \
76   return ((test_return_value > 0) ? 1 : 0)
77
78 void tet_infoline(const char* str);
79 void tet_printf(const char* format, ...);
80
81 /**
82  * DALI_TEST_CHECK is a wrapper for tet_result.
83  * If the condition evaluates to false, the test is stopped.
84  * @param[in] The boolean expression to check
85  */
86 #define DALI_TEST_CHECK(condition)                                                   \
87   if((condition))                                                                    \
88   {                                                                                  \
89     tet_result(TET_PASS);                                                            \
90   }                                                                                  \
91   else                                                                               \
92   {                                                                                  \
93     fprintf(stderr, "Test failed in %s, condition: %s\n", __FILELINE__, #condition); \
94     tet_result(TET_FAIL);                                                            \
95     throw("TET_FAIL");                                                               \
96   }
97
98 bool          operator==(TimePeriod a, TimePeriod b);
99 std::ostream& operator<<(std::ostream& ostream, TimePeriod value);
100 std::ostream& operator<<(std::ostream& ostream, Radian angle);
101 std::ostream& operator<<(std::ostream& ostream, Degree angle);
102
103 /**
104  * Test whether two values are equal.
105  * @param[in] value1 The first value
106  * @param[in] value2 The second value
107  * @param[in] location The TEST_LOCATION macro should be used here
108  */
109 template<typename Type>
110 inline void DALI_TEST_EQUALS(Type value1, Type value2, const char* location)
111 {
112   if(!CompareType<Type>(value1, value2, 0.01f))
113   {
114     std::ostringstream o;
115     o << value1 << " == " << value2 << std::endl;
116     fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
117     tet_result(TET_FAIL);
118     throw("TET_FAIL");
119   }
120   else
121   {
122     tet_result(TET_PASS);
123   }
124 }
125
126 /**
127  * Test whether two values are equal.
128  * @param[in] value1 The first value
129  * @param[in] value2 The second value
130  */
131 #define DALI_TEST_EQUAL(v1, v2) DALI_TEST_EQUALS(v1, v2, __FILELINE__)
132
133 template<typename Type>
134 inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location)
135 {
136   if(!CompareType<Type>(value1, value2, epsilon))
137   {
138     std::ostringstream o;
139     o << value1 << " == " << value2 << std::endl;
140     fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
141     tet_result(TET_FAIL);
142     throw("TET_FAIL");
143   }
144   else
145   {
146     tet_result(TET_PASS);
147   }
148 }
149
150 template<typename Type>
151 inline void DALI_TEST_NOT_EQUALS(Type value1, Type value2, float epsilon, const char* location)
152 {
153   if(CompareType<Type>(value1, value2, epsilon))
154   {
155     std::ostringstream o;
156     o << value1 << " !=  " << value2 << std::endl;
157     fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
158     tet_result(TET_FAIL);
159     throw("TET_FAIL");
160   }
161   else
162   {
163     tet_result(TET_PASS);
164   }
165 }
166
167 /**
168  * Test whether two TimePeriods are within a certain distance of each other.
169  * @param[in] value1 The first value
170  * @param[in] value2 The second value
171  * @param[in] epsilon The values must be within this distance of each other
172  * @param[in] location The TEST_LOCATION macro should be used here
173  */
174 template<>
175 inline void DALI_TEST_EQUALS<TimePeriod>(TimePeriod value1, TimePeriod value2, float epsilon, const char* location)
176 {
177   if((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon))
178   {
179     fprintf(stderr, "Test failed in %s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon);
180     tet_result(TET_FAIL);
181     throw("TET_FAIL");
182   }
183   else if((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon))
184   {
185     fprintf(stderr, "Test failed in %s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon);
186     tet_result(TET_FAIL);
187     throw("TET_FAIL");
188   }
189   else
190   {
191     tet_result(TET_PASS);
192   }
193 }
194
195 /**
196  * Test whether two base handles are equal.
197  * @param[in] baseHandle1 The first value
198  * @param[in] baseHandle2 The second value
199  * @param[in] location The TEST_LOCATION macro should be used here
200  */
201 void DALI_TEST_EQUALS(const BaseHandle& baseHandle1, const BaseHandle& baseHandle2, const char* location);
202
203 /**
204  * Test whether a size_t value and an uint32_t are equal.
205  * @param[in] value1 The first value
206  * @param[in] value2 The second value
207  * @param[in] location The TEST_LOCATION macro should be used here
208  */
209 void DALI_TEST_EQUALS(const size_t value1, const uint32_t value2, const char* location);
210
211 /**
212  * Test whether an uint32_t and a size_t value and are equal.
213  * @param[in] value1 The first value
214  * @param[in] value2 The second value
215  * @param[in] location The TEST_LOCATION macro should be used here
216  */
217 void DALI_TEST_EQUALS(const uint32_t value1, const size_t value2, const char* location);
218
219 /**
220  * Test whether two Matrix3 objects are equal.
221  * @param[in] matrix1 The first object
222  * @param[in] matrix2 The second object
223  * @param[in] location The TEST_LOCATION macro should be used here
224  */
225 void DALI_TEST_EQUALS(const Matrix3& matrix1, const Matrix3& matrix2, const char* location);
226
227 /** Test whether two Matrix3 objects are equal (fuzzy compare).
228  * @param[in] matrix1 The first object
229  * @param[in] matrix2 The second object
230  * @param[in] epsilon The epsilon to use for comparison
231  * @param[in] location The TEST_LOCATION macro should be used here
232  */
233 void DALI_TEST_EQUALS(const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location);
234
235 /**
236  * Test whether two Matrix objects are equal.
237  * @param[in] matrix1 The first object
238  * @param[in] matrix2 The second object
239  * @param[in] location The TEST_LOCATION macro should be used here
240  */
241 void DALI_TEST_EQUALS(const Matrix& matrix1, const Matrix& matrix2, const char* location);
242
243 /**
244  * Test whether two Matrix objects are equal (fuzzy-compare).
245  * @param[in] matrix1 The first object
246  * @param[in] matrix2 The second object
247  * @param[in] location The TEST_LOCATION macro should be used here
248  */
249 void DALI_TEST_EQUALS(const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location);
250
251 /**
252  * Test whether two strings are equal.
253  * @param[in] str1 The first string
254  * @param[in] str2 The second string
255  * @param[in] location The TEST_LOCATION macro should be used here
256  */
257 template<>
258 inline void DALI_TEST_EQUALS<const char*>(const char* str1, const char* str2, const char* location)
259 {
260   if(strcmp(str1, str2))
261   {
262     fprintf(stderr, "Test failed in %s, checking '%s' == '%s'\n", location, str1, str2);
263     tet_result(TET_FAIL);
264     throw("TET_FAIL");
265   }
266   else
267   {
268     tet_result(TET_PASS);
269   }
270 }
271
272 /**
273  * Test whether two strings are equal.
274  * @param[in] str1 The first string
275  * @param[in] str2 The second string
276  * @param[in] location The TEST_LOCATION macro should be used here
277  */
278 template<>
279 inline void DALI_TEST_EQUALS<const std::string&>(const std::string& str1, const std::string& str2, const char* location)
280 {
281   DALI_TEST_EQUALS(str1.c_str(), str2.c_str(), location);
282 }
283
284 /**
285  * Test whether two strings are equal.
286  * @param[in] str1 The first string
287  * @param[in] str2 The second string
288  * @param[in] location The TEST_LOCATION macro should be used here
289  */
290 void DALI_TEST_EQUALS(Property::Value& str1, const char* str2, const char* location);
291
292 /**
293  * Test whether two strings are equal.
294  * @param[in] str1 The first string
295  * @param[in] str2 The second string
296  * @param[in] location The TEST_LOCATION macro should be used here
297  */
298 void DALI_TEST_EQUALS(const std::string& str1, const char* str2, const char* location);
299
300 /**
301  * Test whether two strings are equal.
302  * @param[in] str1 The first string
303  * @param[in] str2 The second string
304  * @param[in] location The TEST_LOCATION macro should be used here
305  */
306 void DALI_TEST_EQUALS(const char* str1, const std::string& str2, const char* location);
307
308 /**
309  * Test if a property value type is equal to a trivial type.
310  */
311 template<typename Type>
312 inline void DALI_TEST_VALUE_EQUALS(Property::Value&& value1, Type value2, float epsilon, const char* location)
313 {
314   Property::Value value2b(value2);
315   DALI_TEST_EQUALS(value1, value2b, epsilon, location);
316 }
317
318 /**
319  * Test whether one unsigned integer value is greater than another.
320  * Test succeeds if value1 > value2
321  * @param[in] value1 The first value
322  * @param[in] value2 The second value
323  * @param[in] location The TEST_LOCATION macro should be used here
324  */
325 template<typename T>
326 void DALI_TEST_GREATER(T value1, T value2, const char* location)
327 {
328   if(!(value1 > value2))
329   {
330     std::cerr << "Test failed in " << location << ", checking " << value1 << " > " << value2 << "\n";
331     tet_result(TET_FAIL);
332     throw("TET_FAIL");
333   }
334   else
335   {
336     tet_result(TET_PASS);
337   }
338 }
339
340 /**
341  * Test whether the assertion condition that failed and thus triggered the
342  * exception \b e contained a given substring.
343  * @param[in] e The exception that we expect was fired by a runtime assertion failure.
344  * @param[in] conditionSubString The text that we expect to be present in an
345  *                               assertion which triggered the exception.
346  * @param[in] location The TEST_LOCATION macro should be used here.
347  */
348 void DALI_TEST_ASSERT(DaliException& e, std::string conditionSubString, const char* location);
349
350 /**
351  * Print the assert
352  * @param[in] e The exception that we expect was fired by a runtime assertion failure.
353  */
354 inline void DALI_TEST_PRINT_ASSERT(DaliException& e)
355 {
356   tet_printf("Assertion %s failed at %s\n", e.condition, e.location);
357 }
358
359 /**
360  * Test that given piece of code triggers the right assertion
361  * Fails the test if the assert didn't occur.
362  * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
363  * @param expressions code to execute
364  * @param assertstring the substring expected in the assert
365  */
366 #define DALI_TEST_ASSERTION(expressions, assertstring)                                                      \
367   try                                                                                                       \
368   {                                                                                                         \
369     TestApplication::EnableLogging(false);                                                                  \
370     expressions;                                                                                            \
371     TestApplication::EnableLogging(true);                                                                   \
372     fprintf(stderr, "Test failed in %s, expected assert: '%s' didn't occur\n", __FILELINE__, assertstring); \
373     tet_result(TET_FAIL);                                                                                   \
374     throw("TET_FAIL");                                                                                      \
375   }                                                                                                         \
376   catch(Dali::DaliException & e)                                                                            \
377   {                                                                                                         \
378     DALI_TEST_ASSERT(e, assertstring, TEST_LOCATION);                                                       \
379   }
380
381 /**
382  * Test that given piece of code triggers an exception
383  * Fails the test if the exception didn't occur.
384  * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
385  * @param expressions code to execute
386  * @param except the exception expected in the assert
387  */
388 #define DALI_TEST_THROWS(expressions, except)                                                               \
389   try                                                                                                       \
390   {                                                                                                         \
391     TestApplication::EnableLogging(false);                                                                  \
392     expressions;                                                                                            \
393     TestApplication::EnableLogging(true);                                                                   \
394     fprintf(stderr, "Test failed in %s, expected exception: '%s' didn't occur\n", __FILELINE__, #except);   \
395     tet_result(TET_FAIL);                                                                                   \
396     throw("TET_FAIL");                                                                                      \
397   }                                                                                                         \
398   catch(except &)                                                                                           \
399   {                                                                                                         \
400     tet_result(TET_PASS);                                                                                   \
401   }                                                                                                         \
402   catch(...)                                                                                                \
403   {                                                                                                         \
404     fprintf(stderr, "Test failed in %s, unexpected exception\n", __FILELINE__);                             \
405     tet_result(TET_FAIL);                                                                                   \
406     throw;                                                                                                  \
407   }
408
409 // Functor to test whether an Applied signal is emitted
410 struct ConstraintAppliedCheck
411 {
412   ConstraintAppliedCheck(bool& signalReceived);
413   void  operator()(Constraint& constraint);
414   void  Reset();
415   void  CheckSignalReceived();
416   void  CheckSignalNotReceived();
417   bool& mSignalReceived; // owned by individual tests
418 };
419
420 /**
421  * A Helper to test default functions
422  */
423 template<typename T>
424 struct DefaultFunctionCoverage
425 {
426   DefaultFunctionCoverage()
427   {
428     T  a;
429     T* b = new T(a);
430     DALI_TEST_CHECK(b);
431     a = *b;
432     delete b;
433   }
434 };
435
436 // Test namespace to prevent pollution of Dali namespace, add Test helper functions here
437 namespace Test
438 {
439 /**
440  *  @brief
441  *
442  *  Helper to check object destruction occurred
443  *  1) In main part of code create an ObjectDestructionTracker
444  *  2) Within sub section of main create object Actor test and call Start with Actor to test for destruction
445  *  3) Perform code which is expected to destroy Actor
446  *  4) Back in main part of code use IsDestroyed() to test if Actor was destroyed
447  */
448 class ObjectDestructionTracker : public ConnectionTracker
449 {
450 public:
451   /**
452    * @brief Call in main part of code
453    * @param[in] objectRegistry The object Registry being used
454    */
455   ObjectDestructionTracker(ObjectRegistry objectRegistry);
456
457   /**
458    * @brief Call in sub bock of code where the Actor being checked is still alive.
459    *
460    * @param[in] actor Actor to be checked for destruction
461    */
462   void Start(Actor actor);
463
464   /**
465    * @brief Call to check if Actor alive or destroyed.
466    *
467    * @return bool true if Actor was destroyed
468    */
469   bool IsDestroyed();
470
471 private:
472   ObjectRegistry mObjectRegistry;
473   bool           mRefObjectDestroyed;
474 };
475
476 } // namespace Test
477
478 #endif // DALI_TEST_SUITE_UTILS_H