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