12 #ifndef hifi_QTestExtensions_hpp
13 #define hifi_QTestExtensions_hpp
15 #include <QtTest/QtTest>
16 #include <QtCore/QFileInfo>
18 #include <NumericalConstants.h>
19 #include <SharedUtil.h>
20 #include "GLMTestUtils.h"
41 float getErrorDifference(
const float& a,
const float& b) {
57 template <
typename T>
inline
58 QString QTest_generateCompareFailureMessage (
59 const char* failMessage,
60 const T& actual,
const T& expected,
61 const char* actual_expr,
const char* expected_expr,
62 std::function<QTextStream& (QTextStream&)> writeAdditionalMessages
64 QString s1 = actual_expr, s2 = expected_expr;
65 int pad1_ = qMax(s2.length() - s1.length(), 0);
66 int pad2_ = qMax(s1.length() - s2.length(), 0);
68 QString pad1 = QString(
")").rightJustified(pad1_,
' ');
69 QString pad2 = QString(
")").rightJustified(pad2_,
' ');
72 QTextStream stream(&msg);
73 stream << failMessage <<
"\n\t"
74 "Actual: (" << actual_expr << pad1 <<
": " << actual <<
"\n\t"
75 "Expected: (" << expected_expr << pad2 <<
": " << expected <<
"\n\t";
76 writeAdditionalMessages(stream);
89 template <
typename T>
inline
90 QString QTest_generateCompareFailureMessage (
91 const char* failMessage,
92 const T& actual,
const T& expected,
93 const char* actual_expr,
const char* expected_expr
95 QString s1 = actual_expr, s2 = expected_expr;
96 int pad1_ = qMax(s2.length() - s1.length(), 0);
97 int pad2_ = qMax(s1.length() - s2.length(), 0);
99 QString pad1 = QString(
"): ").rightJustified(pad1_,
' ');
100 QString pad2 = QString(
"): ").rightJustified(pad2_,
' ');
103 QTextStream stream(&msg);
104 stream << failMessage <<
"\n\t"
105 "Actual: (" << actual_expr << pad1 << actual <<
"\n\t"
106 "Expected: (" << expected_expr << pad2 << expected;
113 QString makeMessageFromStream (std::function<
void(QTextStream&)> writeMessage) {
115 QTextStream stream(&msg);
116 writeMessage(stream);
121 void QTest_failWithCustomMessage (
122 std::function<
void(QTextStream&)> writeMessage,
int line,
const char* file
124 QTest::qFail(qPrintable(makeMessageFromStream(writeMessage)), file, line);
137 #define QFAIL_WITH_MESSAGE(...) \
139 QTest_failWithCustomMessage([&](QTextStream& stream) { stream << __VA_ARGS__; }, __LINE__, __FILE__); \
145 template <
typename T>
inline
146 void QTest_failWithMessage(
147 const char* failMessage,
148 const T& actual,
const T& expected,
149 const char* actualExpr,
const char* expectedExpr,
150 int line,
const char* file
152 QTest::qFail(qPrintable(QTest_generateCompareFailureMessage(
153 failMessage, actual, expected, actualExpr, expectedExpr)), file, line);
158 template <
typename T>
inline
159 void QTest_failWithMessage(
160 const char* failMessage,
161 const T& actual,
const T& expected,
162 const char* actualExpr,
const char* expectedExpr,
163 int line,
const char* file,
164 std::function<QTextStream& (QTextStream&)> writeAdditionalMessageLines
166 QTest::qFail(qPrintable(QTest_generateCompareFailureMessage(
167 failMessage, actual, expected, actualExpr, expectedExpr, writeAdditionalMessageLines)), file, line);
171 template <
typename T,
typename V>
inline
172 bool QTest_compareWithAbsError(
173 const T& actual,
const T& expected,
174 const char* actual_expr,
const char* expected_expr,
175 int line,
const char* file,
178 if (fabsf(getErrorDifference(actual, expected)) > fabsf(epsilon)) {
179 QTest_failWithMessage(
180 "Compared values are not the same (fuzzy compare)",
181 actual, expected, actual_expr, expected_expr, line, file,
182 [&] (QTextStream& stream) -> QTextStream& {
183 return stream <<
"Err tolerance: " << getErrorDifference((actual), (expected)) <<
" > " << epsilon;
203 #define QCOMPARE_WITH_ABS_ERROR(actual, expected, epsilon) \
205 if (!QTest_compareWithAbsError((actual), (expected), #actual, #expected, __LINE__, __FILE__, epsilon)) \
215 #define QCOMPARE_WITH_FUNCTION(actual, expected, testFunc) \
217 if (!(testFunc((actual), (expected)))) { \
218 QTest_failWithMessage("Compared values are not the same", (actual), (expected), #actual, #expected, __LINE__, __FILE__); \
233 #define QCOMPARE_WITH_LAMBDA(actual, expected, testClosure) \
235 if (!(testClosure())) { \
236 QTest_failWithMessage("Compared values are not the same", (actual), (expected), #actual, #expected, __LINE__, __FILE__); \
242 #define QCOMPARE_WITH_FUNCTION_AND_MESSAGE(actual, expected, testfunc, failMessage) \
244 if (!(testFunc((actual), (expected)))) { \
245 QTest_failWithMessage((failMessage), (actual), (expected), #actual, #expected, __LINE__, __FILE__); \
251 #define QCOMPARE_WITH_LAMBDA_AND_MESSAGE(actual, expected, testClosure, failMessage) \
253 if (!(testClosure())) { \
254 QTest_failWithMessage((failMessage), (actual), (expected), #actual, #expected, __LINE__, __FILE__); \
261 #define QCOMPARE_WITH_EXPR(actual, expected, testExpr) \
264 QTest_failWithMessage("Compared values are not the same", (actual), (expected), #actual, #expected, __LINE__, __FILE__); \
269 ByteData (
const char* data,
size_t length)
270 : data(data), length(length) {}
275 QTextStream& operator<<(QTextStream& stream,
const ByteData& wrapper) {
277 stream << QByteArray::fromRawData(wrapper.data, (
int)wrapper.length).toHex();
282 bool compareData(
const char* data,
const char* expectedData,
size_t length) {
283 return memcmp(data, expectedData, length) == 0;
286 #define COMPARE_DATA(actual, expected, length) \
287 QCOMPARE_WITH_EXPR((ByteData(actual, length)), (ByteData(expected, length)), compareData(actual, expected, length))
290 inline auto errorTest (
float actual,
float expected,
float acceptableRelativeError)
291 -> std::function<bool ()> {
292 return [actual, expected, acceptableRelativeError]() {
293 if (fabsf(expected) <= acceptableRelativeError) {
294 return fabsf(actual - expected) < fabsf(acceptableRelativeError);
296 return fabsf((actual - expected) / expected) < fabsf(acceptableRelativeError);
300 #define QCOMPARE_WITH_RELATIVE_ERROR(actual, expected, relativeError) \
301 QCOMPARE_WITH_LAMBDA(actual, expected, errorTest(actual, expected, relativeError))
303 inline QString getTestResource(
const QString& relativePath) {
305 static std::once_flag once;
306 std::call_once(once, [] {
307 QFileInfo fileInfo(__FILE__);
308 auto parentDir = fileInfo.absoluteDir();
309 auto rootDir = parentDir.absoluteFilePath(
"..");
310 dir.setPath(QDir::cleanPath(rootDir));
313 return QDir::cleanPath(dir.absoluteFilePath(relativePath));
316 inline void failAfter(quint64 startUsecs, quint64 secs,
const char* message) {
317 if (afterSecs(startUsecs, secs)) {