1 /*
2  * Copyright (C) 2017 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 <future>
19 #include <mutex>
20 #include "android/hidl/base/1.0/IBase.h"
21 #define LOG_TAG "Lshal"
22 #include <android-base/logging.h>
23 
24 #include <sstream>
25 #include <string>
26 #include <thread>
27 #include <vector>
28 
29 #include <android-base/parseint.h>
30 #include <android/hardware/tests/inheritance/1.0/IChild.h>
31 #include <gmock/gmock.h>
32 #include <gtest/gtest.h>
33 #include <hidl/HidlTransportSupport.h>
34 #include <vintf/parse_xml.h>
35 
36 #include "ListCommand.h"
37 #include "Lshal.h"
38 
39 #define NELEMS(array)   static_cast<int>(sizeof(array) / sizeof(array[0]))
40 
41 using namespace testing;
42 
43 using std::chrono_literals::operator""ms;
44 
45 using ::android::hidl::base::V1_0::DebugInfo;
46 using ::android::hidl::base::V1_0::IBase;
47 using ::android::hidl::manager::V1_0::IServiceManager;
48 using ::android::hidl::manager::V1_0::IServiceNotification;
49 using ::android::hardware::hidl_array;
50 using ::android::hardware::hidl_death_recipient;
51 using ::android::hardware::hidl_handle;
52 using ::android::hardware::hidl_string;
53 using ::android::hardware::hidl_vec;
54 using ::android::hardware::Void;
55 using android::vintf::Arch;
56 using android::vintf::CompatibilityMatrix;
57 using android::vintf::HalManifest;
58 using android::vintf::Transport;
59 using android::vintf::VintfObject;
60 
61 using InstanceDebugInfo = IServiceManager::InstanceDebugInfo;
62 
63 using hidl_hash = hidl_array<uint8_t, 32>;
64 
65 namespace android {
66 namespace hardware {
67 namespace tests {
68 namespace inheritance {
69 namespace V1_0 {
70 namespace implementation {
71 struct Child : android::hardware::tests::inheritance::V1_0::IChild {
doChildandroid::hardware::tests::inheritance::V1_0::implementation::Child72     ::android::hardware::Return<void> doChild() override { return Void(); }
doParentandroid::hardware::tests::inheritance::V1_0::implementation::Child73     ::android::hardware::Return<void> doParent() override { return Void(); }
doGrandparentandroid::hardware::tests::inheritance::V1_0::implementation::Child74     ::android::hardware::Return<void> doGrandparent() override { return Void(); }
75 
debugandroid::hardware::tests::inheritance::V1_0::implementation::Child76     ::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
77         const native_handle_t *handle = hh.getNativeHandle();
78         if (handle->numFds < 1) {
79             return Void();
80         }
81         int fd = handle->data[0];
82         std::string content{descriptor};
83         for (const auto &option : options) {
84             content += "\n";
85             content += option.c_str();
86         }
87         if (options.size() > 0) {
88             uint64_t len;
89             if (android::base::ParseUint(options[0], &len)) {
90                 content += "\n";
91                 content += std::string(len, 'X');
92             }
93         }
94         ssize_t written = write(fd, content.c_str(), content.size());
95         if (written != (ssize_t)content.size()) {
96             LOG(WARNING) << "SERVER(Child) debug writes " << written << " bytes < "
97                     << content.size() << " bytes, errno = " << errno;
98         }
99         return Void();
100     }
101 };
102 
103 } // namespace implementation
104 } // namespace V1_0
105 } // namespace inheritance
106 } // namespace tests
107 } // namespace hardware
108 
109 namespace lshal {
110 
111 class MockServiceManager : public IServiceManager {
112 public:
113     template<typename T>
114     using R = ::android::hardware::Return<T>;
115     using String = const hidl_string&;
116     ~MockServiceManager() = default;
117 
118 #define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb))
119 
120     MOCK_METHOD2(get, R<sp<IBase>>(String, String));
121     MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&));
122     MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String));
123     MOCK_METHOD_CB(list);
124     MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb));
125     MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&));
126     MOCK_METHOD_CB(debugDump);
127     MOCK_METHOD2(registerPassthroughClient, R<void>(String, String));
128     MOCK_METHOD_CB(interfaceChain);
129     MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&));
130     MOCK_METHOD_CB(interfaceDescriptor);
131     MOCK_METHOD_CB(getHashChain);
132     MOCK_METHOD0(setHalInstrumentation, R<void>());
133     MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t));
134     MOCK_METHOD0(ping, R<void>());
135     MOCK_METHOD_CB(getDebugInfo);
136     MOCK_METHOD0(notifySyspropsChanged, R<void>());
137     MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&));
138 
139 };
140 
141 class DebugTest : public ::testing::Test {
142 public:
SetUp()143     void SetUp() override {
144         using ::android::hardware::tests::inheritance::V1_0::IChild;
145         using ::android::hardware::tests::inheritance::V1_0::IParent;
146         using ::android::hardware::tests::inheritance::V1_0::IGrandparent;
147         using ::android::hardware::tests::inheritance::V1_0::implementation::Child;
148 
149         err.str("");
150         out.str("");
151         serviceManager = new testing::NiceMock<MockServiceManager>();
152         ON_CALL(*serviceManager, get(_, _))
153                 .WillByDefault(
154                         Invoke([](const auto& iface,
155                                   const auto& inst) -> ::android::hardware::Return<sp<IBase>> {
156                             if (inst != "default") return nullptr;
157                             if (iface == IChild::descriptor || iface == IParent::descriptor ||
158                                 iface == IGrandparent::descriptor)
159                                 return new Child();
160                             return nullptr;
161                         }));
162 
163         lshal = std::make_unique<Lshal>(out, err, serviceManager, serviceManager);
164     }
TearDown()165     void TearDown() override {}
166 
167     std::stringstream err;
168     std::stringstream out;
169     sp<MockServiceManager> serviceManager;
170 
171     std::unique_ptr<Lshal> lshal;
172 };
173 
createArg(const std::vector<const char * > & args)174 static Arg createArg(const std::vector<const char*>& args) {
175     return Arg{static_cast<int>(args.size()), const_cast<char**>(args.data())};
176 }
177 
178 template<typename T>
callMain(const std::unique_ptr<T> & lshal,const std::vector<const char * > & args)179 static Status callMain(const std::unique_ptr<T>& lshal, const std::vector<const char*>& args) {
180     return lshal->main(createArg(args));
181 }
182 
TEST_F(DebugTest,Debug)183 TEST_F(DebugTest, Debug) {
184     EXPECT_EQ(0u, callMain(lshal, {
185         "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild/default", "foo", "bar"
186     }));
187     EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\nfoo\nbar"));
188     EXPECT_THAT(err.str(), IsEmpty());
189 }
190 
TEST_F(DebugTest,Debug2)191 TEST_F(DebugTest, Debug2) {
192     EXPECT_EQ(0u, callMain(lshal, {
193         "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild", "baz", "quux"
194     }));
195     EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\nbaz\nquux"));
196     EXPECT_THAT(err.str(), IsEmpty());
197 }
198 
TEST_F(DebugTest,Debug3)199 TEST_F(DebugTest, Debug3) {
200     EXPECT_NE(0u, callMain(lshal, {
201         "lshal", "debug", "android.hardware.tests.doesnotexist@1.0::IDoesNotExist",
202     }));
203     EXPECT_THAT(err.str(), HasSubstr("does not exist"));
204 }
205 
TEST_F(DebugTest,DebugLarge)206 TEST_F(DebugTest, DebugLarge) {
207     EXPECT_EQ(0u, callMain(lshal, {
208         "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild/default", "10000"
209     }));
210     EXPECT_THAT(out.str(),
211                 StrEq("android.hardware.tests.inheritance@1.0::IChild\n10000\n" +
212                       std::string(10000, 'X')));
213     EXPECT_THAT(err.str(), IsEmpty());
214 }
215 
TEST_F(DebugTest,DebugParent)216 TEST_F(DebugTest, DebugParent) {
217     EXPECT_EQ(0u, callMain(lshal, {
218         "lshal", "debug", "android.hardware.tests.inheritance@1.0::IParent", "calling parent"
219     }));
220     EXPECT_THAT(out.str(), StrEq("android.hardware.tests.inheritance@1.0::IChild\ncalling parent"));
221     EXPECT_THAT(err.str(), IsEmpty());
222 }
223 
TEST_F(DebugTest,DebugParentExclude)224 TEST_F(DebugTest, DebugParentExclude) {
225     EXPECT_EQ(0u, callMain(lshal, {
226         "lshal", "debug", "-E", "android.hardware.tests.inheritance@1.0::IParent", "excluding"
227     }));
228     EXPECT_THAT(out.str(), IsEmpty());
229     EXPECT_THAT(err.str(), IsEmpty());
230 }
231 
232 class MockLshal : public Lshal {
233 public:
MockLshal()234     MockLshal() {}
235     ~MockLshal() = default;
236     MOCK_CONST_METHOD0(out, NullableOStream<std::ostream>());
237     MOCK_CONST_METHOD0(err, NullableOStream<std::ostream>());
238 };
239 
240 // expose protected fields and methods for ListCommand
241 class MockListCommand : public ListCommand {
242 public:
MockListCommand(Lshal * lshal)243     explicit MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
244 
parseArgs(const Arg & arg)245     Status parseArgs(const Arg& arg) { return ListCommand::parseArgs(arg); }
main(const Arg & arg)246     Status main(const Arg& arg) { return ListCommand::main(arg); }
forEachTable(const std::function<void (Table &)> & f)247     void forEachTable(const std::function<void(Table &)> &f) {
248         return ListCommand::forEachTable(f);
249     }
forEachTable(const std::function<void (const Table &)> & f) const250     void forEachTable(const std::function<void(const Table &)> &f) const {
251         return ListCommand::forEachTable(f);
252     }
fetch()253     Status fetch() { return ListCommand::fetch(); }
dumpVintf(const NullableOStream<std::ostream> & out)254     void dumpVintf(const NullableOStream<std::ostream>& out) {
255         return ListCommand::dumpVintf(out);
256     }
internalPostprocess()257     void internalPostprocess() { ListCommand::postprocess(); }
getPidInfoCached(pid_t serverPid)258     const BinderPidInfo* getPidInfoCached(pid_t serverPid) {
259         return ListCommand::getPidInfoCached(serverPid);
260     }
261 
262     MOCK_METHOD0(postprocess, void());
263     MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, BinderPidInfo*));
264     MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t));
265     MOCK_METHOD1(getPartition, Partition(pid_t));
266 
267     MOCK_CONST_METHOD0(getDeviceManifest, std::shared_ptr<const vintf::HalManifest>());
268     MOCK_CONST_METHOD0(getDeviceMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
269     MOCK_CONST_METHOD0(getFrameworkManifest, std::shared_ptr<const vintf::HalManifest>());
270     MOCK_CONST_METHOD0(getFrameworkMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
271 };
272 
273 class ListParseArgsTest : public ::testing::Test {
274 public:
SetUp()275     void SetUp() override {
276         mockLshal = std::make_unique<NiceMock<MockLshal>>();
277         mockList = std::make_unique<MockListCommand>(mockLshal.get());
278         ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(err)));
279         // ListCommand::parseArgs should parse arguments from the second element
280         optind = 1;
281     }
282     std::unique_ptr<MockLshal> mockLshal;
283     std::unique_ptr<MockListCommand> mockList;
284     std::stringstream err;
285 };
286 
TEST_F(ListParseArgsTest,Args)287 TEST_F(ListParseArgsTest, Args) {
288     EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-p", "-i", "-a", "-c"})));
289     mockList->forEachTable([](const Table& table) {
290         EXPECT_EQ(SelectedColumns({TableColumnType::SERVER_PID, TableColumnType::INTERFACE_NAME,
291                                    TableColumnType::SERVER_ADDR, TableColumnType::CLIENT_PIDS}),
292                   table.getSelectedColumns());
293     });
294     EXPECT_EQ("", err.str());
295 }
296 
TEST_F(ListParseArgsTest,Cmds)297 TEST_F(ListParseArgsTest, Cmds) {
298     EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-m"})));
299     mockList->forEachTable([](const Table& table) {
300         EXPECT_THAT(table.getSelectedColumns(), Not(Contains(TableColumnType::SERVER_PID)))
301                 << "should not print server PID with -m";
302         EXPECT_THAT(table.getSelectedColumns(), Not(Contains(TableColumnType::CLIENT_PIDS)))
303                 << "should not print client PIDs with -m";
304         EXPECT_THAT(table.getSelectedColumns(), Contains(TableColumnType::SERVER_CMD))
305                 << "should print server cmd with -m";
306         EXPECT_THAT(table.getSelectedColumns(), Contains(TableColumnType::CLIENT_CMDS))
307                 << "should print client cmds with -m";
308     });
309     EXPECT_EQ("", err.str());
310 }
311 
TEST_F(ListParseArgsTest,DebugAndNeat)312 TEST_F(ListParseArgsTest, DebugAndNeat) {
313     EXPECT_NE(0u, mockList->parseArgs(createArg({"lshal", "--neat", "-d"})));
314     EXPECT_THAT(err.str(), HasSubstr("--neat should not be used with --debug."));
315 }
316 
317 /// Fetch Test
318 
319 // A set of deterministic functions to generate fake debug infos.
getPtr(pid_t serverId)320 static uint64_t getPtr(pid_t serverId) { return 10000 + serverId; }
getClients(pid_t serverId)321 static std::vector<pid_t> getClients(pid_t serverId) {
322     return {serverId + 1, serverId + 3};
323 }
getPidInfoFromId(pid_t serverId)324 static BinderPidInfo getPidInfoFromId(pid_t serverId) {
325     BinderPidInfo info;
326     info.refPids[getPtr(serverId)] = getClients(serverId);
327     info.threadUsage = 10 + serverId;
328     info.threadCount = 20 + serverId;
329     return info;
330 }
getInterfaceName(pid_t serverId)331 static std::string getInterfaceName(pid_t serverId) {
332     return "a.h.foo" + std::to_string(serverId) + "@" + std::to_string(serverId) + ".0::IFoo";
333 }
getInstanceName(pid_t serverId)334 static std::string getInstanceName(pid_t serverId) {
335     return std::to_string(serverId);
336 }
getIdFromInstanceName(const hidl_string & instance)337 static pid_t getIdFromInstanceName(const hidl_string& instance) {
338     return atoi(instance.c_str());
339 }
getFqInstanceName(pid_t serverId)340 static std::string getFqInstanceName(pid_t serverId) {
341     return getInterfaceName(serverId) + "/" + getInstanceName(serverId);
342 }
getCmdlineFromId(pid_t serverId)343 static std::string getCmdlineFromId(pid_t serverId) {
344     if (serverId == NO_PID) return "";
345     return "command_line_" + std::to_string(serverId);
346 }
getIsReleasedFromId(pid_t p)347 static bool getIsReleasedFromId(pid_t p) { return p % 2 == 0; }
getHashFromId(pid_t serverId)348 static hidl_hash getHashFromId(pid_t serverId) {
349     hidl_hash hash;
350     bool isReleased = getIsReleasedFromId(serverId);
351     for (size_t i = 0; i < hash.size(); ++i) {
352         hash[i] = isReleased ? static_cast<uint8_t>(serverId) : 0u;
353     }
354     return hash;
355 }
356 
357 // Fake service returned by mocked IServiceManager::get.
358 class TestService : public IBase {
359 public:
TestService(pid_t id)360     explicit TestService(pid_t id) : mId(id) {}
getDebugInfo(getDebugInfo_cb cb)361     hardware::Return<void> getDebugInfo(getDebugInfo_cb cb) override {
362         cb({ mId /* pid */, getPtr(mId), DebugInfo::Architecture::IS_64BIT });
363         return hardware::Void();
364     }
interfaceChain(interfaceChain_cb cb)365     hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
366         cb({getInterfaceName(mId), IBase::descriptor});
367         return hardware::Void();
368     }
getHashChain(getHashChain_cb cb)369     hardware::Return<void> getHashChain(getHashChain_cb cb) override {
370         cb({getHashFromId(mId), getHashFromId(0xff)});
371         return hardware::Void();
372     }
373 private:
374     pid_t mId;
375 };
376 
377 class ListTest : public ::testing::Test {
378 public:
SetUp()379     virtual void SetUp() override {
380         initMockServiceManager();
381         lshal = std::make_unique<Lshal>(out, err, serviceManager, passthruManager);
382         initMockList();
383     }
384 
initMockList()385     void initMockList() {
386         mockList = std::make_unique<NiceMock<MockListCommand>>(lshal.get());
387         ON_CALL(*mockList, getPidInfo(_,_)).WillByDefault(Invoke(
388             [](pid_t serverPid, BinderPidInfo* info) {
389                 *info = getPidInfoFromId(serverPid);
390                 return true;
391             }));
392         ON_CALL(*mockList, parseCmdline(_)).WillByDefault(Invoke(&getCmdlineFromId));
393         ON_CALL(*mockList, postprocess()).WillByDefault(Invoke([&]() {
394             mockList->internalPostprocess();
395             size_t i = 0;
396             mockList->forEachTable([&](Table& table) {
397                 table.setDescription("[fake description " + std::to_string(i++) + "]");
398             });
399         }));
400         ON_CALL(*mockList, getPartition(_)).WillByDefault(Return(Partition::VENDOR));
401 
402         ON_CALL(*mockList, getDeviceManifest())
403                 .WillByDefault(Return(std::make_shared<HalManifest>()));
404         ON_CALL(*mockList, getDeviceMatrix())
405                 .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
406         ON_CALL(*mockList, getFrameworkManifest())
407                 .WillByDefault(Return(std::make_shared<HalManifest>()));
408         ON_CALL(*mockList, getFrameworkMatrix())
409                 .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
410     }
411 
initMockServiceManager()412     void initMockServiceManager() {
413         serviceManager = new testing::NiceMock<MockServiceManager>();
414         passthruManager = new testing::NiceMock<MockServiceManager>();
415         using A = DebugInfo::Architecture;
416         ON_CALL(*serviceManager, list(_)).WillByDefault(Invoke(
417             [] (IServiceManager::list_cb cb) {
418                 cb({ getFqInstanceName(1), getFqInstanceName(2) });
419                 return hardware::Void();
420             }));
421 
422         ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
423             [&](const hidl_string&, const hidl_string& instance) {
424                 int id = getIdFromInstanceName(instance);
425                 return sp<IBase>(new TestService(id));
426             }));
427 
428         ON_CALL(*serviceManager, debugDump(_)).WillByDefault(Invoke(
429             [] (IServiceManager::debugDump_cb cb) {
430                 cb({InstanceDebugInfo{getInterfaceName(3), getInstanceName(3), 3,
431                                       getClients(3), A::IS_32BIT},
432                     InstanceDebugInfo{getInterfaceName(4), getInstanceName(4), 4,
433                                       getClients(4), A::IS_32BIT}});
434                 return hardware::Void();
435             }));
436 
437         ON_CALL(*passthruManager, debugDump(_)).WillByDefault(Invoke(
438             [] (IServiceManager::debugDump_cb cb) {
439                 cb({InstanceDebugInfo{getInterfaceName(5), getInstanceName(5), 5,
440                                       getClients(5), A::IS_32BIT},
441                     InstanceDebugInfo{getInterfaceName(6), getInstanceName(6), 6,
442                                       getClients(6), A::IS_32BIT}});
443                 return hardware::Void();
444             }));
445     }
446 
447     std::stringstream err;
448     std::stringstream out;
449     std::unique_ptr<Lshal> lshal;
450     std::unique_ptr<MockListCommand> mockList;
451     sp<MockServiceManager> serviceManager;
452     sp<MockServiceManager> passthruManager;
453 };
454 
TEST_F(ListTest,GetPidInfoCached)455 TEST_F(ListTest, GetPidInfoCached) {
456     EXPECT_CALL(*mockList, getPidInfo(5, _)).Times(1);
457 
458     EXPECT_NE(nullptr, mockList->getPidInfoCached(5));
459     EXPECT_NE(nullptr, mockList->getPidInfoCached(5));
460 }
461 
TEST_F(ListTest,Fetch)462 TEST_F(ListTest, Fetch) {
463     optind = 1; // mimic Lshal::parseArg()
464     ASSERT_EQ(0u, mockList->parseArgs(createArg({"lshal"})));
465     ASSERT_EQ(0u, mockList->fetch());
466     vintf::TransportArch hwbinder{Transport::HWBINDER, Arch::ARCH_64};
467     vintf::TransportArch passthrough{Transport::PASSTHROUGH, Arch::ARCH_32};
468     std::array<vintf::TransportArch, 6> transportArchs{{hwbinder, hwbinder, passthrough,
469                                                         passthrough, passthrough, passthrough}};
470     int i = 0;
471     mockList->forEachTable([&](const Table& table) {
472         for (const auto& entry : table) {
473             if (i >= transportArchs.size()) {
474                 break;
475             }
476 
477             int id = i + 1;
478             auto transport = transportArchs.at(i).transport;
479             TableEntry expected{
480                 .interfaceName = getFqInstanceName(id),
481                 .transport = transport,
482                 .serverPid = transport == Transport::HWBINDER ? id : NO_PID,
483                 .threadUsage =
484                         transport == Transport::HWBINDER ? getPidInfoFromId(id).threadUsage : 0,
485                 .threadCount =
486                         transport == Transport::HWBINDER ? getPidInfoFromId(id).threadCount : 0,
487                 .serverCmdline = {},
488                 .serverObjectAddress = transport == Transport::HWBINDER ? getPtr(id) : NO_PTR,
489                 .clientPids = getClients(id),
490                 .clientCmdlines = {},
491                 .arch = transportArchs.at(i).arch,
492             };
493             EXPECT_EQ(expected, entry) << expected.to_string() << " vs. " << entry.to_string();
494 
495             ++i;
496         }
497     });
498 
499     EXPECT_EQ(transportArchs.size(), i) << "Not all entries are tested.";
500 
501 }
502 
TEST_F(ListTest,DumpVintf)503 TEST_F(ListTest, DumpVintf) {
504     const std::string expected = "    <hal format=\"hidl\">\n"
505                                  "        <name>a.h.foo1</name>\n"
506                                  "        <transport>hwbinder</transport>\n"
507                                  "        <fqname>@1.0::IFoo/1</fqname>\n"
508                                  "    </hal>\n"
509                                  "    <hal format=\"hidl\">\n"
510                                  "        <name>a.h.foo2</name>\n"
511                                  "        <transport>hwbinder</transport>\n"
512                                  "        <fqname>@2.0::IFoo/2</fqname>\n"
513                                  "    </hal>\n"
514                                  "    <hal format=\"hidl\">\n"
515                                  "        <name>a.h.foo3</name>\n"
516                                  "        <transport arch=\"32\">passthrough</transport>\n"
517                                  "        <fqname>@3.0::IFoo/3</fqname>\n"
518                                  "    </hal>\n"
519                                  "    <hal format=\"hidl\">\n"
520                                  "        <name>a.h.foo4</name>\n"
521                                  "        <transport arch=\"32\">passthrough</transport>\n"
522                                  "        <fqname>@4.0::IFoo/4</fqname>\n"
523                                  "    </hal>\n";
524 
525     optind = 1; // mimic Lshal::parseArg()
526     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--init-vintf"})));
527     auto output = out.str();
528     EXPECT_THAT(output, HasSubstr(expected));
529     EXPECT_THAT(output, HasSubstr("a.h.foo5@5.0::IFoo/5"));
530     EXPECT_THAT(output, HasSubstr("a.h.foo6@6.0::IFoo/6"));
531     EXPECT_EQ("", err.str());
532 
533     std::string error;
534     vintf::HalManifest m;
535     EXPECT_EQ(true, vintf::fromXml(&m, out.str(), &error))
536         << "--init-vintf does not emit valid HAL manifest: " << error;
537 }
538 
539 // test default columns
TEST_F(ListTest,DumpDefault)540 TEST_F(ListTest, DumpDefault) {
541     const std::string expected =
542         "[fake description 0]\n"
543         "VINTF R Interface            Thread Use Server Clients\n"
544         "X     N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
545         "X     Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
546         "\n"
547         "[fake description 1]\n"
548         "VINTF R Interface            Thread Use Server Clients\n"
549         "X     ? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
550         "X     ? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
551         "\n"
552         "[fake description 2]\n"
553         "VINTF R Interface            Thread Use Server Clients\n"
554         "X     ? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
555         "X     ? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
556         "\n";
557 
558     optind = 1; // mimic Lshal::parseArg()
559     EXPECT_EQ(0u, mockList->main(createArg({"lshal"})));
560     EXPECT_EQ(expected, out.str());
561     EXPECT_EQ("", err.str());
562 }
563 
TEST_F(ListTest,DumpHash)564 TEST_F(ListTest, DumpHash) {
565     const std::string expected =
566         "[fake description 0]\n"
567         "Interface            R Hash\n"
568         "a.h.foo1@1.0::IFoo/1 N 0000000000000000000000000000000000000000000000000000000000000000\n"
569         "a.h.foo2@2.0::IFoo/2 Y 0202020202020202020202020202020202020202020202020202020202020202\n"
570         "\n"
571         "[fake description 1]\n"
572         "Interface            R Hash\n"
573         "a.h.foo3@3.0::IFoo/3 ? \n"
574         "a.h.foo4@4.0::IFoo/4 ? \n"
575         "\n"
576         "[fake description 2]\n"
577         "Interface            R Hash\n"
578         "a.h.foo5@5.0::IFoo/5 ? \n"
579         "a.h.foo6@6.0::IFoo/6 ? \n"
580         "\n";
581 
582     optind = 1; // mimic Lshal::parseArg()
583     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-ils"})));
584     EXPECT_EQ(expected, out.str());
585     EXPECT_EQ("", err.str());
586 }
587 
TEST_F(ListTest,Dump)588 TEST_F(ListTest, Dump) {
589     const std::string expected =
590         "[fake description 0]\n"
591         "Interface            Transport Arch Thread Use Server PTR              Clients\n"
592         "a.h.foo1@1.0::IFoo/1 hwbinder  64   11/21      1      0000000000002711 2 4\n"
593         "a.h.foo2@2.0::IFoo/2 hwbinder  64   12/22      2      0000000000002712 3 5\n"
594         "\n"
595         "[fake description 1]\n"
596         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
597         "a.h.foo3@3.0::IFoo/3 passthrough 32   N/A        N/A    N/A 4 6\n"
598         "a.h.foo4@4.0::IFoo/4 passthrough 32   N/A        N/A    N/A 5 7\n"
599         "\n"
600         "[fake description 2]\n"
601         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
602         "a.h.foo5@5.0::IFoo/5 passthrough 32   N/A        N/A    N/A 6 8\n"
603         "a.h.foo6@6.0::IFoo/6 passthrough 32   N/A        N/A    N/A 7 9\n"
604         "\n";
605 
606     optind = 1; // mimic Lshal::parseArg()
607     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac"})));
608     EXPECT_EQ(expected, out.str());
609     EXPECT_EQ("", err.str());
610 }
611 
TEST_F(ListTest,DumpCmdline)612 TEST_F(ListTest, DumpCmdline) {
613     const std::string expected =
614         "[fake description 0]\n"
615         "Interface            Transport Arch Thread Use Server CMD     PTR              Clients CMD\n"
616         "a.h.foo1@1.0::IFoo/1 hwbinder  64   11/21      command_line_1 0000000000002711 command_line_2;command_line_4\n"
617         "a.h.foo2@2.0::IFoo/2 hwbinder  64   12/22      command_line_2 0000000000002712 command_line_3;command_line_5\n"
618         "\n"
619         "[fake description 1]\n"
620         "Interface            Transport   Arch Thread Use Server CMD PTR Clients CMD\n"
621         "a.h.foo3@3.0::IFoo/3 passthrough 32   N/A                   N/A command_line_4;command_line_6\n"
622         "a.h.foo4@4.0::IFoo/4 passthrough 32   N/A                   N/A command_line_5;command_line_7\n"
623         "\n"
624         "[fake description 2]\n"
625         "Interface            Transport   Arch Thread Use Server CMD PTR Clients CMD\n"
626         "a.h.foo5@5.0::IFoo/5 passthrough 32   N/A                   N/A command_line_6;command_line_8\n"
627         "a.h.foo6@6.0::IFoo/6 passthrough 32   N/A                   N/A command_line_7;command_line_9\n"
628         "\n";
629 
630     optind = 1; // mimic Lshal::parseArg()
631     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepacm"})));
632     EXPECT_EQ(expected, out.str());
633     EXPECT_EQ("", err.str());
634 }
635 
TEST_F(ListTest,DumpNeat)636 TEST_F(ListTest, DumpNeat) {
637     const std::string expected =
638         "a.h.foo1@1.0::IFoo/1 11/21 1   2 4\n"
639         "a.h.foo2@2.0::IFoo/2 12/22 2   3 5\n"
640         "a.h.foo3@3.0::IFoo/3 N/A   N/A 4 6\n"
641         "a.h.foo4@4.0::IFoo/4 N/A   N/A 5 7\n"
642         "a.h.foo5@5.0::IFoo/5 N/A   N/A 6 8\n"
643         "a.h.foo6@6.0::IFoo/6 N/A   N/A 7 9\n";
644 
645     optind = 1; // mimic Lshal::parseArg()
646     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iepc", "--neat"})));
647     EXPECT_EQ(expected, out.str());
648     EXPECT_EQ("", err.str());
649 }
650 
TEST_F(ListTest,DumpSingleHalType)651 TEST_F(ListTest, DumpSingleHalType) {
652     const std::string expected =
653         "[fake description 0]\n"
654         "Interface            Transport Arch Thread Use Server PTR              Clients\n"
655         "a.h.foo1@1.0::IFoo/1 hwbinder  64   11/21      1      0000000000002711 2 4\n"
656         "a.h.foo2@2.0::IFoo/2 hwbinder  64   12/22      2      0000000000002712 3 5\n"
657         "\n";
658 
659     optind = 1; // mimic Lshal::parseArg()
660     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=binderized"})));
661     EXPECT_EQ(expected, out.str());
662     EXPECT_EQ("", err.str());
663 }
664 
TEST_F(ListTest,DumpReorderedHalTypes)665 TEST_F(ListTest, DumpReorderedHalTypes) {
666     const std::string expected =
667         "[fake description 0]\n"
668         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
669         "a.h.foo3@3.0::IFoo/3 passthrough 32   N/A        N/A    N/A 4 6\n"
670         "a.h.foo4@4.0::IFoo/4 passthrough 32   N/A        N/A    N/A 5 7\n"
671         "\n"
672         "[fake description 1]\n"
673         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
674         "a.h.foo5@5.0::IFoo/5 passthrough 32   N/A        N/A    N/A 6 8\n"
675         "a.h.foo6@6.0::IFoo/6 passthrough 32   N/A        N/A    N/A 7 9\n"
676         "\n"
677         "[fake description 2]\n"
678         "Interface            Transport Arch Thread Use Server PTR              Clients\n"
679         "a.h.foo1@1.0::IFoo/1 hwbinder  64   11/21      1      0000000000002711 2 4\n"
680         "a.h.foo2@2.0::IFoo/2 hwbinder  64   12/22      2      0000000000002712 3 5\n"
681         "\n";
682 
683     optind = 1; // mimic Lshal::parseArg()
684     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=passthrough_clients",
685                                             "--types=passthrough_libs", "--types=binderized"})));
686     EXPECT_EQ(expected, out.str());
687     EXPECT_EQ("", err.str());
688 }
689 
TEST_F(ListTest,DumpAbbreviatedHalTypes)690 TEST_F(ListTest, DumpAbbreviatedHalTypes) {
691     const std::string expected =
692         "[fake description 0]\n"
693         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
694         "a.h.foo3@3.0::IFoo/3 passthrough 32   N/A        N/A    N/A 4 6\n"
695         "a.h.foo4@4.0::IFoo/4 passthrough 32   N/A        N/A    N/A 5 7\n"
696         "\n"
697         "[fake description 1]\n"
698         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
699         "a.h.foo5@5.0::IFoo/5 passthrough 32   N/A        N/A    N/A 6 8\n"
700         "a.h.foo6@6.0::IFoo/6 passthrough 32   N/A        N/A    N/A 7 9\n"
701         "\n";
702 
703     optind = 1; // mimic Lshal::parseArg()
704     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l"})));
705     EXPECT_EQ(expected, out.str());
706     EXPECT_EQ("", err.str());
707 }
708 
TEST_F(ListTest,DumpEmptyAndDuplicateHalTypes)709 TEST_F(ListTest, DumpEmptyAndDuplicateHalTypes) {
710     const std::string expected =
711         "[fake description 0]\n"
712         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
713         "a.h.foo3@3.0::IFoo/3 passthrough 32   N/A        N/A    N/A 4 6\n"
714         "a.h.foo4@4.0::IFoo/4 passthrough 32   N/A        N/A    N/A 5 7\n"
715         "\n"
716         "[fake description 1]\n"
717         "Interface            Transport   Arch Thread Use Server PTR Clients\n"
718         "a.h.foo5@5.0::IFoo/5 passthrough 32   N/A        N/A    N/A 6 8\n"
719         "a.h.foo6@6.0::IFoo/6 passthrough 32   N/A        N/A    N/A 7 9\n"
720         "\n";
721 
722     optind = 1; // mimic Lshal::parseArg()
723     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l,,,l,l,c,",
724                                             "--types=passthrough_libs,passthrough_clients"})));
725     EXPECT_EQ(expected, out.str());
726     EXPECT_EQ("", err.str());
727 }
728 
TEST_F(ListTest,UnknownHalType)729 TEST_F(ListTest, UnknownHalType) {
730     optind = 1; // mimic Lshal::parseArg()
731     EXPECT_EQ(1u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,r"})));
732     EXPECT_THAT(err.str(), HasSubstr("Unrecognized HAL type: r"));
733 }
734 
TEST_F(ListTest,Vintf)735 TEST_F(ListTest, Vintf) {
736     std::string deviceManifestXml =
737             "<manifest version=\"1.0\" type=\"device\">\n"
738             "    <hal>\n"
739             "        <name>a.h.foo1</name>\n"
740             "        <transport>hwbinder</transport>\n"
741             "        <fqname>@1.0::IFoo/1</fqname>\n"
742             "    </hal>\n"
743             "    <hal>\n"
744             "        <name>a.h.foo3</name>\n"
745             "        <transport arch=\"32+64\">passthrough</transport>\n"
746             "        <fqname>@3.0::IFoo/3</fqname>\n"
747             "    </hal>\n"
748             "</manifest>\n";
749     std::string frameworkManifestXml =
750             "<manifest version=\"1.0\" type=\"framework\">\n"
751             "    <hal>\n"
752             "        <name>a.h.foo5</name>\n"
753             "        <transport arch=\"32\">passthrough</transport>\n"
754             "        <fqname>@5.0::IFoo/5</fqname>\n"
755             "    </hal>\n"
756             "</manifest>\n";
757     std::string deviceMatrixXml =
758             "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
759             "    <hal>\n"
760             "        <name>a.h.foo5</name>\n"
761             "        <version>5.0</version>\n"
762             "        <interface>\n"
763             "            <name>IFoo</name>\n"
764             "            <instance>5</instance>\n"
765             "        </interface>\n"
766             "    </hal>\n"
767             "</compatibility-matrix>\n";
768     std::string frameworkMatrixXml =
769             "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
770             "    <hal>\n"
771             "        <name>a.h.foo1</name>\n"
772             "        <version>1.0</version>\n"
773             "        <interface>\n"
774             "            <name>IFoo</name>\n"
775             "            <instance>1</instance>\n"
776             "        </interface>\n"
777             "    </hal>\n"
778             "    <hal>\n"
779             "        <name>a.h.foo3</name>\n"
780             "        <version>3.0</version>\n"
781             "        <interface>\n"
782             "            <name>IFoo</name>\n"
783             "            <instance>3</instance>\n"
784             "        </interface>\n"
785             "    </hal>\n"
786             "</compatibility-matrix>\n";
787 
788     std::string expected = "DM,FC a.h.foo1@1.0::IFoo/1\n"
789                            "X     a.h.foo2@2.0::IFoo/2\n"
790                            "DM,FC a.h.foo3@3.0::IFoo/3\n"
791                            "X     a.h.foo4@4.0::IFoo/4\n"
792                            "DC,FM a.h.foo5@5.0::IFoo/5\n"
793                            "X     a.h.foo6@6.0::IFoo/6\n";
794 
795     auto deviceManifest = std::make_shared<HalManifest>();
796     auto frameworkManifest = std::make_shared<HalManifest>();
797     auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
798     auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
799 
800     ASSERT_TRUE(fromXml(deviceManifest.get(), deviceManifestXml));
801     ASSERT_TRUE(fromXml(frameworkManifest.get(), frameworkManifestXml));
802     ASSERT_TRUE(fromXml(deviceMatrix.get(), deviceMatrixXml));
803     ASSERT_TRUE(fromXml(frameworkMatrix.get(), frameworkMatrixXml));
804 
805     ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
806     ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
807     ON_CALL(*mockList, getFrameworkManifest()).WillByDefault(Return(frameworkManifest));
808     ON_CALL(*mockList, getFrameworkMatrix()).WillByDefault(Return(frameworkMatrix));
809 
810     optind = 1; // mimic Lshal::parseArg()
811     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-Vi", "--neat"})));
812     EXPECT_THAT(out.str(), HasSubstr(expected));
813     EXPECT_EQ("", err.str());
814 }
815 
TEST_F(ListTest,AllColumns)816 TEST_F(ListTest, AllColumns) {
817     // clang-format off
818     const std::string expected =
819         "[fake description 0]\n"
820         "Interface            Transport Server PTR              Arch Thread Use R Hash                                                             VINTF Status Clients\n"
821         "a.h.foo1@1.0::IFoo/1 hwbinder  1      0000000000002711 64   11/21      N 0000000000000000000000000000000000000000000000000000000000000000 X     alive  2 4\n"
822         "a.h.foo2@2.0::IFoo/2 hwbinder  2      0000000000002712 64   12/22      Y 0202020202020202020202020202020202020202020202020202020202020202 X     alive  3 5\n"
823         "\n"
824         "[fake description 1]\n"
825         "Interface            Transport   Server PTR Arch Thread Use R Hash VINTF Status Clients\n"
826         "a.h.foo3@3.0::IFoo/3 passthrough N/A    N/A 32   N/A        ?      X     N/A    4 6\n"
827         "a.h.foo4@4.0::IFoo/4 passthrough N/A    N/A 32   N/A        ?      X     N/A    5 7\n"
828         "\n"
829         "[fake description 2]\n"
830         "Interface            Transport   Server PTR Arch Thread Use R Hash VINTF Status Clients\n"
831         "a.h.foo5@5.0::IFoo/5 passthrough N/A    N/A 32   N/A        ?      X     N/A    6 8\n"
832         "a.h.foo6@6.0::IFoo/6 passthrough N/A    N/A 32   N/A        ?      X     N/A    7 9\n"
833         "\n";
834     // clang-format on
835 
836     optind = 1; // mimic Lshal::parseArg()
837     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--all"})));
838     EXPECT_EQ(expected, out.str());
839     EXPECT_EQ("", err.str());
840 }
841 
TEST_F(ListTest,AllColumnsWithCmd)842 TEST_F(ListTest, AllColumnsWithCmd) {
843     // clang-format off
844     const std::string expected =
845         "[fake description 0]\n"
846         "Interface            Transport Server CMD     PTR              Arch Thread Use R Hash                                                             VINTF Status Clients CMD\n"
847         "a.h.foo1@1.0::IFoo/1 hwbinder  command_line_1 0000000000002711 64   11/21      N 0000000000000000000000000000000000000000000000000000000000000000 X     alive  command_line_2;command_line_4\n"
848         "a.h.foo2@2.0::IFoo/2 hwbinder  command_line_2 0000000000002712 64   12/22      Y 0202020202020202020202020202020202020202020202020202020202020202 X     alive  command_line_3;command_line_5\n"
849         "\n"
850         "[fake description 1]\n"
851         "Interface            Transport   Server CMD PTR Arch Thread Use R Hash VINTF Status Clients CMD\n"
852         "a.h.foo3@3.0::IFoo/3 passthrough            N/A 32   N/A        ?      X     N/A    command_line_4;command_line_6\n"
853         "a.h.foo4@4.0::IFoo/4 passthrough            N/A 32   N/A        ?      X     N/A    command_line_5;command_line_7\n"
854         "\n"
855         "[fake description 2]\n"
856         "Interface            Transport   Server CMD PTR Arch Thread Use R Hash VINTF Status Clients CMD\n"
857         "a.h.foo5@5.0::IFoo/5 passthrough            N/A 32   N/A        ?      X     N/A    command_line_6;command_line_8\n"
858         "a.h.foo6@6.0::IFoo/6 passthrough            N/A 32   N/A        ?      X     N/A    command_line_7;command_line_9\n"
859         "\n";
860     // clang-format on
861 
862     optind = 1; // mimic Lshal::parseArg()
863     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-Am"})));
864     EXPECT_EQ(expected, out.str());
865     EXPECT_EQ("", err.str());
866 }
867 
TEST_F(ListTest,AllSections)868 TEST_F(ListTest, AllSections) {
869     optind = 1; // mimic Lshal::parseArg()
870     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--types=all"})));
871     using HalTypeBase = std::underlying_type_t<HalType>;
872     for (HalTypeBase i = 0; i < static_cast<HalTypeBase>(HalType::LAST); ++i) {
873         EXPECT_THAT(out.str(), HasSubstr("[fake description " + std::to_string(i) + "]"));
874     }
875     EXPECT_THAT(out.str(),
876                 Not(HasSubstr("[fake description " +
877                               std::to_string(static_cast<HalTypeBase>(HalType::LAST)) + "]")));
878     EXPECT_EQ("", err.str());
879 }
880 
881 // Fake service returned by mocked IServiceManager::get for DumpDebug.
882 // The interfaceChain and getHashChain functions returns
883 // foo(id - 1) -> foo(id - 2) -> ... foo1 -> IBase.
884 class InheritingService : public IBase {
885 public:
InheritingService(pid_t id)886     explicit InheritingService(pid_t id) : mId(id) {}
interfaceDescriptor(interfaceDescriptor_cb cb)887     android::hardware::Return<void> interfaceDescriptor(interfaceDescriptor_cb cb) override {
888         cb(getInterfaceName(mId));
889         return hardware::Void();
890     }
interfaceChain(interfaceChain_cb cb)891     android::hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
892         std::vector<hidl_string> ret;
893         for (auto i = mId; i > 0; --i) {
894             ret.push_back(getInterfaceName(i));
895         }
896         ret.push_back(IBase::descriptor);
897         cb(ret);
898         return hardware::Void();
899     }
getHashChain(getHashChain_cb cb)900     android::hardware::Return<void> getHashChain(getHashChain_cb cb) override {
901         std::vector<hidl_hash> ret;
902         for (auto i = mId; i > 0; --i) {
903             ret.push_back(getHashFromId(i));
904         }
905         ret.push_back(getHashFromId(0xff));
906         cb(ret);
907         return hardware::Void();
908     }
debug(const hidl_handle & hh,const hidl_vec<hidl_string> &)909     android::hardware::Return<void> debug(const hidl_handle& hh,
910                                           const hidl_vec<hidl_string>&) override {
911         const native_handle_t* handle = hh.getNativeHandle();
912         if (handle->numFds < 1) {
913             return Void();
914         }
915         int fd = handle->data[0];
916         std::string content = "debug info for ";
917         content += getInterfaceName(mId);
918         ssize_t written = write(fd, content.c_str(), content.size());
919         if (written != (ssize_t)content.size()) {
920             LOG(WARNING) << "SERVER(" << descriptor << ") debug writes " << written << " bytes < "
921                          << content.size() << " bytes, errno = " << errno;
922         }
923         return Void();
924     }
925 
926 private:
927     pid_t mId;
928 };
929 
TEST_F(ListTest,DumpDebug)930 TEST_F(ListTest, DumpDebug) {
931     size_t inheritanceLevel = 3;
932     sp<IBase> service = new InheritingService(inheritanceLevel);
933 
934     EXPECT_CALL(*serviceManager, list(_)).WillRepeatedly(Invoke([&](IServiceManager::list_cb cb) {
935         std::vector<hidl_string> ret;
936         for (auto i = 1; i <= inheritanceLevel; ++i) {
937             ret.push_back(getInterfaceName(i) + "/default");
938         }
939         cb(ret);
940         return hardware::Void();
941     }));
942     EXPECT_CALL(*serviceManager, get(_, _))
943             .WillRepeatedly(Invoke([&](const hidl_string&, const hidl_string&) -> sp<IBase> {
944                 return sp<IBase>(service);
945             }));
946 
947     const std::string expected = "[fake description 0]\n"
948                                  "Interface\n"
949                                  "a.h.foo1@1.0::IFoo/default\n"
950                                  "[See a.h.foo3@3.0::IFoo/default]\n"
951                                  "a.h.foo2@2.0::IFoo/default\n"
952                                  "[See a.h.foo3@3.0::IFoo/default]\n"
953                                  "a.h.foo3@3.0::IFoo/default\n"
954                                  "debug info for a.h.foo3@3.0::IFoo\n"
955                                  "\n";
956 
957     optind = 1; // mimic Lshal::parseArg()
958     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--types=b", "-id"})));
959     EXPECT_EQ(expected, out.str());
960     EXPECT_EQ("", err.str());
961 }
962 
963 // In SlowService, everything goes slooooooow. Each IPC call will wait for
964 // the specified time before calling the callback function or returning.
965 class SlowService : public IBase {
966 public:
SlowService(std::chrono::milliseconds wait)967     explicit SlowService(std::chrono::milliseconds wait) : mWait(wait) {}
interfaceDescriptor(interfaceDescriptor_cb cb)968     android::hardware::Return<void> interfaceDescriptor(interfaceDescriptor_cb cb) override {
969         std::this_thread::sleep_for(mWait);
970         cb(getInterfaceName(1));
971         storeHistory("interfaceDescriptor");
972         return hardware::Void();
973     }
interfaceChain(interfaceChain_cb cb)974     android::hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
975         std::this_thread::sleep_for(mWait);
976         std::vector<hidl_string> ret;
977         ret.push_back(getInterfaceName(1));
978         ret.push_back(IBase::descriptor);
979         cb(ret);
980         storeHistory("interfaceChain");
981         return hardware::Void();
982     }
getHashChain(getHashChain_cb cb)983     android::hardware::Return<void> getHashChain(getHashChain_cb cb) override {
984         std::this_thread::sleep_for(mWait);
985         std::vector<hidl_hash> ret;
986         ret.push_back(getHashFromId(0));
987         ret.push_back(getHashFromId(0xff));
988         cb(ret);
989         storeHistory("getHashChain");
990         return hardware::Void();
991     }
debug(const hidl_handle &,const hidl_vec<hidl_string> &)992     android::hardware::Return<void> debug(const hidl_handle&,
993                                           const hidl_vec<hidl_string>&) override {
994         std::this_thread::sleep_for(mWait);
995         storeHistory("debug");
996         return Void();
997     }
998 
999     template <class R, class P, class Pred>
waitForHistory(std::chrono::duration<R,P> wait,Pred predicate)1000     bool waitForHistory(std::chrono::duration<R, P> wait, Pred predicate) {
1001         std::unique_lock<std::mutex> lock(mLock);
1002         return mCv.wait_for(lock, wait, [&]() { return predicate(mCallHistory); });
1003     }
1004 
1005 private:
storeHistory(std::string hist)1006     void storeHistory(std::string hist) {
1007         {
1008             std::lock_guard<std::mutex> lock(mLock);
1009             mCallHistory.emplace_back(std::move(hist));
1010         }
1011         mCv.notify_all();
1012     }
1013 
1014     const std::chrono::milliseconds mWait;
1015     std::mutex mLock;
1016     std::condition_variable mCv;
1017     // List of functions that have finished being called on this interface.
1018     std::vector<std::string> mCallHistory;
1019 };
1020 
1021 class TimeoutTest : public ListTest {
1022 public:
setMockServiceManager(sp<IBase> service)1023     void setMockServiceManager(sp<IBase> service) {
1024         EXPECT_CALL(*serviceManager, list(_))
1025                 .WillRepeatedly(Invoke([&](IServiceManager::list_cb cb) {
1026                     std::vector<hidl_string> ret;
1027                     ret.push_back(getInterfaceName(1) + "/default");
1028                     cb(ret);
1029                     return hardware::Void();
1030                 }));
1031         EXPECT_CALL(*serviceManager, get(_, _))
1032                 .WillRepeatedly(Invoke([&](const hidl_string&, const hidl_string&) -> sp<IBase> {
1033                     return service;
1034                 }));
1035     }
1036 };
1037 
TEST_F(TimeoutTest,BackgroundThreadIsKept)1038 TEST_F(TimeoutTest, BackgroundThreadIsKept) {
1039     auto lshalIpcTimeout = 100ms;
1040     auto serviceIpcTimeout = 200ms;
1041     lshal->setWaitTimeForTest(lshalIpcTimeout, lshalIpcTimeout);
1042     sp<SlowService> service = new SlowService(serviceIpcTimeout);
1043     setMockServiceManager(service);
1044 
1045     optind = 1; // mimic Lshal::parseArg()
1046     EXPECT_NE(0u, mockList->main(createArg({"lshal", "--types=b", "-i", "--neat"})));
1047     EXPECT_THAT(err.str(), HasSubstr("Skipping \"a.h.foo1@1.0::IFoo/default\""));
1048     EXPECT_TRUE(service->waitForHistory(serviceIpcTimeout * 5, [](const auto& hist) {
1049         return hist.size() == 1 && hist[0] == "interfaceChain";
1050     })) << "The background thread should continue after the main thread moves on, but it is killed";
1051 }
1052 
TEST_F(TimeoutTest,BackgroundThreadDoesNotBlockMainThread)1053 TEST_F(TimeoutTest, BackgroundThreadDoesNotBlockMainThread) {
1054     auto lshalIpcTimeout = 100ms;
1055     auto serviceIpcTimeout = 2000ms;
1056     auto start = std::chrono::system_clock::now();
1057     lshal->setWaitTimeForTest(lshalIpcTimeout, lshalIpcTimeout);
1058     sp<SlowService> service = new SlowService(serviceIpcTimeout);
1059     setMockServiceManager(service);
1060 
1061     optind = 1; // mimic Lshal::parseArg()
1062     EXPECT_NE(0u, mockList->main(createArg({"lshal", "--types=b", "-i", "--neat"})));
1063     EXPECT_LE(std::chrono::system_clock::now(), start + 5 * lshalIpcTimeout)
1064             << "The main thread should not be blocked by the background task";
1065 }
1066 
1067 class ListVintfTest : public ListTest {
1068 public:
SetUp()1069     virtual void SetUp() override {
1070         ListTest::SetUp();
1071         const std::string mockManifestXml =
1072                 "<manifest version=\"1.0\" type=\"device\">\n"
1073                 "    <hal format=\"hidl\">\n"
1074                 "        <name>a.h.foo1</name>\n"
1075                 "        <transport>hwbinder</transport>\n"
1076                 "        <fqname>@1.0::IFoo/1</fqname>\n"
1077                 "    </hal>\n"
1078                 "    <hal format=\"hidl\">\n"
1079                 "        <name>a.h.bar1</name>\n"
1080                 "        <transport>hwbinder</transport>\n"
1081                 "        <fqname>@1.0::IBar/1</fqname>\n"
1082                 "    </hal>\n"
1083                 "    <hal format=\"hidl\">\n"
1084                 "        <name>a.h.bar2</name>\n"
1085                 "        <transport arch=\"32+64\">passthrough</transport>\n"
1086                 "        <fqname>@2.0::IBar/2</fqname>\n"
1087                 "    </hal>\n"
1088                 "</manifest>";
1089         auto manifest = std::make_shared<HalManifest>();
1090         EXPECT_TRUE(fromXml(manifest.get(), mockManifestXml));
1091         EXPECT_CALL(*mockList, getDeviceManifest())
1092             .Times(AnyNumber())
1093             .WillRepeatedly(Return(manifest));
1094     }
1095 };
1096 
TEST_F(ListVintfTest,ManifestHals)1097 TEST_F(ListVintfTest, ManifestHals) {
1098     optind = 1; // mimic Lshal::parseArg()
1099     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=v", "--neat"})));
1100     EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder    ?"));
1101     EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
1102     EXPECT_THAT(out.str(), HasSubstr("a.h.foo1@1.0::IFoo/1 declared hwbinder    ?"));
1103     EXPECT_EQ("", err.str());
1104 }
1105 
TEST_F(ListVintfTest,Lazy)1106 TEST_F(ListVintfTest, Lazy) {
1107     optind = 1; // mimic Lshal::parseArg()
1108     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=z", "--neat"})));
1109     EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder    ?"));
1110     EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
1111     EXPECT_EQ("", err.str());
1112 }
1113 
TEST_F(ListVintfTest,NoLazy)1114 TEST_F(ListVintfTest, NoLazy) {
1115     optind = 1; // mimic Lshal::parseArg()
1116     EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=b,c,l", "--neat"})));
1117     EXPECT_THAT(out.str(), Not(HasSubstr("IBar")));
1118     EXPECT_EQ("", err.str());
1119 }
1120 
1121 class HelpTest : public ::testing::Test {
1122 public:
SetUp()1123     void SetUp() override {
1124         lshal = std::make_unique<Lshal>(out, err, new MockServiceManager() /* serviceManager */,
1125                                         new MockServiceManager() /* passthruManager */);
1126     }
1127 
1128     std::stringstream err;
1129     std::stringstream out;
1130     std::unique_ptr<Lshal> lshal;
1131 };
1132 
TEST_F(HelpTest,GlobalUsage)1133 TEST_F(HelpTest, GlobalUsage) {
1134     (void)callMain(lshal, {"lshal", "--help"}); // ignore return
1135     std::string errStr = err.str();
1136     EXPECT_THAT(errStr, ContainsRegex("(^|\n)commands:($|\n)"))
1137         << "`lshal --help` does not contain global usage";
1138     EXPECT_THAT(errStr, ContainsRegex("(^|\n)list:($|\n)"))
1139         << "`lshal --help` does not contain usage for 'list' command";
1140     EXPECT_THAT(errStr, ContainsRegex("(^|\n)debug:($|\n)"))
1141         << "`lshal --help` does not contain usage for 'debug' command";
1142     EXPECT_THAT(errStr, ContainsRegex("(^|\n)help:($|\n)"))
1143         << "`lshal --help` does not contain usage for 'help' command";
1144 
1145     err.str("");
1146     (void)callMain(lshal, {"lshal", "help"}); // ignore return
1147     EXPECT_EQ(errStr, err.str()) << "`lshal help` should have the same output as `lshal --help`";
1148 
1149     err.str("");
1150     EXPECT_NE(0u, callMain(lshal, {"lshal", "--unknown-option"}));
1151     EXPECT_THAT(err.str(), ContainsRegex("unrecognized option"));
1152     EXPECT_THAT(err.str(), EndsWith(errStr))
1153             << "`lshal --unknown-option` should have the same output as `lshal --help`";
1154     EXPECT_EQ("", out.str());
1155 }
1156 
TEST_F(HelpTest,UnknownOptionList1)1157 TEST_F(HelpTest, UnknownOptionList1) {
1158     (void)callMain(lshal, {"lshal", "help", "list"});
1159     EXPECT_THAT(err.str(), ContainsRegex("(^|\n)list:($|\n)"))
1160         << "`lshal help list` does not contain usage for 'list' command";
1161 }
1162 
TEST_F(HelpTest,UnknownOptionList2)1163 TEST_F(HelpTest, UnknownOptionList2) {
1164     EXPECT_NE(0u, callMain(lshal, {"lshal", "list", "--unknown-option"}));
1165     EXPECT_THAT(err.str(), ContainsRegex("unrecognized option"));
1166     EXPECT_THAT(err.str(), ContainsRegex("(^|\n)list:($|\n)"))
1167         << "`lshal list --unknown-option` does not contain usage for 'list' command";
1168     EXPECT_EQ("", out.str());
1169 }
1170 
TEST_F(HelpTest,UnknownOptionHelp1)1171 TEST_F(HelpTest, UnknownOptionHelp1) {
1172     (void)callMain(lshal, {"lshal", "help", "help"});
1173     EXPECT_THAT(err.str(), ContainsRegex("(^|\n)help:($|\n)"))
1174         << "`lshal help help` does not contain usage for 'help' command";
1175 }
1176 
TEST_F(HelpTest,UnknownOptionHelp2)1177 TEST_F(HelpTest, UnknownOptionHelp2) {
1178     (void)callMain(lshal, {"lshal", "help", "--unknown-option"});
1179     EXPECT_THAT(err.str(), ContainsRegex("(^|\n)help:($|\n)"))
1180         << "`lshal help --unknown-option` does not contain usage for 'help' command";
1181     EXPECT_EQ("", out.str());
1182 }
1183 
1184 } // namespace lshal
1185 } // namespace android
1186 
main(int argc,char ** argv)1187 int main(int argc, char **argv) {
1188     ::testing::InitGoogleMock(&argc, argv);
1189     // Use _exit() to force terminate background threads in Timeout.h
1190     _exit(RUN_ALL_TESTS());
1191 }
1192