168 lines
5.7 KiB
C++
168 lines
5.7 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "Lshal"
|
|
#include <android-base/logging.h>
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
#include <android/hardware/tests/baz/1.0/IQuux.h>
|
|
#include <hidl/HidlTransportSupport.h>
|
|
|
|
#include "Lshal.h"
|
|
|
|
#define NELEMS(array) static_cast<int>(sizeof(array) / sizeof(array[0]))
|
|
|
|
using namespace testing;
|
|
|
|
using ::android::hidl::base::V1_0::IBase;
|
|
using ::android::hidl::manager::V1_0::IServiceManager;
|
|
using ::android::hidl::manager::V1_0::IServiceNotification;
|
|
using ::android::hardware::hidl_death_recipient;
|
|
using ::android::hardware::hidl_handle;
|
|
using ::android::hardware::hidl_string;
|
|
using ::android::hardware::hidl_vec;
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace tests {
|
|
namespace baz {
|
|
namespace V1_0 {
|
|
namespace implementation {
|
|
struct Quux : android::hardware::tests::baz::V1_0::IQuux {
|
|
::android::hardware::Return<void> debug(const hidl_handle& hh, const hidl_vec<hidl_string>& options) override {
|
|
const native_handle_t *handle = hh.getNativeHandle();
|
|
if (handle->numFds < 1) {
|
|
return Void();
|
|
}
|
|
int fd = handle->data[0];
|
|
std::string content{descriptor};
|
|
for (const auto &option : options) {
|
|
content += "\n";
|
|
content += option.c_str();
|
|
}
|
|
ssize_t written = write(fd, content.c_str(), content.size());
|
|
if (written != (ssize_t)content.size()) {
|
|
LOG(WARNING) << "SERVER(Quux) debug writes " << written << " bytes < "
|
|
<< content.size() << " bytes, errno = " << errno;
|
|
}
|
|
return Void();
|
|
}
|
|
};
|
|
|
|
} // namespace implementation
|
|
} // namespace V1_0
|
|
} // namespace baz
|
|
} // namespace tests
|
|
} // namespace hardware
|
|
|
|
namespace lshal {
|
|
|
|
|
|
class MockServiceManager : public IServiceManager {
|
|
public:
|
|
template<typename T>
|
|
using R = ::android::hardware::Return<T>;
|
|
using String = const hidl_string&;
|
|
~MockServiceManager() = default;
|
|
|
|
#define MOCK_METHOD_CB(name) MOCK_METHOD1(name, R<void>(IServiceManager::name##_cb))
|
|
|
|
MOCK_METHOD2(get, R<sp<IBase>>(String, String));
|
|
MOCK_METHOD2(add, R<bool>(String, const sp<IBase>&));
|
|
MOCK_METHOD2(getTransport, R<IServiceManager::Transport>(String, String));
|
|
MOCK_METHOD_CB(list);
|
|
MOCK_METHOD2(listByInterface, R<void>(String, listByInterface_cb));
|
|
MOCK_METHOD3(registerForNotifications, R<bool>(String, String, const sp<IServiceNotification>&));
|
|
MOCK_METHOD_CB(debugDump);
|
|
MOCK_METHOD2(registerPassthroughClient, R<void>(String, String));
|
|
MOCK_METHOD_CB(interfaceChain);
|
|
MOCK_METHOD2(debug, R<void>(const hidl_handle&, const hidl_vec<hidl_string>&));
|
|
MOCK_METHOD_CB(interfaceDescriptor);
|
|
MOCK_METHOD_CB(getHashChain);
|
|
MOCK_METHOD0(setHalInstrumentation, R<void>());
|
|
MOCK_METHOD2(linkToDeath, R<bool>(const sp<hidl_death_recipient>&, uint64_t));
|
|
MOCK_METHOD0(ping, R<void>());
|
|
MOCK_METHOD_CB(getDebugInfo);
|
|
MOCK_METHOD0(notifySyspropsChanged, R<void>());
|
|
MOCK_METHOD1(unlinkToDeath, R<bool>(const sp<hidl_death_recipient>&));
|
|
|
|
};
|
|
|
|
class LshalTest : public ::testing::Test {
|
|
public:
|
|
void SetUp() override {
|
|
using ::android::hardware::tests::baz::V1_0::IQuux;
|
|
using ::android::hardware::tests::baz::V1_0::implementation::Quux;
|
|
|
|
err.str("");
|
|
out.str("");
|
|
serviceManager = new testing::NiceMock<MockServiceManager>();
|
|
ON_CALL(*serviceManager, get(_, _)).WillByDefault(Invoke(
|
|
[](const auto &iface, const auto &inst) -> ::android::hardware::Return<sp<IBase>> {
|
|
if (iface == IQuux::descriptor && inst == "default")
|
|
return new Quux();
|
|
return nullptr;
|
|
}));
|
|
}
|
|
void TearDown() override {}
|
|
|
|
std::stringstream err;
|
|
std::stringstream out;
|
|
sp<MockServiceManager> serviceManager;
|
|
};
|
|
|
|
TEST_F(LshalTest, Debug) {
|
|
const char *args[] = {
|
|
"lshal", "debug", "android.hardware.tests.baz@1.0::IQuux/default", "foo", "bar"
|
|
};
|
|
EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager)
|
|
.main({NELEMS(args), const_cast<char **>(args)}));
|
|
EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nfoo\nbar"));
|
|
EXPECT_THAT(err.str(), IsEmpty());
|
|
}
|
|
|
|
TEST_F(LshalTest, Debug2) {
|
|
const char *args[] = {
|
|
"lshal", "debug", "android.hardware.tests.baz@1.0::IQuux", "baz", "quux"
|
|
};
|
|
EXPECT_EQ(0u, Lshal(out, err, serviceManager, serviceManager)
|
|
.main({NELEMS(args), const_cast<char **>(args)}));
|
|
EXPECT_THAT(out.str(), StrEq("android.hardware.tests.baz@1.0::IQuux\nbaz\nquux"));
|
|
EXPECT_THAT(err.str(), IsEmpty());
|
|
}
|
|
|
|
TEST_F(LshalTest, Debug3) {
|
|
const char *args[] = {
|
|
"lshal", "debug", "android.hardware.tests.doesnotexist@1.0::IDoesNotExist",
|
|
};
|
|
EXPECT_NE(0u, Lshal(out, err, serviceManager, serviceManager)
|
|
.main({NELEMS(args), const_cast<char **>(args)}));
|
|
EXPECT_THAT(err.str(), HasSubstr("does not exist"));
|
|
}
|
|
|
|
} // namespace lshal
|
|
} // namespace android
|
|
|
|
int main(int argc, char **argv) {
|
|
::testing::InitGoogleMock(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|