summaryrefslogtreecommitdiff
path: root/test/style/filter.test.cpp
blob: c59a73eab1ce31bcf35f6d11d466c356ea7bb450 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <mbgl/test/util.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/test/stub_geometry_tile_feature.hpp>

#include <mbgl/style/filter.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/filter.hpp>

using namespace mbgl;
using namespace mbgl::style;

bool filter(const char * json,
            const PropertyMap& featureProperties = {{}},
            optional<FeatureIdentifier> featureId = {},
            FeatureType featureType = FeatureType::Point,
            GeometryCollection featureGeometry = {},
            float zoom = 0.0f) {
    conversion::Error error;
    optional<Filter> filter = conversion::convertJSON<Filter>(json, error);
    EXPECT_TRUE(bool(filter));
    EXPECT_EQ(error.message, "");
    
    StubGeometryTileFeature feature { featureId, featureType, featureGeometry, featureProperties };
    expression::EvaluationContext context = { zoom, &feature };
    
    return (*filter)(context);
}

void invalidFilter(const char * json) {
    conversion::Error error;
    optional<Filter> filter = conversion::convertJSON<Filter>(json, error);
    EXPECT_FALSE(bool(filter));
    EXPECT_NE(error.message, "");
}

TEST(Filter, EqualsNull) {
    auto f = R"(["==", "foo", null])";
    ASSERT_TRUE(filter(f, {{ "foo", mapbox::geometry::null_value }}));

    ASSERT_FALSE(filter(f, {{ "foo", int64_t(0) }}));
    ASSERT_FALSE(filter(f, {{ "foo", int64_t(1) }}));
    ASSERT_FALSE(filter(f, {{ "foo", std::string("0") }}));
    ASSERT_FALSE(filter(f, {{ "foo", true }}));
    ASSERT_FALSE(filter(f, {{ "foo", false }}));
    ASSERT_FALSE(filter(f, {{ }}));
}
TEST(Filter, EqualsString) {
    auto f = R"(["==", "foo", "bar"])";
    ASSERT_TRUE(filter(f, {{ "foo", std::string("bar") }}));
    ASSERT_FALSE(filter(f, {{ "foo", std::string("baz") }}));
}

TEST(Filter, EqualsNumber) {
    auto f = R"(["==", "foo", 0])";
    ASSERT_TRUE(filter(f, {{ "foo", int64_t(0) }}));
    ASSERT_TRUE(filter(f, {{ "foo", uint64_t(0) }}));
    ASSERT_TRUE(filter(f, {{ "foo", double(0) }}));
    ASSERT_FALSE(filter(f, {{ "foo", int64_t(1) }}));
    ASSERT_FALSE(filter(f, {{ "foo", uint64_t(1) }}));
    ASSERT_FALSE(filter(f, {{ "foo", double(1) }}));
    ASSERT_FALSE(filter(f, {{ "foo", std::string("0") }}));
    ASSERT_FALSE(filter(f, {{ "foo", false }}));
    ASSERT_FALSE(filter(f, {{ "foo", true }}));
    ASSERT_FALSE(filter(f, {{ "foo", mapbox::geometry::null_value }}));
    ASSERT_FALSE(filter(f, {{}}));
}

TEST(Filter, EqualsType) {
    auto f = R"(["==", "$type", "LineString"])";
    ASSERT_FALSE(filter(f, {{}}, {}, FeatureType::Point, {}));
    ASSERT_TRUE(filter(f, {{}}, {}, FeatureType::LineString, {}));
    ASSERT_FALSE(filter(f, {{}}, {}, FeatureType::Point, {}));

    invalidFilter("[\"==\", \"$type\"]");
    invalidFilter("[\"==\", \"$type\", null]");
    invalidFilter("[\"==\", \"$type\", \"foo\", 1]");
    invalidFilter("[\"==\", \"$type\", \"foo\", \"Point\"]");
}

TEST(Filter, InType) {
    auto f = R"(["in", "$type", "LineString", "Polygon"])";
    ASSERT_FALSE(filter(f, {{}}, {}, FeatureType::Point));
    ASSERT_TRUE(filter(f, {{}}, {}, FeatureType::LineString));
    ASSERT_TRUE(filter(f, {{}}, {}, FeatureType::Polygon));
}

TEST(Filter, InID) {
    auto f = R"(["in", "$id", "123", "1234", 1234])";
    ASSERT_FALSE(filter(f));
    ASSERT_TRUE(filter(f, {{}}, { uint64_t(1234) }));
    ASSERT_TRUE(filter(f, {{}}, { std::string("1234") }));
    ASSERT_FALSE(filter(f, {{}}, { std::string("4321") }));
}

