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

#include <fuchsia/test/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>

#include <measure_tape/hlcpp/measure_tape_for_case.h>

#include "lib/fidl/cpp/clone.h"

namespace example {

using fuchsia::test::Case;
using fuchsia::test::Result;

TestSuite::TestSuite(async::Loop* loop, std::vector<TestInput> inputs, Options options)
    : binding_(this), test_inputs_(std::move(inputs)), options_(options), loop_(loop) {
  for (auto& test_input : test_inputs_) {
    if (test_input.disabled) {
      disabled_tests_.insert(test_input.name);
    }
  }
}

void TestSuite::GetTests(::fidl::InterfaceRequest<fuchsia::test::CaseIterator> request) {
  if (options_.close_channel_get_tests) {
    binding_.Close(ZX_ERR_PEER_CLOSED);
    return;
  }
  if (options_.dont_service_get_tests) {
    return;
  }

  std::vector<Case> cases;

  for (auto& test_input : test_inputs_) {
    Case test_case;
    test_case.set_name(test_input.name);
    test_case.set_enabled(!test_input.disabled);
    cases.push_back(std::move(test_case));
  }

  auto service = std::make_unique<CaseIterator>(
      test_inputs_, [this](CaseIterator* ptr) { case_iterator_bindings_.RemoveBinding(ptr); });
  case_iterator_bindings_.AddBinding(std::move(service), std::move(request));
}

void TestSuite::Run(std::vector<fuchsia::test::Invocation> tests,
                    fuchsia::test::RunOptions run_options,
                    fidl::InterfaceHandle<fuchsia::test::RunListener> run_listener) {
  if (options_.close_channel_run) {
    binding_.Close(ZX_ERR_PEER_CLOSED);
    return;
  }
  if (options_.dont_service_run) {
    return;
  }
  fuchsia::test::RunListenerPtr ptr;
  ptr.Bind(std::move(run_listener));
  for (auto& test_invocation : tests) {
    const auto& test_name = test_invocation.name();
    zx::socket stdout_sock, stderr_sock, case_stdout, case_stderr;
    zx::socket::create(0, &stdout_sock, &case_stdout);
    zx::socket::create(0, &stderr_sock, &case_stderr);
    fuchsia::test::CaseListenerPtr case_list_ptr;
    fuchsia::test::StdHandles std_handles;
    std_handles.set_out(std::move(stdout_sock));
    std_handles.set_err(std::move(stderr_sock));
    ptr->OnTestCaseStarted(fidl::Clone(test_invocation), std::move(std_handles),
                           case_list_ptr.NewRequest());
    const bool should_skip_test = ShouldSkipTest(run_options, test_name);
    if (!should_skip_test) {
      std::string msg1 = "log1 for " + test_name + "\n";
      std::string msg2 = "log2 for " + test_name + "\n";
      std::string msg3 = "log3 for " + test_name + "\n";
      zx_status_t status;
      FX_CHECK(ZX_OK == (status = case_stdout.write(0, msg1.data(), msg1.length(), nullptr)))
          << status;
      FX_CHECK(ZX_OK == (status = case_stdout.write(0, msg2.data(), msg2.length(), nullptr)))
          << status;
      FX_CHECK(ZX_OK == (status = case_stdout.write(0, msg3.data(), msg3.length(), nullptr)))
          << status;
      for (auto& test_input : test_inputs_) {
        if (test_input.name == test_name) {
          if (test_input.write_stderr_logs) {
            std::string msg1 = "stderr msg1 for " + test_name + "\n";
            std::string msg2 = "stderr msg2 for " + test_name + "\n";
            FX_CHECK(ZX_OK == (status = case_stderr.write(0, msg1.data(), msg1.length(), nullptr)))
                << status;
            FX_CHECK(ZX_OK == (status = case_stderr.write(0, msg2.data(), msg2.length(), nullptr)))
                << status;
          }
        }
      }
    }
    Result result;

    bool send_finished_event = true;
    for (auto& test_input : test_inputs_) {
      if (test_input.name == test_name) {
        if (test_input.set_result_status) {
          result.set_status(should_skip_test ? fuchsia::test::Status::SKIPPED : test_input.status);
        }
        send_finished_event = !test_input.incomplete_test;
        break;
      }
    }
    if (send_finished_event) {
      case_list_ptr->Finished(std::move(result));
    }
  }
  if (!options_.dont_send_on_finish_event) {
    ptr->OnFinished();
  }
}

bool TestSuite::ShouldSkipTest(const fuchsia::test::RunOptions& run_options,
                               const std::string& test_name) const {
  // Disabled tests are excluded && this test is disabled.
  return run_options.has_include_disabled_tests() && !run_options.include_disabled_tests() &&
         (disabled_tests_.find(test_name) != disabled_tests_.end());
}

fidl::InterfaceRequestHandler<fuchsia::test::Suite> TestSuite::GetHandler() {
  auto handler = [this](fidl::InterfaceRequest<fuchsia::test::Suite> request) {
    binding_.Bind(std::move(request));
  };

  binding_.set_error_handler([this](zx_status_t /*unused*/) { loop_->Shutdown(); });
  return handler;
}

void CaseIterator::GetNext(GetNextCallback callback) {
  const size_t page_overhead = sizeof(fidl_message_header_t) + sizeof(fidl_vector_t);
  const size_t max_bytes = ZX_CHANNEL_MAX_MSG_BYTES - page_overhead;
  size_t bytes_used = 0;

  std::vector<Case> cases;
  // Send the next page of Cases
  for (; iter_ < test_inputs_.end(); iter_++) {
    Case test_case;
    test_case.set_name(iter_->name);
    bytes_used += measure_tape::fuchsia::test::Measure(test_case).num_bytes;
    if (bytes_used > max_bytes) {
      break;
    }
    cases.emplace_back(std::move(test_case));
  }
  callback(std::move(cases));

  if (bytes_used == 0) {
    done_callback_(this);
  }
}

}  // namespace example
