// Copyright (c) 2011 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/synchronization/atomic_flag.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/gtest_util.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {

namespace {

void ExpectSetFlagDeath(AtomicFlag* flag) {
  ASSERT_TRUE(flag);
  EXPECT_DCHECK_DEATH(flag->Set());
}

// Busy waits (to explicitly avoid using synchronization constructs that would
// defeat the purpose of testing atomics) until |tested_flag| is set and then
// verifies that non-atomic |*expected_after_flag| is true and sets |*done_flag|
// before returning if it's non-null.
void BusyWaitUntilFlagIsSet(AtomicFlag* tested_flag, bool* expected_after_flag,
                            AtomicFlag* done_flag) {
  while (!tested_flag->IsSet())
    PlatformThread::YieldCurrentThread();

  EXPECT_TRUE(*expected_after_flag);
  if (done_flag)
    done_flag->Set();
}

}  // namespace

TEST(AtomicFlagTest, SimpleSingleThreadedTest) {
  AtomicFlag flag;
  ASSERT_FALSE(flag.IsSet());
  flag.Set();
  ASSERT_TRUE(flag.IsSet());
}

TEST(AtomicFlagTest, DoubleSetTest) {
  AtomicFlag flag;
  ASSERT_FALSE(flag.IsSet());
  flag.Set();
  ASSERT_TRUE(flag.IsSet());
  flag.Set();
  ASSERT_TRUE(flag.IsSet());
}

TEST(AtomicFlagTest, ReadFromDifferentThread) {
  // |tested_flag| is the one being tested below.
  AtomicFlag tested_flag;
  // |expected_after_flag| is used to confirm that sequential consistency is
  // obtained around |tested_flag|.
  bool expected_after_flag = false;
  // |reset_flag| is used to confirm the test flows as intended without using
  // synchronization constructs which would defeat the purpose of exercising
  // atomics.
  AtomicFlag reset_flag;

  Thread thread("AtomicFlagTest.ReadFromDifferentThread");
  ASSERT_TRUE(thread.Start());
  thread.task_runner()->PostTask(FROM_HERE,
                                 BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag,
                                          &expected_after_flag, &reset_flag));

  // To verify that IsSet() fetches the flag's value from memory every time it
  // is called (not just the first time that it is called on a thread), sleep
  // before setting the flag.
  PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));

  // |expected_after_flag| is used to verify that all memory operations
  // performed before |tested_flag| is Set() are visible to threads that can see
  // IsSet().
  expected_after_flag = true;
  tested_flag.Set();

  // Sleep again to give the busy loop time to observe the flag and verify
  // expectations.
  PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));

  // Use |reset_flag| to confirm that the above completed (which the rest of
  // this test assumes).
  while (!reset_flag.IsSet())
    PlatformThread::YieldCurrentThread();

  tested_flag.UnsafeResetForTesting();
  EXPECT_FALSE(tested_flag.IsSet());
  expected_after_flag = false;

  // Perform the same test again after the controlled UnsafeResetForTesting(),
  // |thread| is guaranteed to be synchronized past the
  // |UnsafeResetForTesting()| call when the task runs per the implicit
  // synchronization in the post task mechanism.
  thread.task_runner()->PostTask(FROM_HERE,
                                 BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag,
                                          &expected_after_flag, nullptr));

  PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));

  expected_after_flag = true;
  tested_flag.Set();

  // The |thread|'s destructor will block until the posted task completes, so
  // the test will time out if it fails to see the flag be set.
}

TEST(AtomicFlagTest, SetOnDifferentSequenceDeathTest) {
  // Checks that Set() can't be called from another sequence after being called
  // on this one. AtomicFlag should die on a DCHECK if Set() is called again
  // from another sequence.

  // Note: flag must be declared before the Thread so that its destructor runs
  // later. Otherwise there's a race between destructing flag and running
  // ExpectSetFlagDeath.
  AtomicFlag flag;

  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  Thread t("AtomicFlagTest.SetOnDifferentThreadDeathTest");
  ASSERT_TRUE(t.Start());
  EXPECT_TRUE(t.WaitUntilThreadStarted());

  flag.Set();
  t.task_runner()->PostTask(FROM_HERE, BindOnce(&ExpectSetFlagDeath, &flag));
}

}  // namespace base
