// 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 log_sock;
    zx::socket test_case_log;
    zx::socket::create(0, &log_sock, &test_case_log);
    fuchsia::test::CaseListenerPtr case_list_ptr;
    ptr->OnTestCaseStarted(fidl::Clone(test_invocation), std::move(log_sock),
                           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 = test_case_log.write(0, msg1.data(), msg1.length(), nullptr)))
          << status;
      FX_CHECK(ZX_OK == (status = test_case_log.write(0, msg2.data(), msg2.length(), nullptr)))
          << status;
      FX_CHECK(ZX_OK == (status = test_case_log.write(0, msg3.data(), msg3.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.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
