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 #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 30 #include "Lshal.h" 31 32 #define NELEMS(array) static_cast<int>(sizeof(array) / sizeof(array[0])) 33 34 using namespace testing; 35 36 using ::android::hidl::base::V1_0::IBase; 37 using ::android::hidl::manager::V1_0::IServiceManager; 38 using ::android::hidl::manager::V1_0::IServiceNotification; 39 using ::android::hardware::hidl_death_recipient; 40 using ::android::hardware::hidl_handle; 41 using ::android::hardware::hidl_string; 42 using ::android::hardware::hidl_vec; 43 44 namespace android { 45 namespace hardware { 46 namespace tests { 47 namespace baz { 48 namespace V1_0 { 49 namespace implementation { 50 struct Quux : android::hardware::tests::baz::V1_0::IQuux { 51 ::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override { 52 const native_handle_t *handle = hh.getNativeHandle(); 53 if (handle->numFds < 1) { 54 return Void(); 55 } 56 int fd = handle->data[0]; 57 std::string content{descriptor}; 58 for (const auto &option : options) { 59 content += "\n"; 60 content += option.c_str(); 61 } 62 ssize_t written = write(fd, content.c_str(), content.size()); 63 if (written != (ssize_t)content.size()) { 64 LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < " 65 << content.size() << " bytes, errno = " << errno; 66 } 67 return Void(); 68 } 69 }; 70 71 } // namespace implementation 72 } // namespace V1_0 73 } // namespace baz 74 } // namespace tests 75 } // namespace hardware 76 77 namespace lshal { 78 79 80 class MockServiceManager : public IServiceManager { 81 public: 82 template<typename T> 83 using R = ::android::hardware::Return<T>; 84 using String = const hidl_string&; 85 ~MockServiceManager() = default; 86 87 #define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb)) 88 89 MOCK_METHOD2(get, R<sp<IBase>>(String, String)); 90 MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&)); 91 MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String)); 92 MOCK_METHOD_CB(list); 93 MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb)); 94 MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&)); 95 MOCK_METHOD_CB(debugDump); 96 MOCK_METHOD2(registerPassthroughClient, R<void>(String, String)); 97 MOCK_METHOD_CB(interfaceChain); 98 MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&)); 99 MOCK_METHOD_CB(interfaceDescriptor); 100 MOCK_METHOD_CB(getHashChain); 101 MOCK_METHOD0(setHalInstrumentation, R<void>()); 102 MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t)); 103 MOCK_METHOD0(ping, R<void>()); 104 MOCK_METHOD_CB(getDebugInfo); 105 MOCK_METHOD0(notifySyspropsChanged, R<void>()); 106 MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&)); 107 108 }; 109 110 class LshalTest : public ::testing::Test { 111 public: 112 void SetUp() override { 113 using ::android::hardware::tests::baz::V1_0::IQuux; 114 using ::android::hardware::tests::baz::V1_0::implementation::Quux; 115 116 err.str(""); 117 out.str(""); 118 serviceManager = new testing::NiceMock<MockServiceManager>(); 119 ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke( 120 [](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> { 121 if (iface == IQuux::descriptor && inst == "default") 122 return new Quux(); 123 return nullptr; 124 })); 125 } 126 void TearDown() override {} 127 128 std::stringstream err; 129 std::stringstream out; 130 sp<MockServiceManager> serviceManager; 131 }; 132 133 TEST_F(LshalTest, Debug) { 134 const char *args[] = { 135 "lshal", "debug", "android.hardware.tests.baz (at) 1.0::IQuux/default", "foo", "bar" 136 }; 137 EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager) 138 .main({NELEMS(args), const_cast<char **>(args)})); 139 EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz (at) 1.0::IQuux\nfoo\nbar")); 140 EXPECT_THAT(err.str(), IsEmpty()); 141 } 142 143 TEST_F(LshalTest, Debug2) { 144 const char *args[] = { 145 "lshal", "debug", "android.hardware.tests.baz (at) 1.0::IQuux", "baz", "quux" 146 }; 147 EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager) 148 .main({NELEMS(args), const_cast<char **>(args)})); 149 EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz (at) 1.0::IQuux\nbaz\nquux")); 150 EXPECT_THAT(err.str(), IsEmpty()); 151 } 152 153 TEST_F(LshalTest, Debug3) { 154 const char *args[] = { 155 "lshal", "debug", "android.hardware.tests.doesnotexist (at) 1.0::IDoesNotExist", 156 }; 157 EXPECT_NE(0u, Lshal(out, err, serviceManager, serviceManager) 158 .main({NELEMS(args), const_cast<char **>(args)})); 159 EXPECT_THAT(err.str(), HasSubstr("does not exist")); 160 } 161 162 } // namespace lshal 163 } // namespace android 164 165 int main(int argc, char **argv) { 166 ::testing::InitGoogleMock(&argc, argv); 167 return RUN_ALL_TESTS(); 168 } 169