Add unit tests for GRPC vehicle HAL
Test: unit tests provided
Bug: 181371253
Change-Id: Ib64cc535a9092f4edc9d8ae709f86d1b71b7293d
diff --git a/tests/hal/vehicle/2.0/Android.bp b/tests/hal/vehicle/2.0/Android.bp
new file mode 100644
index 0000000..3545255
--- /dev/null
+++ b/tests/hal/vehicle/2.0/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test {
+ name: "android.hardware.automotive.vehicle@2.0-virtualization-server-unit-tests",
+ vendor: true,
+ defaults: ["vhal_v2_0_defaults"],
+ srcs: [
+ "GrpcServer_test.cpp",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0-virtualization-client-lib",
+ "android.hardware.automotive.vehicle@2.0-virtualization-grpc-server-lib",
+ ],
+ shared_libs: [
+ "libbase",
+ "libjsoncpp",
+ "libprotobuf-cpp-full",
+ "libgrpc++",
+ ],
+}
diff --git a/tests/hal/vehicle/2.0/GrpcServer_test.cpp b/tests/hal/vehicle/2.0/GrpcServer_test.cpp
new file mode 100644
index 0000000..ffa2f0b
--- /dev/null
+++ b/tests/hal/vehicle/2.0/GrpcServer_test.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <chrono>
+#include <fstream>
+#include <thread>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <gtest/gtest.h>
+
+#include "GrpcVehicleClient.h"
+#include "GrpcVehicleServer.h"
+#include "Utils.h"
+#include "vhal_v2_0/VehicleUtils.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+class GrpcServerTest : public ::testing::Test {
+ public:
+ GrpcServerTest()
+ : mPowerStateSocketForTest(std::string(mTestTempDir.path) +
+ std::string("/power_state_socket_for_test_") +
+ std::to_string(getpid())),
+ mServerInfo({{GetTestCID(), 12345},
+ mPowerStateMarkerFileForTest.path,
+ mPowerStateSocketForTest}) {}
+
+ void SetUp() override {
+ mGrpcServer = makeGrpcVehicleServer(mServerInfo);
+
+ ASSERT_TRUE(GetGrpcServer() != nullptr);
+ GetGrpcServer()->Start();
+ }
+
+ void TearDown() override {
+ GetGrpcServer()->Stop().Wait();
+ mGrpcServer.reset();
+ }
+
+ static unsigned GetTestCID();
+
+ GrpcVehicleServer* GetGrpcServer() const { return mGrpcServer.get(); }
+
+ std::string GetGrpcServerUri() const { return mServerInfo.getServerUri(); }
+
+ std::string GetPowerStateSocketPath() const { return mPowerStateSocketForTest; }
+
+ std::string GetPowerStateMarkerFilePath() const {
+ return std::string(mPowerStateMarkerFileForTest.path);
+ }
+
+ void SendDummyValueFromServer();
+
+ void ExpectActivePropValueStreamNum(unsigned expected);
+
+ void WriteToPowerStateSocket(const std::string& val);
+
+ std::string ReadFromPowerStateMarkerFile() const;
+
+ private:
+ TemporaryDir mTestTempDir;
+ TemporaryFile mPowerStateMarkerFileForTest;
+
+ std::string mPowerStateSocketForTest{};
+
+ GrpcVehicleServerPtr mGrpcServer{nullptr};
+ VirtualizedVhalServerInfo mServerInfo;
+};
+
+unsigned GrpcServerTest::GetTestCID() {
+ // TODO(chenhaosjtuacm): find a way to get the local CID
+ return 1000;
+}
+
+void GrpcServerTest::SendDummyValueFromServer() {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INVALID);
+ GetGrpcServer()->onPropertyValueFromCar(value, false);
+}
+
+void GrpcServerTest::ExpectActivePropValueStreamNum(unsigned expected) {
+ // Force the server to refresh streams
+ SendDummyValueFromServer();
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(GetGrpcServer()->NumOfActivePropertyValueStream(), expected);
+}
+
+void GrpcServerTest::WriteToPowerStateSocket(const std::string& val) {
+ int power_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_GE(power_socket_fd, 0);
+
+ struct sockaddr_un addr;
+ std::memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ std::string socket_path = GetPowerStateSocketPath();
+ std::strncpy(addr.sun_path, socket_path.c_str(), socket_path.length() + 1);
+
+ sync();
+
+ ASSERT_EQ(connect(power_socket_fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)), 0);
+ EXPECT_EQ(write(power_socket_fd, val.c_str(), val.length()),
+ static_cast<ssize_t>(val.length()));
+ close(power_socket_fd);
+}
+
+std::string GrpcServerTest::ReadFromPowerStateMarkerFile() const {
+ std::ifstream stream(GetPowerStateMarkerFilePath());
+ std::string val;
+ stream >> val;
+ return val;
+}
+
+TEST_F(GrpcServerTest, PropertyValueStreamTest) {
+ ExpectActivePropValueStreamNum(0);
+ {
+ auto client1 = makeGrpcVehicleClient(GetGrpcServerUri());
+ ExpectActivePropValueStreamNum(1);
+ {
+ auto client2 = makeGrpcVehicleClient(GetGrpcServerUri());
+ ExpectActivePropValueStreamNum(2);
+ }
+ ExpectActivePropValueStreamNum(1);
+ }
+ ExpectActivePropValueStreamNum(0);
+}
+
+TEST_F(GrpcServerTest, PowerStateListenerTest) {
+ {
+ std::string power_state_str = "ok";
+ WriteToPowerStateSocket(power_state_str);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
+ }
+
+ {
+ std::string power_state_str = "shutdown";
+ WriteToPowerStateSocket(power_state_str);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
+ }
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl