// Copyright 2016 The Chromium 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 <string.h>

#include <memory>

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/trace_event/category_registry.h"
#include "base/trace_event/trace_category.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace trace_event {

// Static initializers are generally forbidden. However, in the past we ran in
// the case of some test using tracing in a static initializer. This test checks
// That the category registry doesn't rely on static initializers itself and is
// functional even if called from another static initializer.
bool Initializer() {
  return CategoryRegistry::kCategoryMetadata &&
         CategoryRegistry::kCategoryMetadata->is_valid();
}
bool g_initializer_check = Initializer();

class TraceCategoryTest : public testing::Test {
 public:
  void SetUp() override { CategoryRegistry::Initialize(); }

  void TearDown() override { CategoryRegistry::ResetForTesting(); }

  static bool GetOrCreateCategoryByName(const char* name, TraceCategory** cat) {
    static LazyInstance<Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
    bool is_new_cat = false;
    *cat = CategoryRegistry::GetCategoryByName(name);
    if (!*cat) {
      AutoLock lock(g_lock.Get());
      is_new_cat = CategoryRegistry::GetOrCreateCategoryLocked(
          name, [](TraceCategory*) {}, cat);
    }
    return is_new_cat;
  }

  static CategoryRegistry::Range GetAllCategories() {
    return CategoryRegistry::GetAllCategories();
  }

  static void TestRaceThreadMain(WaitableEvent* event) {
    TraceCategory* cat = nullptr;
    event->Wait();
    GetOrCreateCategoryByName("__test_race", &cat);
    EXPECT_NE(nullptr, cat);
  }

  static constexpr TraceCategory* GetBuiltinCategoryByName(
      const char* category_group) {
    return CategoryRegistry::GetBuiltinCategoryByName(category_group);
  }
};

TEST_F(TraceCategoryTest, Basic) {
  ASSERT_NE(nullptr, CategoryRegistry::kCategoryMetadata);
  ASSERT_TRUE(CategoryRegistry::kCategoryMetadata->is_valid());
  ASSERT_FALSE(CategoryRegistry::kCategoryMetadata->is_enabled());

  // Metadata category is built-in and should create a new category.
  TraceCategory* cat_meta = nullptr;
  const char* kMetadataName = CategoryRegistry::kCategoryMetadata->name();
  ASSERT_FALSE(GetOrCreateCategoryByName(kMetadataName, &cat_meta));
  ASSERT_EQ(CategoryRegistry::kCategoryMetadata, cat_meta);

  TraceCategory* cat_1 = nullptr;
  ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_ab", &cat_1));
  ASSERT_FALSE(cat_1->is_enabled());
  ASSERT_EQ(0u, cat_1->enabled_filters());
  cat_1->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);
  cat_1->set_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
  ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING |
                TraceCategory::ENABLED_FOR_FILTERING,
            cat_1->state());

  cat_1->set_enabled_filters(129);
  ASSERT_EQ(129u, cat_1->enabled_filters());
  ASSERT_EQ(cat_1, CategoryRegistry::GetCategoryByStatePtr(cat_1->state_ptr()));

  cat_1->clear_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
  ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, cat_1->state());
  ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, *cat_1->state_ptr());
  ASSERT_TRUE(cat_1->is_enabled());

  TraceCategory* cat_2 = nullptr;
  ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_a", &cat_2));
  ASSERT_FALSE(cat_2->is_enabled());
  cat_2->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);

  TraceCategory* cat_2_copy = nullptr;
  ASSERT_FALSE(GetOrCreateCategoryByName("__test_basic_a", &cat_2_copy));
  ASSERT_EQ(cat_2, cat_2_copy);

  TraceCategory* cat_3 = nullptr;
  ASSERT_TRUE(
      GetOrCreateCategoryByName("__test_basic_ab,__test_basic_a", &cat_3));
  ASSERT_FALSE(cat_3->is_enabled());
  ASSERT_EQ(0u, cat_3->enabled_filters());

  int num_test_categories_seen = 0;
  for (const TraceCategory& cat : GetAllCategories()) {
    if (strcmp(cat.name(), kMetadataName) == 0)
      ASSERT_TRUE(CategoryRegistry::IsMetaCategory(&cat));

    if (strncmp(cat.name(), "__test_basic_", 13) == 0) {
      ASSERT_FALSE(CategoryRegistry::IsMetaCategory(&cat));
      num_test_categories_seen++;
    }
  }
  ASSERT_EQ(3, num_test_categories_seen);
  ASSERT_TRUE(g_initializer_check);
}

// Tries to cover the case of multiple threads creating the same category
// simultaneously. Should never end up with distinct entries with the same name.
#if defined(OS_FUCHSIA)
// TODO(crbug.com/738275): This is flaky on Fuchsia.
#define MAYBE_ThreadRaces DISABLED_ThreadRaces
#else
#define MAYBE_ThreadRaces ThreadRaces
#endif
TEST_F(TraceCategoryTest, MAYBE_ThreadRaces) {
  const int kNumThreads = 32;
  std::unique_ptr<Thread> threads[kNumThreads];
  for (int i = 0; i < kNumThreads; i++) {
    threads[i].reset(new Thread("test thread"));
    threads[i]->Start();
  }
  WaitableEvent sync_event(WaitableEvent::ResetPolicy::MANUAL,
                           WaitableEvent::InitialState::NOT_SIGNALED);
  for (int i = 0; i < kNumThreads; i++) {
    threads[i]->task_runner()->PostTask(
        FROM_HERE, BindOnce(&TestRaceThreadMain, Unretained(&sync_event)));
  }
  sync_event.Signal();
  for (int i = 0; i < kNumThreads; i++)
    threads[i]->Stop();

  int num_times_seen = 0;
  for (const TraceCategory& cat : GetAllCategories()) {
    if (strcmp(cat.name(), "__test_race") == 0)
      num_times_seen++;
  }
  ASSERT_EQ(1, num_times_seen);
}

// Tests getting trace categories by name at compile-time.
TEST_F(TraceCategoryTest, GetCategoryAtCompileTime) {
  static_assert(GetBuiltinCategoryByName("nonexistent") == nullptr,
                "nonexistent found");
#if defined(OS_WIN) && defined(COMPONENT_BUILD)
  static_assert(GetBuiltinCategoryByName("toplevel") == nullptr,
                "toplevel found");
#else
  static_assert(GetBuiltinCategoryByName("toplevel") != nullptr,
                "toplevel not found");
#endif
}

}  // namespace trace_event
}  // namespace base
