1 /*
2 * Copyright (C) 2016 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 <unordered_map>
18 #include <iostream>
19
20 #include <android-base/macros.h>
21 #include <cutils/native_handle.h>
22 #include <utils/SystemClock.h>
23
24 #include <gtest/gtest.h>
25
26 #include "vhal_v2_0/VehicleHalManager.h"
27
28 #include "VehicleHalTestUtils.h"
29
30 namespace android {
31 namespace hardware {
32 namespace automotive {
33 namespace vehicle {
34 namespace V2_0 {
35
36 // A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
37 class VehicleHalManagerTestHelper {
38 public:
VehicleHalManagerTestHelper(VehicleHalManager * manager)39 VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
cmdSetOneProperty(int fd,const hidl_vec<hidl_string> & options)40 bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
41 return mManager->cmdSetOneProperty(fd, options);
42 }
43
44 public:
45 VehicleHalManager* mManager;
46 };
47
48 namespace {
49
50 using namespace std::placeholders;
51
52 constexpr char kCarMake[] = "Default Car";
53 constexpr int kRetriablePropMockedAttempts = 3;
54
55 class MockedVehicleHal : public VehicleHal {
56 public:
MockedVehicleHal()57 MockedVehicleHal() {
58 mConfigs.assign(std::begin(kVehicleProperties),
59 std::end(kVehicleProperties));
60 }
61
listProperties()62 std::vector<VehiclePropConfig> listProperties() override {
63 return mConfigs;
64 }
65
get(const VehiclePropValue & requestedPropValue,StatusCode * outStatus)66 VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
67 StatusCode* outStatus) override {
68 *outStatus = StatusCode::OK;
69 VehiclePropValuePtr pValue;
70 auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
71 int32_t areaId = requestedPropValue.areaId;
72
73 if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
74 if (fuelCapacityAttemptsLeft-- > 0) {
75 // Emulate property not ready yet.
76 *outStatus = StatusCode::TRY_AGAIN;
77 } else {
78 pValue = getValuePool()->obtainFloat(42.42);
79 }
80 } else {
81 auto key = makeKey(requestedPropValue);
82 if (mValues.count(key) == 0) {
83 ALOGW("key not found\n");
84 *outStatus = StatusCode::INVALID_ARG;
85 return pValue;
86 }
87 pValue = getValuePool()->obtain(mValues[key]);
88 }
89
90 if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
91 pValue->prop = toInt(property);
92 pValue->areaId = areaId;
93 pValue->timestamp = elapsedRealtimeNano();
94 }
95
96 return pValue;
97 }
98
set(const VehiclePropValue & propValue)99 StatusCode set(const VehiclePropValue& propValue) override {
100 if (toInt(VehicleProperty::MIRROR_FOLD) == propValue.prop
101 && mirrorFoldAttemptsLeft-- > 0) {
102 return StatusCode::TRY_AGAIN;
103 }
104 mValues[makeKey(propValue)] = propValue;
105 return StatusCode::OK;
106 }
107
subscribe(int32_t,float)108 StatusCode subscribe(int32_t /* property */,
109 float /* sampleRate */) override {
110 return StatusCode::OK;
111 }
112
unsubscribe(int32_t)113 StatusCode unsubscribe(int32_t /* property */) override {
114 return StatusCode::OK;
115 }
116
sendPropEvent(recyclable_ptr<VehiclePropValue> value)117 void sendPropEvent(recyclable_ptr<VehiclePropValue> value) {
118 doHalEvent(std::move(value));
119 }
120
sendHalError(StatusCode error,int32_t property,int32_t areaId)121 void sendHalError(StatusCode error, int32_t property, int32_t areaId) {
122 doHalPropertySetError(error, property, areaId);
123 }
124
125 public:
126 int fuelCapacityAttemptsLeft = kRetriablePropMockedAttempts;
127 int mirrorFoldAttemptsLeft = kRetriablePropMockedAttempts;
128
129 private:
makeKey(const VehiclePropValue & v) const130 int64_t makeKey(const VehiclePropValue& v) const {
131 return makeKey(v.prop, v.areaId);
132 }
133
makeKey(int32_t prop,int32_t area) const134 int64_t makeKey(int32_t prop, int32_t area) const {
135 return (static_cast<int64_t>(prop) << 32) | area;
136 }
137
138 private:
139 std::vector<VehiclePropConfig> mConfigs;
140 std::unordered_map<int64_t, VehiclePropValue> mValues;
141 };
142
143 class VehicleHalManagerTest : public ::testing::Test {
144 protected:
SetUp()145 void SetUp() override {
146 hal.reset(new MockedVehicleHal);
147 manager.reset(new VehicleHalManager(hal.get()));
148
149 objectPool = hal->getValuePool();
150 }
151
TearDown()152 void TearDown() override {
153 manager.reset(nullptr);
154 hal.reset(nullptr);
155 }
156 public:
invokeGet(int32_t property,int32_t areaId)157 void invokeGet(int32_t property, int32_t areaId) {
158 VehiclePropValue requestedValue {};
159 requestedValue.prop = property;
160 requestedValue.areaId = areaId;
161
162 invokeGet(requestedValue);
163 }
164
invokeGet(const VehiclePropValue & requestedPropValue)165 void invokeGet(const VehiclePropValue& requestedPropValue) {
166 actualValue = VehiclePropValue {}; // reset previous values
167
168 StatusCode refStatus;
169 VehiclePropValue refValue;
170 bool called = false;
171 manager->get(requestedPropValue, [&refStatus, &refValue, &called]
172 (StatusCode status, const VehiclePropValue& value) {
173 refStatus = status;
174 refValue = value;
175 called = true;
176 });
177 ASSERT_TRUE(called) << "callback wasn't called for prop: "
178 << hexString(requestedPropValue.prop);
179
180 actualValue = refValue;
181 actualStatusCode = refStatus;
182 }
183
getComplexProperty()184 MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
185 auto pValue = objectPool->obtainComplex();
186 pValue->prop = kCustomComplexProperty;
187 pValue->areaId = 0;
188 pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
189 pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
190 pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
191 pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
192 pValue->value.stringValue = kCarMake;
193 return pValue;
194 }
195
196 public:
197 VehiclePropValue actualValue;
198 StatusCode actualStatusCode;
199
200 VehiclePropValuePool* objectPool;
201 std::unique_ptr<MockedVehicleHal> hal;
202 std::unique_ptr<VehicleHalManager> manager;
203 };
204
TEST_F(VehicleHalManagerTest,getPropConfigs)205 TEST_F(VehicleHalManagerTest, getPropConfigs) {
206 hidl_vec<int32_t> properties =
207 { toInt(VehicleProperty::HVAC_FAN_SPEED),
208 toInt(VehicleProperty::INFO_MAKE) };
209 bool called = false;
210
211 manager->getPropConfigs(properties,
212 [&called] (StatusCode status,
213 const hidl_vec<VehiclePropConfig>& c) {
214 ASSERT_EQ(StatusCode::OK, status);
215 ASSERT_EQ(2u, c.size());
216 called = true;
217 });
218
219 ASSERT_TRUE(called); // Verify callback received.
220
221 called = false;
222 manager->getPropConfigs({ toInt(VehicleProperty::HVAC_FAN_SPEED) },
223 [&called] (StatusCode status,
224 const hidl_vec<VehiclePropConfig>& c) {
225 ASSERT_EQ(StatusCode::OK, status);
226 ASSERT_EQ(1u, c.size());
227 ASSERT_EQ(toString(kVehicleProperties[1]), toString(c[0]));
228 called = true;
229 });
230 ASSERT_TRUE(called); // Verify callback received.
231
232 // TODO(pavelm): add case case when property was not declared.
233 }
234
TEST_F(VehicleHalManagerTest,getAllPropConfigs)235 TEST_F(VehicleHalManagerTest, getAllPropConfigs) {
236 bool called = false;
237 manager->getAllPropConfigs(
238 [&called] (const hidl_vec<VehiclePropConfig>& propConfigs) {
239 ASSERT_EQ(arraysize(kVehicleProperties), propConfigs.size());
240
241 for (size_t i = 0; i < propConfigs.size(); i++) {
242 ASSERT_EQ(toString(kVehicleProperties[i]),
243 toString(propConfigs[i]));
244 }
245 called = true;
246 });
247 ASSERT_TRUE(called); // Verify callback received.
248 }
249
TEST_F(VehicleHalManagerTest,halErrorEvent)250 TEST_F(VehicleHalManagerTest, halErrorEvent) {
251 const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
252
253 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
254
255 hidl_vec<SubscribeOptions> options = {
256 SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
257 };
258
259 StatusCode res = manager->subscribe(cb, options);
260 ASSERT_EQ(StatusCode::OK, res);
261
262 hal->sendHalError(StatusCode::TRY_AGAIN, PROP, 0 /* area id*/);
263 }
264
TEST_F(VehicleHalManagerTest,subscribe)265 TEST_F(VehicleHalManagerTest, subscribe) {
266 const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
267
268 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
269
270 hidl_vec<SubscribeOptions> options = {
271 SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
272
273 StatusCode res = manager->subscribe(cb, options);
274 ASSERT_EQ(StatusCode::OK, res);
275
276 auto unsubscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
277 unsubscribedValue->prop = toInt(VehicleProperty::HVAC_FAN_SPEED);
278
279 hal->sendPropEvent(std::move(unsubscribedValue));
280 auto& receivedEnvents = cb->getReceivedEvents();
281
282 ASSERT_TRUE(cb->waitForExpectedEvents(0)) << " Unexpected events received: "
283 << receivedEnvents.size()
284 << (receivedEnvents.size() > 0
285 ? toString(receivedEnvents.front()[0]) : "");
286
287 auto subscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
288 subscribedValue->prop = PROP;
289 subscribedValue->value.int32Values[0] = 42;
290
291 cb->reset();
292 VehiclePropValue actualValue(*subscribedValue.get());
293 hal->sendPropEvent(std::move(subscribedValue));
294
295 ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
296 << receivedEnvents.size();
297
298 ASSERT_EQ(toString(actualValue),
299 toString(cb->getReceivedEvents().front()[0]));
300 }
301
TEST_F(VehicleHalManagerTest,subscribe_WriteOnly)302 TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) {
303 const auto PROP = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE);
304
305 sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
306
307 hidl_vec<SubscribeOptions> options = {
308 SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
309 };
310
311 StatusCode res = manager->subscribe(cb, options);
312 // Unable to subscribe on Hal Events for write-only properties.
313 ASSERT_EQ(StatusCode::INVALID_ARG, res);
314
315 options[0].flags = SubscribeFlags::EVENTS_FROM_ANDROID;
316
317 res = manager->subscribe(cb, options);
318 // OK to subscribe on SET method call for write-only properties.
319 ASSERT_EQ(StatusCode::OK, res);
320 }
321
TEST_F(VehicleHalManagerTest,get_Complex)322 TEST_F(VehicleHalManagerTest, get_Complex) {
323 ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
324
325 invokeGet(kCustomComplexProperty, 0);
326
327 ASSERT_EQ(StatusCode::OK, actualStatusCode);
328 ASSERT_EQ(kCustomComplexProperty, actualValue.prop);
329
330 ASSERT_EQ(3u, actualValue.value.bytes.size());
331 ASSERT_EQ(1, actualValue.value.bytes[0]);
332 ASSERT_EQ(2, actualValue.value.bytes[1]);
333 ASSERT_EQ(3, actualValue.value.bytes[2]);
334
335 ASSERT_EQ(2u, actualValue.value.int32Values.size());
336 ASSERT_EQ(10, actualValue.value.int32Values[0]);
337 ASSERT_EQ(20, actualValue.value.int32Values[1]);
338
339 ASSERT_EQ(2u, actualValue.value.floatValues.size());
340 ASSERT_FLOAT_EQ(1.1, actualValue.value.floatValues[0]);
341 ASSERT_FLOAT_EQ(2.2, actualValue.value.floatValues[1]);
342
343 ASSERT_EQ(2u, actualValue.value.int64Values.size());
344 ASSERT_FLOAT_EQ(30, actualValue.value.int64Values[0]);
345 ASSERT_FLOAT_EQ(40, actualValue.value.int64Values[1]);
346
347 ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
348 }
349
TEST_F(VehicleHalManagerTest,get_StaticString)350 TEST_F(VehicleHalManagerTest, get_StaticString) {
351 auto pValue = objectPool->obtainString(kCarMake);
352 pValue->prop = toInt(VehicleProperty::INFO_MAKE);
353 pValue->areaId = 0;
354 ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
355
356 invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
357
358 ASSERT_EQ(StatusCode::OK, actualStatusCode);
359 ASSERT_EQ(toInt(VehicleProperty::INFO_MAKE), actualValue.prop);
360 ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
361 }
362
TEST_F(VehicleHalManagerTest,get_NegativeCases)363 TEST_F(VehicleHalManagerTest, get_NegativeCases) {
364 // Write-only property must fail.
365 invokeGet(toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE), 0);
366 ASSERT_EQ(StatusCode::ACCESS_DENIED, actualStatusCode);
367
368 // Unknown property must fail.
369 invokeGet(toInt(VehicleProperty::MIRROR_Z_MOVE), 0);
370 ASSERT_EQ(StatusCode::INVALID_ARG, actualStatusCode);
371 }
372
TEST_F(VehicleHalManagerTest,get_Retriable)373 TEST_F(VehicleHalManagerTest, get_Retriable) {
374 actualStatusCode = StatusCode::TRY_AGAIN;
375 int attempts = 0;
376 while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
377 invokeGet(toInt(VehicleProperty::INFO_FUEL_CAPACITY), 0);
378
379 }
380 ASSERT_EQ(StatusCode::OK, actualStatusCode);
381 ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
382 ASSERT_FLOAT_EQ(42.42, actualValue.value.floatValues[0]);
383 }
384
TEST_F(VehicleHalManagerTest,set_Basic)385 TEST_F(VehicleHalManagerTest, set_Basic) {
386 const auto PROP = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
387 const auto VAL = 7;
388
389 auto expectedValue = hal->getValuePool()->obtainInt32(VAL);
390 expectedValue->prop = PROP;
391 expectedValue->areaId = 0;
392
393 actualStatusCode = manager->set(*expectedValue.get());
394 ASSERT_EQ(StatusCode::OK, actualStatusCode);
395
396 invokeGet(PROP, 0);
397 ASSERT_EQ(StatusCode::OK, actualStatusCode);
398 ASSERT_EQ(PROP, actualValue.prop);
399 ASSERT_EQ(VAL, actualValue.value.int32Values[0]);
400 }
401
TEST_F(VehicleHalManagerTest,set_DifferentAreas)402 TEST_F(VehicleHalManagerTest, set_DifferentAreas) {
403 const auto PROP = toInt(VehicleProperty::HVAC_FAN_SPEED);
404 const auto VAL1 = 1;
405 const auto VAL2 = 2;
406 const auto AREA1 = toInt(VehicleAreaSeat::ROW_1_LEFT);
407 const auto AREA2 = toInt(VehicleAreaSeat::ROW_1_RIGHT);
408
409 {
410 auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
411 expectedValue1->prop = PROP;
412 expectedValue1->areaId = AREA1;
413 actualStatusCode = manager->set(*expectedValue1.get());
414 ASSERT_EQ(StatusCode::OK, actualStatusCode);
415
416 auto expectedValue2 = hal->getValuePool()->obtainInt32(VAL2);
417 expectedValue2->prop = PROP;
418 expectedValue2->areaId = AREA2;
419 actualStatusCode = manager->set(*expectedValue2.get());
420 ASSERT_EQ(StatusCode::OK, actualStatusCode);
421 }
422
423 {
424 invokeGet(PROP, AREA1);
425 ASSERT_EQ(StatusCode::OK, actualStatusCode);
426 ASSERT_EQ(PROP, actualValue.prop);
427 ASSERT_EQ(AREA1, actualValue.areaId);
428 ASSERT_EQ(VAL1, actualValue.value.int32Values[0]);
429
430 invokeGet(PROP, AREA2);
431 ASSERT_EQ(StatusCode::OK, actualStatusCode);
432 ASSERT_EQ(PROP, actualValue.prop);
433 ASSERT_EQ(AREA2, actualValue.areaId);
434 ASSERT_EQ(VAL2, actualValue.value.int32Values[0]);
435 }
436 }
437
TEST_F(VehicleHalManagerTest,set_Retriable)438 TEST_F(VehicleHalManagerTest, set_Retriable) {
439 const auto PROP = toInt(VehicleProperty::MIRROR_FOLD);
440
441 auto v = hal->getValuePool()->obtainBoolean(true);
442 v->prop = PROP;
443 v->areaId = 0;
444
445 actualStatusCode = StatusCode::TRY_AGAIN;
446 int attempts = 0;
447 while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
448 actualStatusCode = manager->set(*v.get());
449 }
450
451 ASSERT_EQ(StatusCode::OK, actualStatusCode);
452 ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
453
454 invokeGet(PROP, 0);
455 ASSERT_EQ(StatusCode::OK, actualStatusCode);
456 ASSERT_TRUE(actualValue.value.int32Values[0]);
457 }
458
TEST(HalClientVectorTest,basic)459 TEST(HalClientVectorTest, basic) {
460 HalClientVector clients;
461 sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
462
463 sp<HalClient> c1 = new HalClient(callback1);
464 sp<HalClient> c2 = new HalClient(callback1);
465
466 clients.addOrUpdate(c1);
467 clients.addOrUpdate(c1);
468 clients.addOrUpdate(c2);
469 ASSERT_EQ(2u, clients.size());
470 ASSERT_FALSE(clients.isEmpty());
471 ASSERT_LE(0, clients.indexOf(c1));
472 ASSERT_LE(0, clients.remove(c1));
473 ASSERT_GT(0, clients.indexOf(c1)); // c1 was already removed
474 ASSERT_GT(0, clients.remove(c1)); // attempt to remove c1 again
475 ASSERT_LE(0, clients.remove(c2));
476
477 ASSERT_TRUE(clients.isEmpty());
478 }
479
TEST_F(VehicleHalManagerTest,debug)480 TEST_F(VehicleHalManagerTest, debug) {
481 hidl_handle fd = {};
482 fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
483
484 // Because debug function returns void, so no way to check return value.
485 manager->debug(fd, {});
486 manager->debug(fd, {"--help"});
487 manager->debug(fd, {"--list"});
488 manager->debug(fd, {"--get"});
489 manager->debug(fd, {"--set"});
490 manager->debug(fd, {"invalid"});
491 }
492
493 struct SetPropTestCase {
494 std::string test_name;
495 const hidl_vec<hidl_string> configs;
496 bool success;
497 };
498
499 class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
500 public testing::WithParamInterface<SetPropTestCase> {};
501
TEST_P(VehicleHalManagerSetPropTest,cmdSetOneProperty)502 TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
503 const SetPropTestCase& tc = GetParam();
504 VehicleHalManagerTestHelper helper(manager.get());
505 ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
506 }
507
GenSetPropParams()508 std::vector<SetPropTestCase> GenSetPropParams() {
509 char infoMakeProperty[100] = {};
510 snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
511 return {
512 {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
513 {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
514 {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
515 {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
516 {"success_set_ints",
517 {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
518 true},
519 {"success_set_int64",
520 {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
521 true},
522 {"success_set_int64s",
523 {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
524 "9223372036854775807"},
525 true},
526 {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
527 {"success_set_floats",
528 {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
529 true},
530 {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
531 {"fail_no_options", {}, false},
532 {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
533 {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
534 {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
535 {"fail_duplicate_string",
536 {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
537 false},
538 {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
539 {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
540 {"fail_duplicate_bytes",
541 {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
542 false},
543 {"fail_multiple_bytes",
544 {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
545 false},
546 {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
547 {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
548 {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
549 {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
550 {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
551 {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
552 {"fail_int64_out_of_range",
553 {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
554 false},
555 {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
556 {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
557 {"fail_float_out_of_range",
558 {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
559 false},
560 {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
561 {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
562 {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
563 {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
564 {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
565 };
566 }
567
568 INSTANTIATE_TEST_SUITE_P(
569 VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
570 testing::ValuesIn(GenSetPropParams()),
__anon2922a9af0602(const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) 571 [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
572 return info.param.test_name;
573 });
574
TEST_F(VehicleHalManagerTest,SetComplexPropTest)575 TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
576 char infoMakeProperty[100] = {};
577 snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
578 VehicleHalManagerTestHelper helper(manager.get());
579 ASSERT_TRUE(helper.cmdSetOneProperty(
580 STDERR_FILENO, {"--set", infoMakeProperty, "-s", kCarMake,
581 "-b", "0xdeadbeef", "-i", "2147483647",
582 "0", "-2147483648", "-i64", "-9223372036854775808",
583 "0", "9223372036854775807", "-f", "-3.402823466E+38",
584 "0", "3.402823466E+38", "-a", "123"}));
585 StatusCode status = StatusCode::OK;
586 VehiclePropValue requestProp;
587 requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
588 requestProp.areaId = 123;
589 auto value = hal->get(requestProp, &status);
590 ASSERT_EQ(StatusCode::OK, status);
591 ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
592 ASSERT_EQ(value->areaId, 123);
593 ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
594 uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
595 ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
596 ASSERT_EQ(3u, value->value.int32Values.size());
597 ASSERT_EQ(2147483647, value->value.int32Values[0]);
598 ASSERT_EQ(0, value->value.int32Values[1]);
599 ASSERT_EQ(-2147483648, value->value.int32Values[2]);
600 ASSERT_EQ(3u, value->value.int64Values.size());
601 // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
602 // tokens and the later does not fit in unsigned long long.
603 ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
604 ASSERT_EQ(0, value->value.int64Values[1]);
605 ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
606 ASSERT_EQ(3u, value->value.floatValues.size());
607 ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
608 ASSERT_EQ(0.0f, value->value.floatValues[1]);
609 ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
610 }
611
612 } // namespace anonymous
613
614 } // namespace V2_0
615 } // namespace vehicle
616 } // namespace automotive
617 } // namespace hardware
618 } // namespace android
619