// Copyright 2018 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/io/cpp/fidl.h>
#include <fuchsia/logger/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/string.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <stdio.h>

#include <fidl/examples/echo/cpp/fidl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <src/lib/files/glob.h>
#include <test/sysmgr/cpp/fidl.h>

#include "lib/sys/cpp/termination_reason.h"

namespace sysmgr {
namespace test {
namespace {

constexpr char kGlob[] = "/hub/r/sys/*/svc";

class SimpleLogCollector : public fuchsia::logger::LogListenerSafe {
 public:
  explicit SimpleLogCollector(fidl::InterfaceRequest<fuchsia::logger::LogListenerSafe> request,
                              async_dispatcher_t* dispatcher)
      : binding_(this, std::move(request), dispatcher) {
    binding_.set_error_handler([this](zx_status_t s) {
      if (!done_) {
        FAIL() << "Connection to simple collector closed early";
      }
    });
  }

  virtual void Log(fuchsia::logger::LogMessage message, LogCallback received) override {
    messages_.emplace_back(message.msg);
    received();
  };

  virtual void LogMany(std::vector<fuchsia::logger::LogMessage> messages,
                       LogManyCallback received) override {
    for (auto& l : messages) {
      Log(std::move(l), []() {});
    }
    received();
  }

  virtual void Done() override { done_ = true; }

  bool done_;
  fidl::Binding<fuchsia::logger::LogListenerSafe> binding_;
  std::vector<std::string> messages_;
};

class TestSysmgr : public ::gtest::RealLoopFixture {
 protected:
  // Verifies that messages with the given tags match |expected_patterns|.
  void VerifyLogs(const fuchsia::logger::LogPtr& log_ptr, std::vector<std::string> tags,
                  std::vector<std::string> expected_patterns) {
    fidl::InterfaceHandle<fuchsia::logger::LogListenerSafe> listener_handle;
    SimpleLogCollector collector(listener_handle.NewRequest(), dispatcher());
    auto filter_options = fuchsia::logger::LogFilterOptions::New();
    filter_options->tags = tags;

    // FIXME(45589) can't use DumpLogs without a fence
    log_ptr->ListenSafe(std::move(listener_handle), std::move(filter_options));
    RunLoopUntil([&collector, &expected_patterns] {
      return (collector.messages_.size() == expected_patterns.size());
    });

    ASSERT_EQ(expected_patterns.size(), collector.messages_.size());
    auto expected = expected_patterns.begin();
    auto observed = collector.messages_.begin();
    while (expected != expected_patterns.end() || observed != collector.messages_.end()) {
      ASSERT_THAT(*observed, ::testing::MatchesRegex(*expected));
      expected++;
      observed++;
    }
    ASSERT_EQ(expected, expected_patterns.end());
    ASSERT_EQ(observed, collector.messages_.end());
  }
};

TEST_F(TestSysmgr, ServiceStartup) {
  // wait for sysmgr to destroy existing environments.
  RunLoopUntil([] {
    files::Glob glob(kGlob);
    return glob.size() == 0;
  });

  auto environment_services = sys::ComponentContext::CreateAndServeOutgoingDirectory()->svc();
  fuchsia::sys::LaunchInfo launch_info{
      .url = "fuchsia-pkg://fuchsia.com/sysmgr-integration-tests#meta/sysmgr.cmx"};
  fuchsia::sys::ServiceListPtr additional_services = std::make_unique<fuchsia::sys::ServiceList>();
  fuchsia::sys::LauncherPtr launcher;
  environment_services->Connect(launcher.NewRequest());

  fuchsia::sys::ComponentControllerPtr contoller;
  launcher->CreateComponent(std::move(launch_info), contoller.NewRequest());

  bool sysmgr_alive = true;
  contoller.events().OnTerminated = [&](int64_t return_code,
                                        fuchsia::sys::TerminationReason termination_reason) {
    fprintf(stderr, "sysmgr died: %s\n",
            sys::HumanReadableTerminationReason(termination_reason).c_str());
    sysmgr_alive = false;
  };

  // wait for sysmgr to create environment.
  std::string path;
  RunLoopUntil([&] {
    if (!sysmgr_alive) {
      return true;  // end loop if sysmgr died.
    }
    files::Glob glob(kGlob);
    if (glob.size() == 1u) {
      path = std::string(*glob.begin());
      return true;
    }
    return false;
  });

  ASSERT_TRUE(sysmgr_alive);
  // connect to nested environment's svc.
  zx::channel directory;
  auto sysmgr_svc = sys::ServiceDirectory::CreateWithRequest(&directory);

  ASSERT_EQ(ZX_OK, fdio_open(path.c_str(),
                             fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
                             directory.release()));

  std::string response;
  ::test::sysmgr::InterfaceSyncPtr interface_ptr;
  ASSERT_EQ(ZX_OK, sysmgr_svc->Connect(interface_ptr.NewRequest()));
  ASSERT_EQ(ZX_OK, interface_ptr->Ping(&response));

  EXPECT_EQ("test_sysmgr_service_startup", response);

  {
    // sysmgr should create the environment with parent services inherited.
    fidl::StringPtr echo_msg = "test string for echo";
    fidl::examples::echo::EchoSyncPtr echo_ptr;
    ASSERT_EQ(ZX_OK, sysmgr_svc->Connect(echo_ptr.NewRequest()));

    fidl::StringPtr response;
    ASSERT_EQ(ZX_OK, echo_ptr->EchoString(echo_msg, &response));
    EXPECT_EQ(echo_msg, response);
  }
}

}  // namespace
}  // namespace test
}  // namespace sysmgr
