test.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  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. #define LOG_TAG "Lshal"
  17. #include <android-base/logging.h>
  18. #include <sstream>
  19. #include <string>
  20. #include <thread>
  21. #include <vector>
  22. #include <gtest/gtest.h>
  23. #include <gmock/gmock.h>
  24. #include <android/hardware/tests/baz/1.0/IQuux.h>
  25. #include <hidl/HidlTransportSupport.h>
  26. #include <vintf/parse_xml.h>
  27. #include "ListCommand.h"
  28. #include "Lshal.h"
  29. #define NELEMS(array) static_cast<int>(sizeof(array) / sizeof(array[0]))
  30. using namespace testing;
  31. using ::android::hidl::base::V1_0::DebugInfo;
  32. using ::android::hidl::base::V1_0::IBase;
  33. using ::android::hidl::manager::V1_0::IServiceManager;
  34. using ::android::hidl::manager::V1_0::IServiceNotification;
  35. using ::android::hardware::hidl_array;
  36. using ::android::hardware::hidl_death_recipient;
  37. using ::android::hardware::hidl_handle;
  38. using ::android::hardware::hidl_string;
  39. using ::android::hardware::hidl_vec;
  40. using android::vintf::Arch;
  41. using android::vintf::CompatibilityMatrix;
  42. using android::vintf::gCompatibilityMatrixConverter;
  43. using android::vintf::gHalManifestConverter;
  44. using android::vintf::HalManifest;
  45. using android::vintf::Transport;
  46. using android::vintf::VintfObject;
  47. using InstanceDebugInfo = IServiceManager::InstanceDebugInfo;
  48. using hidl_hash = hidl_array<uint8_t, 32>;
  49. namespace android {
  50. namespace hardware {
  51. namespace tests {
  52. namespace baz {
  53. namespace V1_0 {
  54. namespace implementation {
  55. struct Quux : android::hardware::tests::baz::V1_0::IQuux {
  56. ::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
  57. const native_handle_t *handle = hh.getNativeHandle();
  58. if (handle->numFds < 1) {
  59. return Void();
  60. }
  61. int fd = handle->data[0];
  62. std::string content{descriptor};
  63. for (const auto &option : options) {
  64. content += "\n";
  65. content += option.c_str();
  66. }
  67. ssize_t written = write(fd, content.c_str(), content.size());
  68. if (written != (ssize_t)content.size()) {
  69. LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < "
  70. << content.size() << " bytes, errno = " << errno;
  71. }
  72. return Void();
  73. }
  74. };
  75. } // namespace implementation
  76. } // namespace V1_0
  77. } // namespace baz
  78. } // namespace tests
  79. } // namespace hardware
  80. namespace lshal {
  81. class MockServiceManager : public IServiceManager {
  82. public:
  83. template<typename T>
  84. using R = ::android::hardware::Return<T>;
  85. using String = const hidl_string&;
  86. ~MockServiceManager() = default;
  87. #define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb))
  88. MOCK_METHOD2(get, R<sp<IBase>>(String, String));
  89. MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&));
  90. MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String));
  91. MOCK_METHOD_CB(list);
  92. MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb));
  93. MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&));
  94. MOCK_METHOD_CB(debugDump);
  95. MOCK_METHOD2(registerPassthroughClient, R<void>(String, String));
  96. MOCK_METHOD_CB(interfaceChain);
  97. MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&));
  98. MOCK_METHOD_CB(interfaceDescriptor);
  99. MOCK_METHOD_CB(getHashChain);
  100. MOCK_METHOD0(setHalInstrumentation, R<void>());
  101. MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t));
  102. MOCK_METHOD0(ping, R<void>());
  103. MOCK_METHOD_CB(getDebugInfo);
  104. MOCK_METHOD0(notifySyspropsChanged, R<void>());
  105. MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&));
  106. };
  107. class DebugTest : public ::testing::Test {
  108. public:
  109. void SetUp() override {
  110. using ::android::hardware::tests::baz::V1_0::IQuux;
  111. using ::android::hardware::tests::baz::V1_0::implementation::Quux;
  112. err.str("");
  113. out.str("");
  114. serviceManager = new testing::NiceMock<MockServiceManager>();
  115. ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
  116. [](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> {
  117. if (iface == IQuux::descriptor && inst == "default")
  118. return new Quux();
  119. return nullptr;
  120. }));
  121. lshal = std::make_unique<Lshal>(out, err, serviceManager, serviceManager);
  122. }
  123. void TearDown() override {}
  124. std::stringstream err;
  125. std::stringstream out;
  126. sp<MockServiceManager> serviceManager;
  127. std::unique_ptr<Lshal> lshal;
  128. };
  129. static Arg createArg(const std::vector<const char*>& args) {
  130. return Arg{static_cast<int>(args.size()), const_cast<char**>(args.data())};
  131. }
  132. template<typename T>
  133. static Status callMain(const std::unique_ptr<T>& lshal, const std::vector<const char*>& args) {
  134. return lshal->main(createArg(args));
  135. }
  136. TEST_F(DebugTest, Debug) {
  137. EXPECT_EQ(0u, callMain(lshal, {
  138. "lshal", "debug", "[email protected]::IQuux/default", "foo", "bar"
  139. }));
  140. EXPECT_THAT(out.str(), StrEq("[email protected]::IQuux\nfoo\nbar"));
  141. EXPECT_THAT(err.str(), IsEmpty());
  142. }
  143. TEST_F(DebugTest, Debug2) {
  144. EXPECT_EQ(0u, callMain(lshal, {
  145. "lshal", "debug", "[email protected]::IQuux", "baz", "quux"
  146. }));
  147. EXPECT_THAT(out.str(), StrEq("[email protected]::IQuux\nbaz\nquux"));
  148. EXPECT_THAT(err.str(), IsEmpty());
  149. }
  150. TEST_F(DebugTest, Debug3) {
  151. EXPECT_NE(0u, callMain(lshal, {
  152. "lshal", "debug", "[email protected]::IDoesNotExist",
  153. }));
  154. EXPECT_THAT(err.str(), HasSubstr("does not exist"));
  155. }
  156. class MockLshal : public Lshal {
  157. public:
  158. MockLshal() {}
  159. ~MockLshal() = default;
  160. MOCK_CONST_METHOD0(out, NullableOStream<std::ostream>());
  161. MOCK_CONST_METHOD0(err, NullableOStream<std::ostream>());
  162. };
  163. // expose protected fields and methods for ListCommand
  164. class MockListCommand : public ListCommand {
  165. public:
  166. explicit MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
  167. Status parseArgs(const Arg& arg) { return ListCommand::parseArgs(arg); }
  168. Status main(const Arg& arg) { return ListCommand::main(arg); }
  169. void forEachTable(const std::function<void(Table &)> &f) {
  170. return ListCommand::forEachTable(f);
  171. }
  172. void forEachTable(const std::function<void(const Table &)> &f) const {
  173. return ListCommand::forEachTable(f);
  174. }
  175. Status fetch() { return ListCommand::fetch(); }
  176. void dumpVintf(const NullableOStream<std::ostream>& out) {
  177. return ListCommand::dumpVintf(out);
  178. }
  179. void internalPostprocess() { ListCommand::postprocess(); }
  180. const PidInfo* getPidInfoCached(pid_t serverPid) {
  181. return ListCommand::getPidInfoCached(serverPid);
  182. }
  183. MOCK_METHOD0(postprocess, void());
  184. MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, PidInfo*));
  185. MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t));
  186. MOCK_METHOD1(getPartition, Partition(pid_t));
  187. MOCK_CONST_METHOD0(getDeviceManifest, std::shared_ptr<const vintf::HalManifest>());
  188. MOCK_CONST_METHOD0(getDeviceMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
  189. MOCK_CONST_METHOD0(getFrameworkManifest, std::shared_ptr<const vintf::HalManifest>());
  190. MOCK_CONST_METHOD0(getFrameworkMatrix, std::shared_ptr<const vintf::CompatibilityMatrix>());
  191. };
  192. class ListParseArgsTest : public ::testing::Test {
  193. public:
  194. void SetUp() override {
  195. mockLshal = std::make_unique<NiceMock<MockLshal>>();
  196. mockList = std::make_unique<MockListCommand>(mockLshal.get());
  197. ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(err)));
  198. // ListCommand::parseArgs should parse arguments from the second element
  199. optind = 1;
  200. }
  201. std::unique_ptr<MockLshal> mockLshal;
  202. std::unique_ptr<MockListCommand> mockList;
  203. std::stringstream err;
  204. };
  205. TEST_F(ListParseArgsTest, Args) {
  206. EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-p", "-i", "-a", "-c"})));
  207. mockList->forEachTable([](const Table& table) {
  208. EXPECT_EQ(SelectedColumns({TableColumnType::SERVER_PID, TableColumnType::INTERFACE_NAME,
  209. TableColumnType::SERVER_ADDR, TableColumnType::CLIENT_PIDS}),
  210. table.getSelectedColumns());
  211. });
  212. EXPECT_EQ("", err.str());
  213. }
  214. TEST_F(ListParseArgsTest, Cmds) {
  215. EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-m"})));
  216. mockList->forEachTable([](const Table& table) {
  217. EXPECT_THAT(table.getSelectedColumns(), Not(Contains(TableColumnType::SERVER_PID)))
  218. << "should not print server PID with -m";
  219. EXPECT_THAT(table.getSelectedColumns(), Not(Contains(TableColumnType::CLIENT_PIDS)))
  220. << "should not print client PIDs with -m";
  221. EXPECT_THAT(table.getSelectedColumns(), Contains(TableColumnType::SERVER_CMD))
  222. << "should print server cmd with -m";
  223. EXPECT_THAT(table.getSelectedColumns(), Contains(TableColumnType::CLIENT_CMDS))
  224. << "should print client cmds with -m";
  225. });
  226. EXPECT_EQ("", err.str());
  227. }
  228. TEST_F(ListParseArgsTest, DebugAndNeat) {
  229. EXPECT_NE(0u, mockList->parseArgs(createArg({"lshal", "--neat", "-d"})));
  230. EXPECT_THAT(err.str(), HasSubstr("--neat should not be used with --debug."));
  231. }
  232. /// Fetch Test
  233. // A set of deterministic functions to generate fake debug infos.
  234. static uint64_t getPtr(pid_t serverId) { return 10000 + serverId; }
  235. static std::vector<pid_t> getClients(pid_t serverId) {
  236. return {serverId + 1, serverId + 3};
  237. }
  238. static PidInfo getPidInfoFromId(pid_t serverId) {
  239. PidInfo info;
  240. info.refPids[getPtr(serverId)] = getClients(serverId);
  241. info.threadUsage = 10 + serverId;
  242. info.threadCount = 20 + serverId;
  243. return info;
  244. }
  245. static std::string getInterfaceName(pid_t serverId) {
  246. return "a.h.foo" + std::to_string(serverId) + "@" + std::to_string(serverId) + ".0::IFoo";
  247. }
  248. static std::string getInstanceName(pid_t serverId) {
  249. return std::to_string(serverId);
  250. }
  251. static pid_t getIdFromInstanceName(const hidl_string& instance) {
  252. return atoi(instance.c_str());
  253. }
  254. static std::string getFqInstanceName(pid_t serverId) {
  255. return getInterfaceName(serverId) + "/" + getInstanceName(serverId);
  256. }
  257. static std::string getCmdlineFromId(pid_t serverId) {
  258. if (serverId == NO_PID) return "";
  259. return "command_line_" + std::to_string(serverId);
  260. }
  261. static bool getIsReleasedFromId(pid_t p) { return p % 2 == 0; }
  262. static hidl_hash getHashFromId(pid_t serverId) {
  263. hidl_hash hash;
  264. bool isReleased = getIsReleasedFromId(serverId);
  265. for (size_t i = 0; i < hash.size(); ++i) {
  266. hash[i] = isReleased ? static_cast<uint8_t>(serverId) : 0u;
  267. }
  268. return hash;
  269. }
  270. // Fake service returned by mocked IServiceManager::get.
  271. class TestService : public IBase {
  272. public:
  273. explicit TestService(pid_t id) : mId(id) {}
  274. hardware::Return<void> getDebugInfo(getDebugInfo_cb cb) override {
  275. cb({ mId /* pid */, getPtr(mId), DebugInfo::Architecture::IS_64BIT });
  276. return hardware::Void();
  277. }
  278. hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
  279. cb({getInterfaceName(mId), IBase::descriptor});
  280. return hardware::Void();
  281. }
  282. hardware::Return<void> getHashChain(getHashChain_cb cb) override {
  283. cb({getHashFromId(mId), getHashFromId(0xff)});
  284. return hardware::Void();
  285. }
  286. private:
  287. pid_t mId;
  288. };
  289. class ListTest : public ::testing::Test {
  290. public:
  291. virtual void SetUp() override {
  292. initMockServiceManager();
  293. lshal = std::make_unique<Lshal>(out, err, serviceManager, passthruManager);
  294. initMockList();
  295. }
  296. void initMockList() {
  297. mockList = std::make_unique<NiceMock<MockListCommand>>(lshal.get());
  298. ON_CALL(*mockList, getPidInfo(_,_)).WillByDefault(Invoke(
  299. [](pid_t serverPid, PidInfo* info) {
  300. *info = getPidInfoFromId(serverPid);
  301. return true;
  302. }));
  303. ON_CALL(*mockList, parseCmdline(_)).WillByDefault(Invoke(&getCmdlineFromId));
  304. ON_CALL(*mockList, postprocess()).WillByDefault(Invoke([&]() {
  305. mockList->internalPostprocess();
  306. size_t i = 0;
  307. mockList->forEachTable([&](Table& table) {
  308. table.setDescription("[fake description " + std::to_string(i++) + "]");
  309. });
  310. }));
  311. ON_CALL(*mockList, getPartition(_)).WillByDefault(Return(Partition::VENDOR));
  312. ON_CALL(*mockList, getDeviceManifest())
  313. .WillByDefault(Return(std::make_shared<HalManifest>()));
  314. ON_CALL(*mockList, getDeviceMatrix())
  315. .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
  316. ON_CALL(*mockList, getFrameworkManifest())
  317. .WillByDefault(Return(std::make_shared<HalManifest>()));
  318. ON_CALL(*mockList, getFrameworkMatrix())
  319. .WillByDefault(Return(std::make_shared<CompatibilityMatrix>()));
  320. }
  321. void initMockServiceManager() {
  322. serviceManager = new testing::NiceMock<MockServiceManager>();
  323. passthruManager = new testing::NiceMock<MockServiceManager>();
  324. using A = DebugInfo::Architecture;
  325. ON_CALL(*serviceManager, list(_)).WillByDefault(Invoke(
  326. [] (IServiceManager::list_cb cb) {
  327. cb({ getFqInstanceName(1), getFqInstanceName(2) });
  328. return hardware::Void();
  329. }));
  330. ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
  331. [&](const hidl_string&, const hidl_string& instance) {
  332. int id = getIdFromInstanceName(instance);
  333. return sp<IBase>(new TestService(id));
  334. }));
  335. ON_CALL(*serviceManager, debugDump(_)).WillByDefault(Invoke(
  336. [] (IServiceManager::debugDump_cb cb) {
  337. cb({InstanceDebugInfo{getInterfaceName(3), getInstanceName(3), 3,
  338. getClients(3), A::IS_32BIT},
  339. InstanceDebugInfo{getInterfaceName(4), getInstanceName(4), 4,
  340. getClients(4), A::IS_32BIT}});
  341. return hardware::Void();
  342. }));
  343. ON_CALL(*passthruManager, debugDump(_)).WillByDefault(Invoke(
  344. [] (IServiceManager::debugDump_cb cb) {
  345. cb({InstanceDebugInfo{getInterfaceName(5), getInstanceName(5), 5,
  346. getClients(5), A::IS_32BIT},
  347. InstanceDebugInfo{getInterfaceName(6), getInstanceName(6), 6,
  348. getClients(6), A::IS_32BIT}});
  349. return hardware::Void();
  350. }));
  351. }
  352. std::stringstream err;
  353. std::stringstream out;
  354. std::unique_ptr<Lshal> lshal;
  355. std::unique_ptr<MockListCommand> mockList;
  356. sp<MockServiceManager> serviceManager;
  357. sp<MockServiceManager> passthruManager;
  358. };
  359. TEST_F(ListTest, GetPidInfoCached) {
  360. EXPECT_CALL(*mockList, getPidInfo(5, _)).Times(1);
  361. EXPECT_NE(nullptr, mockList->getPidInfoCached(5));
  362. EXPECT_NE(nullptr, mockList->getPidInfoCached(5));
  363. }
  364. TEST_F(ListTest, Fetch) {
  365. optind = 1; // mimic Lshal::parseArg()
  366. ASSERT_EQ(0u, mockList->parseArgs(createArg({"lshal"})));
  367. ASSERT_EQ(0u, mockList->fetch());
  368. vintf::TransportArch hwbinder{Transport::HWBINDER, Arch::ARCH_64};
  369. vintf::TransportArch passthrough{Transport::PASSTHROUGH, Arch::ARCH_32};
  370. std::array<vintf::TransportArch, 6> transportArchs{{hwbinder, hwbinder, passthrough,
  371. passthrough, passthrough, passthrough}};
  372. int i = 0;
  373. mockList->forEachTable([&](const Table& table) {
  374. for (const auto& entry : table) {
  375. if (i >= transportArchs.size()) {
  376. break;
  377. }
  378. int id = i + 1;
  379. auto transport = transportArchs.at(i).transport;
  380. TableEntry expected{
  381. .interfaceName = getFqInstanceName(id),
  382. .transport = transport,
  383. .serverPid = transport == Transport::HWBINDER ? id : NO_PID,
  384. .threadUsage =
  385. transport == Transport::HWBINDER ? getPidInfoFromId(id).threadUsage : 0,
  386. .threadCount =
  387. transport == Transport::HWBINDER ? getPidInfoFromId(id).threadCount : 0,
  388. .serverCmdline = {},
  389. .serverObjectAddress = transport == Transport::HWBINDER ? getPtr(id) : NO_PTR,
  390. .clientPids = getClients(id),
  391. .clientCmdlines = {},
  392. .arch = transportArchs.at(i).arch,
  393. };
  394. EXPECT_EQ(expected, entry) << expected.to_string() << " vs. " << entry.to_string();
  395. ++i;
  396. }
  397. });
  398. EXPECT_EQ(transportArchs.size(), i) << "Not all entries are tested.";
  399. }
  400. TEST_F(ListTest, DumpVintf) {
  401. const std::string expected = "<manifest version=\"1.0\" type=\"device\">\n"
  402. " <hal format=\"hidl\">\n"
  403. " <name>a.h.foo1</name>\n"
  404. " <transport>hwbinder</transport>\n"
  405. " <fqname>@1.0::IFoo/1</fqname>\n"
  406. " </hal>\n"
  407. " <hal format=\"hidl\">\n"
  408. " <name>a.h.foo2</name>\n"
  409. " <transport>hwbinder</transport>\n"
  410. " <fqname>@2.0::IFoo/2</fqname>\n"
  411. " </hal>\n"
  412. " <hal format=\"hidl\">\n"
  413. " <name>a.h.foo3</name>\n"
  414. " <transport arch=\"32\">passthrough</transport>\n"
  415. " <fqname>@3.0::IFoo/3</fqname>\n"
  416. " </hal>\n"
  417. " <hal format=\"hidl\">\n"
  418. " <name>a.h.foo4</name>\n"
  419. " <transport arch=\"32\">passthrough</transport>\n"
  420. " <fqname>@4.0::IFoo/4</fqname>\n"
  421. " </hal>\n"
  422. "</manifest>";
  423. optind = 1; // mimic Lshal::parseArg()
  424. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--init-vintf"})));
  425. auto output = out.str();
  426. EXPECT_THAT(output, HasSubstr(expected));
  427. EXPECT_THAT(output, HasSubstr("[email protected]::IFoo/5"));
  428. EXPECT_THAT(output, HasSubstr("[email protected]::IFoo/6"));
  429. EXPECT_EQ("", err.str());
  430. vintf::HalManifest m;
  431. EXPECT_EQ(true, vintf::gHalManifestConverter(&m, out.str()))
  432. << "--init-vintf does not emit valid HAL manifest: "
  433. << vintf::gHalManifestConverter.lastError();
  434. }
  435. // test default columns
  436. TEST_F(ListTest, DumpDefault) {
  437. const std::string expected =
  438. "[fake description 0]\n"
  439. "R Interface Thread Use Server Clients\n"
  440. "N [email protected]::IFoo/1 11/21 1 2 4\n"
  441. "Y [email protected]::IFoo/2 12/22 2 3 5\n"
  442. "\n"
  443. "[fake description 1]\n"
  444. "R Interface Thread Use Server Clients\n"
  445. "? [email protected]::IFoo/3 N/A N/A 4 6\n"
  446. "? [email protected]::IFoo/4 N/A N/A 5 7\n"
  447. "\n"
  448. "[fake description 2]\n"
  449. "R Interface Thread Use Server Clients\n"
  450. "? [email protected]::IFoo/5 N/A N/A 6 8\n"
  451. "? [email protected]::IFoo/6 N/A N/A 7 9\n"
  452. "\n";
  453. optind = 1; // mimic Lshal::parseArg()
  454. EXPECT_EQ(0u, mockList->main(createArg({"lshal"})));
  455. EXPECT_EQ(expected, out.str());
  456. EXPECT_EQ("", err.str());
  457. }
  458. TEST_F(ListTest, DumpHash) {
  459. const std::string expected =
  460. "[fake description 0]\n"
  461. "Interface R Hash\n"
  462. "[email protected]::IFoo/1 N 0000000000000000000000000000000000000000000000000000000000000000\n"
  463. "[email protected]::IFoo/2 Y 0202020202020202020202020202020202020202020202020202020202020202\n"
  464. "\n"
  465. "[fake description 1]\n"
  466. "Interface R Hash\n"
  467. "[email protected]::IFoo/3 ? \n"
  468. "[email protected]::IFoo/4 ? \n"
  469. "\n"
  470. "[fake description 2]\n"
  471. "Interface R Hash\n"
  472. "[email protected]::IFoo/5 ? \n"
  473. "[email protected]::IFoo/6 ? \n"
  474. "\n";
  475. optind = 1; // mimic Lshal::parseArg()
  476. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-ils"})));
  477. EXPECT_EQ(expected, out.str());
  478. EXPECT_EQ("", err.str());
  479. }
  480. TEST_F(ListTest, Dump) {
  481. const std::string expected =
  482. "[fake description 0]\n"
  483. "Interface Transport Arch Thread Use Server PTR Clients\n"
  484. "[email protected]::IFoo/1 hwbinder 64 11/21 1 0000000000002711 2 4\n"
  485. "[email protected]::IFoo/2 hwbinder 64 12/22 2 0000000000002712 3 5\n"
  486. "\n"
  487. "[fake description 1]\n"
  488. "Interface Transport Arch Thread Use Server PTR Clients\n"
  489. "[email protected]::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
  490. "[email protected]::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
  491. "\n"
  492. "[fake description 2]\n"
  493. "Interface Transport Arch Thread Use Server PTR Clients\n"
  494. "[email protected]::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
  495. "[email protected]::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
  496. "\n";
  497. optind = 1; // mimic Lshal::parseArg()
  498. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac"})));
  499. EXPECT_EQ(expected, out.str());
  500. EXPECT_EQ("", err.str());
  501. }
  502. TEST_F(ListTest, DumpCmdline) {
  503. const std::string expected =
  504. "[fake description 0]\n"
  505. "Interface Transport Arch Thread Use Server CMD PTR Clients CMD\n"
  506. "[email protected]::IFoo/1 hwbinder 64 11/21 command_line_1 0000000000002711 command_line_2;command_line_4\n"
  507. "[email protected]::IFoo/2 hwbinder 64 12/22 command_line_2 0000000000002712 command_line_3;command_line_5\n"
  508. "\n"
  509. "[fake description 1]\n"
  510. "Interface Transport Arch Thread Use Server CMD PTR Clients CMD\n"
  511. "[email protected]::IFoo/3 passthrough 32 N/A N/A command_line_4;command_line_6\n"
  512. "[email protected]::IFoo/4 passthrough 32 N/A N/A command_line_5;command_line_7\n"
  513. "\n"
  514. "[fake description 2]\n"
  515. "Interface Transport Arch Thread Use Server CMD PTR Clients CMD\n"
  516. "[email protected]::IFoo/5 passthrough 32 N/A N/A command_line_6;command_line_8\n"
  517. "[email protected]::IFoo/6 passthrough 32 N/A N/A command_line_7;command_line_9\n"
  518. "\n";
  519. optind = 1; // mimic Lshal::parseArg()
  520. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepacm"})));
  521. EXPECT_EQ(expected, out.str());
  522. EXPECT_EQ("", err.str());
  523. }
  524. TEST_F(ListTest, DumpNeat) {
  525. const std::string expected =
  526. "[email protected]::IFoo/1 11/21 1 2 4\n"
  527. "[email protected]::IFoo/2 12/22 2 3 5\n"
  528. "[email protected]::IFoo/3 N/A N/A 4 6\n"
  529. "[email protected]::IFoo/4 N/A N/A 5 7\n"
  530. "[email protected]::IFoo/5 N/A N/A 6 8\n"
  531. "[email protected]::IFoo/6 N/A N/A 7 9\n";
  532. optind = 1; // mimic Lshal::parseArg()
  533. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iepc", "--neat"})));
  534. EXPECT_EQ(expected, out.str());
  535. EXPECT_EQ("", err.str());
  536. }
  537. TEST_F(ListTest, DumpSingleHalType) {
  538. const std::string expected =
  539. "[fake description 0]\n"
  540. "Interface Transport Arch Thread Use Server PTR Clients\n"
  541. "[email protected]::IFoo/1 hwbinder 64 11/21 1 0000000000002711 2 4\n"
  542. "[email protected]::IFoo/2 hwbinder 64 12/22 2 0000000000002712 3 5\n"
  543. "\n";
  544. optind = 1; // mimic Lshal::parseArg()
  545. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=binderized"})));
  546. EXPECT_EQ(expected, out.str());
  547. EXPECT_EQ("", err.str());
  548. }
  549. TEST_F(ListTest, DumpReorderedHalTypes) {
  550. const std::string expected =
  551. "[fake description 0]\n"
  552. "Interface Transport Arch Thread Use Server PTR Clients\n"
  553. "[email protected]::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
  554. "[email protected]::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
  555. "\n"
  556. "[fake description 1]\n"
  557. "Interface Transport Arch Thread Use Server PTR Clients\n"
  558. "[email protected]::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
  559. "[email protected]::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
  560. "\n"
  561. "[fake description 2]\n"
  562. "Interface Transport Arch Thread Use Server PTR Clients\n"
  563. "[email protected]::IFoo/1 hwbinder 64 11/21 1 0000000000002711 2 4\n"
  564. "[email protected]::IFoo/2 hwbinder 64 12/22 2 0000000000002712 3 5\n"
  565. "\n";
  566. optind = 1; // mimic Lshal::parseArg()
  567. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=passthrough_clients",
  568. "--types=passthrough_libs", "--types=binderized"})));
  569. EXPECT_EQ(expected, out.str());
  570. EXPECT_EQ("", err.str());
  571. }
  572. TEST_F(ListTest, DumpAbbreviatedHalTypes) {
  573. const std::string expected =
  574. "[fake description 0]\n"
  575. "Interface Transport Arch Thread Use Server PTR Clients\n"
  576. "[email protected]::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
  577. "[email protected]::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
  578. "\n"
  579. "[fake description 1]\n"
  580. "Interface Transport Arch Thread Use Server PTR Clients\n"
  581. "[email protected]::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
  582. "[email protected]::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
  583. "\n";
  584. optind = 1; // mimic Lshal::parseArg()
  585. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l"})));
  586. EXPECT_EQ(expected, out.str());
  587. EXPECT_EQ("", err.str());
  588. }
  589. TEST_F(ListTest, DumpEmptyAndDuplicateHalTypes) {
  590. const std::string expected =
  591. "[fake description 0]\n"
  592. "Interface Transport Arch Thread Use Server PTR Clients\n"
  593. "[email protected]::IFoo/3 passthrough 32 N/A N/A N/A 4 6\n"
  594. "[email protected]::IFoo/4 passthrough 32 N/A N/A N/A 5 7\n"
  595. "\n"
  596. "[fake description 1]\n"
  597. "Interface Transport Arch Thread Use Server PTR Clients\n"
  598. "[email protected]::IFoo/5 passthrough 32 N/A N/A N/A 6 8\n"
  599. "[email protected]::IFoo/6 passthrough 32 N/A N/A N/A 7 9\n"
  600. "\n";
  601. optind = 1; // mimic Lshal::parseArg()
  602. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,l,,,l,l,c,",
  603. "--types=passthrough_libs,passthrough_clients"})));
  604. EXPECT_EQ(expected, out.str());
  605. EXPECT_EQ("", err.str());
  606. }
  607. TEST_F(ListTest, UnknownHalType) {
  608. optind = 1; // mimic Lshal::parseArg()
  609. EXPECT_EQ(1u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,a"})));
  610. EXPECT_THAT(err.str(), HasSubstr("Unrecognized HAL type: a"));
  611. }
  612. TEST_F(ListTest, Vintf) {
  613. std::string deviceManifestXml =
  614. "<manifest version=\"1.0\" type=\"device\">\n"
  615. " <hal>\n"
  616. " <name>a.h.foo1</name>\n"
  617. " <transport>hwbinder</transport>\n"
  618. " <fqname>@1.0::IFoo/1</fqname>\n"
  619. " </hal>\n"
  620. " <hal>\n"
  621. " <name>a.h.foo3</name>\n"
  622. " <transport arch=\"32+64\">passthrough</transport>\n"
  623. " <fqname>@3.0::IFoo/3</fqname>\n"
  624. " </hal>\n"
  625. "</manifest>\n";
  626. std::string frameworkManifestXml =
  627. "<manifest version=\"1.0\" type=\"framework\">\n"
  628. " <hal>\n"
  629. " <name>a.h.foo5</name>\n"
  630. " <transport arch=\"32\">passthrough</transport>\n"
  631. " <fqname>@5.0::IFoo/5</fqname>\n"
  632. " </hal>\n"
  633. "</manifest>\n";
  634. std::string deviceMatrixXml =
  635. "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
  636. " <hal>\n"
  637. " <name>a.h.foo5</name>\n"
  638. " <version>5.0</version>\n"
  639. " <interface>\n"
  640. " <name>IFoo</name>\n"
  641. " <instance>5</instance>\n"
  642. " </interface>\n"
  643. " </hal>\n"
  644. "</compatibility-matrix>\n";
  645. std::string frameworkMatrixXml =
  646. "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
  647. " <hal>\n"
  648. " <name>a.h.foo1</name>\n"
  649. " <version>1.0</version>\n"
  650. " <interface>\n"
  651. " <name>IFoo</name>\n"
  652. " <instance>1</instance>\n"
  653. " </interface>\n"
  654. " </hal>\n"
  655. " <hal>\n"
  656. " <name>a.h.foo3</name>\n"
  657. " <version>3.0</version>\n"
  658. " <interface>\n"
  659. " <name>IFoo</name>\n"
  660. " <instance>3</instance>\n"
  661. " </interface>\n"
  662. " </hal>\n"
  663. "</compatibility-matrix>\n";
  664. std::string expected = "DM,FC [email protected]::IFoo/1\n"
  665. "X [email protected]::IFoo/2\n"
  666. "DM,FC [email protected]::IFoo/3\n"
  667. "X [email protected]::IFoo/4\n"
  668. "DC,FM [email protected]::IFoo/5\n"
  669. "X [email protected]::IFoo/6\n";
  670. auto deviceManifest = std::make_shared<HalManifest>();
  671. auto frameworkManifest = std::make_shared<HalManifest>();
  672. auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
  673. auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
  674. ASSERT_TRUE(gHalManifestConverter(deviceManifest.get(), deviceManifestXml));
  675. ASSERT_TRUE(gHalManifestConverter(frameworkManifest.get(), frameworkManifestXml));
  676. ASSERT_TRUE(gCompatibilityMatrixConverter(deviceMatrix.get(), deviceMatrixXml));
  677. ASSERT_TRUE(gCompatibilityMatrixConverter(frameworkMatrix.get(), frameworkMatrixXml));
  678. ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
  679. ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
  680. ON_CALL(*mockList, getFrameworkManifest()).WillByDefault(Return(frameworkManifest));
  681. ON_CALL(*mockList, getFrameworkMatrix()).WillByDefault(Return(frameworkMatrix));
  682. optind = 1; // mimic Lshal::parseArg()
  683. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-Vi", "--neat"})));
  684. EXPECT_THAT(out.str(), HasSubstr(expected));
  685. EXPECT_EQ("", err.str());
  686. }
  687. class ListVintfTest : public ListTest {
  688. public:
  689. virtual void SetUp() override {
  690. ListTest::SetUp();
  691. const std::string mockManifestXml =
  692. "<manifest version=\"1.0\" type=\"device\">\n"
  693. " <hal format=\"hidl\">\n"
  694. " <name>a.h.foo1</name>\n"
  695. " <transport>hwbinder</transport>\n"
  696. " <fqname>@1.0::IFoo/1</fqname>\n"
  697. " </hal>\n"
  698. " <hal format=\"hidl\">\n"
  699. " <name>a.h.bar1</name>\n"
  700. " <transport>hwbinder</transport>\n"
  701. " <fqname>@1.0::IBar/1</fqname>\n"
  702. " </hal>\n"
  703. " <hal format=\"hidl\">\n"
  704. " <name>a.h.bar2</name>\n"
  705. " <transport arch=\"32+64\">passthrough</transport>\n"
  706. " <fqname>@2.0::IBar/2</fqname>\n"
  707. " </hal>\n"
  708. "</manifest>";
  709. auto manifest = std::make_shared<HalManifest>();
  710. EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
  711. EXPECT_CALL(*mockList, getDeviceManifest())
  712. .Times(AnyNumber())
  713. .WillRepeatedly(Return(manifest));
  714. }
  715. };
  716. TEST_F(ListVintfTest, ManifestHals) {
  717. optind = 1; // mimic Lshal::parseArg()
  718. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=v", "--neat"})));
  719. EXPECT_THAT(out.str(), HasSubstr("[email protected]::IBar/1 declared hwbinder ?"));
  720. EXPECT_THAT(out.str(), HasSubstr("[email protected]::IBar/2 declared passthrough 32+64"));
  721. EXPECT_THAT(out.str(), HasSubstr("[email protected]::IFoo/1 declared hwbinder ?"));
  722. EXPECT_EQ("", err.str());
  723. }
  724. TEST_F(ListVintfTest, Lazy) {
  725. optind = 1; // mimic Lshal::parseArg()
  726. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=z", "--neat"})));
  727. EXPECT_THAT(out.str(), HasSubstr("[email protected]::IBar/1 declared hwbinder ?"));
  728. EXPECT_THAT(out.str(), HasSubstr("[email protected]::IBar/2 declared passthrough 32+64"));
  729. EXPECT_EQ("", err.str());
  730. }
  731. TEST_F(ListVintfTest, NoLazy) {
  732. optind = 1; // mimic Lshal::parseArg()
  733. EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=b,c,l", "--neat"})));
  734. EXPECT_THAT(out.str(), Not(HasSubstr("IBar")));
  735. EXPECT_EQ("", err.str());
  736. }
  737. class HelpTest : public ::testing::Test {
  738. public:
  739. void SetUp() override {
  740. lshal = std::make_unique<Lshal>(out, err, new MockServiceManager() /* serviceManager */,
  741. new MockServiceManager() /* passthruManager */);
  742. }
  743. std::stringstream err;
  744. std::stringstream out;
  745. std::unique_ptr<Lshal> lshal;
  746. };
  747. TEST_F(HelpTest, GlobalUsage) {
  748. (void)callMain(lshal, {"lshal", "--help"}); // ignore return
  749. std::string errStr = err.str();
  750. EXPECT_THAT(errStr, ContainsRegex("(^|\n)commands:($|\n)"))
  751. << "`lshal --help` does not contain global usage";
  752. EXPECT_THAT(errStr, ContainsRegex("(^|\n)list:($|\n)"))
  753. << "`lshal --help` does not contain usage for 'list' command";
  754. EXPECT_THAT(errStr, ContainsRegex("(^|\n)debug:($|\n)"))
  755. << "`lshal --help` does not contain usage for 'debug' command";
  756. EXPECT_THAT(errStr, ContainsRegex("(^|\n)help:($|\n)"))
  757. << "`lshal --help` does not contain usage for 'help' command";
  758. err.str("");
  759. (void)callMain(lshal, {"lshal", "help"}); // ignore return
  760. EXPECT_EQ(errStr, err.str()) << "`lshal help` should have the same output as `lshal --help`";
  761. err.str("");
  762. EXPECT_NE(0u, callMain(lshal, {"lshal", "--unknown-option"}));
  763. EXPECT_THAT(err.str(), ContainsRegex("unrecognized option"));
  764. EXPECT_THAT(err.str(), EndsWith(errStr))
  765. << "`lshal --unknown-option` should have the same output as `lshal --help`";
  766. EXPECT_EQ("", out.str());
  767. }
  768. TEST_F(HelpTest, UnknownOptionList1) {
  769. (void)callMain(lshal, {"lshal", "help", "list"});
  770. EXPECT_THAT(err.str(), ContainsRegex("(^|\n)list:($|\n)"))
  771. << "`lshal help list` does not contain usage for 'list' command";
  772. }
  773. TEST_F(HelpTest, UnknownOptionList2) {
  774. EXPECT_NE(0u, callMain(lshal, {"lshal", "list", "--unknown-option"}));
  775. EXPECT_THAT(err.str(), ContainsRegex("unrecognized option"));
  776. EXPECT_THAT(err.str(), ContainsRegex("(^|\n)list:($|\n)"))
  777. << "`lshal list --unknown-option` does not contain usage for 'list' command";
  778. EXPECT_EQ("", out.str());
  779. }
  780. TEST_F(HelpTest, UnknownOptionHelp1) {
  781. (void)callMain(lshal, {"lshal", "help", "help"});
  782. EXPECT_THAT(err.str(), ContainsRegex("(^|\n)help:($|\n)"))
  783. << "`lshal help help` does not contain usage for 'help' command";
  784. }
  785. TEST_F(HelpTest, UnknownOptionHelp2) {
  786. (void)callMain(lshal, {"lshal", "help", "--unknown-option"});
  787. EXPECT_THAT(err.str(), ContainsRegex("(^|\n)help:($|\n)"))
  788. << "`lshal help --unknown-option` does not contain usage for 'help' command";
  789. EXPECT_EQ("", out.str());
  790. }
  791. } // namespace lshal
  792. } // namespace android
  793. int main(int argc, char **argv) {
  794. ::testing::InitGoogleMock(&argc, argv);
  795. return RUN_ALL_TESTS();
  796. }