// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/debuglog.h>
#include <lib/unittest/unittest.h>
#include <zircon/types.h>

#include <ktl/unique_ptr.h>

#include "debuglog_internal.h"

namespace {

bool log_format() {
  BEGIN_TEST;

  fbl::AllocChecker ac;
  ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
  ASSERT_TRUE(ac.check(), "");

  char msg[] = "Hello World";

  log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)});

  dlog_header* header = reinterpret_cast<dlog_header*>(log->data);

  EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
  EXPECT_EQ(0, header->flags);
  EXPECT_EQ(ZX_KOID_INVALID, header->pid);
  EXPECT_NE(ZX_KOID_INVALID, header->tid);
  ASSERT_EQ(12, header->datalen);

  uint8_t* msg_bytes = log->data + sizeof(dlog_header);

  EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, sizeof(msg));

  END_TEST;
}

bool log_wrap() {
  BEGIN_TEST;

  fbl::AllocChecker ac;
  ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
  ASSERT_TRUE(ac.check(), "");

  char msg[] = "Hello World";
  const size_t kTruncateTarget = 5;  // An unaligned length somewhere in the middle of msg.
  const size_t pad = ALIGN4_TRUNC(DLOG_SIZE - sizeof(dlog_header) - kTruncateTarget);

  // We need to trigger some writes, but we don't care what we write, so we just need a buffer large
  // enough to be copied from. Doesn't much matter what's in it.
  char dummy[DLOG_MAX_DATA]{0};

  for (size_t to_write = pad; to_write;) {
    size_t write = to_write - sizeof(dlog_header);
    write = write > DLOG_MAX_DATA ? DLOG_MAX_DATA : write;

    log->write(DEBUGLOG_WARNING, 0, {dummy, write});
    to_write -= write + sizeof(dlog_header);
  }

  EXPECT_EQ(pad, log->head);

  log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)});

  dlog_header* header = reinterpret_cast<dlog_header*>(log->data + pad);

  EXPECT_EQ(DEBUGLOG_WARNING, header->severity);
  EXPECT_EQ(0, header->flags);
  EXPECT_EQ(ZX_KOID_INVALID, header->pid);
  EXPECT_NE(ZX_KOID_INVALID, header->tid);
  ASSERT_EQ(sizeof(msg), header->datalen);

  uint8_t* msg_bytes = log->data + pad + sizeof(dlog_header);

  const size_t kTruncatedSize = DLOG_SIZE - pad - sizeof(dlog_header);

  EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[0]), msg_bytes, kTruncatedSize);
  EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(&msg[8]), log->data, sizeof(msg) - kTruncatedSize);

  END_TEST;
}

// Read a record from the debuglog and verify its fields.
bool log_reader_read() {
  BEGIN_TEST;

  fbl::AllocChecker ac;
  ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
  ASSERT_TRUE(ac.check());

  const zx_time_t now = current_time();

  char msg[] = "Message!";
  ASSERT_EQ(ZX_OK, log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)}));

  DlogReader reader;
  reader.InitializeForTest(log.get());
  size_t got;
  dlog_record_t rec{};
  ASSERT_EQ(ZX_OK, reader.Read(0, &rec, &got));
  ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);
  EXPECT_EQ(0u, rec.hdr.preamble);
  EXPECT_EQ(sizeof(msg), rec.hdr.datalen);
  EXPECT_EQ(DEBUGLOG_WARNING, rec.hdr.severity);
  EXPECT_EQ(0, rec.hdr.flags);
  EXPECT_GE(rec.hdr.timestamp, now);
  EXPECT_EQ(0ull, rec.hdr.pid);
  EXPECT_EQ(Thread::Current::Get()->tid(), rec.hdr.tid);

  reader.Disconnect();

  END_TEST;
}

bool log_reader_rollout() {
  BEGIN_TEST;

  fbl::AllocChecker ac;
  ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
  ASSERT_TRUE(ac.check(), "");

  DlogReader reader;
  reader.InitializeForTest(log.get());

  char msg[] = "Hello World";

  log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)});

  dlog_record_t rec{};
  size_t got;

  ASSERT_EQ(ZX_OK, reader.Read(0, &rec, &got));
  ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);

  EXPECT_EQ(DEBUGLOG_WARNING, rec.hdr.severity);
  EXPECT_EQ(0u, rec.hdr.preamble);
  EXPECT_EQ(0, rec.hdr.flags);
  EXPECT_EQ(ZX_KOID_INVALID, rec.hdr.pid);
  EXPECT_NE(ZX_KOID_INVALID, rec.hdr.tid);
  ASSERT_EQ(sizeof(msg), rec.hdr.datalen);

  EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(msg), reinterpret_cast<uint8_t*>(rec.data),
                  sizeof(msg));

  for (size_t i = 0; i < DLOG_SIZE; i += sizeof(dlog_header) + sizeof(msg)) {
    log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)});
  }

  ASSERT_EQ(ZX_OK, reader.Read(0, &rec, &got));
  ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);

  EXPECT_EQ(DEBUGLOG_WARNING, rec.hdr.severity);

  // The amount of data rolled out should be snuck in here.
  EXPECT_EQ(sizeof(dlog_header) + sizeof(msg), rec.hdr.preamble);

  EXPECT_EQ(0, rec.hdr.flags);
  EXPECT_EQ(ZX_KOID_INVALID, rec.hdr.pid);
  EXPECT_NE(ZX_KOID_INVALID, rec.hdr.tid);
  ASSERT_EQ(sizeof(msg), rec.hdr.datalen);

  EXPECT_BYTES_EQ(reinterpret_cast<uint8_t*>(msg), reinterpret_cast<uint8_t*>(rec.data),
                  sizeof(msg));

  reader.Disconnect();
  END_TEST;
}

// Test that write fails with an error once the |DLog| has been shutdown.
bool shutdown() {
  BEGIN_TEST;

  fbl::AllocChecker ac;
  ktl::unique_ptr<DLog> log = ktl::make_unique<DLog>(&ac);
  ASSERT_TRUE(ac.check());

  // Write one message and see that it succeeds.
  char msg[] = "Message!";
  ASSERT_EQ(ZX_OK, log->write(DEBUGLOG_WARNING, 0, {msg, sizeof(msg)}));

  // Now ask the DLog to shutdown, write another, see that it fails.
  log->shutdown();
  ASSERT_EQ(ZX_ERR_BAD_STATE, log->write(DEBUGLOG_WARNING, 0, msg));

  // See that there is only one message in the DLog.
  DlogReader reader;
  reader.InitializeForTest(log.get());
  size_t got;
  dlog_record_t rec{};
  ASSERT_EQ(ZX_OK, reader.Read(0, &rec, &got));
  ASSERT_EQ(sizeof(dlog_header) + sizeof(msg), got);
  ASSERT_EQ(ZX_ERR_SHOULD_WAIT, reader.Read(0, &rec, &got));
  reader.Disconnect();

  END_TEST;
}

}  // namespace

#define DEBUGLOG_UNITTEST(fname) UNITTEST(#fname, fname)

UNITTEST_START_TESTCASE(debuglog_tests)
DEBUGLOG_UNITTEST(log_format)
DEBUGLOG_UNITTEST(log_wrap)
DEBUGLOG_UNITTEST(log_reader_read)
DEBUGLOG_UNITTEST(log_reader_rollout)
DEBUGLOG_UNITTEST(shutdown)
UNITTEST_END_TESTCASE(debuglog_tests, "debuglog_tests", "Debuglog test")
