1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gestures/PropertyProvider.h>
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20
21 #include "TestConstants.h"
22 #include "include/gestures.h"
23
24 namespace android {
25
26 using testing::ElementsAre;
27
28 class PropertyProviderTest : public testing::Test {
29 protected:
30 PropertyProvider mProvider;
31 };
32
TEST_F(PropertyProviderTest,Int_Create)33 TEST_F(PropertyProviderTest, Int_Create) {
34 const size_t COUNT = 4;
35 int intData[COUNT] = {0, 0, 0, 0};
36 int initialValues[COUNT] = {1, 2, 3, 4};
37 gesturePropProvider.create_int_fn(&mProvider, "Some Integers", intData, COUNT, initialValues);
38
39 ASSERT_TRUE(mProvider.hasProperty("Some Integers"));
40 GesturesProp& prop = mProvider.getProperty("Some Integers");
41 EXPECT_EQ(prop.getName(), "Some Integers");
42 EXPECT_EQ(prop.getCount(), COUNT);
43 EXPECT_THAT(intData, ElementsAre(1, 2, 3, 4));
44 }
45
TEST_F(PropertyProviderTest,Int_Get)46 TEST_F(PropertyProviderTest, Int_Get) {
47 const size_t COUNT = 4;
48 int intData[COUNT] = {0, 0, 0, 0};
49 int initialValues[COUNT] = {9, 9, 9, 9};
50 GesturesProp* propPtr = gesturePropProvider.create_int_fn(&mProvider, "Some Integers", intData,
51 COUNT, initialValues);
52
53 // Get handlers are supposed to be called before the property's data is accessed, so they can
54 // update it if necessary. This getter updates the values, so that the ordering can be checked.
55 GesturesPropGetHandler getter{[](void* handlerData) -> GesturesPropBool {
56 int* array = static_cast<int*>(handlerData);
57 array[0] = 1;
58 array[1] = 2;
59 array[2] = 3;
60 array[3] = 4;
61 return true;
62 }};
63 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ intData,
64 getter, nullptr);
65
66 ASSERT_TRUE(mProvider.hasProperty("Some Integers"));
67 GesturesProp& prop = mProvider.getProperty("Some Integers");
68 EXPECT_THAT(prop.getIntValues(), ElementsAre(1, 2, 3, 4));
69 }
70
TEST_F(PropertyProviderTest,Int_Set)71 TEST_F(PropertyProviderTest, Int_Set) {
72 const size_t COUNT = 4;
73 int intData[COUNT] = {0, 0, 0, 0};
74 int initialValues[COUNT] = {9, 9, 9, 9};
75 GesturesProp* propPtr = gesturePropProvider.create_int_fn(&mProvider, "Some Integers", intData,
76 COUNT, initialValues);
77
78 struct SetterData {
79 bool setterCalled;
80 int* propertyData;
81 };
82 SetterData setterData = {false, intData};
83 GesturesPropSetHandler setter{[](void* handlerData) {
84 SetterData* data = static_cast<SetterData*>(handlerData);
85 // Set handlers should be called after the property's data has changed, so check the data.
86 EXPECT_EQ(data->propertyData[0], 1);
87 EXPECT_EQ(data->propertyData[1], 2);
88 EXPECT_EQ(data->propertyData[2], 3);
89 EXPECT_EQ(data->propertyData[3], 4);
90 data->setterCalled = true;
91 }};
92 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ &setterData,
93 nullptr, setter);
94
95 ASSERT_TRUE(mProvider.hasProperty("Some Integers"));
96 GesturesProp& prop = mProvider.getProperty("Some Integers");
97 prop.setIntValues({1, 2, 3, 4});
98 EXPECT_THAT(intData, ElementsAre(1, 2, 3, 4));
99 EXPECT_TRUE(setterData.setterCalled);
100 EXPECT_THAT(prop.getIntValues(), ElementsAre(1, 2, 3, 4));
101 }
102
TEST_F(PropertyProviderTest,Bool_Create)103 TEST_F(PropertyProviderTest, Bool_Create) {
104 const size_t COUNT = 3;
105 GesturesPropBool boolData[COUNT] = {false, false, false};
106 GesturesPropBool initialValues[COUNT] = {true, false, false};
107 gesturePropProvider.create_bool_fn(&mProvider, "Some Booleans", boolData, COUNT, initialValues);
108
109 ASSERT_TRUE(mProvider.hasProperty("Some Booleans"));
110 GesturesProp& prop = mProvider.getProperty("Some Booleans");
111 EXPECT_EQ(prop.getName(), "Some Booleans");
112 EXPECT_EQ(prop.getCount(), COUNT);
113 EXPECT_THAT(boolData, ElementsAre(true, false, false));
114 }
115
TEST_F(PropertyProviderTest,Bool_Get)116 TEST_F(PropertyProviderTest, Bool_Get) {
117 const size_t COUNT = 3;
118 GesturesPropBool boolData[COUNT] = {false, false, false};
119 GesturesPropBool initialValues[COUNT] = {true, false, false};
120 GesturesProp* propPtr = gesturePropProvider.create_bool_fn(&mProvider, "Some Booleans",
121 boolData, COUNT, initialValues);
122
123 // Get handlers are supposed to be called before the property's data is accessed, so they can
124 // update it if necessary. This getter updates the values, so that the ordering can be checked.
125 GesturesPropGetHandler getter{[](void* handlerData) -> GesturesPropBool {
126 GesturesPropBool* array = static_cast<GesturesPropBool*>(handlerData);
127 array[0] = false;
128 array[1] = true;
129 array[2] = true;
130 return true;
131 }};
132 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ boolData,
133 getter, nullptr);
134
135 ASSERT_TRUE(mProvider.hasProperty("Some Booleans"));
136 GesturesProp& prop = mProvider.getProperty("Some Booleans");
137 EXPECT_THAT(prop.getBoolValues(), ElementsAre(false, true, true));
138 }
139
TEST_F(PropertyProviderTest,Bool_Set)140 TEST_F(PropertyProviderTest, Bool_Set) {
141 const size_t COUNT = 3;
142 GesturesPropBool boolData[COUNT] = {false, false, false};
143 GesturesPropBool initialValues[COUNT] = {true, false, false};
144 GesturesProp* propPtr = gesturePropProvider.create_bool_fn(&mProvider, "Some Booleans",
145 boolData, COUNT, initialValues);
146
147 struct SetterData {
148 bool setterCalled;
149 GesturesPropBool* propertyData;
150 };
151 SetterData setterData = {false, boolData};
152 GesturesPropSetHandler setter{[](void* handlerData) {
153 SetterData* data = static_cast<SetterData*>(handlerData);
154 // Set handlers should be called after the property's data has changed, so check the data.
155 EXPECT_EQ(data->propertyData[0], false);
156 EXPECT_EQ(data->propertyData[1], true);
157 EXPECT_EQ(data->propertyData[2], true);
158 data->setterCalled = true;
159 }};
160 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ &setterData,
161 nullptr, setter);
162
163 ASSERT_TRUE(mProvider.hasProperty("Some Booleans"));
164 GesturesProp& prop = mProvider.getProperty("Some Booleans");
165 prop.setBoolValues({false, true, true});
166 EXPECT_THAT(boolData, ElementsAre(false, true, true));
167 EXPECT_TRUE(setterData.setterCalled);
168 EXPECT_THAT(prop.getBoolValues(), ElementsAre(false, true, true));
169 }
170
TEST_F(PropertyProviderTest,Real_Create)171 TEST_F(PropertyProviderTest, Real_Create) {
172 const size_t COUNT = 3;
173 double realData[COUNT] = {0.0, 0.0, 0.0};
174 double initialValues[COUNT] = {3.14, 0.7, -5.0};
175 gesturePropProvider.create_real_fn(&mProvider, "Some Reals", realData, COUNT, initialValues);
176
177 ASSERT_TRUE(mProvider.hasProperty("Some Reals"));
178 GesturesProp& prop = mProvider.getProperty("Some Reals");
179 EXPECT_EQ(prop.getName(), "Some Reals");
180 EXPECT_EQ(prop.getCount(), COUNT);
181 EXPECT_THAT(realData, ElementsAre(3.14, 0.7, -5.0));
182 }
183
TEST_F(PropertyProviderTest,Real_Get)184 TEST_F(PropertyProviderTest, Real_Get) {
185 const size_t COUNT = 3;
186 double realData[COUNT] = {0.0, 0.0, 0.0};
187 double initialValues[COUNT] = {-1.0, -1.0, -1.0};
188 GesturesProp* propPtr = gesturePropProvider.create_real_fn(&mProvider, "Some Reals", realData,
189 COUNT, initialValues);
190
191 // Get handlers are supposed to be called before the property's data is accessed, so they can
192 // update it if necessary. This getter updates the values, so that the ordering can be checked.
193 GesturesPropGetHandler getter{[](void* handlerData) -> GesturesPropBool {
194 double* array = static_cast<double*>(handlerData);
195 array[0] = 3.14;
196 array[1] = 0.7;
197 array[2] = -5.0;
198 return true;
199 }};
200 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ realData,
201 getter, nullptr);
202
203 ASSERT_TRUE(mProvider.hasProperty("Some Reals"));
204 GesturesProp& prop = mProvider.getProperty("Some Reals");
205 EXPECT_THAT(prop.getRealValues(), ElementsAre(3.14, 0.7, -5.0));
206 }
207
TEST_F(PropertyProviderTest,Real_Set)208 TEST_F(PropertyProviderTest, Real_Set) {
209 const size_t COUNT = 3;
210 double realData[COUNT] = {0.0, 0.0, 0.0};
211 double initialValues[COUNT] = {-1.0, -1.0, -1.0};
212 GesturesProp* propPtr = gesturePropProvider.create_real_fn(&mProvider, "Some Reals", realData,
213 COUNT, initialValues);
214
215 struct SetterData {
216 bool setterCalled;
217 double* propertyData;
218 };
219 SetterData setterData = {false, realData};
220 GesturesPropSetHandler setter{[](void* handlerData) {
221 SetterData* data = static_cast<SetterData*>(handlerData);
222 // Set handlers should be called after the property's data has changed, so check the data.
223 EXPECT_EQ(data->propertyData[0], 3.14);
224 EXPECT_EQ(data->propertyData[1], 0.7);
225 EXPECT_EQ(data->propertyData[2], -5.0);
226 data->setterCalled = true;
227 }};
228 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ &setterData,
229 nullptr, setter);
230
231 ASSERT_TRUE(mProvider.hasProperty("Some Reals"));
232 GesturesProp& prop = mProvider.getProperty("Some Reals");
233 prop.setRealValues({3.14, 0.7, -5.0});
234 EXPECT_THAT(realData, ElementsAre(3.14, 0.7, -5.0));
235 EXPECT_TRUE(setterData.setterCalled);
236 EXPECT_THAT(prop.getRealValues(), ElementsAre(3.14, 0.7, -5.0));
237 }
238
TEST_F(PropertyProviderTest,String_Create)239 TEST_F(PropertyProviderTest, String_Create) {
240 const char* str = nullptr;
241 std::string initialValue = "Foo";
242 gesturePropProvider.create_string_fn(&mProvider, "A String", &str, initialValue.c_str());
243
244 ASSERT_TRUE(mProvider.hasProperty("A String"));
245 GesturesProp& prop = mProvider.getProperty("A String");
246 EXPECT_EQ(prop.getName(), "A String");
247 EXPECT_EQ(prop.getCount(), 1u);
248 EXPECT_STREQ(str, "Foo");
249 }
250
TEST_F(PropertyProviderTest,String_Get)251 TEST_F(PropertyProviderTest, String_Get) {
252 const char* str = nullptr;
253 std::string initialValue = "Foo";
254 GesturesProp* propPtr = gesturePropProvider.create_string_fn(&mProvider, "A String", &str,
255 initialValue.c_str());
256
257 // Get handlers are supposed to be called before the property's data is accessed, so they can
258 // update it if necessary. This getter updates the values, so that the ordering can be checked.
259 struct GetterData {
260 const char** strPtr;
261 std::string newValue; // Have to store the new value outside getter so it stays allocated.
262 };
263 GetterData getterData = {&str, "Bar"};
264 GesturesPropGetHandler getter{[](void* handlerData) -> GesturesPropBool {
265 GetterData* data = static_cast<GetterData*>(handlerData);
266 *data->strPtr = data->newValue.c_str();
267 return true;
268 }};
269 gesturePropProvider.register_handlers_fn(&mProvider, propPtr, /* handler_data= */ &getterData,
270 getter, nullptr);
271
272 ASSERT_TRUE(mProvider.hasProperty("A String"));
273 GesturesProp& prop = mProvider.getProperty("A String");
274 EXPECT_EQ(prop.getStringValue(), "Bar");
275 }
276
TEST_F(PropertyProviderTest,Free)277 TEST_F(PropertyProviderTest, Free) {
278 int intData = 0;
279 int initialValue = 42;
280 GesturesProp* propPtr =
281 gesturePropProvider.create_int_fn(&mProvider, "Foo", &intData, 1, &initialValue);
282 gesturePropProvider.free_fn(&mProvider, propPtr);
283
284 EXPECT_FALSE(mProvider.hasProperty("Foo"));
285 }
286
287 class PropertyProviderIdcLoadingTest : public testing::Test {
288 protected:
SetUp()289 void SetUp() override {
290 int initialInt = 0;
291 GesturesPropBool initialBool = false;
292 double initialReal = 0.0;
293 gesturePropProvider.create_int_fn(&mProvider, "An Integer", &mIntData, 1, &initialInt);
294 gesturePropProvider.create_bool_fn(&mProvider, "A Boolean", &mBoolData, 1, &initialBool);
295 gesturePropProvider.create_real_fn(&mProvider, "A Real", &mRealData, 1, &initialReal);
296 }
297
298 PropertyProvider mProvider;
299
300 int mIntData;
301 GesturesPropBool mBoolData;
302 double mRealData;
303 };
304
TEST_F(PropertyProviderIdcLoadingTest,AllCorrect)305 TEST_F(PropertyProviderIdcLoadingTest, AllCorrect) {
306 PropertyMap idcProps;
307 idcProps.addProperty("gestureProp.An_Integer", "42");
308 idcProps.addProperty("gestureProp.A_Boolean", "1");
309 idcProps.addProperty("gestureProp.A_Real", "3.14159");
310
311 mProvider.loadPropertiesFromIdcFile(idcProps);
312 EXPECT_THAT(mProvider.getProperty("An Integer").getIntValues(), ElementsAre(42));
313 EXPECT_THAT(mProvider.getProperty("A Boolean").getBoolValues(), ElementsAre(true));
314 EXPECT_NEAR(mProvider.getProperty("A Real").getRealValues()[0], 3.14159, EPSILON);
315 }
316
TEST_F(PropertyProviderIdcLoadingTest,InvalidPropsIgnored)317 TEST_F(PropertyProviderIdcLoadingTest, InvalidPropsIgnored) {
318 int intArrayData[2];
319 int initialInts[2] = {0, 1};
320 gesturePropProvider.create_int_fn(&mProvider, "Two Integers", intArrayData, 2, initialInts);
321
322 PropertyMap idcProps;
323 // Wrong type
324 idcProps.addProperty("gestureProp.An_Integer", "37.25");
325 // Wrong size
326 idcProps.addProperty("gestureProp.Two_Integers", "42");
327 // Doesn't exist
328 idcProps.addProperty("gestureProp.Some_Nonexistent_Property", "1");
329 // A valid assignment that should still be applied despite the others being invalid
330 idcProps.addProperty("gestureProp.A_Real", "3.14159");
331
332 mProvider.loadPropertiesFromIdcFile(idcProps);
333 EXPECT_THAT(mProvider.getProperty("An Integer").getIntValues(), ElementsAre(0));
334 EXPECT_THAT(mProvider.getProperty("Two Integers").getIntValues(), ElementsAre(0, 1));
335 EXPECT_FALSE(mProvider.hasProperty("Some Nonexistent Property"));
336 EXPECT_NEAR(mProvider.getProperty("A Real").getRealValues()[0], 3.14159, EPSILON);
337 }
338
TEST_F(PropertyProviderIdcLoadingTest,FunkyName)339 TEST_F(PropertyProviderIdcLoadingTest, FunkyName) {
340 int data;
341 int initialData = 0;
342 gesturePropProvider.create_int_fn(&mProvider, " I lOvE sNAKes ", &data, 1, &initialData);
343
344 PropertyMap idcProps;
345 idcProps.addProperty("gestureProp.__I_lOvE_sNAKes_", "42");
346
347 mProvider.loadPropertiesFromIdcFile(idcProps);
348 EXPECT_THAT(mProvider.getProperty(" I lOvE sNAKes ").getIntValues(), ElementsAre(42));
349 }
350
351 } // namespace android
352