/*
 * 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 "WatchdogBinderMediator.h"

#include <android/automotive/watchdog/BootPhase.h>
#include <android/automotive/watchdog/PowerCycle.h>
#include <android/automotive/watchdog/UserState.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <errno.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <utils/RefBase.h>

#include "gmock/gmock.h"

namespace android {
namespace automotive {
namespace watchdog {

using android::sp;
using android::base::Result;
using binder::Status;
using ::testing::_;
using ::testing::Return;

namespace {

class MockWatchdogProcessService : public WatchdogProcessService {
public:
    MockWatchdogProcessService() : WatchdogProcessService(nullptr) {}
    MOCK_METHOD(Result<void>, dump, (int fd, const Vector<String16>& args), (override));

    MOCK_METHOD(Status, registerClient,
                (const sp<ICarWatchdogClient>& client, TimeoutLength timeout), (override));
    MOCK_METHOD(Status, unregisterClient, (const sp<ICarWatchdogClient>& client), (override));
    MOCK_METHOD(Status, registerMediator, (const sp<ICarWatchdogClient>& mediator), (override));
    MOCK_METHOD(Status, unregisterMediator, (const sp<ICarWatchdogClient>& mediator), (override));
    MOCK_METHOD(Status, registerMonitor, (const sp<ICarWatchdogMonitor>& monitor), (override));
    MOCK_METHOD(Status, unregisterMonitor, (const sp<ICarWatchdogMonitor>& monitor), (override));
    MOCK_METHOD(Status, tellClientAlive, (const sp<ICarWatchdogClient>& client, int32_t sessionId),
                (override));
    MOCK_METHOD(Status, tellMediatorAlive,
                (const sp<ICarWatchdogClient>& mediator,
                 const std::vector<int32_t>& clientsNotResponding, int32_t sessionId),
                (override));
    MOCK_METHOD(Status, tellDumpFinished,
                (const android::sp<ICarWatchdogMonitor>& monitor, int32_t pid), (override));
    MOCK_METHOD(Status, notifyPowerCycleChange, (PowerCycle cycle), (override));
    MOCK_METHOD(Status, notifyUserStateChange, (userid_t userId, UserState state), (override));
    MOCK_METHOD(void, binderDied, (const android::wp<IBinder>& who), (override));
};

class MockIoPerfCollection : public IoPerfCollection {
public:
    MockIoPerfCollection() {}
    MOCK_METHOD(Result<void>, onBootFinished, (), (override));
    MOCK_METHOD(Result<void>, dump, (int fd, const Vector<String16>& args), (override));
};

class MockICarWatchdogClient : public ICarWatchdogClient {
public:
    MOCK_METHOD(Status, checkIfAlive, (int32_t sessionId, TimeoutLength timeout), (override));
    MOCK_METHOD(Status, prepareProcessTermination, (), (override));
    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
    MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
    MOCK_METHOD(std::string, getInterfaceHash, (), (override));
};

class MockICarWatchdogMonitor : public ICarWatchdogMonitor {
public:
    MOCK_METHOD(Status, onClientsNotResponding, (const std::vector<int32_t>& pids), (override));
    MOCK_METHOD(IBinder*, onAsBinder, (), (override));
    MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
    MOCK_METHOD(std::string, getInterfaceHash, (), (override));
};

class ScopedChangeCallingUid : public RefBase {
public:
    explicit ScopedChangeCallingUid(uid_t uid) {
        mCallingUid = IPCThreadState::self()->getCallingUid();
        mCallingPid = IPCThreadState::self()->getCallingPid();
        if (mCallingUid == uid) {
            return;
        }
        mChangedUid = uid;
        int64_t token = ((int64_t)mChangedUid << 32) | mCallingPid;
        IPCThreadState::self()->restoreCallingIdentity(token);
    }
    ~ScopedChangeCallingUid() {
        if (mCallingUid == mChangedUid) {
            return;
        }
        int64_t token = ((int64_t)mCallingUid << 32) | mCallingPid;
        IPCThreadState::self()->restoreCallingIdentity(token);
    }

private:
    uid_t mCallingUid;
    uid_t mChangedUid;
    pid_t mCallingPid;
};

}  // namespace

class WatchdogBinderMediatorTest : public ::testing::Test {
protected:
    virtual void SetUp() {
        mMockWatchdogProcessService = new MockWatchdogProcessService();
        mMockIoPerfCollection = new MockIoPerfCollection();
        mWatchdogBinderMediator = new WatchdogBinderMediator();
        mWatchdogBinderMediator->init(mMockWatchdogProcessService, mMockIoPerfCollection);
    }
    virtual void TearDown() {
        mWatchdogBinderMediator->terminate();
        ASSERT_TRUE(mWatchdogBinderMediator->mWatchdogProcessService == nullptr);
        ASSERT_TRUE(mWatchdogBinderMediator->mIoPerfCollection == nullptr);
        mMockWatchdogProcessService = nullptr;
        mMockIoPerfCollection = nullptr;
        mWatchdogBinderMediator = nullptr;
        mScopedChangeCallingUid = nullptr;
    }
    // Sets calling UID to imitate System's process.
    void setSystemCallingUid() { mScopedChangeCallingUid = new ScopedChangeCallingUid(AID_SYSTEM); }
    sp<MockWatchdogProcessService> mMockWatchdogProcessService;
    sp<MockIoPerfCollection> mMockIoPerfCollection;
    sp<WatchdogBinderMediator> mWatchdogBinderMediator;
    sp<ScopedChangeCallingUid> mScopedChangeCallingUid;
};

TEST_F(WatchdogBinderMediatorTest, TestErrorOnNullptrDuringInit) {
    sp<WatchdogBinderMediator> mediator = new WatchdogBinderMediator();
    ASSERT_FALSE(mediator->init(nullptr, new MockIoPerfCollection()).ok())
            << "No error returned on nullptr watchdog process service";
    ASSERT_FALSE(mediator->init(new MockWatchdogProcessService(), nullptr).ok())
            << "No error returned on nullptr I/O perf collection";
    ASSERT_FALSE(mediator->init(nullptr, nullptr).ok()) << "No error returned on nullptr";
}

TEST_F(WatchdogBinderMediatorTest, TestHandlesEmptyDumpArgs) {
    EXPECT_CALL(*mMockWatchdogProcessService, dump(-1, _)).WillOnce(Return(Result<void>()));
    EXPECT_CALL(*mMockIoPerfCollection, dump(-1, _)).WillOnce(Return(Result<void>()));
    mWatchdogBinderMediator->dump(-1, Vector<String16>());
}

TEST_F(WatchdogBinderMediatorTest, TestHandlesStartCustomIoPerfCollection) {
    EXPECT_CALL(*mMockIoPerfCollection, dump(-1, _)).WillOnce(Return(Result<void>()));

    Vector<String16> args;
    args.push_back(String16(kStartCustomCollectionFlag));
    ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
}

TEST_F(WatchdogBinderMediatorTest, TestHandlesStopCustomIoPerfCollection) {
    EXPECT_CALL(*mMockIoPerfCollection, dump(-1, _)).WillOnce(Return(Result<void>()));

    Vector<String16> args;
    args.push_back(String16(kEndCustomCollectionFlag));
    ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnInvalidDumpArgs) {
    Vector<String16> args;
    args.push_back(String16("--invalid_option"));
    ASSERT_NE(mWatchdogBinderMediator->dump(-1, args), OK) << "No error on invalid args";
}

TEST_F(WatchdogBinderMediatorTest, TestRegisterClient) {
    sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
    TimeoutLength timeout = TimeoutLength::TIMEOUT_MODERATE;
    EXPECT_CALL(*mMockWatchdogProcessService, registerClient(client, timeout))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->registerClient(client, timeout);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestUnregisterClient) {
    sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, unregisterClient(client))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->unregisterClient(client);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestRegisterMediator) {
    setSystemCallingUid();
    sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, registerMediator(mediator))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->registerMediator(mediator);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnRegisterMediatorWithNonSystemCallingUid) {
    sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, registerMediator(mediator)).Times(0);
    Status status = mWatchdogBinderMediator->registerMediator(mediator);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestUnregisterMediator) {
    setSystemCallingUid();
    sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, unregisterMediator(mediator))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->unregisterMediator(mediator);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnUnegisterMediatorWithNonSystemCallingUid) {
    sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, unregisterMediator(mediator)).Times(0);
    Status status = mWatchdogBinderMediator->unregisterMediator(mediator);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestRegisterMonitor) {
    setSystemCallingUid();
    sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
    EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->registerMonitor(monitor);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnRegisterMonitorWithNonSystemCallingUid) {
    sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
    EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor)).Times(0);
    Status status = mWatchdogBinderMediator->registerMonitor(monitor);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestUnregisterMonitor) {
    setSystemCallingUid();
    sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
    EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->unregisterMonitor(monitor);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnUnregisterMonitorWithNonSystemCallingUid) {
    sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
    EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor)).Times(0);
    Status status = mWatchdogBinderMediator->unregisterMonitor(monitor);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestTellClientAlive) {
    sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
    EXPECT_CALL(*mMockWatchdogProcessService, tellClientAlive(client, 456))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->tellClientAlive(client, 456);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestTellMediatorAlive) {
    sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
    std::vector clientsNotResponding = {123};
    EXPECT_CALL(*mMockWatchdogProcessService,
                tellMediatorAlive(mediator, clientsNotResponding, 456))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->tellMediatorAlive(mediator, clientsNotResponding, 456);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestTellDumpFinished) {
    sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
    EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(monitor, 456))
            .WillOnce(Return(Status::ok()));
    Status status = mWatchdogBinderMediator->tellDumpFinished(monitor, 456);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyStateChangeWithNonSystemCallingUid) {
    StateType type = StateType::POWER_CYCLE;
    EXPECT_CALL(*mMockWatchdogProcessService, notifyPowerCycleChange(_)).Times(0);
    Status status =
            mWatchdogBinderMediator
                    ->notifySystemStateChange(type,
                                              static_cast<int32_t>(PowerCycle::POWER_CYCLE_SUSPEND),
                                              -1);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestNotifyPowerCycleChange) {
    setSystemCallingUid();
    StateType type = StateType::POWER_CYCLE;
    EXPECT_CALL(*mMockWatchdogProcessService,
                notifyPowerCycleChange(PowerCycle::POWER_CYCLE_SUSPEND))
            .WillOnce(Return(Status::ok()));
    Status status =
            mWatchdogBinderMediator
                    ->notifySystemStateChange(type,
                                              static_cast<int32_t>(PowerCycle::POWER_CYCLE_SUSPEND),
                                              -1);
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyPowerCycleChangeWithInvalidArgs) {
    EXPECT_CALL(*mMockWatchdogProcessService, notifyPowerCycleChange(_)).Times(0);
    StateType type = StateType::POWER_CYCLE;

    Status status = mWatchdogBinderMediator->notifySystemStateChange(type, -1, -1);
    ASSERT_FALSE(status.isOk()) << status;

    status = mWatchdogBinderMediator->notifySystemStateChange(type, 3000, -1);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestNotifyUserStateChange) {
    setSystemCallingUid();
    StateType type = StateType::USER_STATE;
    EXPECT_CALL(*mMockWatchdogProcessService,
                notifyUserStateChange(234567, UserState::USER_STATE_STOPPED))
            .WillOnce(Return(Status::ok()));
    Status status =
            mWatchdogBinderMediator
                    ->notifySystemStateChange(type, 234567,
                                              static_cast<int32_t>(UserState::USER_STATE_STOPPED));
    ASSERT_TRUE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyUserStateChangeWithInvalidArgs) {
    EXPECT_CALL(*mMockWatchdogProcessService, notifyUserStateChange(_, _)).Times(0);
    StateType type = StateType::USER_STATE;

    Status status = mWatchdogBinderMediator->notifySystemStateChange(type, 234567, -1);
    ASSERT_FALSE(status.isOk()) << status;

    status = mWatchdogBinderMediator->notifySystemStateChange(type, 234567, 3000);
    ASSERT_FALSE(status.isOk()) << status;
}

TEST_F(WatchdogBinderMediatorTest, TestNotifyBootPhaseChange) {
    setSystemCallingUid();
    StateType type = StateType::BOOT_PHASE;
    EXPECT_CALL(*mMockIoPerfCollection, onBootFinished()).WillOnce(Return(Result<void>()));
    Status status = mWatchdogBinderMediator->notifySystemStateChange(
        type, static_cast<int32_t>(BootPhase::BOOT_COMPLETED), -1);
    ASSERT_TRUE(status.isOk()) << status;
}


TEST_F(WatchdogBinderMediatorTest, TestNotifyBootPhaseChangeWithNonBootCompletedPhase) {
    setSystemCallingUid();
    StateType type = StateType::BOOT_PHASE;
    EXPECT_CALL(*mMockIoPerfCollection, onBootFinished()).Times(0);
    Status status = mWatchdogBinderMediator->notifySystemStateChange(type, 0, -1);
    ASSERT_TRUE(status.isOk()) << status;
}

}  // namespace watchdog
}  // namespace automotive
}  // namespace android
