• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
23 
24 #include <chrono>
25 #include <memory>
26 #include <string>
27 
28 namespace android::hardware::automotive::vehicle::virtualization {
29 
30 namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
31 
32 using ::testing::_;
33 using ::testing::DoAll;
34 using ::testing::NiceMock;
35 using ::testing::Return;
36 using ::testing::SaveArg;
37 using ::testing::SetArgPointee;
38 
39 using proto::MockVehicleServerStub;
40 
41 const std::string kFakeServerAddr = "0.0.0.0:54321";
42 
43 class FakeVehicleServer : public proto::VehicleServer::Service {
44   public:
StartPropertyValuesStream(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<proto::VehiclePropValues> * stream)45     ::grpc::Status StartPropertyValuesStream(
46             ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
47             ::grpc::ServerWriter<proto::VehiclePropValues>* stream) override {
48         stream->Write(proto::VehiclePropValues());
49         // A fake disconnection.
50         return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
51     }
52 
53     // Functions that we do not care.
GetAllPropertyConfig(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<proto::VehiclePropConfig> * stream)54     ::grpc::Status GetAllPropertyConfig(
55             ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
56             ::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override {
57         return ::grpc::Status::OK;
58     }
59 
SetValues(::grpc::ServerContext * context,const proto::VehiclePropValueRequests * requests,proto::SetValueResults * results)60     ::grpc::Status SetValues(::grpc::ServerContext* context,
61                              const proto::VehiclePropValueRequests* requests,
62                              proto::SetValueResults* results) override {
63         return ::grpc::Status::OK;
64     }
65 
GetValues(::grpc::ServerContext * context,const proto::VehiclePropValueRequests * requests,proto::GetValueResults * results)66     ::grpc::Status GetValues(::grpc::ServerContext* context,
67                              const proto::VehiclePropValueRequests* requests,
68                              proto::GetValueResults* results) override {
69         return ::grpc::Status::OK;
70     }
71 };
72 
TEST(GRPCVehicleHardwareUnitTest,Reconnect)73 TEST(GRPCVehicleHardwareUnitTest, Reconnect) {
74     auto receivedUpdate = std::make_shared<std::atomic<int>>(0);
75     auto vehicleHardware = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
76     vehicleHardware->registerOnPropertyChangeEvent(
77             std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
78                     [receivedUpdate](const auto&) { receivedUpdate->fetch_add(1); }));
79 
80     constexpr size_t kServerRestartTimes = 5;
81     for (size_t serverStart = 0; serverStart < kServerRestartTimes; ++serverStart) {
82         EXPECT_EQ(receivedUpdate->load(), 0);
83         auto fakeServer = std::make_unique<FakeVehicleServer>();
84         ::grpc::ServerBuilder builder;
85         builder.RegisterService(fakeServer.get());
86         builder.AddListeningPort(kFakeServerAddr, ::grpc::InsecureServerCredentials());
87         auto grpcServer = builder.BuildAndStart();
88 
89         // Wait until the vehicle hardware received the second update (after one fake
90         // disconnection).
91         constexpr auto kMaxWaitTime = std::chrono::seconds(5);
92         auto startTime = std::chrono::steady_clock::now();
93         while (receivedUpdate->load() <= 1 &&
94                std::chrono::steady_clock::now() - startTime < kMaxWaitTime)
95             ;
96 
97         grpcServer->Shutdown();
98         grpcServer->Wait();
99         EXPECT_GT(receivedUpdate->load(), 1);
100 
101         // Reset for the next round.
102         receivedUpdate->store(0);
103     }
104 }
105 
106 class GRPCVehicleHardwareMockServerUnitTest : public ::testing::Test {
107   protected:
108     NiceMock<MockVehicleServerStub>* mGrpcStub;
109     std::unique_ptr<GRPCVehicleHardware> mHardware;
110 
SetUp()111     void SetUp() override {
112         auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
113         ;
114         mGrpcStub = stub.get();
115         mHardware = std::make_unique<GRPCVehicleHardware>(std::move(stub));
116     }
117 
TearDown()118     void TearDown() override { mHardware.reset(); }
119 };
120 
121 MATCHER_P(RepeatedInt32Eq, expected_values, "") {
122     return std::vector<int32_t>(arg.begin(), arg.end()) == expected_values;
123 }
124 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,Subscribe)125 TEST_F(GRPCVehicleHardwareMockServerUnitTest, Subscribe) {
126     proto::VehicleHalCallStatus protoStatus;
127     protoStatus.set_status_code(proto::StatusCode::OK);
128     proto::SubscribeRequest actualRequest;
129 
130     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
131             .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
132                             Return(::grpc::Status::OK)));
133 
134     aidlvhal::SubscribeOptions options = {.propId = 1,
135                                           .areaIds = {1, 2, 3, 4},
136                                           .sampleRate = 1.234,
137                                           .resolution = 0.01,
138                                           .enableVariableUpdateRate = true};
139     auto status = mHardware->subscribe(options);
140 
141     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
142     const auto& protoOptions = actualRequest.options();
143     EXPECT_EQ(protoOptions.prop_id(), 1);
144     EXPECT_THAT(protoOptions.area_ids(), RepeatedInt32Eq(std::vector<int32_t>({1, 2, 3, 4})));
145     EXPECT_FLOAT_EQ(protoOptions.sample_rate(), 1.234);
146     EXPECT_FLOAT_EQ(protoOptions.resolution(), 0.01);
147     EXPECT_EQ(protoOptions.enable_variable_update_rate(), true);
148 }
149 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,SubscribeLegacyServer)150 TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeLegacyServer) {
151     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
152             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
153 
154     aidlvhal::SubscribeOptions options;
155     auto status = mHardware->subscribe(options);
156 
157     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
158 }
159 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,SubscribeGrpcFailure)160 TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeGrpcFailure) {
161     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
162             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
163 
164     aidlvhal::SubscribeOptions options;
165     auto status = mHardware->subscribe(options);
166 
167     EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
168 }
169 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,SubscribeProtoFailure)170 TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeProtoFailure) {
171     proto::VehicleHalCallStatus protoStatus;
172     protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
173 
174     EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
175             .WillOnce(DoAll(SetArgPointee<2>(protoStatus),  // Set the output status
176                             Return(::grpc::Status::OK)));
177 
178     aidlvhal::SubscribeOptions options;
179     auto status = mHardware->subscribe(options);
180 
181     EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
182 }
183 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,Unsubscribe)184 TEST_F(GRPCVehicleHardwareMockServerUnitTest, Unsubscribe) {
185     proto::VehicleHalCallStatus protoStatus;
186     protoStatus.set_status_code(proto::StatusCode::OK);
187     proto::UnsubscribeRequest actualRequest;
188 
189     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
190             .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
191                             Return(::grpc::Status::OK)));
192 
193     int32_t propId = 1;
194     int32_t areaId = 2;
195     auto status = mHardware->unsubscribe(propId, areaId);
196 
197     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
198     EXPECT_EQ(actualRequest.prop_id(), propId);
199     EXPECT_EQ(actualRequest.area_id(), areaId);
200 }
201 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,UnsubscribeLegacyServer)202 TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeLegacyServer) {
203     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
204             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
205 
206     auto status = mHardware->unsubscribe(1, 2);
207 
208     EXPECT_EQ(status, aidlvhal::StatusCode::OK);
209 }
210 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,UnsubscribeGrpcFailure)211 TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeGrpcFailure) {
212     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
213             .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
214 
215     auto status = mHardware->unsubscribe(1, 2);
216 
217     EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
218 }
219 
TEST_F(GRPCVehicleHardwareMockServerUnitTest,UnsubscribeProtoFailure)220 TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeProtoFailure) {
221     proto::VehicleHalCallStatus protoStatus;
222     protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
223 
224     EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
225             .WillOnce(DoAll(SetArgPointee<2>(protoStatus),  // Set the output status
226                             Return(::grpc::Status::OK)));
227 
228     auto status = mHardware->unsubscribe(1, 2);
229 
230     EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
231 }
232 
233 }  // namespace android::hardware::automotive::vehicle::virtualization
234