From 57b86c07622643ab83be5a64da14806108939a23 Mon Sep 17 00:00:00 2001 From: Seiji Emery Date: Tue, 23 Jun 2015 15:27:49 -0700 Subject: [PATCH] Added docs for QTestExtensions.h --- tests/QTestExtensions.hpp | 184 ++++++++--- tests/shared/src/AngularConstraintTests.h | 2 +- tests/shared/src/MovingMinMaxAvgTests.cpp | 366 +++++++++++----------- tests/shared/src/MovingMinMaxAvgTests.h | 22 +- 4 files changed, 336 insertions(+), 238 deletions(-) diff --git a/tests/QTestExtensions.hpp b/tests/QTestExtensions.hpp index e29ba9d426..da70db6472 100644 --- a/tests/QTestExtensions.hpp +++ b/tests/QTestExtensions.hpp @@ -9,36 +9,51 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - #ifndef hifi_QTestExtensions_hpp #define hifi_QTestExtensions_hpp #include #include -// Adds some additional functionality to QtTest (eg. explicitely defined fuzzy comparison -// of float and custom data types), and some extension mechanisms to provide other -// test functionality as needed. - -// QFUZZY_COMPARE (actual_expr, expected_expr, epsilon / error tolerance): -// Requires that you have two functions defined: +// Implements several extensions to QtTest. // -// V fuzzyCompare (const T & a, const T & b) -// QTextStream & operator << (const T & v) +// Problems with QtTest: +// - QCOMPARE can compare float values (using a fuzzy compare), but uses an internal threshold +// that cannot be set explicitely (and we need explicit, adjustable error thresholds for our physics +// and math test code). +// - QFAIL takes a const char * failure message, and writing custom messages to it is complicated. // -// fuzzyCompare should take a data type, T, and return the difference between two -// such values / objects in terms of a second type, V (which should match the error -// value type). For glm::vec3, T = glm::vec3, V = float, for example +// To solve this, we have: +// - QFUZZY_COMPARE (compares floats, or *any other type* using explicitely defined error thresholds. +// To use it, you need to have a fuzzyCompare function ((T, T) -> V), and operator << for QTextStream). +// - QFAIL_WITH_MESSAGE("some " << streamed << " message"), which builds, writes to, and stringifies +// a QTextStream using black magic. +// - QCOMPARE_WITH_LAMBDA / QCOMPARE_WITH_FUNCTION, which implements QCOMPARE, but with a user-defined +// test function ((T, T) -> bool). +// - A simple framework to write additional custom test macros as needed (QCOMPARE is reimplemented +// from scratch using QTest::qFail, for example). // -// Generic function that reimplements the debugging output of a QCOMPARE failure via QFAIL. -// Use this to implement your own QCOMPARE-ish macros (see QEXPLICIT_FUZZY_COMPARE for -// more info). -// This version provides a callback to write additional messages. -// If the messages span more than one line, wrap them with '\n\t' to get proper indentation. + +// Generates a QCOMPARE-style failure message that can be passed to QTest::qFail. +// +// Formatting looks like this: +// +// Actual: () : +// Expected: (): +// < additional messages (should be separated by "\n\t" for indent formatting)> +// Loc: [()] +// +// Additional messages (after actual/expected) can be written using the std::function callback. +// If these messages span more than one line, wrap them with "\n\t" to get proper indentation / formatting) +// template -inline QString QTest_generateCompareFailureMessage (const char * failMessage, const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, std::function writeAdditionalMessages) -{ +inline QString QTest_generateCompareFailureMessage ( + const char * failMessage, + const T & actual, const T & expected, + const char * actual_expr, const char * expected_expr, + std::function writeAdditionalMessages +) { QString s1 = actual_expr, s2 = expected_expr; int pad1_ = qMax(s2.length() - s1.length(), 0); int pad2_ = qMax(s1.length() - s2.length(), 0); @@ -55,9 +70,21 @@ inline QString QTest_generateCompareFailureMessage (const char * failMessage, co return msg; } +// Generates a QCOMPARE-style failure message that can be passed to QTest::qFail. +// +// Formatting looks like this: +// +// Actual: () : +// Expected: (): +// Loc: [()] +// (no message callback) +// template -inline QString QTest_generateCompareFailureMessage (const char * failMessage, const T & actual, const T & expected, const char * actual_expr, const char * expected_expr) -{ +inline QString QTest_generateCompareFailureMessage ( + const char * failMessage, + const T & actual, const T & expected, + const char * actual_expr, const char * expected_expr +) { QString s1 = actual_expr, s2 = expected_expr; int pad1_ = qMax(s2.length() - s1.length(), 0); int pad2_ = qMax(s1.length() - s2.length(), 0); @@ -73,7 +100,8 @@ inline QString QTest_generateCompareFailureMessage (const char * failMessage, co return msg; } -// Why does qt have to make things so complicated...? +// Hacky function that can assemble a QString from a QTextStream via a callback +// (ie. stream operations w/out qDebug()) inline QString makeMessageFromStream (std::function writeMessage) { QString msg; QTextStream stream(&msg); @@ -81,83 +109,137 @@ inline QString makeMessageFromStream (std::function writeMe return msg; } -inline void QTest_failWithCustomMessage (std::function writeMessage, int line, const char *file) -{ +inline void QTest_failWithCustomMessage ( + std::function writeMessage, int line, const char *file +) { QTest::qFail(qPrintable(makeMessageFromStream(writeMessage)), file, line); } +// Equivalent to QFAIL, but takes a message that can be formatted using stream operators. +// Writes to a QTextStream internally, and calls QTest::qFail (the internal impl of QFAIL, +// with the current file and line number) +// +// example: +// inline void foo () { +// int thing = 2; +// QFAIL_WITH_MESSAGE("Message " << thing << ";"); +// } +// #define QFAIL_WITH_MESSAGE(...) \ do { \ QTest_failWithCustomMessage([&](QTextStream& stream) { stream << __VA_ARGS__; }, __LINE__, __FILE__); \ return; \ } while(0) -inline void foo () { - int thing = 2; - QFAIL_WITH_MESSAGE("Message " << thing << ";"); -} - - - -// Generates a QCOMPARE style failure message with custom arguments. -// This is expected to be wrapped in a macro (see QFUZZY_COMPARE), and it must -// actually return on failure (unless other functionality is desired). +// Calls qFail using QTest_generateCompareFailureMessage. +// This is (usually) wrapped in macros, but if you call this directly you should return immediately to get QFAIL semantics. template -inline void QTest_failWithMessage(const char * failMessage, const T & actual, const T & expected, const char * actualExpr, const char * expectedExpr, int line, const char * file) -{ +inline void QTest_failWithMessage( + const char * failMessage, + const T & actual, const T & expected, + const char * actualExpr, const char * expectedExpr, + int line, const char * file +) { QTest::qFail(qPrintable(QTest_generateCompareFailureMessage(failMessage, actual, expected, actualExpr, expectedExpr)), file, line); } -// Generates a QCOMPARE style failure message with custom arguments. -// Writing additional lines (eg:) -// Actual (): -// Expected (): -// -// Loc: [()] -// is provided via a lamdbda / closure that can write to the textstream. -// Be aware that newlines are actually "\n\t" (with this impl), so use that to get -// proper indenting (and add extra '\t's to get additional indentation). +// Calls qFail using QTest_generateCompareFailureMessage. +// This is (usually) wrapped in macros, but if you call this directly you should return immediately to get QFAIL semantics. template -inline void QTest_failWithMessage(const char * failMessage, const T & actual, const T & expected, const char * actualExpr, const char * expectedExpr, int line, const char * file, std::function writeAdditionalMessageLines) { +inline void QTest_failWithMessage( + const char * failMessage, + const T & actual, const T & expected, + const char * actualExpr, const char * expectedExpr, + int line, const char * file, + std::function writeAdditionalMessageLines +) { QTest::qFail(qPrintable(QTest_generateCompareFailureMessage(failMessage, actual, expected, actualExpr, expectedExpr, writeAdditionalMessageLines)), file, line); } +// Implements QFUZZY_COMPARE template inline auto QTest_fuzzyCompare(const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, int line, const char * file, const V & epsilon) -> decltype(fuzzyCompare(actual, expected)) { if (fuzzyCompare(actual, expected) > epsilon) { - QTest::qFail(qPrintable(QTest_generateCompareFailureMessage( + QTest_failWithMessage( "Compared values are not the same (fuzzy compare)", - actual, expected, actual_expr, expected_expr, + actual, expected, actual_expr, expected_expr, line, file, [&] (QTextStream & stream) -> QTextStream & { return stream << "Err tolerance: " << fuzzyCompare((actual), (expected)) << " > " << epsilon; - })), file, line); + }); return false; } return true; } +// Implements a fuzzy QCOMPARE using an explicit epsilon error value. +// If you use this, you must have the following functions defined for the types you're using: +// V fuzzyCompare (const T& a, const T& b) (should return the absolute, max difference between a and b) +// QTextStream & operator << (QTextStream& stream, const T& value) +// +// Here's an implementation for glm::vec3: +// inline float fuzzyCompare (const glm::vec3 & a, const glm::vec3 & b) { // returns +// return glm::distance(a, b); +// } +// inline QTextStream & operator << (QTextStream & stream, const T & v) { +// return stream << "glm::vec3 { " << v.x << ", " << v.y << ", " << v.z << " }" +// } +// #define QFUZZY_COMPARE(actual, expected, epsilon) \ do { \ if (!QTest_fuzzyCompare(actual, expected, #actual, #expected, __LINE__, __FILE__, epsilon)) \ return; \ } while(0) +// Implements QCOMPARE using an explicit, externally defined test function. +// The advantage of this (over a manual check or what have you) is that the values of actual and +// expected are printed in the event that the test fails. +// +// testFunc(const T & actual, const T & expected) -> bool: true (test succeeds) | false (test fails) +// #define QCOMPARE_WITH_FUNCTION(actual, expected, testFunc) \ do { \ if (!testFunc(actual, expected)) { \ QTest_failWithMessage("Compared values are not the same", actual, expected, #actual, #expected, __LINE__, __FILE__); \ return; \ } \ -while (0) +} while (0) +// Implements QCOMPARE using an explicit, externally defined test function. +// Unlike QCOMPARE_WITH_FUNCTION, this func / closure takes no arguments (which is much more convenient +// if you're using a c++11 closure / lambda). +// +// usage: +// QCOMPARE_WITH_LAMBDA(foo, expectedFoo, [&foo, &expectedFoo] () { +// return foo->isFooish() && foo->fooishness() >= expectedFoo->fooishness(); +// }); +// (fails if foo is not as fooish as expectedFoo) +// #define QCOMPARE_WITH_LAMBDA(actual, expected, testClosure) \ do { \ if (!testClosure()) \ QTest_failWithMessage("Compared values are not the same", actual, expected, #actual, #expected, __LINE__, __FILE__); \ return; \ } \ -while (0) +} while (0) + +// Same as QCOMPARE_WITH_FUNCTION, but with a custom fail message +#define QCOMPARE_WITH_FUNCTION_AND_MESSAGE(actual, expected, testfunc, failMessage) \ +do { \ + if (!testFunc(actual, expected)) { \ + QTest_failWithMessage(failMessage, actual, expected, #actual, #expected, __LINE__, __FILE__); \ + return; \ + } \ +} while (0) + +// Same as QCOMPARE_WITH_FUNCTION, but with a custom fail message +#define QCOMPARE_WITH_LAMBDA(actual, expected, testClosure, failMessage) \ + do { \ + if (!testClosure()) \ + QTest_failWithMessage(failMessage, actual, expected, #actual, #expected, __LINE__, __FILE__); \ + return; \ + } \ +} while (0) #endif diff --git a/tests/shared/src/AngularConstraintTests.h b/tests/shared/src/AngularConstraintTests.h index 4eb6a8eec4..ea950471cd 100644 --- a/tests/shared/src/AngularConstraintTests.h +++ b/tests/shared/src/AngularConstraintTests.h @@ -21,7 +21,7 @@ private slots: void testConeRollerConstraint(); }; -// Enable QFUZZY_COMPARE for glm::quat +// Use QFUZZY_COMPARE and define it for glm::quat #include float fuzzyCompare (const glm::quat & a, const glm::quat & b); QTextStream & operator << (QTextStream & stream, const glm::quat & q); diff --git a/tests/shared/src/MovingMinMaxAvgTests.cpp b/tests/shared/src/MovingMinMaxAvgTests.cpp index ef1717d5d8..d5e5ed2883 100644 --- a/tests/shared/src/MovingMinMaxAvgTests.cpp +++ b/tests/shared/src/MovingMinMaxAvgTests.cpp @@ -24,199 +24,203 @@ quint64 MovingMinMaxAvgTests::randQuint64() { return ret; } -void MovingMinMaxAvgTests::runAllTests() { - { - // quint64 test +void MovingMinMaxAvgTests::testQuint64() { + // quint64 test - const int INTERVAL_LENGTH = 100; - const int WINDOW_INTERVALS = 50; + const int INTERVAL_LENGTH = 100; + const int WINDOW_INTERVALS = 50; - MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); + MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); - quint64 min = std::numeric_limits::max(); - quint64 max = 0; - double average = 0.0; - int totalSamples = 0; + quint64 min = std::numeric_limits::max(); + quint64 max = 0; + double average = 0.0; + int totalSamples = 0; - quint64 windowMin; - quint64 windowMax; - double windowAverage; + quint64 windowMin; + quint64 windowMax; + double windowAverage; - QQueue windowSamples; - // fill window samples - for (int i = 0; i < 100000; i++) { + QQueue windowSamples; + // fill window samples + for (int i = 0; i < 100000; i++) { - quint64 sample = randQuint64(); + quint64 sample = randQuint64(); - windowSamples.enqueue(sample); - if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { - windowSamples.dequeue(); + windowSamples.enqueue(sample); + if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { + windowSamples.dequeue(); + } + + stats.update(sample); + + min = std::min(min, sample); + max = std::max(max, sample); + average = (average * totalSamples + sample) / (totalSamples + 1); + totalSamples++; + + QCOMPARE(stats.getMin(), min); + QCOMPARE(stats.getMax(), max); + + QFUZZY_COMPARE((float) stats.getAverage() / (float) average, 1.0f, EPSILON); + QFUZZY_COMPARE((float) stats.getAverage(), (float) average, EPSILON); + +// QCOMPARE(fabsf( +// (float)stats.getAverage() / (float)average - 1.0f +// ) < EPSILON || +// fabsf( +// (float)stats.getAverage() - (float)average) < EPSILON); + + if ((i + 1) % INTERVAL_LENGTH == 0) { + + assert(stats.getNewStatsAvailableFlag()); + stats.clearNewStatsAvailableFlag(); + + windowMin = std::numeric_limits::max(); + windowMax = 0; + windowAverage = 0.0; + foreach(quint64 s, windowSamples) { + windowMin = std::min(windowMin, s); + windowMax = std::max(windowMax, s); + windowAverage += (double)s; } + windowAverage /= (double)windowSamples.size(); - stats.update(sample); - - min = std::min(min, sample); - max = std::max(max, sample); - average = (average * totalSamples + sample) / (totalSamples + 1); - totalSamples++; - - assert(stats.getMin() == min); - assert(stats.getMax() == max); + assert(stats.getWindowMin() == windowMin); + assert(stats.getWindowMax() == windowMax); assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON || fabsf((float)stats.getAverage() - (float)average) < EPSILON); - if ((i + 1) % INTERVAL_LENGTH == 0) { - - assert(stats.getNewStatsAvailableFlag()); - stats.clearNewStatsAvailableFlag(); - - windowMin = std::numeric_limits::max(); - windowMax = 0; - windowAverage = 0.0; - foreach(quint64 s, windowSamples) { - windowMin = std::min(windowMin, s); - windowMax = std::max(windowMax, s); - windowAverage += (double)s; - } - windowAverage /= (double)windowSamples.size(); - - assert(stats.getWindowMin() == windowMin); - assert(stats.getWindowMax() == windowMax); - assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON || - fabsf((float)stats.getAverage() - (float)average) < EPSILON); - - } else { - assert(!stats.getNewStatsAvailableFlag()); - } + } else { + assert(!stats.getNewStatsAvailableFlag()); + } + } +} + +void MovingMinMaxAvgTests::testInt() { + // int test + + const int INTERVAL_LENGTH = 1; + const int WINDOW_INTERVALS = 75; + + MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); + + int min = std::numeric_limits::max(); + int max = 0; + double average = 0.0; + int totalSamples = 0; + + int windowMin; + int windowMax; + double windowAverage; + + QQueue windowSamples; + // fill window samples + for (int i = 0; i < 100000; i++) { + + int sample = rand(); + + windowSamples.enqueue(sample); + if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { + windowSamples.dequeue(); + } + + stats.update(sample); + + min = std::min(min, sample); + max = std::max(max, sample); + average = (average * totalSamples + sample) / (totalSamples + 1); + totalSamples++; + + assert(stats.getMin() == min); + assert(stats.getMax() == max); + assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); + + if ((i + 1) % INTERVAL_LENGTH == 0) { + + assert(stats.getNewStatsAvailableFlag()); + stats.clearNewStatsAvailableFlag(); + + windowMin = std::numeric_limits::max(); + windowMax = 0; + windowAverage = 0.0; + foreach(int s, windowSamples) { + windowMin = std::min(windowMin, s); + windowMax = std::max(windowMax, s); + windowAverage += (double)s; + } + windowAverage /= (double)windowSamples.size(); + + assert(stats.getWindowMin() == windowMin); + assert(stats.getWindowMax() == windowMax); + assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); + + } else { + assert(!stats.getNewStatsAvailableFlag()); + } + } +} + +void MovingMinMaxAvgTests::testFloat() { + // float test + + const int INTERVAL_LENGTH = 57; + const int WINDOW_INTERVALS = 1; + + MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); + + float min = std::numeric_limits::max(); + float max = 0; + double average = 0.0; + int totalSamples = 0; + + float windowMin; + float windowMax; + double windowAverage; + + QQueue windowSamples; + // fill window samples + for (int i = 0; i < 100000; i++) { + + float sample = randFloat(); + + windowSamples.enqueue(sample); + if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { + windowSamples.dequeue(); + } + + stats.update(sample); + + min = std::min(min, sample); + max = std::max(max, sample); + average = (average * totalSamples + (double)sample) / (totalSamples + 1); + totalSamples++; + + assert(stats.getMin() == min); + assert(stats.getMax() == max); + assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); + + if ((i + 1) % INTERVAL_LENGTH == 0) { + + assert(stats.getNewStatsAvailableFlag()); + stats.clearNewStatsAvailableFlag(); + + windowMin = std::numeric_limits::max(); + windowMax = 0; + windowAverage = 0.0; + foreach(float s, windowSamples) { + windowMin = std::min(windowMin, s); + windowMax = std::max(windowMax, s); + windowAverage += (double)s; + } + windowAverage /= (double)windowSamples.size(); + + assert(stats.getWindowMin() == windowMin); + assert(stats.getWindowMax() == windowMax); + assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); + + } else { + assert(!stats.getNewStatsAvailableFlag()); } } - - { - // int test - - const int INTERVAL_LENGTH = 1; - const int WINDOW_INTERVALS = 75; - - MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); - - int min = std::numeric_limits::max(); - int max = 0; - double average = 0.0; - int totalSamples = 0; - - int windowMin; - int windowMax; - double windowAverage; - - QQueue windowSamples; - // fill window samples - for (int i = 0; i < 100000; i++) { - - int sample = rand(); - - windowSamples.enqueue(sample); - if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { - windowSamples.dequeue(); - } - - stats.update(sample); - - min = std::min(min, sample); - max = std::max(max, sample); - average = (average * totalSamples + sample) / (totalSamples + 1); - totalSamples++; - - assert(stats.getMin() == min); - assert(stats.getMax() == max); - assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); - - if ((i + 1) % INTERVAL_LENGTH == 0) { - - assert(stats.getNewStatsAvailableFlag()); - stats.clearNewStatsAvailableFlag(); - - windowMin = std::numeric_limits::max(); - windowMax = 0; - windowAverage = 0.0; - foreach(int s, windowSamples) { - windowMin = std::min(windowMin, s); - windowMax = std::max(windowMax, s); - windowAverage += (double)s; - } - windowAverage /= (double)windowSamples.size(); - - assert(stats.getWindowMin() == windowMin); - assert(stats.getWindowMax() == windowMax); - assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); - - } else { - assert(!stats.getNewStatsAvailableFlag()); - } - } - } - - { - // float test - - const int INTERVAL_LENGTH = 57; - const int WINDOW_INTERVALS = 1; - - MovingMinMaxAvg stats(INTERVAL_LENGTH, WINDOW_INTERVALS); - - float min = std::numeric_limits::max(); - float max = 0; - double average = 0.0; - int totalSamples = 0; - - float windowMin; - float windowMax; - double windowAverage; - - QQueue windowSamples; - // fill window samples - for (int i = 0; i < 100000; i++) { - - float sample = randFloat(); - - windowSamples.enqueue(sample); - if (windowSamples.size() > INTERVAL_LENGTH * WINDOW_INTERVALS) { - windowSamples.dequeue(); - } - - stats.update(sample); - - min = std::min(min, sample); - max = std::max(max, sample); - average = (average * totalSamples + (double)sample) / (totalSamples + 1); - totalSamples++; - - assert(stats.getMin() == min); - assert(stats.getMax() == max); - assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); - - if ((i + 1) % INTERVAL_LENGTH == 0) { - - assert(stats.getNewStatsAvailableFlag()); - stats.clearNewStatsAvailableFlag(); - - windowMin = std::numeric_limits::max(); - windowMax = 0; - windowAverage = 0.0; - foreach(float s, windowSamples) { - windowMin = std::min(windowMin, s); - windowMax = std::max(windowMax, s); - windowAverage += (double)s; - } - windowAverage /= (double)windowSamples.size(); - - assert(stats.getWindowMin() == windowMin); - assert(stats.getWindowMax() == windowMax); - assert(fabsf((float)stats.getAverage() / (float)average - 1.0f) < EPSILON); - - } else { - assert(!stats.getNewStatsAvailableFlag()); - } - } - } - printf("moving min/max/avg test passed!\n"); } diff --git a/tests/shared/src/MovingMinMaxAvgTests.h b/tests/shared/src/MovingMinMaxAvgTests.h index 52a2edf0af..cca7ff4688 100644 --- a/tests/shared/src/MovingMinMaxAvgTests.h +++ b/tests/shared/src/MovingMinMaxAvgTests.h @@ -12,14 +12,26 @@ #ifndef hifi_MovingMinMaxAvgTests_h #define hifi_MovingMinMaxAvgTests_h +#include + +inline float fuzzyCompare (float a, float b) { + return fabsf(a - b); +} + +#include "../QTestExtensions.hpp" + #include "MovingMinMaxAvg.h" #include "SharedUtil.h" -namespace MovingMinMaxAvgTests { - +class MovingMinMaxAvgTests : public QObject { + +private slots: + void testQuint64 (); + void testInt (); + void testFloat (); + +private: quint64 randQuint64(); - - void runAllTests(); -} +}; #endif // hifi_MovingMinMaxAvgTests_h