blob: 6cdec29ad35fde17c615895ee34b824c21a38251 [file] [log] [blame]
Yifan Hong9881df92017-05-10 14:33:05 -07001/*
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#define LOG_TAG "Lshal"
18#include <android-base/logging.h>
19
20#include <sstream>
21#include <string>
22#include <thread>
23#include <vector>
24
25#include <gtest/gtest.h>
26#include <gmock/gmock.h>
27#include <android/hardware/tests/baz/1.0/IQuux.h>
28#include <hidl/HidlTransportSupport.h>
29
Yifan Hongb2a2ecb2017-09-07 15:08:22 -070030#include "ListCommand.h"
Yifan Hong9881df92017-05-10 14:33:05 -070031#include "Lshal.h"
32
33#define NELEMS(array) static_cast<int>(sizeof(array) / sizeof(array[0]))
34
35using namespace testing;
36
37using ::android::hidl::base::V1_0::IBase;
38using ::android::hidl::manager::V1_0::IServiceManager;
39using ::android::hidl::manager::V1_0::IServiceNotification;
40using ::android::hardware::hidl_death_recipient;
41using ::android::hardware::hidl_handle;
42using ::android::hardware::hidl_string;
43using ::android::hardware::hidl_vec;
44
45namespace android {
46namespace hardware {
47namespace tests {
48namespace baz {
49namespace V1_0 {
50namespace implementation {
51struct Quux : android::hardware::tests::baz::V1_0::IQuux {
52 ::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
53 const native_handle_t *handle = hh.getNativeHandle();
54 if (handle->numFds < 1) {
55 return Void();
56 }
57 int fd = handle->data[0];
58 std::string content{descriptor};
59 for (const auto &option : options) {
60 content += "\n";
61 content += option.c_str();
62 }
63 ssize_t written = write(fd, content.c_str(), content.size());
64 if (written != (ssize_t)content.size()) {
65 LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < "
66 << content.size() << " bytes, errno = " << errno;
67 }
68 return Void();
69 }
70};
71
72} // namespace implementation
73} // namespace V1_0
74} // namespace baz
75} // namespace tests
76} // namespace hardware
77
78namespace lshal {
79
80
81class MockServiceManager : public IServiceManager {
82public:
83 template<typename T>
84 using R = ::android::hardware::Return<T>;
85 using String = const hidl_string&;
86 ~MockServiceManager() = default;
87
88#define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb))
89
90 MOCK_METHOD2(get, R<sp<IBase>>(String, String));
91 MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&));
92 MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String));
93 MOCK_METHOD_CB(list);
94 MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb));
95 MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&));
96 MOCK_METHOD_CB(debugDump);
97 MOCK_METHOD2(registerPassthroughClient, R<void>(String, String));
98 MOCK_METHOD_CB(interfaceChain);
99 MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&));
100 MOCK_METHOD_CB(interfaceDescriptor);
101 MOCK_METHOD_CB(getHashChain);
102 MOCK_METHOD0(setHalInstrumentation, R<void>());
103 MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t));
104 MOCK_METHOD0(ping, R<void>());
105 MOCK_METHOD_CB(getDebugInfo);
106 MOCK_METHOD0(notifySyspropsChanged, R<void>());
107 MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&));
108
109};
110
Yifan Hongbf20a262017-09-07 11:10:58 -0700111class DebugTest : public ::testing::Test {
Yifan Hong9881df92017-05-10 14:33:05 -0700112public:
113 void SetUp() override {
114 using ::android::hardware::tests::baz::V1_0::IQuux;
115 using ::android::hardware::tests::baz::V1_0::implementation::Quux;
116
117 err.str("");
118 out.str("");
119 serviceManager = new testing::NiceMock<MockServiceManager>();
120 ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
121 [](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> {
122 if (iface == IQuux::descriptor && inst == "default")
123 return new Quux();
124 return nullptr;
125 }));
Yifan Hongbf20a262017-09-07 11:10:58 -0700126
127 lshal = std::make_unique<Lshal>(out, err, serviceManager, serviceManager);
Yifan Hong9881df92017-05-10 14:33:05 -0700128 }
129 void TearDown() override {}
130
131 std::stringstream err;
132 std::stringstream out;
133 sp<MockServiceManager> serviceManager;
Yifan Hongbf20a262017-09-07 11:10:58 -0700134
135 std::unique_ptr<Lshal> lshal;
Yifan Hong9881df92017-05-10 14:33:05 -0700136};
137
Yifan Hongbf20a262017-09-07 11:10:58 -0700138static Arg createArg(const std::vector<const char*>& args) {
139 return Arg{static_cast<int>(args.size()), const_cast<char**>(args.data())};
140}
141
142template<typename T>
143static Status callMain(const std::unique_ptr<T>& lshal, const std::vector<const char*>& args) {
144 return lshal->main(createArg(args));
145}
146
147TEST_F(DebugTest, Debug) {
148 EXPECT_EQ(0u, callMain(lshal, {
Yifan Hong9881df92017-05-10 14:33:05 -0700149 "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux/default", "foo", "bar"
Yifan Hongbf20a262017-09-07 11:10:58 -0700150 }));
Yifan Hong9881df92017-05-10 14:33:05 -0700151 EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nfoo\nbar"));
152 EXPECT_THAT(err.str(), IsEmpty());
153}
154
Yifan Hongbf20a262017-09-07 11:10:58 -0700155TEST_F(DebugTest, Debug2) {
156 EXPECT_EQ(0u, callMain(lshal, {
Yifan Hong9881df92017-05-10 14:33:05 -0700157 "lshal", "debug", "android.hardware.tests.baz@1.0::IQuux", "baz", "quux"
Yifan Hongbf20a262017-09-07 11:10:58 -0700158 }));
Yifan Hong9881df92017-05-10 14:33:05 -0700159 EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nbaz\nquux"));
160 EXPECT_THAT(err.str(), IsEmpty());
161}
162
Yifan Hongbf20a262017-09-07 11:10:58 -0700163TEST_F(DebugTest, Debug3) {
164 EXPECT_NE(0u, callMain(lshal, {
Yifan Hong9881df92017-05-10 14:33:05 -0700165 "lshal", "debug", "android.hardware.tests.doesnotexist@1.0::IDoesNotExist",
Yifan Hongbf20a262017-09-07 11:10:58 -0700166 }));
Yifan Hong9881df92017-05-10 14:33:05 -0700167 EXPECT_THAT(err.str(), HasSubstr("does not exist"));
168}
169
Yifan Hongb2a2ecb2017-09-07 15:08:22 -0700170class MockLshal : public Lshal {
171public:
172 MockLshal() {}
173 ~MockLshal() = default;
174 MOCK_CONST_METHOD0(out, NullableOStream<std::ostream>());
175 MOCK_CONST_METHOD0(err, NullableOStream<std::ostream>());
176};
177
178// expose protected fields and methods for ListCommand
179class MockListCommand : public ListCommand {
180public:
181 MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
182
183 Status parseArgs(const Arg& arg) { return ListCommand::parseArgs("", arg); }
184 void forEachTable(const std::function<void(const Table &)> &f) const {
185 return ListCommand::forEachTable(f);
186 }
187};
188
189class ListParseArgsTest : public ::testing::Test {
190public:
191 void SetUp() override {
192 mockLshal = std::make_unique<NiceMock<MockLshal>>();
193 mockList = std::make_unique<MockListCommand>(mockLshal.get());
194 // ListCommand::parseArgs should parse arguments from the second element
195 optind = 1;
196 }
197 std::unique_ptr<MockLshal> mockLshal;
198 std::unique_ptr<MockListCommand> mockList;
199 std::stringstream output;
200};
201
202TEST_F(ListParseArgsTest, Default) {
203 // default args
204 EXPECT_EQ(0u, mockList->parseArgs(createArg({})));
205 mockList->forEachTable([](const Table& table) {
206 EXPECT_EQ(SelectedColumns({TableColumnType::INTERFACE_NAME, TableColumnType::THREADS,
207 TableColumnType::SERVER_PID, TableColumnType::CLIENT_PIDS}),
208 table.getSelectedColumns());
209 });
210}
211
212TEST_F(ListParseArgsTest, Args) {
213 EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-p", "-i", "-a", "-c"})));
214 mockList->forEachTable([](const Table& table) {
215 EXPECT_EQ(SelectedColumns({TableColumnType::SERVER_PID, TableColumnType::INTERFACE_NAME,
216 TableColumnType::SERVER_ADDR, TableColumnType::CLIENT_PIDS}),
217 table.getSelectedColumns());
218 });
219}
220
221TEST_F(ListParseArgsTest, Cmds) {
222 EXPECT_EQ(0u, mockList->parseArgs(createArg({"lshal", "-m"})));
223 mockList->forEachTable([](const Table& table) {
224 EXPECT_EQ(SelectedColumns({TableColumnType::INTERFACE_NAME, TableColumnType::THREADS,
225 TableColumnType::SERVER_CMD, TableColumnType::CLIENT_CMDS}),
226 table.getSelectedColumns());
227 });
228}
229
230TEST_F(ListParseArgsTest, DebugAndNeat) {
231 ON_CALL(*mockLshal, err()).WillByDefault(Return(NullableOStream<std::ostream>(output)));
232 EXPECT_NE(0u, mockList->parseArgs(createArg({"lshal", "--neat", "-d"})));
233 EXPECT_THAT(output.str(), StrNe(""));
234}
235
Yifan Hong9881df92017-05-10 14:33:05 -0700236} // namespace lshal
237} // namespace android
238
239int main(int argc, char **argv) {
240 ::testing::InitGoogleMock(&argc, argv);
241 return RUN_ALL_TESTS();
242}