// Copyright 2021 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 "src/sys/fuzzing/realmfuzzer/engine/coverage-data-provider-client.h"

#include <fuchsia/fuzzer/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <zircon/status.h>

#include <memory>

#include <gtest/gtest.h>

#include "src/sys/fuzzing/common/async-deque.h"
#include "src/sys/fuzzing/common/async-eventpair.h"
#include "src/sys/fuzzing/common/async-types.h"
#include "src/sys/fuzzing/common/options.h"
#include "src/sys/fuzzing/common/testing/async-test.h"
#include "src/sys/fuzzing/realmfuzzer/engine/coverage-data.h"
#include "src/sys/fuzzing/realmfuzzer/testing/module.h"

namespace fuzzing {

using fuchsia::fuzzer::InstrumentedProcess;

// Test fixtures.

class CoverageDataProviderImpl final : public fuchsia::fuzzer::CoverageDataProvider {
 public:
  explicit CoverageDataProviderImpl(ExecutorPtr executor)
      : binding_(this), executor_(std::move(executor)), options_(MakeOptions()) {}
  ~CoverageDataProviderImpl() = default;

  OptionsPtr options() const { return options_; }

  zx_status_t Bind(zx::channel channel) {
    return binding_.Bind(std::move(channel), executor_->dispatcher());
  }

  void Pend(CoverageData coverage_data) {
    auto status = pending_.Send(std::move(coverage_data));
    FX_CHECK(status == ZX_OK) << zx_status_get_string(status);
  }

  void SetOptions(Options options) override { *options_ = std::move(options); }

  void GetCoverageData(GetCoverageDataCallback callback) override {
    auto task =
        pending_.Receive()
            .and_then([callback = std::move(callback)](CoverageData& coverage_data) mutable {
              callback(std::move(coverage_data));
              return fpromise::ok();
            })
            .wrap_with(scope_);
    executor_->schedule_task(std::move(task));
  }

  void Unbind() { binding_.Unbind(); }

 private:
  fidl::Binding<CoverageDataProvider> binding_;
  ExecutorPtr executor_;
  OptionsPtr options_;
  AsyncDeque<CoverageData> pending_;
  Scope scope_;
};

class CoverageDataProviderClientTest : public AsyncTest {
 protected:
  void SetUp() override {
    AsyncTest::SetUp();
    provider_ = std::make_unique<CoverageDataProviderImpl>(executor());
  }

  std::unique_ptr<CoverageDataProviderClient> GetProviderClient() {
    auto provider_client = std::make_unique<CoverageDataProviderClient>(executor());
    zx::channel ch1, ch2;
    auto status = zx::channel::create(0, &ch1, &ch2);
    FX_CHECK(status == ZX_OK) << zx_status_get_string(status);
    status = provider_->Bind(std::move(ch1));
    FX_CHECK(status == ZX_OK) << zx_status_get_string(status);
    status = provider_client->Bind(std::move(ch2));
    FX_CHECK(status == ZX_OK) << zx_status_get_string(status);
    return provider_client;
  }

  OptionsPtr GetOptions() const { return provider_->options(); }

  void Pend(CoverageData coverage_data) { provider_->Pend(std::move(coverage_data)); }

 private:
  std::unique_ptr<CoverageDataProviderImpl> provider_;
};

// Unit tests.

TEST_F(CoverageDataProviderClientTest, SetOptions) {
  auto provider_client = GetProviderClient();

  auto options = MakeOptions();
  options->set_runs(3);
  provider_client->Configure(options);
  RunOnce();

  EXPECT_EQ(GetOptions()->runs(), 3U);
}

TEST_F(CoverageDataProviderClientTest, GetProcess) {
  auto provider_client = GetProviderClient();
  CoverageData coverage_data;
  FUZZING_EXPECT_OK(provider_client->GetCoverageData(), &coverage_data);

  auto self = zx::process::self();
  zx_info_handle_basic_t info;
  EXPECT_EQ(self->get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr), ZX_OK);
  auto koid = info.koid;

  zx::process process;
  EXPECT_EQ(self->duplicate(ZX_RIGHT_SAME_RIGHTS, &process), ZX_OK);
  AsyncEventPair eventpair(executor());
  InstrumentedProcess sent{
      .eventpair = eventpair.Create(),
      .process = std::move(process),
  };
  Pend(CoverageData::WithInstrumented(std::move(sent)));
  RunUntilIdle();

  ASSERT_TRUE(coverage_data.is_instrumented());
  auto& received = coverage_data.instrumented();
  EXPECT_EQ(received.process.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr),
            ZX_OK);
  EXPECT_EQ(koid, info.koid);
  FUZZING_EXPECT_OK(eventpair.WaitFor(kSync));
  EXPECT_EQ(received.eventpair.signal_peer(0, kSync), ZX_OK);
  RunUntilIdle();
}

TEST_F(CoverageDataProviderClientTest, GetModule) {
  auto provider_client = GetProviderClient();
  CoverageData coverage_data;

  zx::vmo counters;
  char name[ZX_MAX_NAME_LEN];

  // Send multiple, and verify they arrive in order.
  FakeRealmFuzzerModule module1(1);
  EXPECT_EQ(module1.Share(0x1111, &counters), ZX_OK);
  Pend(CoverageData::WithInline8bitCounters(std::move(counters)));

  FakeRealmFuzzerModule module2(1);
  EXPECT_EQ(module2.Share(0x2222, &counters), ZX_OK);
  Pend(CoverageData::WithInline8bitCounters(std::move(counters)));

  FUZZING_EXPECT_OK(provider_client->GetCoverageData(), &coverage_data);
  RunUntilIdle();
  ASSERT_TRUE(coverage_data.is_inline_8bit_counters());
  auto& counters1 = coverage_data.inline_8bit_counters();
  EXPECT_EQ(counters1.get_property(ZX_PROP_NAME, name, sizeof(name)), ZX_OK);
  EXPECT_EQ(GetTargetId(name), 0x1111U);
  EXPECT_EQ(GetModuleId(name), module1.id());

  FUZZING_EXPECT_OK(provider_client->GetCoverageData(), &coverage_data);
  RunUntilIdle();
  ASSERT_TRUE(coverage_data.is_inline_8bit_counters());
  auto& counters2 = coverage_data.inline_8bit_counters();
  EXPECT_EQ(counters2.get_property(ZX_PROP_NAME, name, sizeof(name)), ZX_OK);
  EXPECT_EQ(GetTargetId(name), 0x2222U);
  EXPECT_EQ(GetModuleId(name), module2.id());

  // Intentionally drop a |GetCoverageData| future and ensure no data is lost.
  FakeRealmFuzzerModule module3(3);
  {
    auto dropped = provider_client->GetCoverageData();
    RunOnce();
    EXPECT_EQ(module3.Share(0x1111, &counters), ZX_OK);
    Pend(CoverageData::WithInline8bitCounters(std::move(counters)));
  }

  FUZZING_EXPECT_OK(provider_client->GetCoverageData(), &coverage_data);
  RunUntilIdle();
  ASSERT_TRUE(coverage_data.is_inline_8bit_counters());
  auto& counters3 = coverage_data.inline_8bit_counters();
  EXPECT_EQ(counters3.get_property(ZX_PROP_NAME, name, sizeof(name)), ZX_OK);
  EXPECT_EQ(GetTargetId(name), 0x1111U);
  EXPECT_EQ(GetModuleId(name), module3.id());
}

}  // namespace fuzzing
