/* * Copyright 2020 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. */ #include "MockIoOveruseMonitor.h" #include "MockResourceOveruseListener.h" #include "MockWatchdogInternalHandler.h" #include "MockWatchdogPerfService.h" #include "MockWatchdogProcessService.h" #include "MockWatchdogServiceHelper.h" #include "WatchdogBinderMediator.h" #include #include #include #include #include #include namespace android { namespace automotive { namespace watchdog { using ::aidl::android::automotive::watchdog::ICarWatchdogClient; using ::aidl::android::automotive::watchdog::ICarWatchdogClientDefault; using ::aidl::android::automotive::watchdog::IoOveruseStats; using ::aidl::android::automotive::watchdog::IResourceOveruseListener; using ::aidl::android::automotive::watchdog::ResourceOveruseStats; using ::aidl::android::automotive::watchdog::ResourceType; using ::aidl::android::automotive::watchdog::StateType; using ::aidl::android::automotive::watchdog::TimeoutLength; using ::android::sp; using ::android::String16; using ::android::base::Result; using ::android::base::StringAppendF; using ::ndk::ICInterface; using ::ndk::ScopedAStatus; using ::ndk::SharedRefBase; using ::testing::_; using ::testing::ByMove; using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; using ::testing::UnorderedElementsAreArray; namespace { const std::function(const char*, ICInterface*, bool, int)> kAddServiceFunctionStub = [](const char*, ICInterface*, bool, int) -> Result { return Result{}; }; std::string toString(const std::vector& resourceOveruseStats) { std::string buffer; for (const auto& stats : resourceOveruseStats) { StringAppendF(&buffer, "%s\n", stats.toString().c_str()); } return buffer; } } // namespace namespace internal { class WatchdogBinderMediatorPeer final { public: explicit WatchdogBinderMediatorPeer(WatchdogBinderMediator* mediator) : mMediator(mediator) {} void setWatchdogInternalHandler( const std::shared_ptr& watchdogInternalHandler) { mMediator->mWatchdogInternalHandler = watchdogInternalHandler; } private: WatchdogBinderMediator* mMediator; }; }; // namespace internal class WatchdogBinderMediatorTest : public ::testing::Test { protected: virtual void SetUp() { mMockWatchdogProcessService = sp::make(); mMockWatchdogPerfService = sp::make(); mMockIoOveruseMonitor = sp::make(); mWatchdogBinderMediator = SharedRefBase::make(mMockWatchdogProcessService, mMockWatchdogPerfService, sp::make(), mMockIoOveruseMonitor, kAddServiceFunctionStub); mMockWatchdogInternalHandler = SharedRefBase::make(); internal::WatchdogBinderMediatorPeer peer(mWatchdogBinderMediator.get()); peer.setWatchdogInternalHandler(mMockWatchdogInternalHandler); } virtual void TearDown() { mMockWatchdogProcessService.clear(); mMockWatchdogPerfService.clear(); mMockIoOveruseMonitor.clear(); mWatchdogBinderMediator.reset(); } sp mMockWatchdogProcessService; sp mMockWatchdogPerfService; sp mMockIoOveruseMonitor; std::shared_ptr mMockWatchdogInternalHandler; std::shared_ptr mWatchdogBinderMediator; }; TEST_F(WatchdogBinderMediatorTest, TestInit) { std::shared_ptr mediator = SharedRefBase::make(sp::make(), sp::make(), sp::make(), sp::make(), kAddServiceFunctionStub); ASSERT_RESULT_OK(mediator->init()); ASSERT_NE(mediator->mWatchdogProcessService, nullptr); ASSERT_NE(mediator->mWatchdogPerfService, nullptr); ASSERT_NE(mediator->mIoOveruseMonitor, nullptr); ASSERT_NE(mediator->mWatchdogInternalHandler, nullptr); } TEST_F(WatchdogBinderMediatorTest, TestErrorOnInitWithNullServiceInstances) { auto mockWatchdogProcessService = sp::make(); auto mockWatchdogPerfservice = sp::make(); auto mockWatchdogServiceHelper = sp::make(); auto mockIoOveruseMonitor = sp::make(); std::shared_ptr mediator = SharedRefBase::make(nullptr, mockWatchdogPerfservice, mockWatchdogServiceHelper, mockIoOveruseMonitor, kAddServiceFunctionStub); EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog process service"; mediator.reset(); mediator = SharedRefBase::make(mockWatchdogProcessService, nullptr, mockWatchdogServiceHelper, mockIoOveruseMonitor, kAddServiceFunctionStub); EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog perf service"; mediator.reset(); mediator = SharedRefBase::make(mockWatchdogProcessService, mockWatchdogPerfservice, nullptr, mockIoOveruseMonitor, kAddServiceFunctionStub); EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog service helper"; mediator.reset(); mediator = SharedRefBase::make(mockWatchdogProcessService, mockWatchdogPerfservice, mockWatchdogServiceHelper, nullptr, kAddServiceFunctionStub); EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr I/O overuse monitor"; mediator.reset(); mediator = SharedRefBase::make(nullptr, nullptr, nullptr, nullptr, kAddServiceFunctionStub); EXPECT_FALSE(mediator->init().ok()) << "No error returned on null services"; mediator.reset(); } TEST_F(WatchdogBinderMediatorTest, TestDump) { const char* args[] = {kStartCustomCollectionFlag, kIntervalFlag, "10", kMaxDurationFlag, "200"}; EXPECT_CALL(*mMockWatchdogInternalHandler, dump(-1, args, /*numArgs=*/5)).WillOnce(Return(OK)); ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args, /*numArgs=*/5), OK); } TEST_F(WatchdogBinderMediatorTest, TestRegisterClient) { std::shared_ptr client = SharedRefBase::make(); TimeoutLength timeout = TimeoutLength::TIMEOUT_MODERATE; EXPECT_CALL(*mMockWatchdogProcessService, registerClient(client, timeout)) .WillOnce(Return(ByMove(ScopedAStatus::ok()))); auto status = mWatchdogBinderMediator->registerClient(client, timeout); ASSERT_TRUE(status.isOk()) << status.getMessage(); } TEST_F(WatchdogBinderMediatorTest, TestUnregisterClient) { std::shared_ptr client = SharedRefBase::make(); EXPECT_CALL(*mMockWatchdogProcessService, unregisterClient(client)) .WillOnce(Return(ByMove(ScopedAStatus::ok()))); auto status = mWatchdogBinderMediator->unregisterClient(client); ASSERT_TRUE(status.isOk()) << status.getMessage(); } TEST_F(WatchdogBinderMediatorTest, TestTellClientAlive) { std::shared_ptr client = SharedRefBase::make(); EXPECT_CALL(*mMockWatchdogProcessService, tellClientAlive(client, 456)) .WillOnce(Return(ByMove(ScopedAStatus::ok()))); auto status = mWatchdogBinderMediator->tellClientAlive(client, 456); ASSERT_TRUE(status.isOk()) << status.getMessage(); } TEST_F(WatchdogBinderMediatorTest, TestAddResourceOveruseListener) { std::shared_ptr listener = SharedRefBase::make(); EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener)) .WillOnce(Return(Result{})); auto status = mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, listener); ASSERT_TRUE(status.isOk()) << status.getMessage(); } TEST_F(WatchdogBinderMediatorTest, TestErrorsAddResourceOveruseListenerOnInvalidArgs) { std::shared_ptr listener = SharedRefBase::make(); EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener)).Times(0); ASSERT_FALSE(mWatchdogBinderMediator->addResourceOveruseListener({}, listener).isOk()) << "Should fail on empty resource types"; ASSERT_FALSE( mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, nullptr).isOk()) << "Should fail on null listener"; } TEST_F(WatchdogBinderMediatorTest, TestRemoveResourceOveruseListener) { std::shared_ptr listener = SharedRefBase::make(); EXPECT_CALL(*mMockIoOveruseMonitor, removeIoOveruseListener(listener)) .WillOnce(Return(Result{})); auto status = mWatchdogBinderMediator->removeResourceOveruseListener(listener); ASSERT_TRUE(status.isOk()) << status.getMessage(); } TEST_F(WatchdogBinderMediatorTest, TestGetResourceOveruseStats) { IoOveruseStats ioOveruseStats; ioOveruseStats.killableOnOveruse = true; ioOveruseStats.startTime = 99898; ioOveruseStats.durationInSeconds = 12345; ioOveruseStats.totalOveruses = 3; std::vector expected; ResourceOveruseStats stats; stats.set(ioOveruseStats); expected.emplace_back(std::move(stats)); EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_)) .WillOnce(DoAll(SetArgPointee<0>(ioOveruseStats), Return(Result{}))); std::vector actual; auto status = mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, &actual); ASSERT_TRUE(status.isOk()) << status.getMessage(); EXPECT_THAT(actual, UnorderedElementsAreArray(expected)) << "Expected: " << toString(expected) << "\nActual: " << toString(actual); } TEST_F(WatchdogBinderMediatorTest, TestErrorsGetResourceOveruseStatsOnInvalidArgs) { EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_)).Times(0); std::vector actual; ASSERT_FALSE(mWatchdogBinderMediator->getResourceOveruseStats({}, &actual).isOk()) << "Should fail on empty resource types"; ASSERT_FALSE( mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, nullptr).isOk()) << "Should fail on null listener"; } TEST_F(WatchdogBinderMediatorTest, TestRegisterMediator) { auto status = mWatchdogBinderMediator->registerMediator(nullptr); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestUnregisterMediator) { auto status = mWatchdogBinderMediator->unregisterMediator(nullptr); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestRegisterMonitor) { auto status = mWatchdogBinderMediator->registerMonitor(nullptr); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestUnregisterMonitor) { auto status = mWatchdogBinderMediator->unregisterMonitor(nullptr); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestTellMediatorAlive) { auto status = mWatchdogBinderMediator->tellMediatorAlive(nullptr, {}, 0); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestTellDumpFinished) { auto status = mWatchdogBinderMediator->tellDumpFinished(nullptr, 0); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } TEST_F(WatchdogBinderMediatorTest, TestNotifySystemStateChange) { auto status = mWatchdogBinderMediator->notifySystemStateChange(StateType::POWER_CYCLE, 0, 0); ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION); } } // namespace watchdog } // namespace automotive } // namespace android