-#ifndef __DALI_TEST_SUITE_UTILS_H__
-#define __DALI_TEST_SUITE_UTILS_H__
+#ifndef DALI_TEST_SUITE_UTILS_H
+#define DALI_TEST_SUITE_UTILS_H
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
+// EXTERNAL INCLUDES
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <string>
+
// INTERNAL INCLUDES
#include <dali/public-api/dali-core.h>
-#include <stdarg.h>
+#include <test-compare-types.h>
-void tet_infoline(const char*str);
-void tet_printf(const char *format, ...);
+extern "C"
+{
+ void tet_infoline(const char* str);
+ void tet_printf(const char* format, ...);
+}
+#include "test-actor-utils.h"
#include "test-application.h"
+#include "test-gesture-generator.h"
using namespace Dali;
#define STRINGIZE_I(text) #text
#define STRINGIZE(text) STRINGIZE_I(text)
-// the following is the other compilers way of token pasting, gcc seems to just concatenate strings automatically
-//#define TOKENPASTE(x,y) x ## y
-#define TOKENPASTE(x,y) x y
-#define TOKENPASTE2(x,y) TOKENPASTE( x, y )
-#define TEST_LOCATION TOKENPASTE2( "Test failed in ", TOKENPASTE2( __FILE__, TOKENPASTE2( ", line ", STRINGIZE(__LINE__) ) ) )
+/**
+ * Inspired by https://stackoverflow.com/questions/1706346/file-macro-manipulation-handling-at-compile-time
+ * answer by Chetan Reddy
+ */
+constexpr int32_t basenameIndex(const char* const path, const int32_t index = 0, const int32_t slashIndex = -1)
+{
+ return path[index]
+ ? (path[index] == '/'
+ ? basenameIndex(path, index + 1, index)
+ : basenameIndex(path, index + 1, slashIndex))
+ : (slashIndex + 1);
+}
+
+#define __FILELINE__ ({ static const int32_t basenameIdx = basenameIndex( __FILE__ ); \
+ static_assert (basenameIdx >= 0, "compile-time basename" ); \
+ __FILE__ ":" STRINGIZE(__LINE__) + basenameIdx ; })
+
+#define TEST_LOCATION __FILELINE__
+#define TEST_INNER_LOCATION(x) (std::string(x) + " (" + STRINGIZE(__LINE__) + ")").c_str()
#define TET_UNDEF 2
#define TET_FAIL 1
#define TET_PASS 0
-extern int test_return_value;
+extern int32_t test_return_value;
-void tet_result(int value);
+void tet_result(int32_t value);
#define END_TEST \
- return ((test_return_value>0)?1:0)
+ return ((test_return_value > 0) ? 1 : 0)
void tet_infoline(const char* str);
-void tet_printf(const char *format, ...);
+void tet_printf(const char* format, ...);
/**
* DALI_TEST_CHECK is a wrapper for tet_result.
- * If the condition evaluates to false, then the function & line number is printed.
+ * If the condition evaluates to false, the test is stopped.
* @param[in] The boolean expression to check
*/
-#define DALI_TEST_CHECK(condition) \
-if ( (condition) ) \
-{ \
- tet_result(TET_PASS); \
-} \
-else \
-{ \
- fprintf(stderr, "%s Failed in %s at line %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__); \
- tet_result(TET_FAIL); \
-}
-
-template <typename Type>
-inline bool CompareType(Type value1, Type value2, float epsilon);
-
-/**
- * A helper for fuzzy-comparing Vector2 objects
- * @param[in] vector1 the first object
- * @param[in] vector2 the second object
- * @param[in] epsilon difference threshold
- * @returns true if difference is smaller than epsilon threshold, false otherwise
- */
-template <>
-inline bool CompareType<float>(float value1, float value2, float epsilon)
-{
- return fabsf(value1 - value2) < epsilon;
-}
-
-/**
- * A helper for fuzzy-comparing Vector2 objects
- * @param[in] vector1 the first object
- * @param[in] vector2 the second object
- * @param[in] epsilon difference threshold
- * @returns true if difference is smaller than epsilon threshold, false otherwise
- */
-template <>
-inline bool CompareType<Vector2>(Vector2 vector1, Vector2 vector2, float epsilon)
-{
- return fabsf(vector1.x - vector2.x)<epsilon && fabsf(vector1.y - vector2.y)<epsilon;
-}
-
-/**
- * A helper for fuzzy-comparing Vector3 objects
- * @param[in] vector1 the first object
- * @param[in] vector2 the second object
- * @param[in] epsilon difference threshold
- * @returns true if difference is smaller than epsilon threshold, false otherwise
- */
-template <>
-inline bool CompareType<Vector3>(Vector3 vector1, Vector3 vector2, float epsilon)
-{
- return fabsf(vector1.x - vector2.x)<epsilon &&
- fabsf(vector1.y - vector2.y)<epsilon &&
- fabsf(vector1.z - vector2.z)<epsilon;
-}
+#define DALI_TEST_CHECK(condition) \
+ if((condition)) \
+ { \
+ tet_result(TET_PASS); \
+ } \
+ else \
+ { \
+ fprintf(stderr, "Test failed in %s, condition: %s\n", __FILELINE__, #condition); \
+ tet_result(TET_FAIL); \
+ throw("TET_FAIL"); \
+ }
+bool operator==(TimePeriod a, TimePeriod b);
+std::ostream& operator<<(std::ostream& ostream, TimePeriod value);
+std::ostream& operator<<(std::ostream& ostream, Radian angle);
+std::ostream& operator<<(std::ostream& ostream, Degree angle);
/**
- * A helper for fuzzy-comparing Vector4 objects
- * @param[in] vector1 the first object
- * @param[in] vector2 the second object
- * @param[in] epsilon difference threshold
- * @returns true if difference is smaller than epsilon threshold, false otherwise
+ * Test whether two values are equal.
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
*/
-template <>
-inline bool CompareType<Vector4>(Vector4 vector1, Vector4 vector2, float epsilon)
-{
- return fabsf(vector1.x - vector2.x)<epsilon &&
- fabsf(vector1.y - vector2.y)<epsilon &&
- fabsf(vector1.z - vector2.z)<epsilon &&
- fabsf(vector1.w - vector2.w)<epsilon;
-}
-
-template <>
-inline bool CompareType<Quaternion>(Quaternion q1, Quaternion q2, float epsilon)
-{
- Quaternion q2N = -q2; // These quaternions represent the same rotation
- return CompareType<Vector4>(q1.mVector, q2.mVector, epsilon) || CompareType<Vector4>(q1.mVector, q2N.mVector, epsilon);
-}
-
-template <>
-inline bool CompareType<Radian>(Radian q1, Radian q2, float epsilon)
-{
- return CompareType<float>(float(q1), float(q2), epsilon);
-}
-
-template <>
-inline bool CompareType<Degree>(Degree q1, Degree q2, float epsilon)
+template<typename Type>
+inline void DALI_TEST_EQUALS(Type value1, Type value2, const char* location)
{
- return CompareType<float>(float(q1), float(q2), epsilon);
+ if(!CompareType<Type>(value1, value2, 0.01f))
+ {
+ std::ostringstream o;
+ o << value1 << " == " << value2 << std::endl;
+ fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
+ tet_result(TET_FAIL);
+ throw("TET_FAIL");
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
}
-bool operator==(TimePeriod a, TimePeriod b);
-std::ostream& operator<< (std::ostream& o, const TimePeriod value);
-
/**
* Test whether two values are equal.
* @param[in] value1 The first value
* @param[in] value2 The second value
- * @param[in] location The TEST_LOCATION macro should be used here
*/
-template<typename TypeA, typename TypeB>
-inline void DALI_TEST_EQUALS(TypeA value1, TypeB value2, const char* location)
+#define DALI_TEST_EQUAL(v1, v2) DALI_TEST_EQUALS(v1, v2, __FILELINE__)
+
+template<typename Type>
+inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location)
{
- if (!(value1 == value2))
+ if(!CompareType<Type>(value1, value2, epsilon))
{
std::ostringstream o;
o << value1 << " == " << value2 << std::endl;
- fprintf(stderr, "%s, checking %s", location, o.str().c_str());
+ fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
tet_result(TET_FAIL);
+ throw("TET_FAIL");
}
else
{
}
template<typename Type>
-inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location)
+inline void DALI_TEST_NOT_EQUALS(Type value1, Type value2, float epsilon, const char* location)
{
- if( !CompareType<Type>(value1, value2, epsilon) )
+ if(CompareType<Type>(value1, value2, epsilon))
{
std::ostringstream o;
- o << value1 << " == " << value2 << std::endl;
- fprintf(stderr, "%s, checking %s", location, o.str().c_str());
+ o << value1 << " != " << value2 << std::endl;
+ fprintf(stderr, "Test failed in %s, checking %s", location, o.str().c_str());
tet_result(TET_FAIL);
+ throw("TET_FAIL");
}
else
{
* @param[in] location The TEST_LOCATION macro should be used here
*/
template<>
-inline void DALI_TEST_EQUALS<TimePeriod>( TimePeriod value1, TimePeriod value2, float epsilon, const char* location)
+inline void DALI_TEST_EQUALS<TimePeriod>(TimePeriod value1, TimePeriod value2, float epsilon, const char* location)
{
- if ((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon))
+ if((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon))
{
- fprintf(stderr, "%s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon);
+ fprintf(stderr, "Test failed in %s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon);
tet_result(TET_FAIL);
+ throw("TET_FAIL");
}
- else if ((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon))
+ else if((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon))
{
- fprintf(stderr, "%s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon);
+ fprintf(stderr, "Test failed in %s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon);
tet_result(TET_FAIL);
+ throw("TET_FAIL");
}
else
{
}
/**
+ * Test whether two base handles are equal.
+ * @param[in] baseHandle1 The first value
+ * @param[in] baseHandle2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS(const BaseHandle& baseHandle1, const BaseHandle& baseHandle2, const char* location);
+
+/**
+ * Test whether a size_t value and an uint32_t are equal.
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS(const size_t value1, const uint32_t value2, const char* location);
+
+/**
+ * Test whether an uint32_t and a size_t value and are equal.
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS(const uint32_t value1, const size_t value2, const char* location);
+
+/**
* Test whether two Matrix3 objects are equal.
* @param[in] matrix1 The first object
* @param[in] matrix2 The second object
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const char* location);
+void DALI_TEST_EQUALS(const Matrix3& matrix1, const Matrix3& matrix2, const char* location);
/** Test whether two Matrix3 objects are equal (fuzzy compare).
* @param[in] matrix1 The first object
* @param[in] epsilon The epsilon to use for comparison
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location);
+void DALI_TEST_EQUALS(const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location);
/**
* Test whether two Matrix objects are equal.
* @param[in] matrix2 The second object
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, const char* location);
+void DALI_TEST_EQUALS(const Matrix& matrix1, const Matrix& matrix2, const char* location);
/**
* Test whether two Matrix objects are equal (fuzzy-compare).
* @param[in] matrix2 The second object
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location);
+void DALI_TEST_EQUALS(const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location);
/**
* Test whether two strings are equal.
* @param[in] location The TEST_LOCATION macro should be used here
*/
template<>
-inline void DALI_TEST_EQUALS<const char*>( const char* str1, const char* str2, const char* location)
+inline void DALI_TEST_EQUALS<const char*>(const char* str1, const char* str2, const char* location)
{
- if (strcmp(str1, str2))
+ if(strcmp(str1, str2))
{
- fprintf(stderr, "%s, checking '%s' == '%s'\n", location, str1, str2);
+ fprintf(stderr, "Test failed in %s, checking '%s' == '%s'\n", location, str1, str2);
tet_result(TET_FAIL);
+ throw("TET_FAIL");
}
else
{
* @param[in] location The TEST_LOCATION macro should be used here
*/
template<>
-inline void DALI_TEST_EQUALS<const std::string&>( const std::string &str1, const std::string &str2, const char* location)
+inline void DALI_TEST_EQUALS<const std::string&>(const std::string& str1, const std::string& str2, const char* location)
{
DALI_TEST_EQUALS(str1.c_str(), str2.c_str(), location);
}
* @param[in] str2 The second string
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* location);
+void DALI_TEST_EQUALS(Property::Value& str1, const char* str2, const char* location);
/**
* Test whether two strings are equal.
* @param[in] str2 The second string
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location);
+void DALI_TEST_EQUALS(const std::string& str1, const char* str2, const char* location);
/**
- * Test whether one unsigned integer value is greater than another.
- * Test succeeds if value1 > value2
- * @param[in] value1 The first value
- * @param[in] value2 The second value
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_GREATER(unsigned int value1, unsigned int value2, const char* location);
+void DALI_TEST_EQUALS(const char* str1, const std::string& str2, const char* location);
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<>
+inline void DALI_TEST_EQUALS<const std::string_view>(std::string_view str1, std::string_view str2, const char* location)
+{
+ DALI_TEST_EQUALS(str1.data(), str2.data(), location);
+}
+
+inline void DALI_TEST_EQUALS(std::string_view str1, const char* str2, const char* location)
+{
+ DALI_TEST_EQUALS(str1.data(), str2, location);
+}
+
+inline void DALI_TEST_EQUALS(std::string_view str1, const std::string& str2, const char* location)
+{
+ DALI_TEST_EQUALS(str1.data(), str2.c_str(), location);
+}
+
+inline void DALI_TEST_EQUALS(const std::string& str2, std::string_view str1, const char* location)
+{
+ DALI_TEST_EQUALS(str2.c_str(), str1.data(), location);
+}
+
+inline void DALI_TEST_EQUALS(const char* str1, std::string_view str2, const char* location)
+{
+ DALI_TEST_EQUALS(str1, str2.data(), location);
+}
+
+/**
+ * Test if a property value type is equal to a trivial type.
+ */
+template<typename Type>
+inline void DALI_TEST_VALUE_EQUALS(Property::Value&& value1, Type value2, float epsilon, const char* location)
+{
+ Property::Value value2b(value2);
+ DALI_TEST_EQUALS(value1, value2b, epsilon, location);
+}
/**
- * Test whether one float value is greater than another.
+ * Test whether one unsigned integer value is greater than another.
* Test succeeds if value1 > value2
* @param[in] value1 The first value
* @param[in] value2 The second value
* @param[in] location The TEST_LOCATION macro should be used here
*/
-void DALI_TEST_GREATER( float value1, float value2, const char* location);
+template<typename T>
+void DALI_TEST_GREATER(T value1, T value2, const char* location)
+{
+ if(!(value1 > value2))
+ {
+ std::cerr << "Test failed in " << location << ", checking " << value1 << " > " << value2 << "\n";
+ tet_result(TET_FAIL);
+ throw("TET_FAIL");
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
+}
/**
* Test whether the assertion condition that failed and thus triggered the
* assertion which triggered the exception.
* @param[in] location The TEST_LOCATION macro should be used here.
*/
-void DALI_TEST_ASSERT( DaliException& e, std::string conditionSubString, const char* location );
+void DALI_TEST_ASSERT(DaliException& e, std::string conditionSubString, const char* location);
/**
* Print the assert
* @param[in] e The exception that we expect was fired by a runtime assertion failure.
*/
-inline void DALI_TEST_PRINT_ASSERT( DaliException& e )
+inline void DALI_TEST_PRINT_ASSERT(DaliException& e)
{
- tet_printf("Assertion %s failed at %s\n", e.condition, e.location );
+ tet_printf("Assertion %s failed at %s\n", e.condition, e.location);
}
+/**
+ * Test that given piece of code triggers the right assertion
+ * Fails the test if the assert didn't occur.
+ * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
+ * @param expressions code to execute
+ * @param assertstring the substring expected in the assert
+ */
+#define DALI_TEST_ASSERTION(expressions, assertstring) \
+ try \
+ { \
+ TestApplication::EnableLogging(false); \
+ expressions; \
+ TestApplication::EnableLogging(true); \
+ fprintf(stderr, "Test failed in %s, expected assert: '%s' didn't occur\n", __FILELINE__, assertstring); \
+ tet_result(TET_FAIL); \
+ throw("TET_FAIL"); \
+ } \
+ catch(Dali::DaliException & e) \
+ { \
+ DALI_TEST_ASSERT(e, assertstring, TEST_LOCATION); \
+ }
+
+/**
+ * Test that given piece of code triggers an exception
+ * Fails the test if the exception didn't occur.
+ * Turns off logging during the execution of the code to avoid excessive false positive log output from the assertions
+ * @param expressions code to execute
+ * @param except the exception expected in the assert
+ */
+#define DALI_TEST_THROWS(expressions, except) \
+ try \
+ { \
+ TestApplication::EnableLogging(false); \
+ expressions; \
+ TestApplication::EnableLogging(true); \
+ fprintf(stderr, "Test failed in %s, expected exception: '%s' didn't occur\n", __FILELINE__, #except); \
+ tet_result(TET_FAIL); \
+ throw("TET_FAIL"); \
+ } \
+ catch(except&) \
+ { \
+ tet_result(TET_PASS); \
+ } \
+ catch(...) \
+ { \
+ fprintf(stderr, "Test failed in %s, unexpected exception\n", __FILELINE__); \
+ tet_result(TET_FAIL); \
+ throw; \
+ }
+
// Functor to test whether an Applied signal is emitted
struct ConstraintAppliedCheck
{
- ConstraintAppliedCheck( bool& signalReceived );
- void operator()( Constraint& constraint );
- void Reset();
- void CheckSignalReceived();
- void CheckSignalNotReceived();
+ ConstraintAppliedCheck(bool& signalReceived);
+ void operator()(Constraint& constraint);
+ void Reset();
+ void CheckSignalReceived();
+ void CheckSignalNotReceived();
bool& mSignalReceived; // owned by individual tests
};
/**
* A Helper to test default functions
*/
-template <typename T>
+template<typename T>
struct DefaultFunctionCoverage
{
DefaultFunctionCoverage()
{
- T a;
- T *b = new T(a);
+ T a;
+ T* b = new T(a);
DALI_TEST_CHECK(b);
a = *b;
delete b;
}
};
+// Test namespace to prevent pollution of Dali namespace, add Test helper functions here
+namespace Test
+{
+/**
+ * @brief
+ *
+ * Helper to check object destruction occurred
+ * 1) In main part of code create an ObjectDestructionTracker
+ * 2) Within sub section of main create object Actor test and call Start with Actor to test for destruction
+ * 3) Perform code which is expected to destroy Actor
+ * 4) Back in main part of code use IsDestroyed() to test if Actor was destroyed
+ */
+class ObjectDestructionTracker : public ConnectionTracker
+{
+public:
+ /**
+ * @brief Call in main part of code
+ * @param[in] objectRegistry The object Registry being used
+ */
+ ObjectDestructionTracker(ObjectRegistry objectRegistry);
+
+ /**
+ * @brief Call in sub bock of code where the Actor being checked is still alive.
+ *
+ * @param[in] actor Actor to be checked for destruction
+ */
+ void Start(Actor actor);
+
+ /**
+ * @brief Call to check if Actor alive or destroyed.
+ *
+ * @return bool true if Actor was destroyed
+ */
+ bool IsDestroyed();
+
+private:
+ ObjectRegistry mObjectRegistry;
+ bool mRefObjectDestroyed;
+};
-// Helper to Create bitmap image
-BufferImage CreateBufferImage();
-BufferImage CreateBufferImage(int width, int height, const Vector4& color);
-
+} // namespace Test
-#endif // __DALI_TEST_SUITE_UTILS_H__
+#endif // DALI_TEST_SUITE_UTILS_H