summaryrefslogtreecommitdiff
path: root/base/sequence_checker_unittest.cc
diff options
context:
space:
mode:
authorJay Civelli <jcivelli@google.com>2017-03-22 17:31:44 -0700
committerHidehiko Abe <hidehiko@google.com>2017-11-28 15:02:44 +0900
commit3a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6 (patch)
tree48410da6c48424c0ee9ef43a63557dcf8d14cc43 /base/sequence_checker_unittest.cc
parent09d94c97aef7397204249ca2b173e04fa3723ca3 (diff)
downloadlibchrome-3a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6.tar.gz
libchrome: Uprev the library to r456626 from Chromium
Pulled the latest and greatest version of libchrome from Chromium. The merge was done against r456626 which corresponds to git commit 08266b3fca707804065a2cfd60331722ade41969 of Mar 14, 2017 Notable changes are: - FOR_EACH_OBSERVER macro removed (replaced by use of C++ 11 range-base for loop) - base::Values no more FundamentalValue - stl_util moved to base namespace - some scoped pointers removed in crypto/ in favor of BoringSSL UniquePtr. - path() accessor renamed to GetPath() in ScopedTempDir (and other classes) - introduction of base::CallbackOnce Test: All unit-tests should still pass. Change-Id: I180f9defc7607f462389fae17701fff553c4a2d0
Diffstat (limited to 'base/sequence_checker_unittest.cc')
-rw-r--r--base/sequence_checker_unittest.cc419
1 files changed, 171 insertions, 248 deletions
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
index 196bb1cc79..86e9298d97 100644
--- a/base/sequence_checker_unittest.cc
+++ b/base/sequence_checker_unittest.cc
@@ -2,334 +2,257 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/sequence_checker.h"
-
#include <stddef.h>
#include <memory>
-#include <utility>
+#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/logging.h"
+#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/sequence_checker_impl.h"
+#include "base/sequence_token.h"
#include "base/single_thread_task_runner.h"
#include "base/test/sequenced_worker_pool_owner.h"
-#include "base/threading/thread.h"
+#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
-// Duplicated from base/sequence_checker.h so that we can be good citizens
-// there and undef the macro.
-#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
-#define ENABLE_SEQUENCE_CHECKER 1
-#else
-#define ENABLE_SEQUENCE_CHECKER 0
-#endif
-
namespace base {
namespace {
-const size_t kNumWorkerThreads = 3;
+constexpr size_t kNumWorkerThreads = 3;
-// Simple class to exercise the basics of SequenceChecker.
-// DoStuff should verify that it's called on a valid sequenced thread.
-// SequenceCheckedObject can be destroyed on any thread (like WeakPtr).
-class SequenceCheckedObject {
+// Runs a callback on another thread.
+class RunCallbackThread : public SimpleThread {
public:
- SequenceCheckedObject() {}
- ~SequenceCheckedObject() {}
-
- // Verifies that it was called on the same thread as the constructor.
- void DoStuff() {
- DCHECK(sequence_checker_.CalledOnValidSequencedThread());
- }
-
- void DetachFromSequence() {
- sequence_checker_.DetachFromSequence();
+ explicit RunCallbackThread(const Closure& callback)
+ : SimpleThread("RunCallbackThread"), callback_(callback) {
+ Start();
+ Join();
}
private:
- SequenceChecker sequence_checker_;
+ // SimpleThread:
+ void Run() override { callback_.Run(); }
+
+ const Closure callback_;
- DISALLOW_COPY_AND_ASSIGN(SequenceCheckedObject);
+ DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
};
class SequenceCheckerTest : public testing::Test {
- public:
- SequenceCheckerTest() : other_thread_("sequence_checker_test_other_thread") {}
-
- void SetUp() override {
- other_thread_.Start();
- ResetPool();
- }
-
- void TearDown() override {
- other_thread_.Stop();
- }
-
protected:
- base::Thread* other_thread() { return &other_thread_; }
+ SequenceCheckerTest() : pool_owner_(kNumWorkerThreads, "test") {}
- const scoped_refptr<SequencedWorkerPool>& pool() {
- return pool_owner_->pool();
+ void PostToSequencedWorkerPool(const Closure& callback,
+ const std::string& token_name) {
+ pool_owner_.pool()->PostNamedSequencedWorkerTask(token_name, FROM_HERE,
+ callback);
}
- void PostDoStuffToWorkerPool(SequenceCheckedObject* sequence_checked_object,
- const std::string& token_name) {
- pool()->PostNamedSequencedWorkerTask(
- token_name,
- FROM_HERE,
- base::Bind(&SequenceCheckedObject::DoStuff,
- base::Unretained(sequence_checked_object)));
+ void FlushSequencedWorkerPoolForTesting() {
+ pool_owner_.pool()->FlushForTesting();
}
- void PostDoStuffToOtherThread(
- SequenceCheckedObject* sequence_checked_object) {
- other_thread()->task_runner()->PostTask(
- FROM_HERE, base::Bind(&SequenceCheckedObject::DoStuff,
- base::Unretained(sequence_checked_object)));
- }
-
- void PostDeleteToOtherThread(
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object) {
- other_thread()->message_loop()->task_runner()->DeleteSoon(
- FROM_HERE, sequence_checked_object.release());
- }
-
- // Destroys the SequencedWorkerPool instance, blocking until it is fully shut
- // down, and creates a new instance.
- void ResetPool() {
- pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test"));
- }
-
- void MethodOnDifferentThreadDeathTest();
- void DetachThenCallFromDifferentThreadDeathTest();
- void DifferentSequenceTokensDeathTest();
- void WorkerPoolAndSimpleThreadDeathTest();
- void TwoDifferentWorkerPoolsDeathTest();
-
private:
MessageLoop message_loop_; // Needed by SequencedWorkerPool to function.
- base::Thread other_thread_;
- std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_;
+ SequencedWorkerPoolOwner pool_owner_;
+
+ DISALLOW_COPY_AND_ASSIGN(SequenceCheckerTest);
};
-TEST_F(SequenceCheckerTest, CallsAllowedOnSameThread) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
+ ASSERT_TRUE(sequence_checker);
- // Verify that DoStuff doesn't assert.
- sequence_checked_object->DoStuff();
+ // This should bind |sequence_checker| to the current sequence if it wasn't
+ // already bound to a sequence.
+ EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- // Verify that the destructor doesn't assert.
- sequence_checked_object.reset();
+ // Since |sequence_checker| is now bound to the current sequence, another call
+ // to CalledOnValidSequence() should return true.
+ EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
}
-TEST_F(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+void ExpectCalledOnValidSequenceWithSequenceToken(
+ SequenceCheckerImpl* sequence_checker,
+ SequenceToken sequence_token) {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(sequence_token);
+ ExpectCalledOnValidSequence(sequence_checker);
+}
- // Verify the destructor doesn't assert when called on a different thread.
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
+ ASSERT_TRUE(sequence_checker);
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
}
-TEST_F(SequenceCheckerTest, DetachFromSequence) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+} // namespace
- // Verify that DoStuff doesn't assert when called on a different thread after
- // a call to DetachFromSequence.
- sequence_checked_object->DetachFromSequence();
+TEST_F(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
+}
- PostDoStuffToOtherThread(sequence_checked_object.get());
- other_thread()->Stop();
+TEST_F(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
}
-TEST_F(SequenceCheckerTest, SameSequenceTokenValid) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
+ SequenceCheckerImpl sequence_checker;
+ RunCallbackThread thread(
+ Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
+}
+
+TEST_F(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
+ const SequenceToken sequence_token(SequenceToken::Create());
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- pool()->FlushForTesting();
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(sequence_token);
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+ RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken,
+ Unretained(&sequence_checker), sequence_token));
}
-TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
+ std::unique_ptr<SequenceCheckerImpl> sequence_checker;
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- pool()->FlushForTesting();
+ {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ sequence_checker.reset(new SequenceCheckerImpl);
+ }
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- pool()->FlushForTesting();
+ {
+ // Different SequenceToken.
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
+ }
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+ // No SequenceToken.
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
}
-#if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER
+TEST_F(SequenceCheckerTest, DetachFromSequence) {
+ std::unique_ptr<SequenceCheckerImpl> sequence_checker;
-void SequenceCheckerTest::MethodOnDifferentThreadDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+ {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ sequence_checker.reset(new SequenceCheckerImpl);
+ }
- // DoStuff should assert in debug builds only when called on a
- // different thread.
- PostDoStuffToOtherThread(sequence_checked_object.get());
- other_thread()->Stop();
-}
+ sequence_checker->DetachFromSequence();
-#if ENABLE_SEQUENCE_CHECKER
-TEST_F(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadDeathTestInDebug) {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_DEATH({
- MethodOnDifferentThreadDeathTest();
- }, "");
-}
-#else
-TEST_F(SequenceCheckerTest, MethodAllowedOnDifferentThreadDeathTestInRelease) {
- MethodOnDifferentThreadDeathTest();
+ {
+ // Verify that CalledOnValidSequence() returns true when called with
+ // a different sequence token after a call to DetachFromSequence().
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
+ }
}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::DetachThenCallFromDifferentThreadDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
- // DoStuff doesn't assert when called on a different thread
- // after a call to DetachFromSequence.
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToOtherThread(sequence_checked_object.get());
- other_thread()->Stop();
+ // Verify that CalledOnValidSequence() returns true when called on a
+ // different thread after a call to DetachFromSequence().
+ RunCallbackThread thread(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)));
- // DoStuff should assert in debug builds only after moving to
- // another thread.
- sequence_checked_object->DoStuff();
+ EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
}
-#if ENABLE_SEQUENCE_CHECKER
-TEST_F(SequenceCheckerTest, DetachFromSequenceDeathTestInDebug) {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_DEATH({
- DetachThenCallFromDifferentThreadDeathTest();
- }, "");
-}
-#else
-TEST_F(SequenceCheckerTest, DetachFromThreadDeathTestInRelease) {
- DetachThenCallFromDifferentThreadDeathTest();
+TEST_F(SequenceCheckerTest, SequencedWorkerPool_SameSequenceTokenValid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ FlushSequencedWorkerPoolForTesting();
}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::DifferentSequenceTokensDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, SequencedWorkerPool_DetachSequenceTokenValid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- pool()->FlushForTesting();
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ FlushSequencedWorkerPoolForTesting();
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
-}
+ sequence_checker.DetachFromSequence();
-#if ENABLE_SEQUENCE_CHECKER
-TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInDebug) {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_DEATH({
- DifferentSequenceTokensDeathTest();
- }, "");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "B");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "B");
+ FlushSequencedWorkerPoolForTesting();
}
-#else
-TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInRelease) {
- DifferentSequenceTokensDeathTest();
-}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::WorkerPoolAndSimpleThreadDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest,
+ SequencedWorkerPool_DifferentSequenceTokensInvalid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ FlushSequencedWorkerPoolForTesting();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)),
+ "B");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)),
+ "B");
+ FlushSequencedWorkerPoolForTesting();
+}
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- pool()->FlushForTesting();
+TEST_F(SequenceCheckerTest,
+ SequencedWorkerPool_WorkerPoolAndSimpleThreadInvalid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
- PostDoStuffToOtherThread(sequence_checked_object.get());
- other_thread()->Stop();
-}
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ FlushSequencedWorkerPoolForTesting();
-#if ENABLE_SEQUENCE_CHECKER
-TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInDebug) {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_DEATH({
- WorkerPoolAndSimpleThreadDeathTest();
- }, "");
+ EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
}
-#else
-TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInRelease) {
- WorkerPoolAndSimpleThreadDeathTest();
-}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::TwoDifferentWorkerPoolsDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest,
+ SequencedWorkerPool_TwoDifferentWorkerPoolsInvalid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- pool()->FlushForTesting();
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)), "A");
+ FlushSequencedWorkerPoolForTesting();
SequencedWorkerPoolOwner second_pool_owner(kNumWorkerThreads, "test2");
second_pool_owner.pool()->PostNamedSequencedWorkerTask(
- "A",
- FROM_HERE,
- base::Bind(&SequenceCheckedObject::DoStuff,
- base::Unretained(sequence_checked_object.get())));
+ "A", FROM_HERE, base::Bind(&ExpectNotCalledOnValidSequence,
+ base::Unretained(&sequence_checker)));
second_pool_owner.pool()->FlushForTesting();
}
-#if ENABLE_SEQUENCE_CHECKER
-TEST_F(SequenceCheckerTest, TwoDifferentWorkerPoolsDeathTestInDebug) {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- ASSERT_DEATH({
- TwoDifferentWorkerPoolsDeathTest();
- }, "");
-}
-#else
-TEST_F(SequenceCheckerTest, TwoDifferentWorkerPoolsDeathTestInRelease) {
- TwoDifferentWorkerPoolsDeathTest();
-}
-#endif // ENABLE_SEQUENCE_CHECKER
-
-#endif // GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER
-
-} // namespace
-
} // namespace base
-
-// Just in case we ever get lumped together with other compilation units.
-#undef ENABLE_SEQUENCE_CHECKER