/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/base/logging.h"

#include <stdint.h>

#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>

#include "perfetto/ext/base/crash_keys.h"
#include "perfetto/ext/base/string_utils.h"
#include "src/base/log_ring_buffer.h"
#include "test/gtest_and_gmock.h"

namespace perfetto {
namespace base {
namespace {

char g_last_line[256];

TEST(LoggingTest, Basic) {
  SetLogMessageCallback(nullptr);
  LogMessage(kLogDebug, "file.cc", 100, "test message %d", 1);

  SetLogMessageCallback(+[](LogMessageCallbackArgs log) {
    sprintf(g_last_line, "%d:%s:%d:%s", log.level, log.filename, log.line,
            log.message);
  });

  g_last_line[0] = 0;
  LogMessage(kLogDebug, "file.cc", 101, "test message %d", 2);
  ASSERT_STREQ(g_last_line, "0:file.cc:101:test message 2");

  g_last_line[0] = 0;
  SetLogMessageCallback(nullptr);
  LogMessage(kLogDebug, "file.cc", 102, "test message %d", 3);
  ASSERT_STREQ(g_last_line, "");
}

TEST(LogRingBufferTest, SimpleCases) {
  char buf[4096];
  memset(buf, 'x', sizeof(buf));  // Deliberately not 0-initialized.

  LogRingBuffer lrb;
  EXPECT_EQ(0u, lrb.Read(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "");

  // Append one entry and read back.
  lrb.Append("tstamp1,", "src1.cc", "message1");
  EXPECT_EQ(25u, lrb.Read(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "tstamp1,src1.cc message1\n");

  lrb.Append("tstamp2,", "src2.cc", "message2");
  EXPECT_EQ(50u, lrb.Read(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "tstamp1,src1.cc message1\ntstamp2,src2.cc message2\n");
}

TEST(LogRingBufferTest, Truncation) {
  // Append a long entry that overflows the event slot.
  std::string long_msg;
  long_msg.resize(kLogRingBufMsgLen * 2);
  for (size_t i = 0; i < long_msg.size(); i++)
    long_msg[i] = static_cast<char>('a' + (i % 27));
  LogRingBuffer lrb;
  lrb.Append("A", "B", StringView(long_msg));

  // Check that it gets truncated with no side effects.
  char buf[4096];
  memset(buf, 'x', sizeof(buf));  // Deliberately not 0-initialized.
  auto expected = "AB " + long_msg.substr(0, kLogRingBufMsgLen - 4) + "\n";
  EXPECT_EQ(expected.size(), lrb.Read(buf, sizeof(buf)));
  EXPECT_EQ(buf, expected);

  // Append a short message and check everything still works.
  lrb.Append("X", "Y", "foo");
  EXPECT_EQ(expected.size() + 7, lrb.Read(buf, sizeof(buf)));
  EXPECT_EQ(buf, expected + "XY foo\n");
}

TEST(LogRingBufferTest, Wrapping) {
  LogRingBuffer lrb;

  std::vector<std::string> expected_logs;
  for (uint32_t i = 0; i < 128; i++) {
    std::string id = std::to_string(i);
    std::string tstamp = "tstamp" + id + ",";
    std::string src = "src";
    std::string msg;
    msg.resize(1 + (i % 16));
    for (size_t c = 0; c < msg.size(); c++)
      msg[c] = static_cast<char>('a' + c);
    lrb.Append(StringView(tstamp), StringView(src), StringView(msg));
    auto expected_log =
        (tstamp + src + " " + msg).substr(0, kLogRingBufMsgLen) + "\n";
    expected_logs.emplace_back(expected_log);
  }

  std::string expected;
  for (size_t i = expected_logs.size() - kLogRingBufEntries;
       i < expected_logs.size(); i++) {
    expected += expected_logs[i];
  }

  char buf[kLogRingBufMsgLen * kLogRingBufEntries];
  memset(buf, 'x', sizeof(buf));  // Deliberately not 0-initialized.
  lrb.Read(buf, sizeof(buf));
  EXPECT_EQ(buf, expected);

  // Do a partial readback which will cause output truncation.
  lrb.Read(buf, 127);
  EXPECT_EQ(buf, expected.substr(0, 127 - 1));  // - 1 for the NUL terminator.
}

// Writes concurrently into the ring buffer and check that all the events are
// seen in some order.
TEST(LogRingBufferTest, MultiThreadedWrites) {
  LogRingBuffer lrb;

  std::vector<std::thread> threads;
  const size_t kNumThreads = 8;

  std::mutex mutex;
  std::condition_variable cond;
  bool sync_start = false;

  auto thread_main = [&](size_t thread_idx) {
    std::unique_lock<std::mutex> lock(mutex);
    cond.wait(lock, [&] { return sync_start; });

    std::string tstamp = "ts" + std::to_string(thread_idx) + ",";
    std::string src = "src";
    std::string msg(thread_idx + 1, '.');  // A variable number of dots.
    lrb.Append(StringView(tstamp), StringView(src), StringView(msg));
  };

  std::vector<std::string> expected_events;
  for (size_t i = 0; i < kNumThreads; i++) {
    threads.emplace_back(thread_main, i);
    std::string id = std::to_string(i);
    expected_events.emplace_back("ts" + id + ",src " + std::string(i + 1, '.'));
  }

  // Unlock all the threads as close as possible to maximize races.
  {
    std::unique_lock<std::mutex> lock(mutex);
    sync_start = true;
    cond.notify_all();
  }

  for (auto& thread : threads)
    thread.join();

  char buf[kLogRingBufEntries * 40];
  memset(buf, 'x', sizeof(buf));  // Deliberately not 0-initialized.
  lrb.Read(buf, sizeof(buf));

  std::vector<std::string> actual_events = SplitString(buf, "\n");
  EXPECT_THAT(actual_events,
              testing::UnorderedElementsAreArray(expected_events));
}

TEST(CrashKeysTest, SetClearAndLongKeys) {
  UnregisterAllCrashKeysForTesting();

  char buf[1024];
  memset(buf, 'x', sizeof(buf));
  EXPECT_EQ(0u, SerializeCrashKeys(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "");

  CrashKey k1("key1");
  CrashKey k2("key2");
  CrashKey k3("key3");
  CrashKey k4("key4");

  k1.Set(0);
  k1.Clear();

  k2.Set(42);

  k3.Set("xx");
  k3.Clear();

  k4.Set("value");

  EXPECT_EQ(21u, SerializeCrashKeys(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "key2: 42\nkey4: value\n");

  EXPECT_EQ(0u, SerializeCrashKeys(buf, 0));

  EXPECT_EQ(0u, SerializeCrashKeys(buf, 1));
  EXPECT_STREQ(buf, "");

  // Test truncated output.
  EXPECT_EQ(5u, SerializeCrashKeys(buf, 5 + 1));
  EXPECT_STREQ(buf, "key2:");

  k2.Clear();

  std::string long_str(1024, 'x');
  k4.Set(StringView(long_str));

  EXPECT_EQ(6 + kCrashKeyMaxStrSize, SerializeCrashKeys(buf, sizeof(buf)));
  std::string expected =
      "key4: " + long_str.substr(0, kCrashKeyMaxStrSize - 1) + "\n";
  EXPECT_EQ(buf, expected);

  UnregisterAllCrashKeysForTesting();
}

TEST(CrashKeysTest, ScopedSet) {
  UnregisterAllCrashKeysForTesting();

  char buf[1024];
  memset(buf, 'x', sizeof(buf));

  CrashKey k1("key1");
  CrashKey k2("key2");

  auto scoped_key = k1.SetScoped(42);
  EXPECT_GT(SerializeCrashKeys(buf, sizeof(buf)), 0u);
  EXPECT_STREQ(buf, "key1: 42\n");

  {
    auto scoped_key2 = k2.SetScoped("foo");
    EXPECT_GT(SerializeCrashKeys(buf, sizeof(buf)), 0u);
    EXPECT_STREQ(buf, "key1: 42\nkey2: foo\n");
  }

  EXPECT_GT(SerializeCrashKeys(buf, sizeof(buf)), 0u);
  EXPECT_STREQ(buf, "key1: 42\n");

  k1.Clear();
  EXPECT_EQ(0u, SerializeCrashKeys(buf, sizeof(buf)));
  EXPECT_STREQ(buf, "");

  UnregisterAllCrashKeysForTesting();
}

}  // namespace
}  // namespace base
}  // namespace perfetto
