// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fuchsia/sys/cpp/fidl.h>
#include <lib/sys/cpp/file_descriptor.h>
#include <lib/sys/cpp/testing/test_with_environment.h>
#include <lib/syslog/cpp/macros.h>

#include "src/lib/files/file.h"
#include "src/lib/files/scoped_temp_dir.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace component {
namespace {

using fuchsia::sys::TerminationReason;
using sys::testing::EnclosingEnvironment;

constexpr char kRealm[] = "test";

class ComponentsBinaryTest : public sys::testing::TestWithEnvironment {
 protected:
  void OpenNewOutFile() {
    ASSERT_TRUE(tmp_dir_.NewTempFile(&out_file_));
    outf_ = fileno(std::fopen(out_file_.c_str(), "w"));
  }

  std::string ReadOutFile() {
    std::string out;
    if (!files::ReadFileToString(out_file_, &out)) {
      FX_LOGS(ERROR) << "Could not read output file " << out_file_;
      return "";
    }
    return out;
  }

  fuchsia::sys::LaunchInfo CreateLaunchInfo(const std::string& url,
                                            const std::vector<std::string>& args = {}) {
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.url = url;
    launch_info.arguments = args;
    launch_info.out = sys::CloneFileDescriptor(outf_);
    launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
    return launch_info;
  }

  static std::string UrlFromCmx(const std::string& cmx) {
    return fxl::StringPrintf("fuchsia-pkg://fuchsia.com/components_binary_tests#meta/%s",
                             cmx.c_str());
  }

  void RunComponent(const std::string& url, int64_t* return_code = nullptr,
                    TerminationReason* termination_reason = nullptr,
                    const std::vector<std::string>& args = {}) {
    fuchsia::sys::ComponentControllerPtr controller;
    environment_->CreateComponent(CreateLaunchInfo(url, std::move(args)), controller.NewRequest());

    bool terminated = false;
    controller.events().OnTerminated = [&terminated, &return_code, &termination_reason](
                                           int64_t code, TerminationReason reason) {
      if (return_code != nullptr) {
        *return_code = code;
      }
      if (termination_reason != nullptr) {
        *termination_reason = reason;
      }
      terminated = true;
    };
    RunLoopUntil([&terminated] { return terminated; });
  }

  ComponentsBinaryTest() {
    OpenNewOutFile();

    environment_ = CreateNewEnclosingEnvironment(kRealm, CreateServices());
  }

 private:
  std::unique_ptr<EnclosingEnvironment> environment_;
  files::ScopedTempDir tmp_dir_;
  std::string out_file_;
  int outf_;
};

// We therefore test that targeting a binary by a component manifest works, that
// argv0 properly propagates the binary path, and that the args field in the
// manifest is being properly passed through to the component.
TEST_F(ComponentsBinaryTest, EchoNoArgs) {
  int64_t return_code = -1;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("echo1.cmx"), &return_code);
  EXPECT_EQ(0, return_code);
  std::string output = ReadOutFile();
  ASSERT_EQ(output, "/pkg/bin/echo1\n");
}

TEST_F(ComponentsBinaryTest, EchoHelloWorld) {
  int64_t return_code = -1;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("echo2.cmx"), &return_code);
  EXPECT_EQ(0, return_code);
  std::string output = ReadOutFile();
  ASSERT_EQ(output, "/pkg/bin/echo2 helloworld\n");
}

TEST_F(ComponentsBinaryTest, GetEnvMatched) {
  int64_t return_code = -1;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("getenv1.cmx"), &return_code);
  EXPECT_EQ(0, return_code);
  std::string output = ReadOutFile();
  ASSERT_EQ(output, "FOO=bar BAR=baz\n");
}

TEST_F(ComponentsBinaryTest, GetEnvMismatch) {
  int64_t return_code = -1;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("getenv2.cmx"), &return_code);
  EXPECT_EQ(0, return_code);
  std::string output = ReadOutFile();
  ASSERT_EQ(output, "FOO=bar BAR=NULL\n");
}

TEST_F(ComponentsBinaryTest, UnallowedDeprecatedShellFailsToLaunch) {
  int64_t return_code = -1;
  TerminationReason termination_reason;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("echo_deprecated_shell.cmx"), &return_code,
               &termination_reason);
  EXPECT_NE(TerminationReason::EXITED, termination_reason);
}

TEST_F(ComponentsBinaryTest, EchoStdin) {
  int64_t return_code = -1;
  TerminationReason termination_reason;
  RunComponent(ComponentsBinaryTest::UrlFromCmx("echo_stdin.cmx"), &return_code,
               &termination_reason, {std::string("hello world")});
  EXPECT_EQ(0, return_code);
  EXPECT_EQ(TerminationReason::EXITED, termination_reason);
}

}  // namespace
}  // namespace component
