diff options
-rw-r--r-- | include/mbgl/map/vector_tile.hpp | 9 | ||||
-rw-r--r-- | include/mbgl/style/filter_comparison.hpp | 65 | ||||
-rw-r--r-- | include/mbgl/style/filter_comparison_private.hpp | 23 | ||||
-rw-r--r-- | include/mbgl/style/filter_expression.hpp | 139 | ||||
-rw-r--r-- | include/mbgl/style/filter_expression_private.hpp | 161 | ||||
-rw-r--r-- | include/mbgl/style/style_parser.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/value.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/style/value_comparison.hpp | 36 | ||||
-rw-r--r-- | src/map/vector_tile.cpp | 131 | ||||
-rw-r--r-- | src/style/filter_comparison.cpp | 143 | ||||
-rw-r--r-- | src/style/filter_expression.cpp | 145 | ||||
-rw-r--r-- | src/style/style_parser.cpp | 89 | ||||
-rw-r--r-- | src/style/value.cpp | 22 | ||||
-rw-r--r-- | test/comparisons.cpp | 349 | ||||
-rw-r--r-- | test/variant.cpp | 357 |
15 files changed, 583 insertions, 1092 deletions
diff --git a/include/mbgl/map/vector_tile.hpp b/include/mbgl/map/vector_tile.hpp index 1bbe645307..2d02ba3a0b 100644 --- a/include/mbgl/map/vector_tile.hpp +++ b/include/mbgl/map/vector_tile.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/value.hpp> #include <mbgl/text/glyph.hpp> #include <mbgl/util/pbf.hpp> +#include <mbgl/util/optional.hpp> #include <cstdint> #include <iosfwd> @@ -44,14 +45,14 @@ public: VectorTileTagExtractor(const VectorTileLayer &layer); void setTags(const pbf &pbf); - std::vector<Value> getValues(const std::string &key) const; - void setType(FilterExpression::GeometryType type); - FilterExpression::GeometryType getType() const; + mapbox::util::optional<Value> getValue(const std::string &key) const; + void setType(FeatureType type); + FeatureType getType() const; private: const VectorTileLayer &layer_; pbf tags_; - FilterExpression::GeometryType type_ = FilterExpression::GeometryType::Any; + FeatureType type_ = FeatureType::Unknown; }; /* diff --git a/include/mbgl/style/filter_comparison.hpp b/include/mbgl/style/filter_comparison.hpp deleted file mode 100644 index 1b0a9b5486..0000000000 --- a/include/mbgl/style/filter_comparison.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef MBGL_STYLE_FILTER_COMPARISON -#define MBGL_STYLE_FILTER_COMPARISON - -#include <mbgl/style/value.hpp> - -#include <vector> -#include <string> -#include <iosfwd> - -namespace mbgl { - -class FilterComparison { -public: - enum class Operator : uint8_t { - Equal, - NotEqual, - Greater, - GreaterEqual, - Less, - LessEqual, - In, - NotIn - }; - - class Instance { - public: - Instance(Operator op_, std::vector<Value> &&values_) - : op(op_), values(values_) {} - - bool compare(const std::vector<Value> &property_values) const; - - private: - Operator op = Operator::Equal; - std::vector<Value> values; - - friend std::ostream& operator <<(std::ostream &, const Instance &); - }; - -public: - FilterComparison(const std::string &field_) : field(field_) {}; - - const std::string &getField() const; - template <typename Extractor> inline bool compare(const Extractor &extractor) const; - - template <typename ...Args> - inline void add(Args&& ...args) { - instances.emplace_back(::std::forward<Args>(args)...); - } - -private: - std::string field; - std::vector<Instance> instances; - - friend std::ostream& operator <<(std::ostream &, const FilterComparison &); -}; - -std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison); -std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance); - - -FilterComparison::Operator parseFilterComparisonOperator(const std::string &op); - -} - -#endif diff --git a/include/mbgl/style/filter_comparison_private.hpp b/include/mbgl/style/filter_comparison_private.hpp deleted file mode 100644 index 6486832424..0000000000 --- a/include/mbgl/style/filter_comparison_private.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MBGL_STYLE_FILTER_COMPARISON_PRIVATE -#define MBGL_STYLE_FILTER_COMPARISON_PRIVATE - -#include "filter_comparison.hpp" - -namespace mbgl { - -template <typename Extractor> -inline bool FilterComparison::compare(const Extractor &extractor) const { - const std::vector<Value> values = extractor.getValues(field); - - // All instances are ANDed together. - for (const Instance &instance : instances) { - if (!instance.compare(values)) { - return false; - } - } - return true; -} - -} - -#endif diff --git a/include/mbgl/style/filter_expression.hpp b/include/mbgl/style/filter_expression.hpp index 915d3931d1..8c6f447770 100644 --- a/include/mbgl/style/filter_expression.hpp +++ b/include/mbgl/style/filter_expression.hpp @@ -1,54 +1,125 @@ #ifndef MBGL_STYLE_FILTER_EXPRESSION #define MBGL_STYLE_FILTER_EXPRESSION -#include <mbgl/style/filter_comparison.hpp> -#include <mbgl/util/recursive_wrapper.hpp> +#include <mbgl/style/value.hpp> -#include <iosfwd> +#include <rapidjson/document.h> + +#include <string> +#include <vector> namespace mbgl { -class FilterExpression { -public: - typedef mapbox::util::recursive_wrapper<FilterExpression> Wrapper; +typedef mapbox::util::variant< + struct NullExpression, + struct EqualsExpression, + struct NotEqualsExpression, + struct LessThanExpression, + struct LessThanEqualsExpression, + struct GreaterThanExpression, + struct GreaterThanEqualsExpression, + struct InExpression, + struct NotInExpression, + struct AnyExpression, + struct AllExpression, + struct NoneExpression + > FilterExpression; + +FilterExpression parseFilterExpression(const rapidjson::Value&); + +template <class Extractor> +bool evaluate(const FilterExpression&, const Extractor&); + +struct NullExpression { + template <class Extractor> + bool evaluate(const Extractor&) const { return true; } +}; + +struct EqualsExpression { + std::string key; + Value value; - enum class Operator : uint8_t { - And, - Or, - Xor, - Nor - }; + template <class Extractor> + bool evaluate(const Extractor&) const; +}; - enum class GeometryType : uint8_t { - Any, - Point, - LineString, - Polygon - }; +struct NotEqualsExpression { + std::string key; + Value value; -public: - FilterExpression() = default; - FilterExpression(Operator op_) : op(op_) {}; + template <class Extractor> + bool evaluate(const Extractor&) const; +}; - bool empty() const; +struct LessThanExpression { + std::string key; + Value value; - template <typename Extractor> bool compare(const Extractor &extractor) const; - void add(const FilterComparison &comparison); - void add(const FilterExpression &expression); - void setGeometryType(GeometryType g); + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct LessThanEqualsExpression { + std::string key; + Value value; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct GreaterThanExpression { + std::string key; + Value value; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; -private: - Operator op = Operator::And; - GeometryType type = GeometryType::Any; - std::vector<FilterComparison> comparisons; - std::vector<FilterExpression::Wrapper> expressions; +struct GreaterThanEqualsExpression { + std::string key; + Value value; - friend std::ostream& operator <<(std::ostream &, const FilterExpression &); + template <class Extractor> + bool evaluate(const Extractor&) const; }; -std::ostream& operator <<(std::ostream &s, const FilterExpression &expression); +struct InExpression { + std::string key; + std::vector<Value> values; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct NotInExpression { + std::string key; + std::vector<Value> values; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct AnyExpression { + std::vector<FilterExpression> expressions; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct AllExpression { + std::vector<FilterExpression> expressions; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; + +struct NoneExpression { + std::vector<FilterExpression> expressions; + + template <class Extractor> + bool evaluate(const Extractor&) const; +}; -FilterExpression::GeometryType parseGeometryType(const std::string &geometry); } #endif diff --git a/include/mbgl/style/filter_expression_private.hpp b/include/mbgl/style/filter_expression_private.hpp index 9379d250ba..381f8f617c 100644 --- a/include/mbgl/style/filter_expression_private.hpp +++ b/include/mbgl/style/filter_expression_private.hpp @@ -1,75 +1,118 @@ -#ifndef MBGL_STYLE_FILTER_EXPRESSION_PRIVATE -#define MBGL_STYLE_FILTER_EXPRESSION_PRIVATE - -#include "filter_expression.hpp" -#include "filter_comparison_private.hpp" +#include <mbgl/util/optional.hpp> +#include <mbgl/style/value_comparison.hpp> namespace mbgl { -template <typename Extractor> -bool FilterExpression::compare(const Extractor &extractor) const { - if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) { +template <class Extractor> +struct Evaluator : public mapbox::util::static_visitor<bool> +{ + const Extractor& extractor; + + Evaluator(const Extractor& extractor_) + : extractor(extractor_) {} + + template <class E> + bool operator()(const E& e) const { return e.evaluate(extractor); } +}; + +template <class Extractor> +bool evaluate(const FilterExpression& expression, const Extractor& extractor) { + return mapbox::util::apply_visitor(Evaluator<Extractor>(extractor), expression); +}; + +template <class Extractor> +bool EqualsExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return actual && util::relaxed_equal(*actual, value); +} + +template <class Extractor> +bool NotEqualsExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return !actual || util::relaxed_not_equal(*actual, value); +} + +template <class Extractor> +bool LessThanExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return actual && util::relaxed_less(*actual, value); +} + +template <class Extractor> +bool LessThanEqualsExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return actual && util::relaxed_less_equal(*actual, value); +} + +template <class Extractor> +bool GreaterThanExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return actual && util::relaxed_greater(*actual, value); +} + +template <class Extractor> +bool GreaterThanEqualsExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + return actual && util::relaxed_greater_equal(*actual, value); +} + +template <class Extractor> +bool InExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + if (!actual) return false; + for (const auto& v: values) { + if (util::relaxed_equal(*actual, v)) { + return true; + } } + return false; +} - switch (op) { - case Operator::And: - for (const FilterComparison &comparison : comparisons) { - if (!comparison.compare(extractor)) { - return false; - } - } - for (const FilterExpression &expression: expressions) { - if (!expression.compare(extractor)) { - return false; - } - } +template <class Extractor> +bool NotInExpression::evaluate(const Extractor& extractor) const { + mapbox::util::optional<Value> actual = extractor.getValue(key); + if (!actual) return true; - case Operator::Or: - for (const FilterComparison &comparison : comparisons) { - if (comparison.compare(extractor)) { - return true; - } + for (const auto& v: values) { + if (util::relaxed_equal(*actual, v)) { + return false; } - for (const FilterExpression &expression: expressions) { - if (expression.compare(extractor)) { - return true; - } - } - return false; - case Operator::Xor: { - int count = 0; - for (const FilterComparison &comparison : comparisons) { - count += comparison.compare(extractor); - if (count > 1) { - return false; - } - } - for (const FilterExpression &expression: expressions) { - count += expression.compare(extractor); - if (count > 1) { - return false; - } - } - return count == 1; } - case Operator::Nor: - for (const FilterComparison &comparison : comparisons) { - if (comparison.compare(extractor)) { - return false; - } + return true; +} + +template <class Extractor> +bool AnyExpression::evaluate(const Extractor& extractor) const { + Evaluator<Extractor> evaluator(extractor); + for (const auto& e: expressions) { + if (mapbox::util::apply_visitor(evaluator, e)) { + return true; } - for (const FilterExpression &expression: expressions) { - if (expression.compare(extractor)) { - return false; - } + } + return false; +} + +template <class Extractor> +bool AllExpression::evaluate(const Extractor& extractor) const { + Evaluator<Extractor> evaluator(extractor); + for (const auto& e: expressions) { + if (!mapbox::util::apply_visitor(evaluator, e)) { + return false; } - return true; - default: - return true; } + return true; } +template <class Extractor> +bool NoneExpression::evaluate(const Extractor& extractor) const { + Evaluator<Extractor> evaluator(extractor); + for (const auto& e: expressions) { + if (mapbox::util::apply_visitor(evaluator, e)) { + return false; + } + } + return true; } -#endif +} diff --git a/include/mbgl/style/style_parser.hpp b/include/mbgl/style/style_parser.hpp index fc253bb1dd..a1c57cf2df 100644 --- a/include/mbgl/style/style_parser.hpp +++ b/include/mbgl/style/style_parser.hpp @@ -85,11 +85,7 @@ private: template <typename T> T parseFunctionArgument(JSVal value); - - FilterExpression parseFilter(JSVal, FilterExpression::Operator op); FilterExpression parseFilter(JSVal); - Value parseValue(JSVal value); - std::vector<Value> parseValues(JSVal values); private: std::unordered_map<std::string, const rapidjson::Value *> constants; diff --git a/include/mbgl/style/value.hpp b/include/mbgl/style/value.hpp index b981f1db9c..87d6f4cda3 100644 --- a/include/mbgl/style/value.hpp +++ b/include/mbgl/style/value.hpp @@ -3,6 +3,7 @@ #include <mbgl/util/variant.hpp> #include <mbgl/util/pbf.hpp> +#include <rapidjson/document.h> #include <cstdlib> #include <cerrno> @@ -14,6 +15,7 @@ typedef mapbox::util::variant<bool, int64_t, uint64_t, double, std::string> Valu std::string toString(const Value &value); Value parseValue(pbf data); +Value parseValue(const rapidjson::Value&); namespace util { inline bool parseNumericString(const std::string &str, double &result) { diff --git a/include/mbgl/style/value_comparison.hpp b/include/mbgl/style/value_comparison.hpp index 41c1d44123..98e29afa7c 100644 --- a/include/mbgl/style/value_comparison.hpp +++ b/include/mbgl/style/value_comparison.hpp @@ -15,35 +15,35 @@ template <typename Operator> struct relaxed_operator_visitor { typedef bool result_type; - inline bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); } - - template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> - inline bool operator()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); } + template <typename T0, typename T1> + inline bool operator()(T0, T1) const { return false; } - template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> - inline bool operator()(T lhs, bool rhs) const { return Operator()(lhs, T(rhs)); } + template <typename T> + inline bool operator()(T lhs, T rhs) const { return Operator()(lhs, rhs); } inline bool operator()(int64_t lhs, uint64_t rhs) const { - return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs); + return Operator()(double(lhs), double(rhs)); + } + + inline bool operator()(int64_t lhs, double rhs) const { + return Operator()(double(lhs), rhs); } + inline bool operator()(uint64_t lhs, int64_t rhs) const { - return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs)); + return Operator()(double(lhs), double(rhs)); } - template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> - inline bool operator()(const std::string &lhs, T rhs) const { - double value; - return parseNumericString(lhs, value) ? Operator()(value, double(rhs)) : false; + inline bool operator()(uint64_t lhs, double rhs) const { + return Operator()(double(lhs), rhs); } - template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> - inline bool operator()(T lhs, const std::string &rhs) const { - double value; - return parseNumericString(rhs, value) ? Operator()(double(lhs), value) : false; + inline bool operator()(double lhs, uint64_t rhs) const { + return Operator()(lhs, double(rhs)); } - template <typename T0, typename T1> - inline bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); } + inline bool operator()(double lhs, int64_t rhs) const { + return Operator()(lhs, double(rhs)); + } }; struct relaxed_equal_operator { diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index 8f097c8292..ac7134fb0c 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -1,6 +1,5 @@ #include <mbgl/map/vector_tile.hpp> #include <mbgl/style/filter_expression_private.hpp> -#include <mbgl/style/filter_comparison_private.hpp> #include <algorithm> #include <iostream> @@ -123,81 +122,6 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren operator++(); } -//bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const FilterExpression &filterExpression, const pbf &tags_pbf) { -// if (filterExpression.empty()) { -// return true; -// } -// -// -// -// -// if (filterExpression.is<util::recursive_wrapper<PropertyFilter>>()) { -// return matchesFilter(filterExpression.get<util::recursive_wrapper<PropertyFilter>>().get(), tags_pbf); -// } else if (filterExpression.is<util::recursive_wrapper<PropertyExpression>>()) { -// return matchesExpression(filterExpression.get<util::recursive_wrapper<PropertyExpression>>().get(), tags_pbf); -// } else if (filterExpression.is<std::true_type>()) { -// return true; -// } else { -// return false; -// } -// return true; -//} - -// -//bool FilteredVectorTileLayer::iterator::matchesFilter(const PropertyFilter &filter, const pbf &const_tags_pbf) { -// auto field_it = parent.layer.key_index.find(filter.field); -// if (field_it != parent.layer.key_index.end()) { -// const uint32_t filter_key = field_it->second; -// -// // Now loop through all the key/value pair tags. -// // tags are packed varints. They should have an even length. -// pbf tags_pbf = const_tags_pbf; -// while (tags_pbf) { -// uint32_t tag_key = tags_pbf.varint(); -// if (!tags_pbf) { -// // This should not happen; otherwise the vector tile -// // is invalid. -// throw std::runtime_error("uneven number of feature tag ids"); -// } -// uint32_t tag_val = tags_pbf.varint(); -// -// if (tag_key == filter_key) { -// if (parent.layer.values.size() > tag_val) { -// const Value &value = parent.layer.values[tag_val]; -// return filter.compare(value); -// } else { -// throw std::runtime_error("feature references out of range value"); -// } -// } -// } -// } -// -// // The feature doesn't contain the field that we're looking to compare. -// // Depending on the filter, this may still be okay. -// return filter.isMissingFieldOkay(); -//} -// -//bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) { -// if (expression.op == ExpressionOperator::Or) { -// for (const PropertyFilterExpression &filterExpression : expression.operands) { -// if (matchesFilterExpression(filterExpression, tags_pbf)) { -// return true; -// } -// } -// return false; -// } else if (expression.op == ExpressionOperator::And) { -// for (const PropertyFilterExpression &filterExpression : expression.operands) { -// if (!matchesFilterExpression(filterExpression, tags_pbf)) { -// return false; -// } -// } -// return true; -// } else { -// return false; -// } -//} -// - VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {} @@ -205,8 +129,12 @@ void VectorTileTagExtractor::setTags(const pbf &pbf) { tags_ = pbf; } -std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) const { - std::vector<Value> values; +mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const { + if (key == "$type") { + return Value(uint64_t(type_)); + } + + mapbox::util::optional<Value> value; auto field_it = layer_.key_index.find(key); if (field_it != layer_.key_index.end()) { @@ -221,14 +149,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con if (!tags_pbf) { // This should not happen; otherwise the vector tile is invalid. fprintf(stderr, "[WARNING] uneven number of feature tag ids\n"); - return values; + return value; } // Note: We need to run this command in all cases, even if the keys don't match. tag_val = tags_pbf.varint(); if (tag_key == filter_key) { if (layer_.values.size() > tag_val) { - values.emplace_back(layer_.values[tag_val]); + value = layer_.values[tag_val]; } else { fprintf(stderr, "[WARNING] feature references out of range value\n"); break; @@ -237,16 +165,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con } } - return values; + return value; } -void VectorTileTagExtractor::setType(FilterExpression::GeometryType type) { +void VectorTileTagExtractor::setType(FeatureType type) { type_ = type; } -FilterExpression::GeometryType VectorTileTagExtractor::getType() const { - return type_; -} +template bool mbgl::evaluate(const FilterExpression&, const VectorTileTagExtractor&); void FilteredVectorTileLayer::iterator::operator++() { valid = false; @@ -256,36 +182,21 @@ void FilteredVectorTileLayer::iterator::operator++() { while (data.next(2)) { // feature feature = data.message(); pbf feature_pbf = feature; - bool matched = false; - // Treat the absence of any expression filters as a match. - if (expression.empty()) { - matched = true; - } + VectorTileTagExtractor extractor(parent.layer); - if (!matched) { - VectorTileTagExtractor extractor(parent.layer); - - // Retrieve the basic information - while (feature_pbf.next()) { - if (feature_pbf.tag == 2) { // tags - extractor.setTags(feature_pbf.message()); - } else if (feature_pbf.tag == 3) { // geometry type - switch (FeatureType(feature_pbf.varint())) { - case FeatureType::Point: extractor.setType(FilterExpression::GeometryType::Point); break; - case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::LineString); break; - case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break; - default: break; - } - } else { - feature_pbf.skip(); - } + // Retrieve the basic information + while (feature_pbf.next()) { + if (feature_pbf.tag == 2) { // tags + extractor.setTags(feature_pbf.message()); + } else if (feature_pbf.tag == 3) { // geometry type + extractor.setType(FeatureType(feature_pbf.varint())); + } else { + feature_pbf.skip(); } - - matched = expression.compare(extractor); } - if (matched) { + if (evaluate(expression, extractor)) { valid = true; return; // data loop } else { diff --git a/src/style/filter_comparison.cpp b/src/style/filter_comparison.cpp deleted file mode 100644 index b3f3a9ef08..0000000000 --- a/src/style/filter_comparison.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include <mbgl/map/vector_tile.hpp> -#include <mbgl/style/filter_comparison_private.hpp> - -#include <mbgl/style/value_comparison.hpp> - -#include <ostream> - -namespace mbgl { - - -inline bool includes(const Value &property_value, const std::vector<Value> &filter_values) { - for (const Value &filter_value : filter_values) { - if (util::relaxed_equal(property_value, filter_value)) { - return true; - } - } - return false; -} - -template <typename Comparer> -inline bool compare(const Value &property_value, const std::vector<Value> &filter_values, const Comparer &comparer) { - for (const Value &filter_value : filter_values) { - if (!comparer(property_value, filter_value)) { - return false; - } - } - return true; -} - -template <typename Comparer> -inline bool all(const std::vector<Value> &property_values, const std::vector<Value> &filter_values, const Comparer &comparer) { - for (const Value &property_value : property_values) { - if (!compare(property_value, filter_values, comparer)) { - return false; - } - } - return true; -} - - -inline bool set_equal(const std::vector<Value> &property_values, const std::vector<Value> &filter_values) { - for (const Value &property_value : property_values) { - if (!includes(property_value, filter_values)) { - return false; - } - } - if (property_values.size() == filter_values.size()) { - // Optimization: When the count is the same, the set is guaranteed to be identical. - return true; - } - // Otherwise, check again for identical reverse-mapped values. - for (const Value &filter_value : filter_values) { - if (!includes(filter_value, property_values)) { - return false; - } - } - return true; -} - - -bool FilterComparison::Instance::compare(const std::vector<Value> &property_values) const { - switch (op) { - case Operator::Equal: - return set_equal(property_values, values); - case Operator::NotEqual: - return !set_equal(property_values, values); - case Operator::In: - for (const Value &property_value : property_values) { - if (includes(property_value, values)) { - return true; - } - } - return false; - case Operator::NotIn: - for (const Value &property_value : property_values) { - if (!includes(property_value, values)) { - return true; - } - } - return false; - case Operator::Greater: - return all(property_values, values, util::relaxed_greater); - case Operator::GreaterEqual: - return all(property_values, values, util::relaxed_greater_equal); - case Operator::Less: - return all(property_values, values, util::relaxed_less); - case Operator::LessEqual: - return all(property_values, values, util::relaxed_less_equal); - default: - return false; - } -} - - -const std::string &FilterComparison::getField() const { - return field; -} - -std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) { - s << "comparison" << std::endl; - for (const FilterComparison::Instance &instance : comparison.instances) { - s << " - " << comparison.field << " " << instance << std::endl; - } - return s; -} - - -std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance) { - switch (instance.op) { - case FilterComparison::Operator::Equal: s << "=="; break; - case FilterComparison::Operator::NotEqual: s << "!="; break; - case FilterComparison::Operator::Greater: s << ">"; break; - case FilterComparison::Operator::GreaterEqual: s << ">="; break; - case FilterComparison::Operator::Less: s << "<"; break; - case FilterComparison::Operator::LessEqual: s << "<="; break; - case FilterComparison::Operator::In: s << "in"; break; - case FilterComparison::Operator::NotIn: s << "!in"; break; - } - - s << " [ "; - for (const Value &value : instance.values) { - s << toString(value) << " "; - } - s << "]"; - return s; -} - - -FilterComparison::Operator parseFilterComparisonOperator(const std::string &op) { - if (op == "==") return FilterComparison::Operator::Equal; - if (op == "!=") return FilterComparison::Operator::NotEqual; - if (op == ">") return FilterComparison::Operator::Greater; - if (op == ">=") return FilterComparison::Operator::GreaterEqual; - if (op == "<") return FilterComparison::Operator::Less; - if (op == "<=") return FilterComparison::Operator::LessEqual; - if (op == "in") return FilterComparison::Operator::In; - if (op == "!in") return FilterComparison::Operator::NotIn; - return FilterComparison::Operator::Equal; -} - -template bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const; - -} diff --git a/src/style/filter_expression.cpp b/src/style/filter_expression.cpp index ff4073b129..7d4f60b3ed 100644 --- a/src/style/filter_expression.cpp +++ b/src/style/filter_expression.cpp @@ -1,66 +1,123 @@ -#include <mbgl/style/filter_expression_private.hpp> #include <mbgl/map/vector_tile.hpp> - -#include <mbgl/style/value_comparison.hpp> - -#include <ostream> +#include <mbgl/platform/log.hpp> namespace mbgl { -std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) { - switch (op) { - case FilterExpression::Operator::And: s << "AND"; break; - case FilterExpression::Operator::Or: s << "OR"; break; - case FilterExpression::Operator::Xor: s << "XOR"; break; - case FilterExpression::Operator::Nor: s << "NOR"; break; +Value parseFeatureType(const Value& value) { + if (value == std::string("Point")) { + return Value(uint64_t(FeatureType::Point)); + } else if (value == std::string("LineString")) { + return Value(uint64_t(FeatureType::LineString)); + } else if (value == std::string("Polygon")) { + return Value(uint64_t(FeatureType::Polygon)); + } else { + Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon"); + return Value(uint64_t(FeatureType::Unknown)); } - return s; } +template <class Expression> +FilterExpression parseBinaryFilter(const rapidjson::Value& value) { + FilterExpression empty; -std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) { - switch (type) { - case FilterExpression::GeometryType::Point: s << "Point"; break; - case FilterExpression::GeometryType::LineString: s << "LineString"; break; - case FilterExpression::GeometryType::Polygon: s << "Polygon"; break; - case FilterExpression::GeometryType::Any: s << "<Any>"; break; + if (value.Size() < 3) { + Log::Warning(Event::ParseStyle, "filter expression must have 3 elements"); + return empty; } - return s; -} -bool FilterExpression::empty() const { - return type == GeometryType::Any && comparisons.empty() && expressions.empty(); -} + if (!value[1u].IsString()) { + Log::Warning(Event::ParseStyle, "filter expression key must be a string"); + return empty; + } -void FilterExpression::add(const FilterComparison &comparison) { - comparisons.emplace_back(comparison); -} + Expression expression; + expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; + expression.value = parseValue(value[2u]); -void FilterExpression::add(const FilterExpression &expression) { - expressions.emplace_back(expression); -} + if (expression.key == "$type") { + expression.value = parseFeatureType(expression.value); + } -void FilterExpression::setGeometryType(GeometryType g) { - type = g; + return expression; } -FilterExpression::GeometryType parseGeometryType(const std::string &geometry) { - if (geometry == "Point") return FilterExpression::GeometryType::Point; - if (geometry == "LineString") return FilterExpression::GeometryType::LineString; - if (geometry == "Polygon") return FilterExpression::GeometryType::Polygon; - return FilterExpression::GeometryType::Any; +template <class Expression> +FilterExpression parseSetFilter(const rapidjson::Value& value) { + FilterExpression empty; + + if (value.Size() < 2) { + Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements"); + return empty; + } + + if (!value[1u].IsString()) { + Log::Warning(Event::ParseStyle, "filter expression key must be a string"); + return empty; + } + + Expression expression; + expression.key = { value[1u].GetString(), value[1u].GetStringLength() }; + for (rapidjson::SizeType i = 2; i < value.Size(); ++i) { + expression.values.push_back(parseValue(value[i])); + } + return expression; } -std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) { - s << "expression " << expression.op << std::endl; - s << " - $type = " << expression.type << std::endl; - for (const FilterComparison &comparison : expression.comparisons) { - s << comparison; +template <class Expression> +FilterExpression parseCompoundFilter(const rapidjson::Value& value) { + Expression expression; + for (rapidjson::SizeType i = 1; i < value.Size(); ++i) { + expression.expressions.push_back(parseFilterExpression(value[i])); } - s << "end expression" << std::endl; - return s; + return expression; } -template bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const; +FilterExpression parseFilterExpression(const rapidjson::Value& value) { + FilterExpression empty; + + if (!value.IsArray()) { + Log::Warning(Event::ParseStyle, "filter expression must be an array"); + return empty; + } + + if (value.Size() < 1) { + Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element"); + return empty; + } + + if (!value[0u].IsString()) { + Log::Warning(Event::ParseStyle, "filter operator must be a string"); + return empty; + } + + std::string op = { value[0u].GetString(), value[0u].GetStringLength() }; + + if (op == "==") { + return parseBinaryFilter<EqualsExpression>(value); + } else if (op == "!=") { + return parseBinaryFilter<NotEqualsExpression>(value); + } else if (op == ">") { + return parseBinaryFilter<GreaterThanExpression>(value); + } else if (op == ">=") { + return parseBinaryFilter<GreaterThanEqualsExpression>(value); + } else if (op == "<") { + return parseBinaryFilter<LessThanExpression>(value); + } else if (op == "<=") { + return parseBinaryFilter<LessThanEqualsExpression>(value); + } else if (op == "in") { + return parseSetFilter<InExpression>(value); + } else if (op == "!in") { + return parseSetFilter<NotInExpression>(value); + } else if (op == "all") { + return parseCompoundFilter<AllExpression>(value); + } else if (op == "any") { + return parseCompoundFilter<AnyExpression>(value); + } else if (op == "none") { + return parseCompoundFilter<NoneExpression>(value); + } else { + Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\""); + return empty; + } +} } diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 6dd2e678cc..9f23074419 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -711,7 +711,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) { if (value.HasMember("filter")) { JSVal value_filter = replaceConstant(value["filter"]); - layer->bucket->filter = parseFilter(value_filter); + layer->bucket->filter = parseFilterExpression(value_filter); } if (value.HasMember("render")) { @@ -738,93 +738,6 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) { } } -FilterExpression StyleParser::parseFilter(JSVal value) { - return parseFilter(value, value.IsArray() ? FilterExpression::Operator::Or : FilterExpression::Operator::And); -} - -FilterExpression StyleParser::parseFilter(JSVal value, FilterExpression::Operator op) { - FilterExpression expression(op); - if (value.IsObject()) { - rapidjson::Value::ConstMemberIterator itr = value.MemberBegin(); - for (; itr != value.MemberEnd(); ++itr) { - const std::string name { itr->name.GetString(), itr->name.GetStringLength() }; - if (name == "&") { - expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::And)); - } else if (name == "|") { - expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Or)); - } else if (name == "^") { - expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Xor)); - } else if (name == "!") { - expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Nor)); - } else if (name == "$type") { - JSVal type = replaceConstant(itr->value); - if (type.IsString()) { - expression.setGeometryType(parseGeometryType({ type.GetString(), type.GetStringLength() })); - } - } else { - FilterComparison comparison(name); - JSVal filterValue = replaceConstant(itr->value); - if (filterValue.IsObject()) { - rapidjson::Value::ConstMemberIterator filter_itr = filterValue.MemberBegin(); - for (; filter_itr != filterValue.MemberEnd(); ++filter_itr) { - comparison.add( - parseFilterComparisonOperator({ filter_itr->name.GetString(), filter_itr->name.GetStringLength() }), - parseValues(replaceConstant(filter_itr->value)) - ); - } - } else if (filterValue.IsArray()) { - comparison.add(FilterComparison::Operator::In, parseValues(filterValue)); - } else { - comparison.add(FilterComparison::Operator::Equal, std::vector<Value>({ parseValue(filterValue) })); - } - expression.add(comparison); - } - } - } else if (value.IsArray()) { - for (rapidjson::SizeType i = 0; i < value.Size(); i++) { - expression.add(parseFilter(replaceConstant(value[i]))); - } - } else { - Log::Warning(Event::ParseStyle, "expression must be either an array or an object"); - } - - return expression; -} - -Value StyleParser::parseValue(JSVal value) { - switch (value.GetType()) { - case rapidjson::kNullType: - case rapidjson::kFalseType: - return false; - - case rapidjson::kTrueType: - return true; - - case rapidjson::kStringType: - return std::string { value.GetString(), value.GetStringLength() }; - - case rapidjson::kNumberType: - if (value.IsUint64()) return value.GetUint64(); - if (value.IsInt64()) return value.GetInt64(); - return value.GetDouble(); - - default: - return false; - } -} - -std::vector<Value> StyleParser::parseValues(JSVal value) { - std::vector<Value> values; - if (value.IsArray()) { - for (rapidjson::SizeType i = 0; i < value.Size(); i++) { - values.emplace_back(parseValue(replaceConstant(value[i]))); - } - } else { - values.emplace_back(parseValue(value)); - } - return values; -} - void StyleParser::parseRender(JSVal value, util::ptr<StyleLayer> &layer) { if (!value.IsObject()) { Log::Warning(Event::ParseStyle, "render property of layer '%s' must be an object", layer->id.c_str()); diff --git a/src/style/value.cpp b/src/style/value.cpp index 5cd32376ab..bda9a089a8 100644 --- a/src/style/value.cpp +++ b/src/style/value.cpp @@ -42,3 +42,25 @@ std::string mbgl::toString(const mbgl::Value& value) { else if (value.is<double>()) return boost::lexical_cast<std::string>(value.get<double>()); else return "null"; } + +mbgl::Value mbgl::parseValue(const rapidjson::Value& value) { + switch (value.GetType()) { + case rapidjson::kNullType: + case rapidjson::kFalseType: + return false; + + case rapidjson::kTrueType: + return true; + + case rapidjson::kStringType: + return std::string { value.GetString(), value.GetStringLength() }; + + case rapidjson::kNumberType: + if (value.IsUint64()) return value.GetUint64(); + if (value.IsInt64()) return value.GetInt64(); + return value.GetDouble(); + + default: + return false; + } +} diff --git a/test/comparisons.cpp b/test/comparisons.cpp index 4ffcf2e2ec..9b74d6e36f 100644 --- a/test/comparisons.cpp +++ b/test/comparisons.cpp @@ -1,306 +1,103 @@ #include <iostream> #include "gtest/gtest.h" -#include <mbgl/style/filter_comparison_private.hpp> +#include <mbgl/map/vector_tile.hpp> +#include <mbgl/style/filter_expression.hpp> #include <mbgl/style/filter_expression_private.hpp> #include <map> +using namespace mbgl; +typedef std::multimap<std::string, mbgl::Value> Properties; -class MockExtractor { +class Extractor { public: - inline MockExtractor(const std::multimap<std::string, mbgl::Value> &values_) : values(values_) {} - inline MockExtractor() {} + inline Extractor(const Properties& properties_, FeatureType type_) + : properties(properties_) + , type(type_) + {} + + mapbox::util::optional<Value> getValue(const std::string &key) const { + if (key == "$type") + return Value(uint64_t(type)); + auto it = properties.find(key); + if (it == properties.end()) + return mapbox::util::optional<Value>(); + return it->second; + } - inline std::vector<mbgl::Value> getValues(const std::string &key) const { - std::vector<mbgl::Value> result; - // Find all values with the requested key. - const auto ret = values.equal_range(key); - for (auto it = ret.first; it != ret.second; it++) { - // Append the newly found value to the forward list. - result.emplace_back(it->second); - } - return result; + FeatureType getType() const { + return type; } private: - const std::multimap<std::string, mbgl::Value> values; + const Properties properties; + FeatureType type; }; - -TEST(FilterComparison, EqualsSingleStringValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar") }); - // comparison is { "test": { "==": "bar" } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor())); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("barst") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); -} - - -TEST(FilterComparison, EqualsSingleDoubleValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { double(32.8) }); - // comparison is { "test": { "==": 32.8 } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", double(32.8) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor())); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.9) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); -} - -TEST(FilterComparison, EqualsSingleUintValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { uint64_t(42) }); - // comparison is { "test": { "==": 42 } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("42") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor())); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(43) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); -} - -TEST(FilterComparison, EqualsSingleIntValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { int64_t(-42) }); - // comparison is { "test": { "==": -42 } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("-42") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor())); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-43) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); -} - -TEST(FilterComparison, EqualsSingleBoolValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { bool(true) }); - // comparison is { "test": { "==": true } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(1) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(1) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("1") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", bool(true) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor())); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); -} - - - -TEST(FilterComparison, EqualsMultipleStringValues) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("baz") }); - // comparison is { "test": { "==": ["bar", "baz"]̇ } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }}))); -} - -TEST(FilterComparison, EqualsMultipleIdenticalStringValues) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("bar") }); - // comparison is { "test": { "==": ["bar", "bar"]̇ } } - - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }}))); -} - - - -TEST(FilterComparison, NotEqualsSingleStringValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar") }); - // comparison is { "test": { "!=": "bar" } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor())); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("barst") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); +FilterExpression parse(const char * expression) { + rapidjson::Document doc; + doc.Parse<0>(expression); + return parseFilterExpression(doc); } - -TEST(FilterComparison, NotEqualsSingleDoubleValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { double(32.8) }); - // comparison is { "test": { "!=": 32.8 } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", double(32.8) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor())); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.9) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); +bool evaluate(const FilterExpression& expression, const Properties& properties, FeatureType type = FeatureType::Unknown) { + return mbgl::evaluate(expression, Extractor(properties, type)); } -TEST(FilterComparison, NotEqualsSingleUintValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { uint64_t(42) }); - // comparison is { "test": { "!=": 42 } } +TEST(FilterComparison, EqualsString) { + FilterExpression f = parse("[\"==\", \"foo\", \"bar\"]"); + ASSERT_TRUE(evaluate(f, {{ "foo", std::string("bar") }})); + ASSERT_FALSE(evaluate(f, {{ "foo", std::string("baz") }})); +}; - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("42") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor())); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(43) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); +TEST(FilterComparison, EqualsNumber) { + FilterExpression f = parse("[\"==\", \"foo\", 0]"); + ASSERT_TRUE(evaluate(f, {{ "foo", int64_t(0) }})); + ASSERT_TRUE(evaluate(f, {{ "foo", uint64_t(0) }})); + ASSERT_TRUE(evaluate(f, {{ "foo", double(0) }})); + ASSERT_FALSE(evaluate(f, {{ "foo", int64_t(1) }})); + ASSERT_FALSE(evaluate(f, {{ "foo", uint64_t(1) }})); + ASSERT_FALSE(evaluate(f, {{ "foo", double(1) }})); + ASSERT_FALSE(evaluate(f, {{ "foo", std::string("0") }})); + ASSERT_FALSE(evaluate(f, {{ "foo", false }})); + ASSERT_FALSE(evaluate(f, {{ "foo", true }})); + ASSERT_FALSE(evaluate(f, {{}})); } - -TEST(FilterComparison, NotEqualsSingleIntValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { int64_t(-42) }); - // comparison is { "test": { "!=": -42 } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-42) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("-42") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor())); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-43) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); +TEST(FilterComparison, EqualsType) { + FilterExpression f = parse("[\"==\", \"$type\", \"LineString\"]"); + ASSERT_FALSE(evaluate(f, {{}}, FeatureType::Point)); + ASSERT_TRUE(evaluate(f, {{}}, FeatureType::LineString)); } - -TEST(FilterComparison, NotEqualsSingleBoolValue) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { bool(true) }); - // comparison is { "test": { "!=": true } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(1) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(1) }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("1") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", bool(true) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor())); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); +TEST(FilterComparison, Any) { + ASSERT_FALSE(evaluate(parse("[\"any\"]"), {{}})); + ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_FALSE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); } - - -TEST(FilterComparison, NotEqualsMultipleStringValues) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("baz") }); - // comparison is { "test": { "!=": ["bar", "baz"]̇ } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }}))); +TEST(FilterComparison, All) { + ASSERT_TRUE(evaluate(parse("[\"all\"]"), {{}})); + ASSERT_TRUE(evaluate(parse("[\"all\", [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); } - - -TEST(FilterComparison, NotEqualsMultipleIdenticalStringValues) { - using namespace mbgl; - - FilterComparison comparison("test"); - comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("bar") }); - // comparison is { "test": { "!=": ["bar", "bar"]̇ } } - - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); - ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }}))); - ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }}))); +TEST(FilterComparison, None) { + ASSERT_TRUE(evaluate(parse("[\"none\"]"), {{}})); + ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_TRUE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0]]"), + {{ std::string("foo"), int64_t(1) }})); + ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"), + {{ std::string("foo"), int64_t(1) }})); } diff --git a/test/variant.cpp b/test/variant.cpp index 4557465cfa..e4caba9f2d 100644 --- a/test/variant.cpp +++ b/test/variant.cpp @@ -17,110 +17,26 @@ TEST(Variant, toString) { EXPECT_EQ("false", toString( false )); } - -TEST(Variant, RelaxedEqualityStringToBool) { - // 1-ish values are true - EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("1.0"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 1"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0x1"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0X1"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 1.0"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 1 "), bool(true))); - - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1.0"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0x1"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0X1"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1.0"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1 "))); - - // 0-ish values are false - EXPECT_TRUE(util::relaxed_equal(std::string("0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("0.0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0x0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0X0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0.0"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" 0 "), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string(" "), bool(false))); - - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0.0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0x0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0X0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0.0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0 "))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" "))); - - - // other string values are neither true nor false - EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(true))); - EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(true))); - - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" 1.0 g"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("foo"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("true"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inf "))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inFINITY "))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" nan "))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" NAN "))); - - - EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(false))); - EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(false))); - - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" 1.0 g"))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("foo"))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("true"))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inf "))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inFINITY "))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" nan "))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" NAN "))); -} - TEST(Variant, RelaxedEquality) { // Compare to bool EXPECT_TRUE(util::relaxed_equal(bool(false), bool(false))); - EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(false), double(0))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); - EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true))); - EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(1))); - EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(1))); - EXPECT_TRUE(util::relaxed_equal(bool(true), double(1))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1"))); - - EXPECT_FALSE(util::relaxed_equal(bool(false), bool(true))); + EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(0))); + EXPECT_FALSE(util::relaxed_equal(bool(false), double(0))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("0"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(""))); EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(386))); EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-7042))); EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(386))); EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145))); EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("386"))); EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test"))); - + EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(1))); + EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(1))); + EXPECT_FALSE(util::relaxed_equal(bool(true), double(1))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("1"))); EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false))); EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(386))); EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(-7042))); @@ -135,10 +51,9 @@ TEST(Variant, RelaxedEquality) { EXPECT_TRUE(util::relaxed_equal(int64_t(-7042), int64_t(-7042))); EXPECT_TRUE(util::relaxed_equal(int64_t(386), uint64_t(386))); EXPECT_TRUE(util::relaxed_equal(int64_t(386), double(386))); - EXPECT_TRUE(util::relaxed_equal(int64_t(386), std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(int64_t(1), bool(true))); - EXPECT_TRUE(util::relaxed_equal(int64_t(0), bool(false))); - + EXPECT_FALSE(util::relaxed_equal(int64_t(386), std::string("386"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(1), bool(true))); + EXPECT_FALSE(util::relaxed_equal(int64_t(0), bool(false))); EXPECT_FALSE(util::relaxed_equal(int64_t(386), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(int64_t(-7042), int64_t(-7043))); EXPECT_FALSE(util::relaxed_equal(int64_t(386), uint64_t(387))); @@ -151,16 +66,14 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("true"))); - // Compare to uint64_t EXPECT_TRUE(util::relaxed_equal(uint64_t(386), int64_t(386))); EXPECT_TRUE(util::relaxed_equal(uint64_t(386), uint64_t(386))); EXPECT_TRUE(util::relaxed_equal(uint64_t(0), uint64_t(0))); EXPECT_TRUE(util::relaxed_equal(uint64_t(386), double(386))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(386), std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(1), bool(true))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(0), bool(false))); - + EXPECT_FALSE(util::relaxed_equal(uint64_t(386), std::string("386"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1), bool(true))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0), bool(false))); EXPECT_FALSE(util::relaxed_equal(uint64_t(386), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(uint64_t(386), uint64_t(387))); EXPECT_FALSE(util::relaxed_equal(uint64_t(0), uint64_t(1))); @@ -173,17 +86,15 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("true"))); - // Compare to double EXPECT_TRUE(util::relaxed_equal(double(3.159385), double(3.159385))); EXPECT_TRUE(util::relaxed_equal(double(386), int64_t(386))); EXPECT_TRUE(util::relaxed_equal(double(386), uint64_t(386))); EXPECT_TRUE(util::relaxed_equal(double(0), uint64_t(0))); EXPECT_TRUE(util::relaxed_equal(double(386), double(386))); - EXPECT_TRUE(util::relaxed_equal(double(386), std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(double(1), bool(true))); - EXPECT_TRUE(util::relaxed_equal(double(0), bool(false))); - + EXPECT_FALSE(util::relaxed_equal(double(386), std::string("386"))); + EXPECT_FALSE(util::relaxed_equal(double(1), bool(true))); + EXPECT_FALSE(util::relaxed_equal(double(0), bool(false))); EXPECT_FALSE(util::relaxed_equal(double(3.159385), double(3.159383))); EXPECT_FALSE(util::relaxed_equal(double(386), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(double(386), uint64_t(387))); @@ -205,16 +116,14 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(double(0), std::string("true"))); EXPECT_FALSE(util::relaxed_equal(double(0), std::string("TRUE"))); - // Compare to string EXPECT_TRUE(util::relaxed_equal(std::string("lord"), std::string("lord"))); - EXPECT_TRUE(util::relaxed_equal(std::string("386"), int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(std::string("-386"), int64_t(-386))); - EXPECT_TRUE(util::relaxed_equal(std::string("386"), uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(std::string("386.36"), double(386.36))); - EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true))); - + EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(386))); + EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-386))); + EXPECT_FALSE(util::relaxed_equal(std::string("386"), uint64_t(386))); + EXPECT_FALSE(util::relaxed_equal(std::string("386.36"), double(386.36))); + EXPECT_FALSE(util::relaxed_equal(std::string(""), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("1"), bool(true))); EXPECT_FALSE(util::relaxed_equal(std::string("lord"), std::string("baron"))); EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-387))); @@ -239,46 +148,46 @@ TEST(Variant, RelaxedEquality) { TEST(Variant, RelaxedGreater) { EXPECT_TRUE(util::relaxed_greater(std::string("387"), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater(uint64_t(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater(int64_t(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater(double(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater(bool(true), std::string("0"))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater(double(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater(bool(true), std::string("0"))); - EXPECT_TRUE(util::relaxed_greater(std::string("387"), uint64_t(386))); + EXPECT_FALSE(util::relaxed_greater(std::string("387"), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater(uint64_t(387), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater(int64_t(387), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater(double(387), uint64_t(386))); - EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0))); + EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0))); - EXPECT_TRUE(util::relaxed_greater(std::string("387"), int64_t(386))); + EXPECT_FALSE(util::relaxed_greater(std::string("387"), int64_t(386))); EXPECT_TRUE(util::relaxed_greater(uint64_t(387), int64_t(386))); EXPECT_TRUE(util::relaxed_greater(int64_t(387), int64_t(386))); EXPECT_TRUE(util::relaxed_greater(double(387), int64_t(386))); - EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0))); + EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0))); - EXPECT_TRUE(util::relaxed_greater(std::string("387"), double(386.7))); + EXPECT_FALSE(util::relaxed_greater(std::string("387"), double(386.7))); EXPECT_TRUE(util::relaxed_greater(uint64_t(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater(int64_t(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater(double(387), double(386.7))); - EXPECT_TRUE(util::relaxed_greater(bool(true), double(0))); - - EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(true))); - EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(false))); - EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater(double(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater(double(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(true))); - EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(true))); - EXPECT_TRUE(util::relaxed_greater(double(387), bool(true))); - EXPECT_TRUE(util::relaxed_greater(double(387), bool(true))); - - EXPECT_TRUE(util::relaxed_greater(bool(true), double(0))); - EXPECT_TRUE(util::relaxed_greater(bool(true), double(0.5))); - EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false))); - EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0))); - EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0))); + EXPECT_FALSE(util::relaxed_greater(bool(true), double(0))); + + EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(true))); + EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(false))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater(double(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater(double(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(double(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater(double(387), bool(true))); + + EXPECT_FALSE(util::relaxed_greater(bool(true), double(0))); + EXPECT_FALSE(util::relaxed_greater(bool(true), double(0.5))); EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false))); + EXPECT_FALSE(util::relaxed_greater(bool(true), bool(true))); + EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0))); + EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0))); @@ -315,52 +224,52 @@ TEST(Variant, RelaxedGreater) { TEST(Variant, RelaxedGreaterEqual) { EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("386"))); EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("387"))); - EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("386"))); - EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_greater_equal(bool(true), std::string("0"))); - - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(386))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(387))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("386"))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_greater_equal(bool(true), std::string("0"))); + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(386))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(387))); - EXPECT_TRUE(util::relaxed_greater_equal(bool(true), uint64_t(0))); + EXPECT_FALSE(util::relaxed_greater_equal(bool(true), uint64_t(0))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(386))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(387))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(386))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(387))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(386))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(387))); - EXPECT_TRUE(util::relaxed_greater_equal(bool(true), int64_t(0))); + EXPECT_FALSE(util::relaxed_greater_equal(bool(true), int64_t(0))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(386.7))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(387))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(386.7))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(387))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(387))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(387))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(387))); - EXPECT_TRUE(util::relaxed_greater_equal(bool(true), double(0))); - - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(false))); - EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(true))); - EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(true))); - EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(true))); - EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater_equal(bool(true), double(0))); + + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(false))); + EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(true))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(true))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(false))); + EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(true))); EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(false))); EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(true))); @@ -391,43 +300,43 @@ TEST(Variant, RelaxedGreaterEqual) { TEST(Variant, RelaxedLess) { EXPECT_TRUE(util::relaxed_less(std::string("387"), std::string("388"))); - EXPECT_TRUE(util::relaxed_less(uint64_t(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less(int64_t(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less(double(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less(bool(false), std::string("388"))); - EXPECT_TRUE(util::relaxed_less(bool(false), std::string("1"))); + EXPECT_FALSE(util::relaxed_less(uint64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less(int64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less(double(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less(bool(false), std::string("388"))); + EXPECT_FALSE(util::relaxed_less(bool(false), std::string("1"))); - EXPECT_TRUE(util::relaxed_less(std::string("387"), uint64_t(388))); + EXPECT_FALSE(util::relaxed_less(std::string("387"), uint64_t(388))); EXPECT_TRUE(util::relaxed_less(uint64_t(387), uint64_t(388))); EXPECT_TRUE(util::relaxed_less(int64_t(387), uint64_t(388))); EXPECT_TRUE(util::relaxed_less(double(387), uint64_t(388))); - EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(388))); - EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(1))); + EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(388))); + EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(1))); - EXPECT_TRUE(util::relaxed_less(std::string("387"), int64_t(388))); + EXPECT_FALSE(util::relaxed_less(std::string("387"), int64_t(388))); EXPECT_TRUE(util::relaxed_less(uint64_t(387), int64_t(388))); EXPECT_TRUE(util::relaxed_less(int64_t(387), int64_t(388))); EXPECT_TRUE(util::relaxed_less(double(387), int64_t(388))); - EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(388))); - EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(1))); + EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(388))); + EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(1))); - EXPECT_TRUE(util::relaxed_less(std::string("387"), double(387.7))); + EXPECT_FALSE(util::relaxed_less(std::string("387"), double(387.7))); EXPECT_TRUE(util::relaxed_less(uint64_t(387), double(387.7))); EXPECT_TRUE(util::relaxed_less(int64_t(387), double(387.7))); EXPECT_TRUE(util::relaxed_less(double(387), double(387.7))); - EXPECT_TRUE(util::relaxed_less(bool(false), double(387))); - EXPECT_TRUE(util::relaxed_less(bool(false), double(1))); + EXPECT_FALSE(util::relaxed_less(bool(false), double(387))); + EXPECT_FALSE(util::relaxed_less(bool(false), double(1))); - EXPECT_TRUE(util::relaxed_less(std::string("0"), bool(true))); - EXPECT_TRUE(util::relaxed_less(uint64_t(0), bool(true))); - EXPECT_TRUE(util::relaxed_less(int64_t(0), bool(true))); - EXPECT_TRUE(util::relaxed_less(double(0), bool(true))); + EXPECT_FALSE(util::relaxed_less(std::string("0"), bool(true))); + EXPECT_FALSE(util::relaxed_less(uint64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_less(int64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_less(double(0), bool(true))); EXPECT_TRUE(util::relaxed_less(bool(false), bool(true))); - EXPECT_TRUE(util::relaxed_less(bool(true), std::string("386"))); - EXPECT_TRUE(util::relaxed_less(bool(true), uint64_t(386))); - EXPECT_TRUE(util::relaxed_less(bool(true), int64_t(386))); - EXPECT_TRUE(util::relaxed_less(bool(true), double(386))); + EXPECT_FALSE(util::relaxed_less(bool(true), std::string("386"))); + EXPECT_FALSE(util::relaxed_less(bool(true), uint64_t(386))); + EXPECT_FALSE(util::relaxed_less(bool(true), int64_t(386))); + EXPECT_FALSE(util::relaxed_less(bool(true), double(386))); @@ -464,60 +373,60 @@ TEST(Variant, RelaxedLess) { TEST(Variant, RelaxedLessEqual) { EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("388"))); EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("387"))); - EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("388"))); - EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("387"))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("388"))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("1"))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("0"))); - - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(388))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(387))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("388"))); + EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("387"))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("388"))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("1"))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("0"))); + + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(388))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(387))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(388))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(1))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(0))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(388))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(1))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(0))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(388))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(387))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(388))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(387))); EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(388))); EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(387))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(388))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(1))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(0))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(388))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(1))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(0))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387.7))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387.7))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387.7))); EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387.7))); EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387))); EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387.7))); EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(387))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(1))); - EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(0))); - - EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(true))); - EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(false))); - EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(true))); - EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(false))); - EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(true))); - EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(false))); - EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(true))); - EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(false))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(387))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(1))); + EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(0))); + + EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(true))); + EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(false))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(false))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(false))); + EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(true))); + EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(false))); EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(true))); EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(false))); |