TEST(Filter, Any) {
    ASSERT_FALSE(filter("[\"any\"]"));
    ASSERT_TRUE(filter("[\"any\", [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"any\", [\"==\", \"foo\", 0]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_TRUE(filter("[\"any\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
}

TEST(Filter, AnyExpression) {
    ASSERT_FALSE(filter("[\"any\"]"));
    ASSERT_TRUE(filter("[\"any\", [\"==\", [\"get\", \"foo\"], 1]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"any\", [\"==\", [\"get\", \"foo\"], 0]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_TRUE(filter("[\"any\", [\"==\", [\"get\", \"foo\"], 0], [\"==\", [\"get\", \"foo\"], 1]]", {{ std::string("foo"), int64_t(1) }}));
}

TEST(Filter, All) {
    ASSERT_TRUE(filter("[\"all\"]", {{}}));
    ASSERT_TRUE(filter("[\"all\", [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"all\", [\"==\", \"foo\", 0]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"all\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
}

TEST(Filter, AllExpression) {
    ASSERT_TRUE(filter("[\"all\", [\"==\", [\"get\", \"foo\"], 1]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"all\", [\"==\", [\"get\", \"foo\"], 0]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"all\", [\"==\", [\"get\", \"foo\"], 0], [\"==\", [\"get\", \"foo\"], 1]]", {{ std::string("foo"), int64_t(1) }}));
}

TEST(Filter, None) {
    ASSERT_TRUE(filter("[\"none\"]"));
    ASSERT_FALSE(filter("[\"none\", [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_TRUE(filter("[\"none\", [\"==\", \"foo\", 0]]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"none\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]", {{ std::string("foo"), int64_t(1) }}));
}

TEST(Filter, Has) {
    ASSERT_TRUE(filter("[\"has\", \"foo\"]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_TRUE(filter("[\"has\", \"foo\"]", {{ std::string("foo"), int64_t(0) }}));
    ASSERT_TRUE(filter("[\"has\", \"foo\"]", {{ std::string("foo"), false }}));
    ASSERT_FALSE(filter("[\"has\", \"foo\"]"));
    ASSERT_FALSE(filter("[\"has\", \"$id\"]"));
}

TEST(Filter, NotHas) {
    ASSERT_FALSE(filter("[\"!has\", \"foo\"]", {{ std::string("foo"), int64_t(1) }}));
    ASSERT_FALSE(filter("[\"!has\", \"foo\"]", {{ std::string("foo"), int64_t(0) }}));
    ASSERT_FALSE(filter("[\"!has\", \"foo\"]", {{ std::string("foo"), false }}));
    ASSERT_TRUE(filter("[\"!has\", \"foo\"]"));
}

TEST(Filter, ID) {
    FeatureIdentifier id1 { uint64_t{ 1234 } };
    ASSERT_TRUE(filter("[\"==\", \"$id\", 1234]", {{}}, id1));
    ASSERT_FALSE(filter("[\"==\", \"$id\", \"1234\"]", {{}}, id1));

    FeatureIdentifier id2 { std::string{ "1" } };
    ASSERT_FALSE(filter("[\"<\", \"$id\", \"0\"]", {{}}, id2));
    ASSERT_TRUE(filter("[\"<\", \"$id\", \"1234\"]", {{}}, id2));

    ASSERT_FALSE(filter("[\"==\", \"$id\", 1234]", {{ "id", uint64_t(1234) }}));
}

TEST(Filter, Expression) {
    ASSERT_TRUE(filter("[\"==\", [\"+\", 1, 1], 2]"));
    ASSERT_FALSE(filter("[\"==\", [\"+\", 1, 1], 4]"));
}

TEST(Filter, PropertyExpression) {
    ASSERT_TRUE(filter("[\"==\", [\"get\", \"two\"], 2]", {{"two", int64_t(2)}}));
    ASSERT_FALSE(filter("[\"==\", [\"get\", \"two\"], 4]", {{"two", int64_t(2)}}));
}

TEST(Filter, LegacyProperty) {
    ASSERT_TRUE(filter("[\"<=\", \"two\", 2]", {{"two", int64_t(2)}}));
    ASSERT_FALSE(filter("[\"==\", \"two\", 4]", {{"two", int64_t(2)}}));

    ASSERT_FALSE(filter("[\"<=\", \"two\", \"2\"]", {{"two", int64_t(2)}}));
    ASSERT_FALSE(filter("[\"==\", \"bool\", false]", {{"two", true}}));

    ASSERT_TRUE(filter("[\"<=\", \"two\", \"2\"]", {{"two", std::string("2")}}));
    ASSERT_FALSE(filter("[\"<\", \"two\", \"1\"]", {{"two", std::string("2")}}));
    ASSERT_FALSE(filter("[\"==\", \"two\", 4]", {{"two", std::string("2")}}));
}

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));
}