/*
 * Copyright (C) 2019 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 <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <strings.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>
#include <vector>

#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>

#include "adb.h"
#include "adb_io.h"
#include "fuse_adb_provider.h"
#include "fuse_sideload.h"
#include "minadbd_services.h"
#include "minadbd_types.h"
#include "socket.h"

class MinadbdServicesTest : public ::testing::Test {
 protected:
  static constexpr int EXIT_TIME_OUT = 10;

  void SetUp() override {
    ASSERT_TRUE(
        android::base::Socketpair(AF_UNIX, SOCK_STREAM, 0, &minadbd_socket_, &recovery_socket_));
    SetMinadbdSocketFd(minadbd_socket_);
    SetSideloadMountPoint(mount_point_.path);

    package_path_ = std::string(mount_point_.path) + "/" + FUSE_SIDELOAD_HOST_FILENAME;
    exit_flag_ = std::string(mount_point_.path) + "/" + FUSE_SIDELOAD_HOST_EXIT_FLAG;

    signal(SIGPIPE, SIG_IGN);
  }

  void TearDown() override {
    // Umount in case the test fails. Ignore the result.
    umount(mount_point_.path);

    signal(SIGPIPE, SIG_DFL);
  }

  void ReadAndCheckCommandMessage(int fd, MinadbdCommand expected_command) {
    std::vector<uint8_t> received(kMinadbdMessageSize, '\0');
    ASSERT_TRUE(android::base::ReadFully(fd, received.data(), kMinadbdMessageSize));

    std::vector<uint8_t> expected(kMinadbdMessageSize, '\0');
    memcpy(expected.data(), kMinadbdCommandPrefix, strlen(kMinadbdCommandPrefix));
    memcpy(expected.data() + strlen(kMinadbdCommandPrefix), &expected_command,
           sizeof(expected_command));
    ASSERT_EQ(expected, received);
  }

  void WaitForFusePath() {
    constexpr int TIME_OUT = 10;
    for (int i = 0; i < TIME_OUT; ++i) {
      struct stat sb;
      if (stat(package_path_.c_str(), &sb) == 0) {
        return;
      }

      if (errno == ENOENT) {
        sleep(1);
        continue;
      }
      FAIL() << "Timed out waiting for the fuse-provided package " << strerror(errno);
    }
  }

  void StatExitFlagAndExitProcess(int exit_code) {
    struct stat sb;
    if (stat(exit_flag_.c_str(), &sb) != 0) {
      PLOG(ERROR) << "Failed to stat " << exit_flag_;
    }

    exit(exit_code);
  }

  void WriteMinadbdCommandStatus(MinadbdCommandStatus status) {
    std::string status_message(kMinadbdMessageSize, '\0');
    memcpy(status_message.data(), kMinadbdStatusPrefix, strlen(kMinadbdStatusPrefix));
    memcpy(status_message.data() + strlen(kMinadbdStatusPrefix), &status, sizeof(status));
    ASSERT_TRUE(
        android::base::WriteFully(recovery_socket_, status_message.data(), kMinadbdMessageSize));
  }

  void ExecuteCommandAndWaitForExit(const std::string& command) {
    unique_fd fd = daemon_service_to_fd(command, nullptr);
    ASSERT_NE(-1, fd);
    sleep(EXIT_TIME_OUT);
  }

  android::base::unique_fd minadbd_socket_;
  android::base::unique_fd recovery_socket_;

  TemporaryDir mount_point_;
  std::string package_path_;
  std::string exit_flag_;
};

TEST_F(MinadbdServicesTest, SideloadHostService_wrong_size_argument) {
  ASSERT_EXIT(ExecuteCommandAndWaitForExit("sideload-host:abc:4096"),
              ::testing::ExitedWithCode(kMinadbdHostCommandArgumentError), "");
}

TEST_F(MinadbdServicesTest, SideloadHostService_wrong_block_size) {
  ASSERT_EXIT(ExecuteCommandAndWaitForExit("sideload-host:10:20"),
              ::testing::ExitedWithCode(kMinadbdFuseStartError), "");
}

TEST_F(MinadbdServicesTest, SideloadHostService_broken_minadbd_socket) {
  SetMinadbdSocketFd(-1);
  ASSERT_EXIT(ExecuteCommandAndWaitForExit("sideload-host:4096:4096"),
              ::testing::ExitedWithCode(kMinadbdSocketIOError), "");
}

TEST_F(MinadbdServicesTest, SideloadHostService_broken_recovery_socket) {
  recovery_socket_.reset();
  ASSERT_EXIT(ExecuteCommandAndWaitForExit("sideload-host:4096:4096"),
              ::testing::ExitedWithCode(kMinadbdSocketIOError), "");
}

TEST_F(MinadbdServicesTest, SideloadHostService_wrong_command_format) {
  auto test_body = [&](const std::string& command) {
    unique_fd fd = daemon_service_to_fd(command, nullptr);
    ASSERT_NE(-1, fd);
    WaitForFusePath();
    ReadAndCheckCommandMessage(recovery_socket_, MinadbdCommand::kInstall);

    struct stat sb;
    ASSERT_EQ(0, stat(exit_flag_.c_str(), &sb));
    ASSERT_TRUE(android::base::WriteStringToFd("12345678", recovery_socket_));
    sleep(EXIT_TIME_OUT);
  };

  ASSERT_EXIT(test_body("sideload-host:4096:4096"),
              ::testing::ExitedWithCode(kMinadbdMessageFormatError), "");
}

TEST_F(MinadbdServicesTest, SideloadHostService_read_data_from_fuse) {
  auto test_body = [&]() {
    std::vector<uint8_t> content(4096, 'a');
    // Start a new process instead of a thread to read from the package mounted by FUSE. Because
    // the test may not exit and report failures correctly when the thread blocks by a syscall.
    pid_t pid = fork();
    if (pid == 0) {
      WaitForFusePath();
      android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(package_path_.c_str(), O_RDONLY)));
      // Do not use assertion here because we want to stat the exit flag and exit the process.
      // Otherwise the test will wait for the time out instead of failing immediately.
      if (fd == -1) {
        PLOG(ERROR) << "Failed to open " << package_path_;
        StatExitFlagAndExitProcess(1);
      }
      std::vector<uint8_t> content_from_fuse(4096);
      if (!android::base::ReadFully(fd, content_from_fuse.data(), 4096)) {
        PLOG(ERROR) << "Failed to read from " << package_path_;
        StatExitFlagAndExitProcess(1);
      }
      if (content_from_fuse != content) {
        LOG(ERROR) << "Content read from fuse doesn't match with the expected value";
        StatExitFlagAndExitProcess(1);
      }
      StatExitFlagAndExitProcess(0);
    }

    unique_fd fd = daemon_service_to_fd("sideload-host:4096:4096", nullptr);
    ASSERT_NE(-1, fd);
    ReadAndCheckCommandMessage(recovery_socket_, MinadbdCommand::kInstall);

    // Mimic the response from adb host.
    std::string adb_message(8, '\0');
    ASSERT_TRUE(android::base::ReadFully(fd, adb_message.data(), 8));
    ASSERT_EQ(android::base::StringPrintf("%08u", 0), adb_message);
    ASSERT_TRUE(android::base::WriteFully(fd, content.data(), 4096));

    // Check that we read the correct data from fuse.
    int child_status;
    waitpid(pid, &child_status, 0);
    ASSERT_TRUE(WIFEXITED(child_status));
    ASSERT_EQ(0, WEXITSTATUS(child_status));

    WriteMinadbdCommandStatus(MinadbdCommandStatus::kSuccess);

    // TODO(xunchang) check if adb host-side receives "DONEDONE", there's a race condition between
    // receiving the message and exit of test body (by detached thread in minadbd service).
    exit(kMinadbdSuccess);
  };

  ASSERT_EXIT(test_body(), ::testing::ExitedWithCode(kMinadbdSuccess), "");
}
