aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAsheem Mamoowala <asheem.mamoowala@mapbox.com>2018-10-10 11:36:43 -0700
committerAsheem Mamoowala <asheem.mamoowala@mapbox.com>2018-10-10 11:36:43 -0700
commitf66fafdc7de1282f82face8c0f0d51ae01a2a09e (patch)
treed05e0a0b4a7fd036584902d40c0c274ab9e77c2c
parent3852451ccc2154cbe987d7bef223ad41baef8548 (diff)
Add unit tests for feature-state
-rw-r--r--include/mbgl/style/expression/dsl.hpp3
-rw-r--r--include/mbgl/style/expression/parsing_context.hpp7
-rw-r--r--src/mbgl/style/conversion/filter.cpp2
-rw-r--r--src/mbgl/style/expression/dsl.cpp8
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp10
-rw-r--r--test/style/expression/expression.test.cpp3
-rw-r--r--test/style/filter.test.cpp7
-rw-r--r--test/style/property_expression.test.cpp15
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(),