Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: base/sequence_checker_unittest.cc

Issue 2165663003: TaskScheduler: Add SequenceToken and ScopedSetSequenceTokenForCurrentThread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: self-review Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/sequence_checker_unittest.cc
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
index 196bb1cc7972309ddba5c85ba42d074ddb3138c3..0d4a0c20c7953b92edb71cbfae7d4409263fae17 100644
--- a/base/sequence_checker_unittest.cc
+++ b/base/sequence_checker_unittest.cc
@@ -2,334 +2,271 @@
// 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 ExpectCalledOnValidSequencedThread(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->CalledOnValidSequencedThread());
- // Verify that the destructor doesn't assert.
- sequence_checked_object.reset();
+ // Since |sequence_checker| is now bound to the current sequence, another call
+ // to CalledOnValidSequencedThread() should return true.
+ EXPECT_TRUE(sequence_checker->CalledOnValidSequencedThread());
}
-TEST_F(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
-
- // Verify the destructor doesn't assert when called on a different thread.
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+void ExpectCalledOnValidSequencedThreadWithSequenceToken(
+ SequenceCheckerImpl* sequence_checker,
+ SequenceToken sequence_token) {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(sequence_token);
+ ExpectCalledOnValidSequencedThread(sequence_checker);
}
-TEST_F(SequenceCheckerTest, DetachFromSequence) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
-
- // Verify that 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();
+void ExpectNotCalledOnValidSequencedThread(
+ SequenceCheckerImpl* sequence_checker) {
+ ASSERT_TRUE(sequence_checker);
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequencedThread());
}
-TEST_F(SequenceCheckerTest, SameSequenceTokenValid) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+} // namespace
- 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();
+TEST_F(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequencedThread());
+}
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+TEST_F(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequencedThread());
}
-TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
+ SequenceCheckerImpl sequence_checker;
+ RunCallbackThread thread(Bind(&ExpectNotCalledOnValidSequencedThread,
+ Unretained(&sequence_checker)));
+}
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
- pool()->FlushForTesting();
+TEST_F(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
+ const SequenceToken sequence_token(SequenceToken::Create());
- sequence_checked_object->DetachFromSequence();
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
- pool()->FlushForTesting();
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(sequence_token);
+ SequenceCheckerImpl sequence_checker;
+ EXPECT_TRUE(sequence_checker.CalledOnValidSequencedThread());
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+ RunCallbackThread thread(
+ Bind(&ExpectCalledOnValidSequencedThreadWithSequenceToken,
+ Unretained(&sequence_checker), sequence_token));
}
-#if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER
+TEST_F(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
+ 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();
-}
+ {
+ // Different SequenceToken.
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequencedThread());
+ }
-#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();
- }, "");
+ // No SequenceToken.
+ EXPECT_FALSE(sequence_checker->CalledOnValidSequencedThread());
}
-#else
-TEST_F(SequenceCheckerTest, MethodAllowedOnDifferentThreadDeathTestInRelease) {
- MethodOnDifferentThreadDeathTest();
-}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::DetachThenCallFromDifferentThreadDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, DetachFromSequence) {
+ std::unique_ptr<SequenceCheckerImpl> sequence_checker;
- // 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();
+ {
+ ScopedSetSequenceTokenForCurrentThread
+ scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+ sequence_checker.reset(new SequenceCheckerImpl);
+ }
- // DoStuff should assert in debug builds only after moving to
- // another thread.
- sequence_checked_object->DoStuff();
-}
+ sequence_checker->DetachFromSequence();
-#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();
+ {
+ // Verify that CalledOnValidSequencedThread() 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->CalledOnValidSequencedThread());
+ }
}
-#endif // ENABLE_SEQUENCE_CHECKER
-void SequenceCheckerTest::DifferentSequenceTokensDeathTest() {
- std::unique_ptr<SequenceCheckedObject> sequence_checked_object(
- new SequenceCheckedObject);
+TEST_F(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
+ 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();
+ // Verify that CalledOnValidSequencedThread() returns true when called on a
+ // different thread after a call to DetachFromSequence().
+ RunCallbackThread thread(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)));
- PostDeleteToOtherThread(std::move(sequence_checked_object));
- other_thread()->Stop();
+ EXPECT_FALSE(sequence_checker.CalledOnValidSequencedThread());
}
-#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();
- }, "");
+TEST_F(SequenceCheckerTest, SequencedWorkerPool_SameSequenceTokenValid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ FlushSequencedWorkerPoolForTesting();
}
-#else
-TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInRelease) {
- DifferentSequenceTokensDeathTest();
+
+TEST_F(SequenceCheckerTest, SequencedWorkerPool_DetachSequenceTokenValid) {
+ SequenceCheckerImpl sequence_checker;
+ sequence_checker.DetachFromSequence();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ FlushSequencedWorkerPoolForTesting();
+
+ sequence_checker.DetachFromSequence();
+
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "B");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "B");
+ FlushSequencedWorkerPoolForTesting();
}
-#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(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ FlushSequencedWorkerPoolForTesting();
+
+ PostToSequencedWorkerPool(Bind(&ExpectNotCalledOnValidSequencedThread,
+ Unretained(&sequence_checker)),
+ "B");
+ PostToSequencedWorkerPool(Bind(&ExpectNotCalledOnValidSequencedThread,
+ 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(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, 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.CalledOnValidSequencedThread());
}
-#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(&ExpectCalledOnValidSequencedThread, Unretained(&sequence_checker)),
+ "A");
+ PostToSequencedWorkerPool(
+ Bind(&ExpectCalledOnValidSequencedThread, 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(&ExpectNotCalledOnValidSequencedThread,
+ 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

Powered by Google App Engine
This is Rietveld 408576698