diff options
-rw-r--r-- | cmake/expression-test.cmake | 2 | ||||
-rw-r--r-- | cmake/render-test.cmake | 2 | ||||
-rw-r--r-- | expression-test/expression_test_runner.cpp | 110 | ||||
-rw-r--r-- | expression-test/test_runner_common.cpp | 131 | ||||
-rw-r--r-- | expression-test/test_runner_common.hpp | 13 | ||||
-rw-r--r-- | next/expression-test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | next/render-test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | render-test/runner.cpp | 115 |
8 files changed, 155 insertions, 222 deletions
diff --git a/cmake/expression-test.cmake b/cmake/expression-test.cmake index 6c5b71a4f6..da4f90d751 100644 --- a/cmake/expression-test.cmake +++ b/cmake/expression-test.cmake @@ -3,6 +3,8 @@ add_executable(mbgl-expression-test expression-test/expression_test_parser.cpp expression-test/expression_test_runner.cpp expression-test/expression_test_logger.cpp + expression-test/test_runner_common.cpp + expression-test/test_runner_common.hpp ) if(APPLE) diff --git a/cmake/render-test.cmake b/cmake/render-test.cmake index 7369655630..65240b54f3 100644 --- a/cmake/render-test.cmake +++ b/cmake/render-test.cmake @@ -3,6 +3,8 @@ add_executable(mbgl-render-test render-test/main.cpp render-test/parser.cpp render-test/runner.cpp + expression-test/test_runner_common.cpp + expression-test/test_runner_common.hpp ) if(APPLE) diff --git a/expression-test/expression_test_runner.cpp b/expression-test/expression_test_runner.cpp index e52c9b1186..c8a39f07ce 100644 --- a/expression-test/expression_test_runner.cpp +++ b/expression-test/expression_test_runner.cpp @@ -1,7 +1,8 @@ #include "expression_test_runner.hpp" -#include "expression_test_parser.hpp" #include "expression_test_logger.hpp" +#include "expression_test_parser.hpp" #include "filesystem.hpp" +#include "test_runner_common.hpp" #include <mbgl/util/io.hpp> @@ -16,113 +17,6 @@ using namespace std::literals; namespace { -// Strip precision for numbers, so that we can compare evaluated results with fixtures. -// Copied from JS expression harness. -Value stripPrecision(const Value& value) { - const double decimalSigFigs = 6; - if (auto num = numericValue<double>(value)) { - if (*num == 0) { - return *num; - } - - const double multiplier = std::pow(10, - std::max(0.0, decimalSigFigs - std::ceil(std::log10(std::fabs(*num))))); - - // We strip precision twice in a row here to avoid cases where - // stripping an already stripped number will modify its value - // due to bad floating point precision luck - // eg `Math.floor(8.16598 * 100000) / 100000` -> 8.16597 - const double firstStrip = std::floor(*num * multiplier) / multiplier; - return std::floor(firstStrip * multiplier) / multiplier; - } - - if (value.is<std::vector<Value>>()) { - std::vector<Value> stripped; - const auto& vec = value.get<std::vector<Value>>(); - stripped.reserve(vec.size()); - for (const auto& val : vec) { - stripped.emplace_back(stripPrecision(val)); - } - return stripped; - } else if (value.is<std::unordered_map<std::string, Value>>()) { - std::unordered_map<std::string, Value> stripped; - const auto& map = value.get<std::unordered_map<std::string, Value>>(); - for (const auto& pair : map) { - stripped.emplace(pair.first, stripPrecision(pair.second)); - } - return stripped; - } - - return value; -} - -bool deepEqual(const Value& a, const Value& b) { - const auto& anum = numericValue<double>(a); - const auto& bnum = numericValue<double>(b); - if (anum && bnum) { - return stripPrecision(*anum) == stripPrecision(*bnum); - } - - if (a.which() != b.which()) { - return false; - } - - if (a.is<std::vector<Value>>()) { - const auto& avec = a.get<std::vector<Value>>(); - const auto& bvec = b.get<std::vector<Value>>(); - if (avec.size() != bvec.size()) { - return false; - } - for (std::size_t i = 0; i < avec.size(); ++i) { - if (!deepEqual(avec[i], bvec[i])) { - return false; - } - } - return true; - } - - if (a.is<std::unordered_map<std::string, Value>>()) { - const auto& amap = a.get<std::unordered_map<std::string, Value>>(); - const auto& bmap = b.get<std::unordered_map<std::string, Value>>(); - if (amap.size() != bmap.size()) { - return false; - } - for (const auto& pair : amap) { - auto it = bmap.find(pair.first); - if (it == bmap.end()) { - return false; - } - if (!deepEqual(pair.second, it->second)) { - return false; - } - } - return true; - } - - return a == b; -} - -bool deepEqual(const optional<Value>& a, const optional<Value>& b) { - if ((a && !b) || (!a && b)) { - return false; - } - - if (a && b) { - return deepEqual(*a, *b); - } - - return true; -} - -std::vector<std::string> tokenize(std::string str) { - std::vector<std::string> tokens; - std::regex re("\n"); - std::copy(std::regex_token_iterator<std::string::iterator>(str.begin(), str.end(), re, -1), - std::regex_token_iterator<std::string::iterator>(), - std::back_inserter(tokens)); - return tokens; -} - std::string simpleDiff(const Value& result, const Value& expected) { std::vector<std::string> resultTokens {tokenize(toJSON(result, 2, true))}; std::vector<std::string> expectedTokens {tokenize(toJSON(expected, 2, true))}; diff --git a/expression-test/test_runner_common.cpp b/expression-test/test_runner_common.cpp new file mode 100644 index 0000000000..745ef9fced --- /dev/null +++ b/expression-test/test_runner_common.cpp @@ -0,0 +1,131 @@ +#include "test_runner_common.hpp" + +#include <cmath> +#include <regex> + +using namespace mbgl; + +// Strip precision for numbers, so that we can compare evaluated results with fixtures. +// Copied from JS expression harness. +Value stripPrecision(const Value& value) { + const double decimalSigFigs = 6; + if (auto num = numericValue<double>(value)) { + if (*num == 0) { + return *num; + } + + const double multiplier = std::pow(10, std::max(0.0, decimalSigFigs - std::ceil(std::log10(std::fabs(*num))))); + + // We strip precision twice in a row here to avoid cases where + // stripping an already stripped number will modify its value + // due to bad floating point precision luck + // eg `Math.floor(8.16598 * 100000) / 100000` -> 8.16597 + const double firstStrip = std::floor(*num * multiplier) / multiplier; + return std::floor(firstStrip * multiplier) / multiplier; + } + + if (value.is<std::vector<Value>>()) { + std::vector<Value> stripped; + const auto& vec = value.get<std::vector<Value>>(); + stripped.reserve(vec.size()); + for (const auto& val : vec) { + stripped.emplace_back(stripPrecision(val)); + } + return stripped; + } else if (value.is<std::unordered_map<std::string, Value>>()) { + std::unordered_map<std::string, Value> stripped; + const auto& map = value.get<std::unordered_map<std::string, Value>>(); + for (const auto& pair : map) { + stripped.emplace(pair.first, stripPrecision(pair.second)); + } + return stripped; + } + + return value; +} + +std::vector<std::string> tokenize(std::string str) { + std::vector<std::string> tokens; + std::regex re("\n"); + std::copy(std::regex_token_iterator<std::string::iterator>(str.begin(), str.end(), re, -1), + std::regex_token_iterator<std::string::iterator>(), + std::back_inserter(tokens)); + return tokens; +} + +bool deepEqual(const Value& a, const Value& b) { + const auto& anum = numericValue<double>(a); + const auto& bnum = numericValue<double>(b); + if (anum && bnum) { + return stripPrecision(*anum) == stripPrecision(*bnum); + } + + if (a.which() != b.which()) { + return false; + } + + if (a.getArray() && b.getArray()) { + const auto& avec = *a.getArray(); + const auto& bvec = *b.getArray(); + if (avec.size() != bvec.size()) { + return false; + } + for (std::size_t i = 0; i < avec.size(); ++i) { + if (!deepEqual(avec[i], bvec[i])) { + return false; + } + } + return true; + } + + if (a.getObject() && b.getObject()) { + const auto& amap = *a.getObject(); + const auto& bmap = *b.getObject(); + if (amap.size() != bmap.size()) { + return false; + } + for (const auto& pair : amap) { + auto it = bmap.find(pair.first); + if (it == bmap.end()) { + return false; + } + if (!deepEqual(pair.second, it->second)) { + return false; + } + } + return true; + } + + if (a == b) { + return true; + } + + if (a.getString() && b.getString()) { + const auto& strA = *a.getString(); + const auto& strB = *b.getString(); + if (strA == strB) { + return true; + } + + try { + double numA = std::stod(strA); + double numB = std::stod(strB); + return stripPrecision(numA) == stripPrecision(numB); + } catch (...) { + } + } + + return false; +} + +bool deepEqual(const optional<Value>& a, const optional<Value>& b) { + if ((a && !b) || (!a && b)) { + return false; + } + + if (a && b) { + return deepEqual(*a, *b); + } + + return true; +} diff --git a/expression-test/test_runner_common.hpp b/expression-test/test_runner_common.hpp new file mode 100644 index 0000000000..b30d1a145c --- /dev/null +++ b/expression-test/test_runner_common.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <mbgl/util/feature.hpp> + +#include <string> +#include <vector> + +using namespace mbgl; + +Value stripPrecision(const Value& value); +std::vector<std::string> tokenize(std::string str); +bool deepEqual(const Value& a, const Value& b); +bool deepEqual(const optional<Value>& a, const optional<Value>& b); diff --git a/next/expression-test/CMakeLists.txt b/next/expression-test/CMakeLists.txt index 1713f0b655..f7d694b054 100644 --- a/next/expression-test/CMakeLists.txt +++ b/next/expression-test/CMakeLists.txt @@ -6,6 +6,8 @@ add_executable( ${MBGL_ROOT}/expression-test/expression_test_parser.hpp ${MBGL_ROOT}/expression-test/expression_test_runner.cpp ${MBGL_ROOT}/expression-test/expression_test_runner.hpp + ${MBGL_ROOT}/expression-test/test_runner_common.cpp + ${MBGL_ROOT}/expression-test/test_runner_common.hpp ${MBGL_ROOT}/expression-test/main.cpp ) diff --git a/next/render-test/CMakeLists.txt b/next/render-test/CMakeLists.txt index 6edd11ca95..5aadd0f859 100644 --- a/next/render-test/CMakeLists.txt +++ b/next/render-test/CMakeLists.txt @@ -9,6 +9,8 @@ add_executable( ${MBGL_ROOT}/render-test/parser.hpp ${MBGL_ROOT}/render-test/runner.cpp ${MBGL_ROOT}/render-test/runner.hpp + ${MBGL_ROOT}/expression-test/test_runner_common.cpp + ${MBGL_ROOT}/expression-test/test_runner_common.hpp ) target_compile_definitions( diff --git a/render-test/runner.cpp b/render-test/runner.cpp index 868e1a9a32..4d4b586a17 100644 --- a/render-test/runner.cpp +++ b/render-test/runner.cpp @@ -19,6 +19,7 @@ #include <mapbox/pixelmatch.hpp> +#include <../expression-test/test_runner_common.hpp> #include "allocation_index.hpp" #include "metadata.hpp" #include "parser.hpp" @@ -26,7 +27,6 @@ #include <algorithm> #include <cassert> -#include <regex> #include <utility> #include <sstream> @@ -47,119 +47,6 @@ const std::vector<std::string>& TestRunner::getPlatformExpectationsPaths() { return result; } -// Strip precision for numbers, so that we can compare evaluated results with fixtures. -// Copied from JS expression harness. -Value stripPrecision(const Value& value) { - const double decimalSigFigs = 6; - if (auto num = numericValue<double>(value)) { - if (*num == 0) { - return *num; - } - - const double multiplier = std::pow(10, std::max(0.0, decimalSigFigs - std::ceil(std::log10(std::fabs(*num))))); - - // We strip precision twice in a row here to avoid cases where - // stripping an already stripped number will modify its value - // due to bad floating point precision luck - // eg `Math.floor(8.16598 * 100000) / 100000` -> 8.16597 - const double firstStrip = std::floor(*num * multiplier) / multiplier; - return std::floor(firstStrip * multiplier) / multiplier; - } - - if (value.getArray()) { - std::vector<Value> stripped; - const auto& vec = *value.getArray(); - stripped.reserve(vec.size()); - for (const auto& val : vec) { - stripped.emplace_back(stripPrecision(val)); - } - return stripped; - } else if (value.getObject()) { - std::unordered_map<std::string, Value> stripped; - const auto& map = *value.getObject(); - for (const auto& pair : map) { - stripped.emplace(pair.first, stripPrecision(pair.second)); - } - return stripped; - } - - return value; -} - -bool deepEqual(const Value& a, const Value& b) { - const auto& anum = numericValue<double>(a); - const auto& bnum = numericValue<double>(b); - if (anum && bnum) { - return stripPrecision(*anum) == stripPrecision(*bnum); - } - - if (a.which() != b.which()) { - return false; - } - - if (a.getArray() && b.getArray()) { - const auto& avec = *a.getArray(); - const auto& bvec = *b.getArray(); - if (avec.size() != bvec.size()) { - return false; - } - for (std::size_t i = 0; i < avec.size(); ++i) { - if (!deepEqual(avec[i], bvec[i])) { - return false; - } - } - return true; - } - - if (a.getObject() && b.getObject()) { - const auto& amap = *a.getObject(); - const auto& bmap = *b.getObject(); - if (amap.size() != bmap.size()) { - return false; - } - for (const auto& pair : amap) { - auto it = bmap.find(pair.first); - if (it == bmap.end()) { - return false; - } - if (!deepEqual(pair.second, it->second)) { - return false; - } - } - return true; - } - - if (a == b) { - return true; - } - - if (a.getString() && b.getString()) { - const auto& strA = *a.getString(); - const auto& strB = *b.getString(); - if (strA == strB) { - return true; - } - - try { - double numA = std::stod(strA); - double numB = std::stod(strB); - return stripPrecision(numA) == stripPrecision(numB); - } catch (...) { - } - } - - return false; -} - -std::vector<std::string> tokenize(std::string str) { - std::vector<std::string> tokens; - std::regex re("\n"); - std::copy(std::regex_token_iterator<std::string::iterator>(str.begin(), str.end(), re, -1), - std::regex_token_iterator<std::string::iterator>(), - std::back_inserter(tokens)); - return tokens; -} - std::string simpleDiff(const Value& result, const Value& expected) { std::vector<std::string> resultTokens{tokenize(toJSON(result, 2, false))}; std::vector<std::string> expectedTokens{tokenize(toJSON(expected, 2, false))}; |