// Copyright (c) 2012 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 "base/threading/non_thread_safe.h"

#include <memory>

#include "base/logging.h"
#include "base/macros.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"

// Duplicated from base/threading/non_thread_safe.h so that we can be
// good citizens there and undef the macro.
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define ENABLE_NON_THREAD_SAFE 1
#else
#define ENABLE_NON_THREAD_SAFE 0
#endif

namespace base {

namespace {

// Simple class to exersice the basics of NonThreadSafe.
// Both the destructor and DoStuff should verify that they were
// called on the same thread as the constructor.
class NonThreadSafeClass : public NonThreadSafe {
 public:
  NonThreadSafeClass() {}

  // Verifies that it was called on the same thread as the constructor.
  void DoStuff() {
    DCHECK(CalledOnValidThread());
  }

  void DetachFromThread() {
    NonThreadSafe::DetachFromThread();
  }

  static void MethodOnDifferentThreadImpl();
  static void DestructorOnDifferentThreadImpl();

 private:
  DISALLOW_COPY_AND_ASSIGN(NonThreadSafeClass);
};

// Calls NonThreadSafeClass::DoStuff on another thread.
class CallDoStuffOnThread : public SimpleThread {
 public:
  explicit CallDoStuffOnThread(NonThreadSafeClass* non_thread_safe_class)
      : SimpleThread("call_do_stuff_on_thread"),
        non_thread_safe_class_(non_thread_safe_class) {
  }

  void Run() override { non_thread_safe_class_->DoStuff(); }

 private:
  NonThreadSafeClass* non_thread_safe_class_;

  DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
};

// Deletes NonThreadSafeClass on a different thread.
class DeleteNonThreadSafeClassOnThread : public SimpleThread {
 public:
  explicit DeleteNonThreadSafeClassOnThread(
      NonThreadSafeClass* non_thread_safe_class)
      : SimpleThread("delete_non_thread_safe_class_on_thread"),
        non_thread_safe_class_(non_thread_safe_class) {
  }

  void Run() override { non_thread_safe_class_.reset(); }

 private:
  std::unique_ptr<NonThreadSafeClass> non_thread_safe_class_;

  DISALLOW_COPY_AND_ASSIGN(DeleteNonThreadSafeClassOnThread);
};

}  // namespace

TEST(NonThreadSafeTest, CallsAllowedOnSameThread) {
  std::unique_ptr<NonThreadSafeClass> non_thread_safe_class(
      new NonThreadSafeClass);

  // Verify that DoStuff doesn't assert.
  non_thread_safe_class->DoStuff();

  // Verify that the destructor doesn't assert.
  non_thread_safe_class.reset();
}

TEST(NonThreadSafeTest, DetachThenDestructOnDifferentThread) {
  std::unique_ptr<NonThreadSafeClass> non_thread_safe_class(
      new NonThreadSafeClass);

  // Verify that the destructor doesn't assert when called on a different thread
  // after a detach.
  non_thread_safe_class->DetachFromThread();
  DeleteNonThreadSafeClassOnThread delete_on_thread(
      non_thread_safe_class.release());

  delete_on_thread.Start();
  delete_on_thread.Join();
}

#if GTEST_HAS_DEATH_TEST || !ENABLE_NON_THREAD_SAFE

void NonThreadSafeClass::MethodOnDifferentThreadImpl() {
  std::unique_ptr<NonThreadSafeClass> non_thread_safe_class(
      new NonThreadSafeClass);

  // Verify that DoStuff asserts in debug builds only when called
  // on a different thread.
  CallDoStuffOnThread call_on_thread(non_thread_safe_class.get());

  call_on_thread.Start();
  call_on_thread.Join();
}

#if ENABLE_NON_THREAD_SAFE
TEST(NonThreadSafeDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
  ASSERT_DEATH({
      NonThreadSafeClass::MethodOnDifferentThreadImpl();
    }, "");
}
#else
TEST(NonThreadSafeTest, MethodAllowedOnDifferentThreadInRelease) {
  NonThreadSafeClass::MethodOnDifferentThreadImpl();
}
#endif  // ENABLE_NON_THREAD_SAFE

void NonThreadSafeClass::DestructorOnDifferentThreadImpl() {
  std::unique_ptr<NonThreadSafeClass> non_thread_safe_class(
      new NonThreadSafeClass);

  // Verify that the destructor asserts in debug builds only
  // when called on a different thread.
  DeleteNonThreadSafeClassOnThread delete_on_thread(
      non_thread_safe_class.release());

  delete_on_thread.Start();
  delete_on_thread.Join();
}

#if ENABLE_NON_THREAD_SAFE
TEST(NonThreadSafeDeathTest, DestructorNotAllowedOnDifferentThreadInDebug) {
  ASSERT_DEATH({
      NonThreadSafeClass::DestructorOnDifferentThreadImpl();
    }, "");
}
#else
TEST(NonThreadSafeTest, DestructorAllowedOnDifferentThreadInRelease) {
  NonThreadSafeClass::DestructorOnDifferentThreadImpl();
}
#endif  // ENABLE_NON_THREAD_SAFE

#endif  // GTEST_HAS_DEATH_TEST || !ENABLE_NON_THREAD_SAFE

// Just in case we ever get lumped together with other compilation units.
#undef ENABLE_NON_THREAD_SAFE

}  // namespace base
