// 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 "debugdata.h"

#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/io.h>
#include <lib/fdio/spawn.h>
#include <lib/fit/defer.h>
#include <lib/ld/testing/mock-debugdata.h>
#include <lib/zx/channel.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <zircon/status.h>

#include <string>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "../sanitizers/fuchsia-io-constants.h"

namespace {

using ::testing::AllOf;
using ::testing::Ne;

constexpr char kTestHelper[] = "/pkg/bin/debugdata-test-helper";

constexpr const char* kHelperPublishCommand = "publish_data";
constexpr const char* kHelperPublishFailCommand = "publish_data_fail";

void RunHelper(const char* mode, const size_t action_count, const fdio_spawn_action_t* fdio_actions,
               int expected_return_code) {
  zx::job test_job;
  zx_status_t status = zx::job::create(*zx::job::default_job(), 0, &test_job);
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
  auto auto_call_kill_job = fit::defer([&test_job]() { test_job.kill(); });

  const char* args[] = {kTestHelper, mode, nullptr};

  zx::process process;
  char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
  status = fdio_spawn_etc(test_job.get(), FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_NAMESPACE,
                          args[0], args, nullptr, action_count, fdio_actions,
                          process.reset_and_get_address(), err_msg);
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);

  status = process.wait_one(ZX_PROCESS_TERMINATED, zx::time::infinite(), nullptr);
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);

  zx_info_process_t proc_info;
  status = process.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr);
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
  ASSERT_EQ(expected_return_code, proc_info.return_code);
}

void RunHelperWithSvc(const char* mode, fidl::ClientEnd<fuchsia_io::Directory> client_end,
                      int expected_return_code) {
  fdio_spawn_action_t fdio_actions[] = {
      fdio_spawn_action_t{
          .action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
          .ns =
              {
                  .prefix = "/svc",
                  .handle = client_end.TakeChannel().release(),
              },
      },
  };
  RunHelper(mode, 1, fdio_actions, expected_return_code);
}

void RunHelperWithoutSvc(const char* mode, int expected_return_code) {
  RunHelper(mode, 0, nullptr, expected_return_code);
}

TEST(DebugDataTests, PublishData) {
  auto mock = std::make_unique<::testing::StrictMock<ld::testing::MockDebugdata>>();
  EXPECT_CALL(*mock,
              Publish(kTestName,
                      AllOf(ld::testing::ObjNameMatches(kTestName),
                            ld::testing::VmoContentsMatch(std::string(
                                reinterpret_cast<const char*>(kTestData), sizeof(kTestData)))),
                      ld::testing::ObjKoidMatches(Ne(ZX_KOID_INVALID))));

  ld::testing::MockSvcDirectory svc_dir;
  ASSERT_NO_FATAL_FAILURE(svc_dir.Init());
  ASSERT_NO_FATAL_FAILURE(svc_dir.AddEntry<fuchsia_debugdata::Publisher>(std::move(mock)));

  fidl::ClientEnd<fuchsia_io::Directory> svc_client_end;
  ASSERT_NO_FATAL_FAILURE(svc_dir.Serve(svc_client_end));

  ASSERT_NO_FATAL_FAILURE(RunHelperWithSvc(kHelperPublishCommand, std::move(svc_client_end), 0));

  zx_status_t status = svc_dir.loop().RunUntilIdle();
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
}

TEST(DebugDataTests, PublishDataWithoutSvc) {
  ASSERT_NO_FATAL_FAILURE(RunHelperWithoutSvc(kHelperPublishFailCommand, 0));
}

TEST(DebugDataTests, PublishDataWithBadSvc) {
  zx::channel client_channel_end, server_channel_end;
  zx_status_t status = zx::channel::create(0, &client_channel_end, &server_channel_end);
  ASSERT_EQ(status, ZX_OK) << zx_status_get_string(status);
  fidl::ClientEnd<fuchsia_io::Directory> client_end{
      std::move(client_channel_end),
  };
  server_channel_end.reset();
  ASSERT_NO_FATAL_FAILURE(RunHelperWithSvc(kHelperPublishFailCommand, std::move(client_end), 0));
}

// debugdata.cc cannot use LLCPP (because it allocates with new/delete) so
// instead defines a local set of a few constants and structure definition in
// fuchsia-io-constants.h to call fuchsia.io.Directory/Open(). Confirm that the
// local copy matches the canonical definition here.
static_assert(fuchsia_io_DirectoryOpenOrdinal == fuchsia_io::Directory::Open::kOrdinal);
static_assert(fidl::TypeTraits<fidl::internal::TransactionalRequest<fuchsia_io::Directory::Open>>::
                  kPrimarySize == sizeof(fuchsia_io_DirectoryOpenRequest));

}  // anonymous namespace
