diff options
author | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2018-10-10 11:36:43 -0700 |
---|---|---|
committer | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2018-10-10 11:36:43 -0700 |
commit | f66fafdc7de1282f82face8c0f0d51ae01a2a09e (patch) | |
tree | d05e0a0b4a7fd036584902d40c0c274ab9e77c2c | |
parent | 3852451ccc2154cbe987d7bef223ad41baef8548 (diff) |
Add unit tests for feature-state
-rw-r--r-- | include/mbgl/style/expression/dsl.hpp | 3 | ||||
-rw-r--r-- | include/mbgl/style/expression/parsing_context.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/style/conversion/filter.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/expression/dsl.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/style/expression/parsing_context.cpp | 10 | ||||
-rw-r--r-- | test/style/expression/expression.test.cpp | 3 | ||||
-rw-r--r-- | test/style/filter.test.cpp | 7 | ||||
-rw-r--r-- | test/style/property_expression.test.cpp | 15 |
8 files changed, 52 insertions, 3 deletions
diff --git a/include/mbgl/style/expression/dsl.hpp b/include/mbgl/style/expression/dsl.hpp index a4483a6fe..af5a5a8f8 100644 --- a/include/mbgl/style/expression/dsl.hpp +++ b/include/mbgl/style/expression/dsl.hpp @@ -42,6 +42,9 @@ std::unique_ptr<Expression> toString(std::unique_ptr<Expression>); std::unique_ptr<Expression> get(const char* value); std::unique_ptr<Expression> get(std::unique_ptr<Expression>); +std::unique_ptr<Expression> featureState(const char* value); +std::unique_ptr<Expression> featureState(std::unique_ptr<Expression>); + std::unique_ptr<Expression> id(); std::unique_ptr<Expression> zoom(); diff --git a/include/mbgl/style/expression/parsing_context.hpp b/include/mbgl/style/expression/parsing_context.hpp index dde907ec2..4c6ae8d24 100644 --- a/include/mbgl/style/expression/parsing_context.hpp +++ b/include/mbgl/style/expression/parsing_context.hpp @@ -103,6 +103,13 @@ public: ParseResult parseLayerPropertyExpression(const mbgl::style::conversion::Convertible& value); /* + Parse the given style-spec JSON value as an expression intended to be used + in a layer filter. This entails checking additional constraints + that exist in that context but not, e.g., for layer properties. + */ + ParseResult parseLayerFilterExpression(const mbgl::style::conversion::Convertible& value); + + /* Parse a child expression. For use by individual Expression::parse() methods. */ ParseResult parse(const mbgl::style::conversion::Convertible&, diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp index fc25ab0b0..32de7bbb6 100644 --- a/src/mbgl/style/conversion/filter.cpp +++ b/src/mbgl/style/conversion/filter.cpp @@ -20,7 +20,7 @@ optional<mbgl::Value> serializeLegacyFilter(const Convertible& values); optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error& error) const { if (isExpression(value)) { ParsingContext parsingContext(type::Boolean); - ParseResult parseResult = parsingContext.parseExpression(value); + ParseResult parseResult = parsingContext.parseLayerFilterExpression(value); if (!parseResult) { error.message = parsingContext.getCombinedErrors(); return nullopt; diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp index c6318fb63..dfd79a336 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -85,6 +85,14 @@ std::unique_ptr<Expression> get(std::unique_ptr<Expression> property) { return compound("get", std::move(property)); } +std::unique_ptr<Expression> featureState(const char* value) { + return featureState(literal(value)); +} + +std::unique_ptr<Expression> featureState(std::unique_ptr<Expression> property) { + return compound("feature-state", std::move(property)); +} + std::unique_ptr<Expression> id() { return compound("id"); } diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp index e309d9a89..f359c2696 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -243,6 +243,16 @@ ParseResult ParsingContext::parseLayerPropertyExpression(const Convertible& valu return parsed; } +ParseResult ParsingContext::parseLayerFilterExpression(const Convertible& value) { + assert(*expected == type::Boolean); + ParseResult parsed = parse(value); + if (parsed && !isFeatureStateConstant(**parsed)) { + error(R"("feature-state" expression may not be used in filter expressions.)"); + return ParseResult(); + } + return parsed; +} + const std::string ParsingContext::getCombinedErrors() const { std::string combinedError; for (const ParsingError& parsingError : *errors) { diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp index bed3d4f06..4f0e61f1e 100644 --- a/test/style/expression/expression.test.cpp +++ b/test/style/expression/expression.test.cpp @@ -33,11 +33,10 @@ TEST(Expression, IsExpression) { document.Parse<0>(R"([")" + name + R"("])"); const JSValue* expression = &document; - // TODO: "feature-state": https://github.com/mapbox/mapbox-gl-native/issues/12613 // TODO: "interpolate-hcl": https://github.com/mapbox/mapbox-gl-native/issues/8720 // TODO: "interpolate-lab": https://github.com/mapbox/mapbox-gl-native/issues/8720 // TODO: "format": https://github.com/mapbox/mapbox-gl-native/issues/12612 - if (name == "feature-state" || name == "interpolate-hcl" || name == "interpolate-lab" || name == "format") { + if (name == "interpolate-hcl" || name == "interpolate-lab" || name == "format") { if (expression::isExpression(conversion::Convertible(expression))) { ASSERT_TRUE(false) << "Expression name" << name << "is implemented - please update Expression.IsExpression test."; } diff --git a/test/style/filter.test.cpp b/test/style/filter.test.cpp index 37a5309b4..4ed123adf 100644 --- a/test/style/filter.test.cpp +++ b/test/style/filter.test.cpp @@ -243,6 +243,13 @@ TEST(Filter, ExpressionLegacyMix) { EXPECT_TRUE(error.message.size() > 0); } +TEST(Filter, ExpressionFeatureState) { + conversion::Error error; + optional<Filter> filter = conversion::convertJSON<Filter>(R"(["==", ["feature-state", "state"], 1])", error); + EXPECT_FALSE(bool(filter)); + EXPECT_TRUE(error.message.size() > 0); +} + TEST(Filter, ZoomExpressionNested) { ASSERT_TRUE(filter(R"(["==", ["get", "two"], ["zoom"]])", {{"two", int64_t(2)}}, {}, FeatureType::Point, {}, 2.0f)); ASSERT_FALSE(filter(R"(["==", ["get", "two"], ["+", ["zoom"], 1]])", {{"two", int64_t(2)}}, {}, FeatureType::Point, {}, 2.0f)); diff --git a/test/style/property_expression.test.cpp b/test/style/property_expression.test.cpp index 4e972d71b..0df4dd4dc 100644 --- a/test/style/property_expression.test.cpp +++ b/test/style/property_expression.test.cpp @@ -12,6 +12,10 @@ using namespace mbgl::style::expression::dsl; using namespace std::string_literals; +static StubGeometryTileFeature stubFeature { + PropertyMap {} +}; + static StubGeometryTileFeature oneInteger { PropertyMap {{ "property", uint64_t(1) }} }; @@ -57,6 +61,17 @@ TEST(PropertyExpression, Defaults) { .evaluate(oneString, {}, 2.0f)); } +TEST(PropertyExpression, FeatureState) { + EXPECT_EQ(1.0f, PropertyExpression<float>(number(featureState("state")), 0.0) + .evaluate(stubFeature, PropertyMap {{ "state", uint64_t(1) }}, 2.0f)); + EXPECT_EQ(1.0f, PropertyExpression<float>(number(featureState("state")), 0.0) + .evaluate(stubFeature, PropertyMap {{ "state", 1.0 }}, 2.0f)); + EXPECT_EQ(0.0f, PropertyExpression<float>(number(featureState("state")), 0.0) + .evaluate(stubFeature, PropertyMap {{"state", "1"s }}, 2.0f)); + EXPECT_EQ("1"s, PropertyExpression<std::string>(featureState("state")) + .evaluate(stubFeature, PropertyMap {{"state", "1"s }}, "0"s)); +} + TEST(PropertyExpression, ZoomInterpolation) { EXPECT_EQ(40.0f, PropertyExpression<float>( interpolate(linear(), zoom(), |