1 /*
2  * Copyright (C) 2021 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 <chrono>
18 #include <fstream>
19 #include <thread>
20 
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <unistd.h>
24 
25 #include <android-base/file.h>
26 #include <android/hardware/automotive/vehicle/2.0/types.h>
27 #include <gtest/gtest.h>
28 
29 #include "GrpcVehicleClient.h"
30 #include "GrpcVehicleServer.h"
31 #include "Utils.h"
32 #include "vhal_v2_0/VehicleUtils.h"
33 
34 namespace android::hardware::automotive::vehicle::V2_0::impl {
35 
36 class GrpcServerTest : public ::testing::Test {
37   public:
38     GrpcServerTest()
39         : mPowerStateSocketForTest(std::string(mTestTempDir.path) +
40                                    std::string("/power_state_socket_for_test_") +
41                                    std::to_string(getpid())),
42           mServerInfo({{GetTestCID(), 12345},
43                        mPowerStateMarkerFileForTest.path,
44                        mPowerStateSocketForTest}) {}
45 
46     void SetUp() override {
47         mGrpcServer = makeGrpcVehicleServer(mServerInfo);
48 
49         ASSERT_TRUE(GetGrpcServer() != nullptr);
50         GetGrpcServer()->Start();
51     }
52 
53     void TearDown() override {
54         GetGrpcServer()->Stop().Wait();
55         mGrpcServer.reset();
56     }
57 
58     static unsigned GetTestCID();
59 
60     GrpcVehicleServer* GetGrpcServer() const { return mGrpcServer.get(); }
61 
62     std::string GetGrpcServerUri() const { return mServerInfo.getServerUri(); }
63 
64     std::string GetPowerStateSocketPath() const { return mPowerStateSocketForTest; }
65 
66     std::string GetPowerStateMarkerFilePath() const {
67         return std::string(mPowerStateMarkerFileForTest.path);
68     }
69 
70     void SendDummyValueFromServer();
71 
72     void ExpectActivePropValueStreamNum(unsigned expected);
73 
74     void WriteToPowerStateSocket(const std::string& val);
75 
76     std::string ReadFromPowerStateMarkerFile() const;
77 
78   private:
79     TemporaryDir mTestTempDir;
80     TemporaryFile mPowerStateMarkerFileForTest;
81 
82     std::string mPowerStateSocketForTest{};
83 
84     GrpcVehicleServerPtr mGrpcServer{nullptr};
85     VirtualizedVhalServerInfo mServerInfo;
86 };
87 
88 unsigned GrpcServerTest::GetTestCID() {
89     // TODO(chenhaosjtuacm): find a way to get the local CID
90     return 1000;
91 }
92 
93 void GrpcServerTest::SendDummyValueFromServer() {
94     VehiclePropValue value;
95     value.prop = toInt(VehicleProperty::INVALID);
96     GetGrpcServer()->onPropertyValueFromCar(value, false);
97 }
98 
99 void GrpcServerTest::ExpectActivePropValueStreamNum(unsigned expected) {
100     // Force the server to refresh streams
101     SendDummyValueFromServer();
102 
103     std::this_thread::sleep_for(std::chrono::seconds(1));
104     EXPECT_EQ(GetGrpcServer()->NumOfActivePropertyValueStream(), expected);
105 }
106 
107 void GrpcServerTest::WriteToPowerStateSocket(const std::string& val) {
108     int power_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
109     ASSERT_GE(power_socket_fd, 0);
110 
111     struct sockaddr_un addr;
112     std::memset(&addr, 0, sizeof(addr));
113     addr.sun_family = AF_UNIX;
114     std::string socket_path = GetPowerStateSocketPath();
115     std::strncpy(addr.sun_path, socket_path.c_str(), socket_path.length() + 1);
116 
117     sync();
118 
119     ASSERT_EQ(connect(power_socket_fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)), 0);
120     EXPECT_EQ(write(power_socket_fd, val.c_str(), val.length()),
121               static_cast<ssize_t>(val.length()));
122     close(power_socket_fd);
123 }
124 
125 std::string GrpcServerTest::ReadFromPowerStateMarkerFile() const {
126     std::ifstream stream(GetPowerStateMarkerFilePath());
127     std::string val;
128     stream >> val;
129     return val;
130 }
131 
132 TEST_F(GrpcServerTest, PropertyValueStreamTest) {
133     ExpectActivePropValueStreamNum(0);
134     {
135         auto client1 = makeGrpcVehicleClient(GetGrpcServerUri());
136         ExpectActivePropValueStreamNum(1);
137         {
138             auto client2 = makeGrpcVehicleClient(GetGrpcServerUri());
139             ExpectActivePropValueStreamNum(2);
140         }
141         ExpectActivePropValueStreamNum(1);
142     }
143     ExpectActivePropValueStreamNum(0);
144 }
145 
146 TEST_F(GrpcServerTest, PowerStateListenerTest) {
147     {
148         std::string power_state_str = "ok";
149         WriteToPowerStateSocket(power_state_str);
150         std::this_thread::sleep_for(std::chrono::seconds(1));
151         EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
152     }
153 
154     {
155         std::string power_state_str = "shutdown";
156         WriteToPowerStateSocket(power_state_str);
157         std::this_thread::sleep_for(std::chrono::seconds(1));
158         EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
159     }
160 }
161 
162 }  // namespace android::hardware::automotive::vehicle::V2_0::impl
163