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