c6e63e7e47116861c3c9f1664c1e64201590530c
[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) 2021 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 whether two strings are equal.
310  * @param[in] str1 The first string
311  * @param[in] str2 The second string
312  * @param[in] location The TEST_LOCATION macro should be used here
313  */
314 template<>
315 inline void DALI_TEST_EQUALS<const std::string_view>(std::string_view str1, std::string_view str2, const char* location)
316 {
317   DALI_TEST_EQUALS(str1.data(), str2.data(), location);
318 }
319
320 inline void DALI_TEST_EQUALS(std::string_view str1, const char* str2, const char* location)
321 {
322   DALI_TEST_EQUALS(str1.data(), str2, location);
323 }
324
325 inline void DALI_TEST_EQUALS(std::string_view str1, const std::string& str2, const char* location)
326 {
327   DALI_TEST_EQUALS(str1.data(), str2.c_str(), location);
328 }
329
330 inline void DALI_TEST_EQUALS(const std::string& str2, std::string_view str1, const char* location)
331 {
332   DALI_TEST_EQUALS(str2.c_str(), str1.data(), location);
333 }
334
335 inline void DALI_TEST_EQUALS(const char* str1, std::string_view str2, const char* location)
336 {
337   DALI_TEST_EQUALS(str1, str2.data(), location);
338 }
339
340 /**
341  * Test if a property value type is equal to a trivial type.
342  */
343 template<typename Type>
344 inline void DALI_TEST_VALUE_EQUALS(Property::Value&& value1, Type value2, float epsilon, const char* location)
345 {
346   Property::Value value2b(value2);
347   DALI_TEST_EQUALS(value1, value2b, epsilon, location);
348 }
349
350 /**
351  * Test whether one unsigned integer value is greater than another.
352  * Test succeeds if value1 > value2
353  * @param[in] value1 The first value
354  * @param[in] value2 The second value
355  * @param[in] location The TEST_LOCATION macro should be used here
356  */
357 template<typename T>
358 void DALI_TEST_GREATER(T value1, T value2, const char* location)
359 {
360   if(!(value1 > value2))
361   {
362     std::cerr << "Test failed in " << location << ", checking " << value1 << " > " << value2 << "\n";
363     tet_result(TET_FAIL);
364     throw("TET_FAIL");
365   }
366   else
367   {
368     tet_result(TET_PASS);
369   }
370 }
371
372 /**
373  * Test whether the assertion condition that failed and thus triggered the
374  * exception \b e contained a given substring.
375  * @param[in] e The exception that we expect was fired by a runtime assertion failure.
376  * @param[in] conditionSubString The text that we expect to be present in an
377  *                               assertion which triggered the exception.
378  * @param[in] location The TEST_LOCATION macro should be used here.
379  */
380 void DALI_TEST_ASSERT(DaliException& e, std::string conditionSubString, const char* location);
381
382 /**
383  * Print the assert
384  * @param[in] e The exception that we expect was fired by a runtime assertion failure.
385  */
386 inline void DALI_TEST_PRINT_ASSERT(DaliException& e)
387 {
388   tet_printf("Assertion %s failed at %s\n", e.condition, e.location);
389 }
390
391 /**
392  * Test that given piece of code triggers the right assertion
393  * Fails the test if the assert didn't occur.
394  * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
395  * @param expressions code to execute
396  * @param assertstring the substring expected in the assert
397  */
398 #define DALI_TEST_ASSERTION(expressions, assertstring)                                                      \
399   try                                                                                                       \
400   {                                                                                                         \
401     TestApplication::EnableLogging(false);                                                                  \
402     expressions;                                                                                            \
403     TestApplication::EnableLogging(true);                                                                   \
404     fprintf(stderr, "Test failed in %s, expected assert: '%s' didn't occur\n", __FILELINE__, assertstring); \
405     tet_result(TET_FAIL);                                                                                   \
406     throw("TET_FAIL");                                                                                      \
407   }                                                                                                         \
408   catch(Dali::DaliException & e)                                                                            \
409   {                                                                                                         \
410     DALI_TEST_ASSERT(e, assertstring, TEST_LOCATION);                                                       \
411   }
412
413 /**
414  * Test that given piece of code triggers an exception
415  * Fails the test if the exception didn't occur.
416  * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
417  * @param expressions code to execute
418  * @param except the exception expected in the assert
419  */
420 #define DALI_TEST_THROWS(expressions, except)                                                             \
421   try                                                                                                     \
422   {                                                                                                       \
423     TestApplication::EnableLogging(false);                                                                \
424     expressions;                                                                                          \
425     TestApplication::EnableLogging(true);                                                                 \
426     fprintf(stderr, "Test failed in %s, expected exception: '%s' didn't occur\n", __FILELINE__, #except); \
427     tet_result(TET_FAIL);                                                                                 \
428     throw("TET_FAIL");                                                                                    \
429   }                                                                                                       \
430   catch(except&)                                                                                          \
431   {                                                                                                       \
432     tet_result(TET_PASS);                                                                                 \
433   }                                                                                                       \
434   catch(...)                                                                                              \
435   {                                                                                                       \
436     fprintf(stderr, "Test failed in %s, unexpected exception\n", __FILELINE__);                           \
437     tet_result(TET_FAIL);                                                                                 \
438     throw;                                                                                                \
439   }
440
441 // Functor to test whether an Applied signal is emitted
442 struct ConstraintAppliedCheck
443 {
444   ConstraintAppliedCheck(bool& signalReceived);
445   void  operator()(Constraint& constraint);
446   void  Reset();
447   void  CheckSignalReceived();
448   void  CheckSignalNotReceived();
449   bool& mSignalReceived; // owned by individual tests
450 };
451
452 /**
453  * A Helper to test default functions
454  */
455 template<typename T>
456 struct DefaultFunctionCoverage
457 {
458   DefaultFunctionCoverage()
459   {
460     T  a;
461     T* b = new T(a);
462     DALI_TEST_CHECK(b);
463     a = *b;
464     delete b;
465   }
466 };
467
468 // Test namespace to prevent pollution of Dali namespace, add Test helper functions here
469 namespace Test
470 {
471 /**
472  *  @brief
473  *
474  *  Helper to check object destruction occurred
475  *  1) In main part of code create an ObjectDestructionTracker
476  *  2) Within sub section of main create object Actor test and call Start with Actor to test for destruction
477  *  3) Perform code which is expected to destroy Actor
478  *  4) Back in main part of code use IsDestroyed() to test if Actor was destroyed
479  */
480 class ObjectDestructionTracker : public ConnectionTracker
481 {
482 public:
483   /**
484    * @brief Call in main part of code
485    * @param[in] objectRegistry The object Registry being used
486    */
487   ObjectDestructionTracker(ObjectRegistry objectRegistry);
488
489   /**
490    * @brief Call in sub bock of code where the Actor being checked is still alive.
491    *
492    * @param[in] actor Actor to be checked for destruction
493    */
494   void Start(Actor actor);
495
496   /**
497    * @brief Call to check if Actor alive or destroyed.
498    *
499    * @return bool true if Actor was destroyed
500    */
501   bool IsDestroyed();
502
503 private:
504   ObjectRegistry mObjectRegistry;
505   bool           mRefObjectDestroyed;
506 };
507
508 } // namespace Test
509
510 #endif // DALI_TEST_SUITE_UTILS_H