// Copyright 2020 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 "../session.h"

#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/trace-provider/provider.h>
#include <lib/trace/event.h>

#include <zxtest/zxtest.h>

namespace trace {
namespace {

static constexpr size_t kBufferSize = 65535;
static constexpr size_t kFifoCount = 4;
static const std::string kAlertName = "alert_name";
static const std::string kAlertNameMin = "a";
static const std::string kAlertNameMax = "alert_name_max";

void CheckAlertNameAndZeroPadding(const std::string& alert_name, const void* p, size_t size) {
  const char* pchar = reinterpret_cast<const char*>(p);
  for (size_t index = 0; size > 0; --size, ++pchar, ++index) {
    if (index >= alert_name.size()) {
      ASSERT_EQ(0, *pchar);
      continue;
    }

    ASSERT_EQ(alert_name[index], *pchar);
  }
}

// Tests that alerts are send over the fifo.
TEST(SessionTest, AlertSent) {
  async::Loop loop{&kAsyncLoopConfigNoAttachToCurrentThread};

  zx::vmo buffer;
  zx_status_t status = zx::vmo::create(kBufferSize, 0, &buffer);
  ASSERT_EQ(ZX_OK, status);

  zx::fifo fifo_provider;
  zx::fifo fifo_manager;
  status = zx::fifo::create(kFifoCount, sizeof(trace_provider_packet_t), 0, &fifo_provider,
                            &fifo_manager);
  ASSERT_EQ(ZX_OK, status);

  std::vector<std::string> categories;
  categories.push_back("test_category");

  internal::Session::InitializeEngine(loop.dispatcher(), TRACE_BUFFERING_MODE_CIRCULAR,
                                      std::move(buffer), std::move(fifo_provider), categories);

  // Not started yet.
  TRACE_ALERT("test_category", kAlertName.c_str());

  trace_provider_packet_t packet;
  size_t actual;
  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_ERR_SHOULD_WAIT, status);

  internal::Session::StartEngine(TRACE_START_CLEAR_ENTIRE_BUFFER);

  // No alerts since start.
  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_ERR_SHOULD_WAIT, status);

  // Alert name neither min nor max length.
  TRACE_ALERT("test_category", kAlertName.c_str());

  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_OK, status);
  ASSERT_EQ(1, actual);

  ASSERT_EQ(TRACE_PROVIDER_ALERT, packet.request);
  CheckAlertNameAndZeroPadding(
      kAlertName, &packet.data16,
      sizeof(packet.data16) + sizeof(packet.data32) + sizeof(packet.data64));

  // Alert name of min length (1).
  TRACE_ALERT("test_category", kAlertNameMin.c_str());

  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_OK, status);
  ASSERT_EQ(1, actual);

  ASSERT_EQ(TRACE_PROVIDER_ALERT, packet.request);
  CheckAlertNameAndZeroPadding(
      kAlertNameMin, &packet.data16,
      sizeof(packet.data16) + sizeof(packet.data32) + sizeof(packet.data64));

  // Alert name of max length (14).
  TRACE_ALERT("test_category", kAlertNameMax.c_str());

  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_OK, status);
  ASSERT_EQ(1, actual);

  ASSERT_EQ(TRACE_PROVIDER_ALERT, packet.request);
  CheckAlertNameAndZeroPadding(
      kAlertNameMax, &packet.data16,
      sizeof(packet.data16) + sizeof(packet.data32) + sizeof(packet.data64));

  // Disabled category.
  TRACE_ALERT("other_category", kAlertName.c_str());

  status = fifo_manager.read(sizeof(trace_provider_packet_t), &packet, 1, &actual);
  ASSERT_EQ(ZX_ERR_SHOULD_WAIT, status);

  loop.RunUntilIdle();
  loop.Shutdown();
}

}  // namespace
}  // namespace trace
