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 "GRPCVehicleProxyServer.h"
17 #include "IVehicleHardware.h"
18 #include "VehicleServer.grpc.pb.h"
19 #include "VehicleServer.pb.h"
20
21 #include <gmock/gmock.h>
22 #include <grpc++/grpc++.h>
23 #include <gtest/gtest.h>
24
25 #include <chrono>
26 #include <memory>
27 #include <string>
28 #include <thread>
29 #include <utility>
30
31 namespace android::hardware::automotive::vehicle::virtualization {
32
33 namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
34
35 using ::testing::_;
36 using ::testing::DoAll;
37 using ::testing::Return;
38 using ::testing::SaveArg;
39
40 const std::string kFakeServerAddr = "0.0.0.0:54321";
41
42 class VehicleHardwareForTest : public IVehicleHardware {
43 public:
registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback> callback)44 void registerOnPropertyChangeEvent(
45 std::unique_ptr<const PropertyChangeCallback> callback) override {
46 mOnProp = std::move(callback);
47 }
48
onPropertyEvent(std::vector<aidlvhal::VehiclePropValue> values)49 void onPropertyEvent(std::vector<aidlvhal::VehiclePropValue> values) {
50 if (mOnProp) {
51 (*mOnProp)(std::move(values));
52 }
53 }
54
55 // Functions that we do not care.
getAllPropertyConfigs() const56 std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override { return {}; }
57
setValues(std::shared_ptr<const SetValuesCallback> callback,const std::vector<aidlvhal::SetValueRequest> & requests)58 aidlvhal::StatusCode setValues(
59 std::shared_ptr<const SetValuesCallback> callback,
60 const std::vector<aidlvhal::SetValueRequest>& requests) override {
61 return aidlvhal::StatusCode::OK;
62 }
63
getValues(std::shared_ptr<const GetValuesCallback> callback,const std::vector<aidlvhal::GetValueRequest> & requests) const64 aidlvhal::StatusCode getValues(
65 std::shared_ptr<const GetValuesCallback> callback,
66 const std::vector<aidlvhal::GetValueRequest>& requests) const override {
67 return aidlvhal::StatusCode::OK;
68 }
69
dump(const std::vector<std::string> & options)70 DumpResult dump(const std::vector<std::string>& options) override { return {}; }
71
checkHealth()72 aidlvhal::StatusCode checkHealth() override { return aidlvhal::StatusCode::OK; }
73
registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback> callback)74 void registerOnPropertySetErrorEvent(
75 std::unique_ptr<const PropertySetErrorCallback> callback) override {}
76
77 private:
78 std::unique_ptr<const PropertyChangeCallback> mOnProp;
79 };
80
81 class MockVehicleHardware : public IVehicleHardware {
82 public:
83 // Mock methods from IVehicleHardware
84 MOCK_METHOD(std::vector<aidlvhal::VehiclePropConfig>, getAllPropertyConfigs, (),
85 (const, override));
86
87 MOCK_METHOD((aidlvhal::StatusCode), setValues,
88 (std::shared_ptr<const SetValuesCallback> callback,
89 const std::vector<aidlvhal::SetValueRequest>& requests),
90 (override));
91
92 MOCK_METHOD((aidlvhal::StatusCode), getValues,
93 (std::shared_ptr<const GetValuesCallback> callback,
94 const std::vector<aidlvhal::GetValueRequest>& requests),
95 (const, override));
96
97 MOCK_METHOD(DumpResult, dump, (const std::vector<std::string>& options), (override));
98 MOCK_METHOD(aidlvhal::StatusCode, checkHealth, (), (override));
99 MOCK_METHOD(void, registerOnPropertyChangeEvent,
100 (std::unique_ptr<const PropertyChangeCallback> callback), (override));
101 MOCK_METHOD(void, registerOnPropertySetErrorEvent,
102 (std::unique_ptr<const PropertySetErrorCallback> callback), (override));
103 MOCK_METHOD(std::chrono::nanoseconds, getPropertyOnChangeEventBatchingWindow, (), (override));
104 MOCK_METHOD(aidlvhal::StatusCode, subscribe, (aidlvhal::SubscribeOptions options), (override));
105 MOCK_METHOD(aidlvhal::StatusCode, unsubscribe, (int32_t propId, int32_t areaId), (override));
106 MOCK_METHOD(aidlvhal::StatusCode, updateSampleRate,
107 (int32_t propId, int32_t areaId, float sampleRate), (override));
108 };
109
TEST(GRPCVehicleProxyServerUnitTest,ClientConnectDisconnect)110 TEST(GRPCVehicleProxyServerUnitTest, ClientConnectDisconnect) {
111 auto testHardware = std::make_unique<VehicleHardwareForTest>();
112 // HACK: manipulate the underlying hardware via raw pointer for testing.
113 auto* testHardwareRaw = testHardware.get();
114 auto vehicleServer =
115 std::make_unique<GrpcVehicleProxyServer>(kFakeServerAddr, std::move(testHardware));
116 vehicleServer->Start();
117
118 constexpr auto kWaitForConnectionMaxTime = std::chrono::seconds(5);
119 constexpr auto kWaitForStreamStartTime = std::chrono::seconds(1);
120 constexpr auto kWaitForUpdateDeliveryTime = std::chrono::milliseconds(100);
121
122 auto updateReceived1 = std::make_shared<bool>(false);
123 auto vehicleHardware1 = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
124 vehicleHardware1->registerOnPropertyChangeEvent(
125 std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
126 [updateReceived1](const auto&) { *updateReceived1 = true; }));
127 EXPECT_TRUE(vehicleHardware1->waitForConnected(kWaitForConnectionMaxTime));
128 std::this_thread::sleep_for(kWaitForStreamStartTime);
129
130 // Client hardware 1 received update from the server.
131 EXPECT_FALSE(*updateReceived1);
132 testHardwareRaw->onPropertyEvent({});
133 // Wait for the update delivery.
134 std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
135 EXPECT_TRUE(*updateReceived1);
136
137 // Reset.
138 *updateReceived1 = false;
139
140 auto updateReceived2 = std::make_shared<bool>(false);
141 auto vehicleHardware2 = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
142 vehicleHardware2->registerOnPropertyChangeEvent(
143 std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
144 [updateReceived2](const auto&) { *updateReceived2 = true; }));
145 EXPECT_TRUE(vehicleHardware2->waitForConnected(kWaitForConnectionMaxTime));
146 std::this_thread::sleep_for(kWaitForStreamStartTime);
147
148 // Both client hardware 1 and 2 received update from the server.
149 EXPECT_FALSE(*updateReceived1);
150 EXPECT_FALSE(*updateReceived2);
151 testHardwareRaw->onPropertyEvent({});
152 // Wait for the update delivery.
153 std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
154 EXPECT_TRUE(*updateReceived1);
155 EXPECT_TRUE(*updateReceived2);
156
157 // Reset.
158 *updateReceived1 = false;
159 *updateReceived2 = false;
160
161 vehicleHardware1.reset();
162
163 // Client 1 exited, only client hardware 2 received update from the server.
164 EXPECT_FALSE(*updateReceived1);
165 EXPECT_FALSE(*updateReceived2);
166 testHardwareRaw->onPropertyEvent({});
167 // Wait for the update delivery.
168 std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
169 EXPECT_FALSE(*updateReceived1);
170 EXPECT_TRUE(*updateReceived2);
171
172 vehicleServer->Shutdown().Wait();
173 }
174
TEST(GRPCVehicleProxyServerUnitTest,Subscribe)175 TEST(GRPCVehicleProxyServerUnitTest, Subscribe) {
176 auto mockHardware = std::make_unique<MockVehicleHardware>();
177 // We make sure this is alive inside the function scope.
178 MockVehicleHardware* mockHardwarePtr = mockHardware.get();
179 GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
180 ::grpc::ServerContext context;
181 proto::SubscribeRequest request;
182 proto::VehicleHalCallStatus returnStatus;
183 aidlvhal::SubscribeOptions aidlOptions;
184 request.mutable_options()->set_prop_id(1);
185 request.mutable_options()->add_area_ids(2);
186 request.mutable_options()->set_sample_rate(1.234);
187 request.mutable_options()->set_resolution(0.01);
188 request.mutable_options()->set_enable_variable_update_rate(true);
189
190 EXPECT_CALL(*mockHardwarePtr, subscribe(_))
191 .WillOnce(DoAll(SaveArg<0>(&aidlOptions), Return(aidlvhal::StatusCode::OK)));
192
193 auto grpcStatus = server.Subscribe(&context, &request, &returnStatus);
194
195 EXPECT_TRUE(grpcStatus.ok());
196 EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK);
197 EXPECT_EQ(aidlOptions.propId, 1);
198 EXPECT_EQ(aidlOptions.areaIds, std::vector<int32_t>{2});
199 EXPECT_FLOAT_EQ(aidlOptions.sampleRate, 1.234);
200 EXPECT_FLOAT_EQ(aidlOptions.resolution, 0.01);
201 EXPECT_TRUE(aidlOptions.enableVariableUpdateRate);
202 }
203
TEST(GRPCVehicleProxyServerUnitTest,SubscribeNotAvailable)204 TEST(GRPCVehicleProxyServerUnitTest, SubscribeNotAvailable) {
205 auto mockHardware = std::make_unique<MockVehicleHardware>();
206 // We make sure this is alive inside the function scope.
207 MockVehicleHardware* mockHardwarePtr = mockHardware.get();
208 GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
209 ::grpc::ServerContext context;
210 proto::SubscribeRequest request;
211 proto::VehicleHalCallStatus returnStatus;
212
213 EXPECT_CALL(*mockHardwarePtr, subscribe(_))
214 .WillOnce(Return(aidlvhal::StatusCode::NOT_AVAILABLE));
215
216 auto grpcStatus = server.Subscribe(&context, &request, &returnStatus);
217
218 EXPECT_TRUE(grpcStatus.ok());
219 EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::NOT_AVAILABLE);
220 }
221
TEST(GRPCVehicleProxyServerUnitTest,Unsubscribe)222 TEST(GRPCVehicleProxyServerUnitTest, Unsubscribe) {
223 auto mockHardware = std::make_unique<MockVehicleHardware>();
224 // We make sure this is alive inside the function scope.
225 MockVehicleHardware* mockHardwarePtr = mockHardware.get();
226 GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
227 ::grpc::ServerContext context;
228 proto::UnsubscribeRequest request;
229 proto::VehicleHalCallStatus returnStatus;
230 request.set_prop_id(1);
231 request.set_area_id(2);
232
233 EXPECT_CALL(*mockHardwarePtr, unsubscribe(1, 2)).WillOnce(Return(aidlvhal::StatusCode::OK));
234
235 auto grpcStatus = server.Unsubscribe(&context, &request, &returnStatus);
236
237 EXPECT_TRUE(grpcStatus.ok());
238 EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK);
239 }
240
241 } // namespace android::hardware::automotive::vehicle::virtualization
242