1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "GRPCVehicleHardware.h"
16 #include "VehicleServer.grpc.pb.h"
17 #include "VehicleServer.pb.h"
18 #include "VehicleServer_mock.grpc.pb.h"
19
20 #include <gmock/gmock.h>
21 #include <grpc++/grpc++.h>
22 #include <grpcpp/test/mock_stream.h>
23 #include <gtest/gtest.h>
24
25 #include <utils/SystemClock.h>
26 #include <chrono>
27 #include <memory>
28 #include <string>
29
30 namespace android::hardware::automotive::vehicle::virtualization {
31
32 namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
33
34 using ::testing::_;
35 using ::testing::DoAll;
36 using ::testing::ElementsAre;
37 using ::testing::NiceMock;
38 using ::testing::Return;
39 using ::testing::SaveArg;
40 using ::testing::SetArgPointee;
41 using ::testing::SizeIs;
42
43 using ::grpc::testing::MockClientReader;
44
45 using proto::MockVehicleServerStub;
46
47 class GRPCVehicleHardwareUnitTest : public ::testing::Test {
48 protected:
49 NiceMock<MockVehicleServerStub>* mGrpcStub;
50 std::unique_ptr<GRPCVehicleHardware> mHardware;
51
SetUp()52 void SetUp() override {
53 auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
54 mGrpcStub = stub.get();
55 // Cannot use make_unique here since the constructor is a private method.
56 mHardware = std::unique_ptr<GRPCVehicleHardware>(
57 new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/false));
58 }
59
TearDown()60 void TearDown() override { mHardware.reset(); }
61
62 // Access GRPCVehicleHardware private method.
pollValue()63 void pollValue() { mHardware->pollValue(); }
64
startValuePollingLoop(std::unique_ptr<proto::VehicleServer::StubInterface> stub)65 void startValuePollingLoop(std::unique_ptr<proto::VehicleServer::StubInterface> stub) {
66 mHardware = std::unique_ptr<GRPCVehicleHardware>(
67 new GRPCVehicleHardware(std::move(stub), /*startValuePollingLoop=*/true));
68 }
69
70 void generatePropertyUpdateEvent(int32_t propId, int64_t timestamp);
71 };
72
73 MATCHER_P(RepeatedInt32Eq, expected_values, "") {
74 return std::vector<int32_t>(arg.begin(), arg.end()) == expected_values;
75 }
76
TEST_F(GRPCVehicleHardwareUnitTest,TestSubscribe)77 TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribe) {
78 proto::VehicleHalCallStatus protoStatus;
79 protoStatus.set_status_code(proto::StatusCode::OK);
80 proto::SubscribeRequest actualRequest;
81
82 EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
83 .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
84 Return(::grpc::Status::OK)));
85
86 aidlvhal::SubscribeOptions options = {.propId = 1,
87 .areaIds = {1, 2, 3, 4},
88 .sampleRate = 1.234,
89 .resolution = 0.01,
90 .enableVariableUpdateRate = true};
91 auto status = mHardware->subscribe(options);
92
93 EXPECT_EQ(status, aidlvhal::StatusCode::OK);
94 const auto& protoOptions = actualRequest.options();
95 EXPECT_EQ(protoOptions.prop_id(), 1);
96 EXPECT_THAT(protoOptions.area_ids(), RepeatedInt32Eq(std::vector<int32_t>({1, 2, 3, 4})));
97 EXPECT_FLOAT_EQ(protoOptions.sample_rate(), 1.234);
98 EXPECT_FLOAT_EQ(protoOptions.resolution(), 0.01);
99 EXPECT_EQ(protoOptions.enable_variable_update_rate(), true);
100 }
101
TEST_F(GRPCVehicleHardwareUnitTest,TestSubscribeLegacyServer)102 TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeLegacyServer) {
103 EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
104 .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
105
106 aidlvhal::SubscribeOptions options;
107 auto status = mHardware->subscribe(options);
108
109 EXPECT_EQ(status, aidlvhal::StatusCode::OK);
110 }
111
TEST_F(GRPCVehicleHardwareUnitTest,TestSubscribeGrpcFailure)112 TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeGrpcFailure) {
113 EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
114 .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
115
116 aidlvhal::SubscribeOptions options;
117 auto status = mHardware->subscribe(options);
118
119 EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
120 }
121
TEST_F(GRPCVehicleHardwareUnitTest,TestSubscribeProtoFailure)122 TEST_F(GRPCVehicleHardwareUnitTest, TestSubscribeProtoFailure) {
123 proto::VehicleHalCallStatus protoStatus;
124 protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
125
126 EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
127 .WillOnce(DoAll(SetArgPointee<2>(protoStatus), // Set the output status
128 Return(::grpc::Status::OK)));
129
130 aidlvhal::SubscribeOptions options;
131 auto status = mHardware->subscribe(options);
132
133 EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
134 }
135
TEST_F(GRPCVehicleHardwareUnitTest,TestUnsubscribe)136 TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribe) {
137 proto::VehicleHalCallStatus protoStatus;
138 protoStatus.set_status_code(proto::StatusCode::OK);
139 proto::UnsubscribeRequest actualRequest;
140
141 EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
142 .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
143 Return(::grpc::Status::OK)));
144
145 int32_t propId = 1;
146 int32_t areaId = 2;
147 auto status = mHardware->unsubscribe(propId, areaId);
148
149 EXPECT_EQ(status, aidlvhal::StatusCode::OK);
150 EXPECT_EQ(actualRequest.prop_id(), propId);
151 EXPECT_EQ(actualRequest.area_id(), areaId);
152 }
153
TEST_F(GRPCVehicleHardwareUnitTest,TestUnsubscribeLegacyServer)154 TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeLegacyServer) {
155 EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
156 .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
157
158 auto status = mHardware->unsubscribe(1, 2);
159
160 EXPECT_EQ(status, aidlvhal::StatusCode::OK);
161 }
162
TEST_F(GRPCVehicleHardwareUnitTest,TestUnsubscribeGrpcFailure)163 TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeGrpcFailure) {
164 EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
165 .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
166
167 auto status = mHardware->unsubscribe(1, 2);
168
169 EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
170 }
171
TEST_F(GRPCVehicleHardwareUnitTest,TestUnsubscribeProtoFailure)172 TEST_F(GRPCVehicleHardwareUnitTest, TestUnsubscribeProtoFailure) {
173 proto::VehicleHalCallStatus protoStatus;
174 protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
175
176 EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
177 .WillOnce(DoAll(SetArgPointee<2>(protoStatus), // Set the output status
178 Return(::grpc::Status::OK)));
179
180 auto status = mHardware->unsubscribe(1, 2);
181
182 EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
183 }
184
TEST_F(GRPCVehicleHardwareUnitTest,TestPollValue)185 TEST_F(GRPCVehicleHardwareUnitTest, TestPollValue) {
186 int64_t testTimestamp = 12345;
187 int32_t testPropId = 54321;
188 int64_t startTimestamp = elapsedRealtimeNano();
189
190 // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
191 // there.
192 auto clientReader = new MockClientReader<proto::VehiclePropValues>();
193 EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
194 EXPECT_CALL(*clientReader, Read(_))
195 .WillOnce([testTimestamp, testPropId](proto::VehiclePropValues* values) {
196 values->Clear();
197 auto value = values->add_values();
198 value->set_timestamp(testTimestamp);
199 value->set_prop(testPropId);
200 return true;
201 })
202 .WillOnce(Return(false));
203 EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
204
205 std::vector<aidlvhal::VehiclePropValue> propertyEvents;
206
207 mHardware->registerOnPropertyChangeEvent(
208 std::make_unique<GRPCVehicleHardware::PropertyChangeCallback>(
209 [&propertyEvents](const std::vector<aidlvhal::VehiclePropValue>& events) {
210 for (const auto& event : events) {
211 propertyEvents.push_back(event);
212 }
213 }));
214
215 pollValue();
216
217 ASSERT_THAT(propertyEvents, SizeIs(1));
218 EXPECT_EQ(propertyEvents[0].prop, testPropId);
219 EXPECT_GT(propertyEvents[0].timestamp, startTimestamp)
220 << "Timestamp must be updated to Android timestamp";
221 EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano())
222 << "Timestamp must be updated to Android timestamp";
223 }
224
TEST_F(GRPCVehicleHardwareUnitTest,TestPollValueIgnoreOutdatedValue)225 TEST_F(GRPCVehicleHardwareUnitTest, TestPollValueIgnoreOutdatedValue) {
226 int64_t testTimestamp1 = 12345;
227 int32_t value1 = 1324;
228 int64_t testTimestamp2 = 12340;
229 int32_t value2 = 1423;
230 int32_t testPropId = 54321;
231 int64_t startTimestamp = elapsedRealtimeNano();
232
233 // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
234 // there.
235 auto clientReader = new MockClientReader<proto::VehiclePropValues>();
236 EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
237 EXPECT_CALL(*clientReader, Read(_))
238 .WillOnce([testTimestamp1, value1, testPropId](proto::VehiclePropValues* values) {
239 values->Clear();
240 auto value = values->add_values();
241 value->set_timestamp(testTimestamp1);
242 value->set_prop(testPropId);
243 value->add_int32_values(value1);
244 return true;
245 })
246 .WillOnce([testTimestamp2, value2, testPropId](proto::VehiclePropValues* values) {
247 values->Clear();
248 // This event is outdated, must be ignored.
249 auto value = values->add_values();
250 value->set_timestamp(testTimestamp2);
251 value->set_prop(testPropId);
252 value->add_int32_values(value2);
253 return true;
254 })
255 .WillOnce(Return(false));
256 EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
257
258 std::vector<aidlvhal::VehiclePropValue> propertyEvents;
259
260 mHardware->registerOnPropertyChangeEvent(
261 std::make_unique<GRPCVehicleHardware::PropertyChangeCallback>(
262 [&propertyEvents](const std::vector<aidlvhal::VehiclePropValue>& events) {
263 for (const auto& event : events) {
264 propertyEvents.push_back(event);
265 }
266 }));
267
268 pollValue();
269
270 ASSERT_THAT(propertyEvents, SizeIs(1)) << "Outdated event must be ignored";
271 EXPECT_EQ(propertyEvents[0].prop, testPropId);
272 EXPECT_GT(propertyEvents[0].timestamp, startTimestamp);
273 EXPECT_LT(propertyEvents[0].timestamp, elapsedRealtimeNano());
274 EXPECT_THAT(propertyEvents[0].value.int32Values, ElementsAre(value1));
275 }
276
TEST_F(GRPCVehicleHardwareUnitTest,TestValuePollingLoop)277 TEST_F(GRPCVehicleHardwareUnitTest, TestValuePollingLoop) {
278 int64_t testTimestamp = 12345;
279 int32_t testPropId = 54321;
280 auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
281
282 // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
283 // there.
284 auto clientReader = new MockClientReader<proto::VehiclePropValues>();
285 EXPECT_CALL(*stub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
286 EXPECT_CALL(*clientReader, Read(_))
287 .WillRepeatedly([testTimestamp, testPropId](proto::VehiclePropValues* values) {
288 // Sleep for 10ms and always return the same property event.
289 std::this_thread::sleep_for(std::chrono::milliseconds(10));
290 values->Clear();
291 auto value = values->add_values();
292 value->set_timestamp(testTimestamp);
293 value->set_prop(testPropId);
294 return true;
295 });
296 EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
297
298 startValuePollingLoop(std::move(stub));
299
300 std::this_thread::sleep_for(std::chrono::milliseconds(100));
301
302 // This must stop the loop and wait for the thread to finish.
303 mHardware.reset();
304 }
305
TEST_F(GRPCVehicleHardwareUnitTest,TestGetValues)306 TEST_F(GRPCVehicleHardwareUnitTest, TestGetValues) {
307 int64_t testRequestId = 1234;
308 int32_t testPropId = 4321;
309 int32_t testValue = 123456;
310 proto::VehiclePropValueRequests gotRequests;
311 EXPECT_CALL(*mGrpcStub, GetValues(_, _, _))
312 .WillOnce([&gotRequests, testRequestId, testPropId, testValue](
313 ::grpc::ClientContext* context,
314 const proto::VehiclePropValueRequests& request,
315 proto::GetValueResults* response) {
316 gotRequests = request;
317 response->Clear();
318 auto* resultPtr = response->add_results();
319 resultPtr->set_request_id(testRequestId);
320 resultPtr->set_status(proto::StatusCode::OK);
321 auto* valuePtr = resultPtr->mutable_value();
322 valuePtr->set_prop(testPropId);
323 valuePtr->add_int32_values(testValue);
324 return ::grpc::Status::OK;
325 });
326
327 std::vector<aidlvhal::GetValueRequest> requests;
328 requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId,
329 .prop = {
330 .prop = testPropId,
331 }});
332
333 std::vector<aidlvhal::GetValueResult> gotResults;
334
335 auto status = mHardware->getValues(
336 std::make_shared<GRPCVehicleHardware::GetValuesCallback>(
337 [&gotResults](std::vector<aidlvhal::GetValueResult> results) {
338 for (const auto& result : results) {
339 gotResults.push_back(result);
340 }
341 }),
342 requests);
343
344 ASSERT_EQ(status, aidlvhal::StatusCode::OK);
345 ASSERT_THAT(gotRequests.requests(), SizeIs(1));
346 EXPECT_THAT(gotRequests.requests(0).request_id(), testRequestId);
347 EXPECT_THAT(gotRequests.requests(0).value().prop(), testPropId);
348
349 ASSERT_THAT(gotResults, SizeIs(1));
350 EXPECT_EQ(gotResults[0].requestId, testRequestId);
351 EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK);
352 EXPECT_EQ(gotResults[0].prop->prop, testPropId);
353 EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue));
354 }
355
generatePropertyUpdateEvent(int32_t propId,int64_t timestamp)356 void GRPCVehicleHardwareUnitTest::generatePropertyUpdateEvent(int32_t propId, int64_t timestamp) {
357 // This will be converted to a unique_ptr in StartPropertyValuesStream. The ownership is passed
358 // there.
359 auto clientReader = new MockClientReader<proto::VehiclePropValues>();
360 EXPECT_CALL(*mGrpcStub, StartPropertyValuesStreamRaw(_, _)).WillOnce(Return(clientReader));
361 EXPECT_CALL(*clientReader, Read(_))
362 .WillOnce([timestamp, propId](proto::VehiclePropValues* values) {
363 values->Clear();
364 auto value = values->add_values();
365 value->set_timestamp(timestamp);
366 value->set_prop(propId);
367 return true;
368 })
369 .WillOnce(Return(false));
370 EXPECT_CALL(*clientReader, Finish()).WillOnce(Return(::grpc::Status::OK));
371
372 pollValue();
373 }
374
TEST_F(GRPCVehicleHardwareUnitTest,TestGetValuesOutdatedRetry)375 TEST_F(GRPCVehicleHardwareUnitTest, TestGetValuesOutdatedRetry) {
376 int64_t startTimestamp = elapsedRealtimeNano();
377 int64_t testRequestId = 1234;
378 int32_t testPropId = 4321;
379 int32_t testValue1 = 123456;
380 int32_t testValue2 = 654321;
381 int32_t testTimestamp1 = 1000;
382 int32_t testTimestamp2 = 2000;
383
384 // A property update event for testTimestamp2 happens before getValues returns.
385 generatePropertyUpdateEvent(testPropId, testTimestamp2);
386
387 // GetValues first returns an outdated result, then an up-to-date result.
388 EXPECT_CALL(*mGrpcStub, GetValues(_, _, _))
389 .WillOnce([testRequestId, testPropId, testValue1, testTimestamp1](
390 ::grpc::ClientContext* context,
391 const proto::VehiclePropValueRequests& request,
392 proto::GetValueResults* response) {
393 response->Clear();
394 auto* resultPtr = response->add_results();
395 resultPtr->set_request_id(testRequestId);
396 resultPtr->set_status(proto::StatusCode::OK);
397 auto* valuePtr = resultPtr->mutable_value();
398 valuePtr->set_prop(testPropId);
399 valuePtr->set_timestamp(testTimestamp1);
400 valuePtr->add_int32_values(testValue1);
401 return ::grpc::Status::OK;
402 })
403 .WillOnce([testRequestId, testPropId, testValue2, testTimestamp2](
404 ::grpc::ClientContext* context,
405 const proto::VehiclePropValueRequests& request,
406 proto::GetValueResults* response) {
407 response->Clear();
408 auto* resultPtr = response->add_results();
409 resultPtr->set_request_id(testRequestId);
410 resultPtr->set_status(proto::StatusCode::OK);
411 auto* valuePtr = resultPtr->mutable_value();
412 valuePtr->set_prop(testPropId);
413 valuePtr->set_timestamp(testTimestamp2);
414 valuePtr->add_int32_values(testValue2);
415 return ::grpc::Status::OK;
416 });
417
418 std::vector<aidlvhal::GetValueRequest> requests;
419 requests.push_back(aidlvhal::GetValueRequest{.requestId = testRequestId,
420 .prop = {
421 .prop = testPropId,
422 }});
423
424 std::vector<aidlvhal::GetValueResult> gotResults;
425
426 auto status = mHardware->getValues(
427 std::make_shared<GRPCVehicleHardware::GetValuesCallback>(
428 [&gotResults](std::vector<aidlvhal::GetValueResult> results) {
429 for (const auto& result : results) {
430 gotResults.push_back(result);
431 }
432 }),
433 requests);
434
435 ASSERT_EQ(status, aidlvhal::StatusCode::OK);
436 ASSERT_THAT(gotResults, SizeIs(1));
437 EXPECT_EQ(gotResults[0].requestId, testRequestId);
438 EXPECT_EQ(gotResults[0].status, aidlvhal::StatusCode::OK);
439 EXPECT_EQ(gotResults[0].prop->prop, testPropId);
440 EXPECT_THAT(gotResults[0].prop->value.int32Values, ElementsAre(testValue2));
441 EXPECT_GT(gotResults[0].prop->timestamp, startTimestamp);
442 EXPECT_LT(gotResults[0].prop->timestamp, elapsedRealtimeNano());
443 }
444
TEST_F(GRPCVehicleHardwareUnitTest,testGetMinMaxSupportedValues)445 TEST_F(GRPCVehicleHardwareUnitTest, testGetMinMaxSupportedValues) {
446 int32_t testPropId = 1234;
447 int32_t testAreaId = 4321;
448 int32_t testValue1 = 12345;
449 int32_t testValue2 = 123456;
450 std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
451
452 EXPECT_CALL(*mGrpcStub, GetMinMaxSupportedValues(_, _, _))
453 .WillOnce([=](::grpc::ClientContext* context,
454 const proto::GetMinMaxSupportedValuesRequest& request,
455 proto::GetMinMaxSupportedValuesResult* response) {
456 for (const auto& propIdAreaId : request.prop_id_area_id()) {
457 proto::MinMaxSupportedValueResult* individualResult = response->add_result();
458 individualResult->set_status(proto::StatusCode::OK);
459 individualResult->mutable_min_supported_value()->add_int32_values(testValue1);
460 individualResult->mutable_max_supported_value()->add_int32_values(testValue2);
461 }
462 return ::grpc::Status::OK;
463 });
464
465 auto results = mHardware->getMinMaxSupportedValues(propIdAreaIds);
466
467 ASSERT_THAT(results, ::testing::SizeIs(1));
468 EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
469 ASSERT_TRUE(results[0].minSupportedValue.has_value());
470 EXPECT_EQ(results[0].minSupportedValue.value(),
471 aidlvhal::RawPropValues{.int32Values = {testValue1}});
472 ASSERT_TRUE(results[0].maxSupportedValue.has_value());
473 EXPECT_EQ(results[0].maxSupportedValue.value(),
474 aidlvhal::RawPropValues{.int32Values = {testValue2}});
475 }
476
TEST_F(GRPCVehicleHardwareUnitTest,testGetMinMaxSupportedValues_noMaxValue)477 TEST_F(GRPCVehicleHardwareUnitTest, testGetMinMaxSupportedValues_noMaxValue) {
478 int32_t testPropId = 1234;
479 int32_t testAreaId = 4321;
480 int32_t testValue1 = 12345;
481 std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
482
483 EXPECT_CALL(*mGrpcStub, GetMinMaxSupportedValues(_, _, _))
484 .WillOnce([=](::grpc::ClientContext* context,
485 const proto::GetMinMaxSupportedValuesRequest& request,
486 proto::GetMinMaxSupportedValuesResult* response) {
487 for (const auto& propIdAreaId : request.prop_id_area_id()) {
488 proto::MinMaxSupportedValueResult* individualResult = response->add_result();
489 individualResult->set_status(proto::StatusCode::OK);
490 individualResult->mutable_min_supported_value()->add_int32_values(testValue1);
491 }
492 return ::grpc::Status::OK;
493 });
494
495 auto results = mHardware->getMinMaxSupportedValues(propIdAreaIds);
496
497 ASSERT_THAT(results, ::testing::SizeIs(1));
498 EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
499 ASSERT_TRUE(results[0].minSupportedValue.has_value());
500 EXPECT_EQ(results[0].minSupportedValue.value(),
501 aidlvhal::RawPropValues{.int32Values = {testValue1}});
502 ASSERT_FALSE(results[0].maxSupportedValue.has_value());
503 }
504
TEST_F(GRPCVehicleHardwareUnitTest,testGetSupportedValuesLists)505 TEST_F(GRPCVehicleHardwareUnitTest, testGetSupportedValuesLists) {
506 int32_t testPropId = 1234;
507 int32_t testAreaId = 4321;
508 int32_t testValue1 = 12345;
509 int32_t testValue2 = 123456;
510 std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
511
512 EXPECT_CALL(*mGrpcStub, GetSupportedValuesLists(_, _, _))
513 .WillOnce([=](::grpc::ClientContext* context,
514 const proto::GetSupportedValuesListsRequest& request,
515 proto::GetSupportedValuesListsResult* response) {
516 for (const auto& propIdAreaId : request.prop_id_area_id()) {
517 proto::SupportedValuesListResult* individualResult = response->add_result();
518 individualResult->set_status(proto::StatusCode::OK);
519 individualResult->add_supported_values_list()->add_int32_values(testValue1);
520 individualResult->add_supported_values_list()->add_int32_values(testValue2);
521 }
522 return ::grpc::Status::OK;
523 });
524
525 auto results = mHardware->getSupportedValuesLists(propIdAreaIds);
526
527 ASSERT_THAT(results, ::testing::SizeIs(1));
528 EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
529 ASSERT_TRUE(results[0].supportedValuesList.has_value());
530 ASSERT_THAT(results[0].supportedValuesList.value(), ::testing::SizeIs(2));
531 EXPECT_EQ(results[0].supportedValuesList.value()[0],
532 aidlvhal::RawPropValues{.int32Values = {testValue1}});
533 EXPECT_EQ(results[0].supportedValuesList.value()[1],
534 aidlvhal::RawPropValues{.int32Values = {testValue2}});
535 }
536
TEST_F(GRPCVehicleHardwareUnitTest,testGetSupportedValuesLists_noSupportedValue)537 TEST_F(GRPCVehicleHardwareUnitTest, testGetSupportedValuesLists_noSupportedValue) {
538 int32_t testPropId = 1234;
539 int32_t testAreaId = 4321;
540 std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
541
542 EXPECT_CALL(*mGrpcStub, GetSupportedValuesLists(_, _, _))
543 .WillOnce([=](::grpc::ClientContext* context,
544 const proto::GetSupportedValuesListsRequest& request,
545 proto::GetSupportedValuesListsResult* response) {
546 for (const auto& propIdAreaId : request.prop_id_area_id()) {
547 proto::SupportedValuesListResult* individualResult = response->add_result();
548 individualResult->set_status(proto::StatusCode::INTERNAL_ERROR);
549 }
550 return ::grpc::Status::OK;
551 });
552
553 auto results = mHardware->getSupportedValuesLists(propIdAreaIds);
554
555 ASSERT_THAT(results, ::testing::SizeIs(1));
556 EXPECT_EQ(results[0].status, aidlvhal::StatusCode::INTERNAL_ERROR);
557 ASSERT_FALSE(results[0].supportedValuesList.has_value());
558 }
559
560 } // namespace android::hardware::automotive::vehicle::virtualization
561