1 /*
2  * Copyright (C) 2019 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 <android-base/logging.h>
18 #include <android-base/strings.h>
19 #include <android/hardware/automotive/can/1.0/ICanBus.h>
20 #include <android/hardware/automotive/can/1.0/ICanController.h>
21 #include <android/hardware/automotive/can/1.0/types.h>
22 #include <android/hidl/manager/1.2/IServiceManager.h>
23 #include <can-vts-utils/bus-enumerator.h>
24 #include <can-vts-utils/can-hal-printers.h>
25 #include <gmock/gmock.h>
26 #include <hidl-utils/hidl-utils.h>
27 #include <hidl/GtestPrinter.h>
28 #include <hidl/ServiceManagement.h>
29 
30 namespace android::hardware::automotive::can::V1_0::vts {
31 
32 using hardware::hidl_vec;
33 using InterfaceType = ICanController::InterfaceType;
34 using IfId = ICanController::BusConfig::InterfaceId;
35 
36 class CanControllerHalTest : public ::testing::TestWithParam<std::string> {
37   protected:
38     virtual void SetUp() override;
39     virtual void TearDown() override;
40     static void SetUpTestCase();
41 
42     hidl_vec<InterfaceType> getSupportedInterfaceTypes();
43     bool isSupported(InterfaceType iftype);
44 
45     bool up(InterfaceType iftype, const std::string srvname, std::string ifname,
46             ICanController::Result expected);
47     void assertRegistered(const std::string srvname, bool expectRegistered);
48 
49     sp<ICanController> mCanController;
50     static hidl_vec<hidl_string> mBusNames;
51 
52   private:
53     static bool mTestCaseInitialized;
54 };
55 
56 hidl_vec<hidl_string> CanControllerHalTest::mBusNames;
57 bool CanControllerHalTest::mTestCaseInitialized = false;
58 
SetUp()59 void CanControllerHalTest::SetUp() {
60     ASSERT_TRUE(mTestCaseInitialized);
61 
62     mCanController = ICanController::getService(GetParam());
63     ASSERT_TRUE(mCanController) << "Couldn't open CAN Controller: " << GetParam();
64 }
65 
TearDown()66 void CanControllerHalTest::TearDown() {
67     mCanController.clear();
68 }
69 
SetUpTestCase()70 void CanControllerHalTest::SetUpTestCase() {
71     mBusNames = utils::getBusNames();
72     ASSERT_NE(0u, mBusNames.size()) << "No ICanBus HALs defined in device manifest";
73 
74     mTestCaseInitialized = true;
75 }
76 
getSupportedInterfaceTypes()77 hidl_vec<InterfaceType> CanControllerHalTest::getSupportedInterfaceTypes() {
78     hidl_vec<InterfaceType> iftypesResult;
79     mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult)).assertOk();
80     return iftypesResult;
81 }
82 
isSupported(InterfaceType iftype)83 bool CanControllerHalTest::isSupported(InterfaceType iftype) {
84     const auto supported = getSupportedInterfaceTypes();
85     return std::find(supported.begin(), supported.end(), iftype) != supported.end();
86 }
87 
up(InterfaceType iftype,std::string srvname,std::string ifname,ICanController::Result expected)88 bool CanControllerHalTest::up(InterfaceType iftype, std::string srvname, std::string ifname,
89                               ICanController::Result expected) {
90     ICanController::BusConfig config = {};
91     config.name = srvname;
92 
93     // TODO(b/146214370): move interfaceId constructors to a library
94     if (iftype == InterfaceType::SOCKETCAN) {
95         IfId::Socketcan socketcan = {};
96         socketcan.ifname(ifname);
97         config.interfaceId.socketcan(socketcan);
98     } else if (iftype == InterfaceType::SLCAN) {
99         IfId::Slcan slcan = {};
100         slcan.ttyname(ifname);
101         config.interfaceId.slcan(slcan);
102     } else if (iftype == InterfaceType::VIRTUAL) {
103         config.interfaceId.virtualif({ifname});
104     } else {
105         EXPECT_TRUE(false) << "Unexpected iftype: " << toString(iftype);
106     }
107 
108     const auto upresult = mCanController->upInterface(config);
109 
110     if (!isSupported(iftype)) {
111         LOG(INFO) << iftype << " interfaces not supported";
112         EXPECT_EQ(ICanController::Result::NOT_SUPPORTED, upresult);
113         return false;
114     }
115 
116     EXPECT_EQ(expected, upresult);
117     return true;
118 }
119 
assertRegistered(std::string srvname,bool expectRegistered)120 void CanControllerHalTest::assertRegistered(std::string srvname, bool expectRegistered) {
121     /* Not using ICanBus::tryGetService here, since it ignores interfaces not in the manifest
122      * file -- this is a test, so we don't want to add fake services to a device manifest. */
123     auto manager = hidl::manager::V1_2::IServiceManager::getService();
124     auto busService = manager->get(ICanBus::descriptor, srvname);
125     ASSERT_EQ(expectRegistered, busService.withDefault(nullptr) != nullptr)
126             << "ICanBus/" << srvname << (expectRegistered ? " is not " : " is ") << "registered"
127             << " (should be otherwise)";
128 }
129 
TEST_P(CanControllerHalTest,SupportsSomething)130 TEST_P(CanControllerHalTest, SupportsSomething) {
131     const auto supported = getSupportedInterfaceTypes();
132     ASSERT_GT(supported.size(), 0u);
133 }
134 
TEST_P(CanControllerHalTest,BringUpDown)135 TEST_P(CanControllerHalTest, BringUpDown) {
136     const std::string name = mBusNames[0];
137 
138     assertRegistered(name, false);
139     if (!up(InterfaceType::VIRTUAL, name, "vcan57", ICanController::Result::OK)) GTEST_SKIP();
140     assertRegistered(name, true);
141 
142     const auto dnresult = mCanController->downInterface(name);
143     ASSERT_TRUE(dnresult);
144 
145     assertRegistered(name, false);
146 }
147 
TEST_P(CanControllerHalTest,DownFake)148 TEST_P(CanControllerHalTest, DownFake) {
149     const auto result = mCanController->downInterface("imnotup");
150     ASSERT_FALSE(result);
151 }
152 
TEST_P(CanControllerHalTest,UpTwice)153 TEST_P(CanControllerHalTest, UpTwice) {
154     const std::string name = mBusNames[0];
155 
156     assertRegistered(name, false);
157     if (!up(InterfaceType::VIRTUAL, name, "vcan72", ICanController::Result::OK)) GTEST_SKIP();
158     assertRegistered(name, true);
159     if (!up(InterfaceType::VIRTUAL, name, "vcan73", ICanController::Result::INVALID_STATE)) {
160         GTEST_SKIP();
161     }
162     assertRegistered(name, true);
163 
164     const auto result = mCanController->downInterface(name);
165     ASSERT_TRUE(result);
166     assertRegistered(name, false);
167 }
168 
TEST_P(CanControllerHalTest,ConfigCompatibility)169 TEST_P(CanControllerHalTest, ConfigCompatibility) {
170     // using random-ish addresses, which may not be valid - we can't test the success case
171     // TODO(b/146214370): move interfaceId constructors to a library
172     IfId virtualCfg = {};
173     virtualCfg.virtualif({"vcan70"});
174 
175     IfId::Socketcan socketcanIfname = {};
176     socketcanIfname.ifname("can0");
177     IfId socketcanIfnameCfg = {};
178     socketcanIfnameCfg.socketcan(socketcanIfname);
179 
180     IfId::Socketcan socketcanSerial = {};
181     socketcanSerial.serialno({"1234", "2345"});
182     IfId socketcanSerialCfg = {};
183     socketcanSerialCfg.socketcan(socketcanSerial);
184 
185     IfId::Slcan slcanTtyname = {};
186     slcanTtyname.ttyname("/dev/ttyUSB0");
187     IfId slcanTtynameCfg = {};
188     slcanTtynameCfg.slcan(slcanTtyname);
189 
190     IfId::Slcan slcanSerial = {};
191     slcanSerial.serialno({"dead", "beef"});
192     IfId slcanSerialCfg = {};
193     slcanSerialCfg.slcan(slcanSerial);
194 
195     IfId indexedCfg = {};
196     indexedCfg.indexed({0});
197 
198     static const std::vector<std::pair<InterfaceType, IfId>> compatMatrix = {
199             {InterfaceType::VIRTUAL, virtualCfg},
200             {InterfaceType::SOCKETCAN, socketcanIfnameCfg},
201             {InterfaceType::SOCKETCAN, socketcanSerialCfg},
202             {InterfaceType::SLCAN, slcanTtynameCfg},
203             {InterfaceType::SLCAN, slcanSerialCfg},
204             {InterfaceType::INDEXED, indexedCfg},
205     };
206 
207     for (const auto [iftype, cfg] : compatMatrix) {
208         LOG(INFO) << "Compatibility testing: " << iftype << " / " << cfg;
209 
210         ICanController::BusConfig config = {};
211         config.name = "compattestsrv";
212         config.bitrate = 125000;
213         config.interfaceId = cfg;
214 
215         const auto upresult = mCanController->upInterface(config);
216 
217         if (!isSupported(iftype)) {
218             ASSERT_EQ(ICanController::Result::NOT_SUPPORTED, upresult);
219             continue;
220         }
221         ASSERT_NE(ICanController::Result::NOT_SUPPORTED, upresult);
222 
223         if (upresult == ICanController::Result::OK) {
224             const auto dnresult = mCanController->downInterface(config.name);
225             ASSERT_TRUE(dnresult);
226             continue;
227         }
228     }
229 }
230 
TEST_P(CanControllerHalTest,FailEmptyName)231 TEST_P(CanControllerHalTest, FailEmptyName) {
232     const std::string name = "";
233 
234     assertRegistered(name, false);
235     if (!up(InterfaceType::VIRTUAL, name, "vcan57", ICanController::Result::BAD_SERVICE_NAME)) {
236         GTEST_SKIP();
237     }
238     assertRegistered(name, false);
239 }
240 
TEST_P(CanControllerHalTest,FailBadName)241 TEST_P(CanControllerHalTest, FailBadName) {
242     // 33 characters (name can be at most 32 characters long)
243     const std::string name = "ab012345678901234567890123456789c";
244 
245     assertRegistered(name, false);
246     if (!up(InterfaceType::VIRTUAL, name, "vcan57", ICanController::Result::BAD_SERVICE_NAME)) {
247         GTEST_SKIP();
248     }
249     assertRegistered(name, false);
250 }
251 
TEST_P(CanControllerHalTest,FailBadVirtualAddress)252 TEST_P(CanControllerHalTest, FailBadVirtualAddress) {
253     const std::string name = mBusNames[0];
254 
255     assertRegistered(name, false);
256     if (!up(InterfaceType::VIRTUAL, name, "", ICanController::Result::BAD_INTERFACE_ID)) {
257         GTEST_SKIP();
258     }
259     assertRegistered(name, false);
260 }
261 
TEST_P(CanControllerHalTest,FailBadSocketcanAddress)262 TEST_P(CanControllerHalTest, FailBadSocketcanAddress) {
263     const std::string name = mBusNames[0];
264 
265     assertRegistered(name, false);
266     if (!up(InterfaceType::SOCKETCAN, name, "can87", ICanController::Result::BAD_INTERFACE_ID)) {
267         GTEST_SKIP();
268     }
269     assertRegistered(name, false);
270 
271     auto supported =
272             up(InterfaceType::SOCKETCAN, name, "", ICanController::Result::BAD_INTERFACE_ID);
273     ASSERT_TRUE(supported);
274     assertRegistered(name, false);
275 }
276 
TEST_P(CanControllerHalTest,FailBadSlcanAddress)277 TEST_P(CanControllerHalTest, FailBadSlcanAddress) {
278     const std::string name = mBusNames[0];
279 
280     assertRegistered(name, false);
281     if (!up(InterfaceType::SLCAN, name, "/dev/shouldnotexist123",
282             ICanController::Result::BAD_INTERFACE_ID)) {
283         GTEST_SKIP();
284     }
285     assertRegistered(name, false);
286 
287     auto supported = up(InterfaceType::SLCAN, name, "", ICanController::Result::BAD_INTERFACE_ID);
288     ASSERT_TRUE(supported);
289     assertRegistered(name, false);
290 }
291 
292 /**
293  * Example manual invocation:
294  * adb shell /data/nativetest64/VtsHalCanControllerV1_0TargetTest/VtsHalCanControllerV1_0TargetTest
295  */
296 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CanControllerHalTest);
297 INSTANTIATE_TEST_SUITE_P(PerInstance, CanControllerHalTest,
298                          testing::ValuesIn(getAllHalInstanceNames(ICanController::descriptor)),
299                          PrintInstanceNameToString);
300 
301 }  // namespace android::hardware::automotive::can::V1_0::vts
302