/*
 * 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, MinadbdCommands 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(kMinadbdPackageSizeError), "");
}

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_, MinadbdCommands::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_, MinadbdCommands::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), "");
}
