// Copyright 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/emulation/AdbHostListener.h"

#include "android/base/async/ThreadLooper.h"
#include "android/base/Log.h"
#include "android/base/sockets/ScopedSocket.h"
#include "android/base/sockets/SocketUtils.h"
#include "android/base/StringFormat.h"
#include "android/base/StringView.h"
#include "android/base/synchronization/Lock.h"
#include "android/base/threads/Thread.h"
#include "android/base/testing/TestInputBufferSocketServerThread.h"

#include <gtest/gtest.h>

// Because gtest includes Windows headers that declare the ERROR
// macro that prevents LOG(ERROR) from compiling!!
#ifdef _WIN32
#undef ERROR
#endif

#include <memory>
#include <errno.h>

namespace android {
namespace emulation {

using android::base::AutoLock;
using android::base::Lock;
using android::base::ScopedSocket;
using android::base::StringFormat;
using android::base::ThreadLooper;
using android::base::TestInputBufferSocketServerThread;

namespace {

// A thread that will connect to a given TCP4 loopback port, send a 32-bit ID
// integer through it, then exit. Usage is:
//
//   1) Create intsance, passing a |port| and |id| value.
//   2) Start the thread.
//   3) Join/wait for the thread.
//
// It's possible to query the thread's state any time, and from any thread,
// by calling the state() method.
class TestConnectThread : public android::base::Thread {
public:
    enum State {
        kInit = 0,
        kConnected,
        kDisconnected,
    };

    explicit TestConnectThread(int port, int id) : mPort(port), mId(id) {}

    State state() const {
        AutoLock lock(mLock);
        return mState;
    }

    virtual intptr_t main() override {
        // Connect
        std::string prefix = StringFormat("[thread %d] ", mId);
        ScopedSocket fd(android::base::socketTcp4LoopbackClient(mPort));
        if (!fd.valid()) {
            PLOG(ERROR) << prefix << "Connection failed";
            return -1;
        }
        setState(kConnected);
        uint32_t id = static_cast<uint32_t>(mId);
        ssize_t len = android::base::socketSend(fd.get(), &id, sizeof(id));
        if (len == 0) {
            LOG(INFO) << prefix << "End of stream";
        }
        if (len < 0) {
            PLOG(ERROR) << prefix;
        }
        if (len != static_cast<ssize_t>(sizeof(id))) {
            LOG(INFO) << prefix << "Invalid sent byte count=" << len;
        }
        setState(kDisconnected);
        return 0;
    }

private:
    void setState(State newState) {
        AutoLock lock(mLock);
        mState = newState;
    }

    int mPort = -1;
    int mId = -1;
    mutable Lock mLock;
    State mState = kInit;
};

struct TestAdbGuestAgent : public AdbGuestAgent {
    TestAdbGuestAgent(int id)
        : mId(id), mPrefix(StringFormat("[guest %d] ", id)) {}

    virtual void onHostConnection(ScopedSocket&& socket) override {
        mSocket = socket;

        uint32_t id = 0;
        ssize_t len = android::base::socketRecv(mSocket.get(), &id, sizeof(id));
        if (len == 0) {
            PLOG(ERROR) << mPrefix << "End of stream";
        } else if (len < 0) {
            PLOG(ERROR) << mPrefix << "I/O Error";
        } else if (len != static_cast<ssize_t>(sizeof(id))) {
            LOG(ERROR) << mPrefix << "Invalid read byte count=" << len;
        }
        mId = static_cast<int>(id);
    }

    int id() const { return mId; }

    void close() { mSocket.close(); }

    int socket() const { return mSocket.get(); }

private:
    int mId = -1;
    ScopedSocket mSocket;
    std::string mPrefix;
};

}  // namespace

TEST(AdbHostListener, reset) {
    AdbHostListener testListener;
    EXPECT_EQ(-1, testListener.port());

    const int adbPort = 0;  // Bind to random port.
    EXPECT_TRUE(testListener.reset(adbPort));
    EXPECT_NE(adbPort, testListener.port());

    // Second reset with the same port number should not fail.
    EXPECT_TRUE(testListener.reset(adbPort));
    EXPECT_NE(adbPort, testListener.port());

    testListener.reset(-1);
    EXPECT_EQ(-1, testListener.port());
}

TEST(AdbHostListener, startListening) {
    TestAdbGuestAgent testAgent(1);
    AdbHostListener testListener;

    testListener.setGuestAgent(&testAgent);
    EXPECT_TRUE(testListener.reset(0));

    {
        TestConnectThread testThread(testListener.port(), 2);

        // Start the thread, it will be unable to send data until
        // startListening()
        // is called. Even if we run the current thread looper for 10 ms.
        testThread.start();
        ThreadLooper::get()->runWithTimeoutMs(10);
        EXPECT_EQ(-1, testAgent.socket());
        EXPECT_EQ(1, testAgent.id());

        // Start listening and run the thread looper again, this time the
        // send should work.
        testListener.startListening();
        ThreadLooper::get()->runWithTimeoutMs(10);
        EXPECT_EQ(2, testAgent.id());
        EXPECT_EQ(TestConnectThread::kDisconnected, testThread.state());
    }

    {
        TestConnectThread testThread(testListener.port(), 3);

        // Start a second thread, it will be unable to send data until
        // startListening() is called again. Even if we run the current
        // thread looper for 10 ms.
        testThread.start();
        ThreadLooper::get()->runWithTimeoutMs(10);
        EXPECT_EQ(2, testAgent.id());

        // Start listening and run the thread looper again, this time the
        // send should work.
        testListener.startListening();
        ThreadLooper::get()->runWithTimeoutMs(10);
        EXPECT_EQ(3, testAgent.id());
        EXPECT_EQ(TestConnectThread::kDisconnected, testThread.state());
    }
}

TEST(AdbHostListener, stopListening) {
    TestAdbGuestAgent testAgent(1);
    AdbHostListener testListener;

    testListener.setGuestAgent(&testAgent);
    EXPECT_TRUE(testListener.reset(0));

    TestConnectThread testThread(testListener.port(), 2);

    // Start the thread, it will be unable to send data until startListening()
    // is called. Even if we run the current thread looper for 10 ms.
    testThread.start();
    ThreadLooper::get()->runWithTimeoutMs(10);
    EXPECT_EQ(-1, testAgent.socket());
    EXPECT_EQ(1, testAgent.id());

    // Start the stop listening, this will prevent the thread to send data
    // even if the looper runs for 10 ms.
    testListener.startListening();
    testListener.stopListening();
    ThreadLooper::get()->runWithTimeoutMs(10);
    EXPECT_EQ(-1, testAgent.socket());
    EXPECT_EQ(1, testAgent.id());
}

TEST(AdbHostListener, notifyServer) {
    TestInputBufferSocketServerThread serverThread;
    int adbClientPort = serverThread.port();
    serverThread.start();

    AdbHostListener testListener(adbClientPort);
    EXPECT_EQ(adbClientPort, testListener.clientPort());

    testListener.reset(0);  // Bind to random port.
    int adbEmulatorPort = testListener.port();

    testListener.notifyServer();

    intptr_t bufferSize = 0;
    EXPECT_TRUE(serverThread.wait(&bufferSize));

    // Verify message content.
    std::string message = StringFormat("host:emulator:%d", adbEmulatorPort);
    std::string expected =
            StringFormat("%04x%s", message.size(), message.c_str());
    EXPECT_EQ(expected.size(), static_cast<size_t>(bufferSize));
    EXPECT_EQ(expected.size(), serverThread.view().size());
    EXPECT_STREQ(expected.c_str(), serverThread.view().c_str());
}

}  // namespace emulation
}  // namespace base
