blob: 8d44f3e41baf36617c728fe94ad6a7b27927e07b [file] [log] [blame]
[email protected]d52426c2013-07-30 19:26:401// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]399ed422012-12-27 19:58:002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
gabd52c912a2017-05-11 04:15:595#include "base/sequence_checker.h"
6
avi9b6f42932015-12-26 22:15:147#include <stddef.h>
8
dcheng093de9b2016-04-04 21:25:519#include <memory>
fdorayeed5fa72016-07-26 22:28:4510#include <string>
danakj0c8d4aa2015-11-25 05:29:5811
[email protected]d52426c2013-07-30 19:26:4012#include "base/bind.h"
13#include "base/bind_helpers.h"
fdorayeed5fa72016-07-26 22:28:4514#include "base/callback_forward.h"
avi9b6f42932015-12-26 22:15:1415#include "base/macros.h"
fdorayeed5fa72016-07-26 22:28:4516#include "base/sequence_token.h"
skyostil054861d2015-04-30 19:06:1517#include "base/single_thread_task_runner.h"
gabd52c912a2017-05-11 04:15:5918#include "base/test/gtest_util.h"
fdorayeed5fa72016-07-26 22:28:4519#include "base/threading/simple_thread.h"
[email protected]8e765972013-07-26 17:10:0220#include "testing/gtest/include/gtest/gtest.h"
[email protected]5c0b4432013-07-26 14:23:5621
[email protected]399ed422012-12-27 19:58:0022namespace base {
23
24namespace {
25
fdorayeed5fa72016-07-26 22:28:4526// Runs a callback on another thread.
27class RunCallbackThread : public SimpleThread {
[email protected]d52426c2013-07-30 19:26:4028 public:
fdorayeed5fa72016-07-26 22:28:4529 explicit RunCallbackThread(const Closure& callback)
30 : SimpleThread("RunCallbackThread"), callback_(callback) {
31 Start();
32 Join();
[email protected]d52426c2013-07-30 19:26:4033 }
34
35 private:
fdorayeed5fa72016-07-26 22:28:4536 // SimpleThread:
37 void Run() override { callback_.Run(); }
[email protected]d52426c2013-07-30 19:26:4038
fdorayeed5fa72016-07-26 22:28:4539 const Closure callback_;
40
41 DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
[email protected]d52426c2013-07-30 19:26:4042};
43
fdoraye2b19a12016-07-29 02:30:1644void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
fdorayeed5fa72016-07-26 22:28:4545 ASSERT_TRUE(sequence_checker);
[email protected]d52426c2013-07-30 19:26:4046
fdorayeed5fa72016-07-26 22:28:4547 // This should bind |sequence_checker| to the current sequence if it wasn't
48 // already bound to a sequence.
fdoraye2b19a12016-07-29 02:30:1649 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
[email protected]d52426c2013-07-30 19:26:4050
fdorayeed5fa72016-07-26 22:28:4551 // Since |sequence_checker| is now bound to the current sequence, another call
fdoraye2b19a12016-07-29 02:30:1652 // to CalledOnValidSequence() should return true.
53 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
[email protected]399ed422012-12-27 19:58:0054}
55
fdoraye2b19a12016-07-29 02:30:1656void ExpectCalledOnValidSequenceWithSequenceToken(
fdorayeed5fa72016-07-26 22:28:4557 SequenceCheckerImpl* sequence_checker,
58 SequenceToken sequence_token) {
59 ScopedSetSequenceTokenForCurrentThread
60 scoped_set_sequence_token_for_current_thread(sequence_token);
fdoraye2b19a12016-07-29 02:30:1661 ExpectCalledOnValidSequence(sequence_checker);
[email protected]d52426c2013-07-30 19:26:4062}
63
fdoraye2b19a12016-07-29 02:30:1664void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
fdorayeed5fa72016-07-26 22:28:4565 ASSERT_TRUE(sequence_checker);
fdoraye2b19a12016-07-29 02:30:1666 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
[email protected]d52426c2013-07-30 19:26:4067}
68
[email protected]399ed422012-12-27 19:58:0069} // namespace
70
Francois Doray4914ec142018-02-22 12:48:3871TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
fdorayeed5fa72016-07-26 22:28:4572 SequenceCheckerImpl sequence_checker;
fdoraye2b19a12016-07-29 02:30:1673 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:4574}
[email protected]d52426c2013-07-30 19:26:4075
Francois Doray4914ec142018-02-22 12:48:3876TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
fdorayeed5fa72016-07-26 22:28:4577 ScopedSetSequenceTokenForCurrentThread
78 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
79 SequenceCheckerImpl sequence_checker;
fdoraye2b19a12016-07-29 02:30:1680 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:4581}
82
Francois Doray4914ec142018-02-22 12:48:3883TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
fdorayeed5fa72016-07-26 22:28:4584 SequenceCheckerImpl sequence_checker;
fdoraye2b19a12016-07-29 02:30:1685 RunCallbackThread thread(
86 Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
fdorayeed5fa72016-07-26 22:28:4587}
88
Francois Doray4914ec142018-02-22 12:48:3889TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
fdorayeed5fa72016-07-26 22:28:4590 const SequenceToken sequence_token(SequenceToken::Create());
91
92 ScopedSetSequenceTokenForCurrentThread
93 scoped_set_sequence_token_for_current_thread(sequence_token);
94 SequenceCheckerImpl sequence_checker;
fdoraye2b19a12016-07-29 02:30:1695 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:4596
fdoraye2b19a12016-07-29 02:30:1697 RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken,
98 Unretained(&sequence_checker), sequence_token));
fdorayeed5fa72016-07-26 22:28:4599}
100
Francois Doray4914ec142018-02-22 12:48:38101TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
fdorayeed5fa72016-07-26 22:28:45102 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
103
104 {
105 ScopedSetSequenceTokenForCurrentThread
106 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
107 sequence_checker.reset(new SequenceCheckerImpl);
108 }
109
110 {
111 // Different SequenceToken.
112 ScopedSetSequenceTokenForCurrentThread
113 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
fdoraye2b19a12016-07-29 02:30:16114 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:45115 }
116
117 // No SequenceToken.
fdoraye2b19a12016-07-29 02:30:16118 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:45119}
120
Francois Doray4914ec142018-02-22 12:48:38121TEST(SequenceCheckerTest, DetachFromSequence) {
fdorayeed5fa72016-07-26 22:28:45122 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
123
124 {
125 ScopedSetSequenceTokenForCurrentThread
126 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
127 sequence_checker.reset(new SequenceCheckerImpl);
128 }
129
130 sequence_checker->DetachFromSequence();
131
132 {
fdoraye2b19a12016-07-29 02:30:16133 // Verify that CalledOnValidSequence() returns true when called with
fdorayeed5fa72016-07-26 22:28:45134 // a different sequence token after a call to DetachFromSequence().
135 ScopedSetSequenceTokenForCurrentThread
136 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
fdoraye2b19a12016-07-29 02:30:16137 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:45138 }
139}
140
Francois Doray4914ec142018-02-22 12:48:38141TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
fdorayeed5fa72016-07-26 22:28:45142 SequenceCheckerImpl sequence_checker;
143 sequence_checker.DetachFromSequence();
144
fdoraye2b19a12016-07-29 02:30:16145 // Verify that CalledOnValidSequence() returns true when called on a
fdorayeed5fa72016-07-26 22:28:45146 // different thread after a call to DetachFromSequence().
147 RunCallbackThread thread(
fdoraye2b19a12016-07-29 02:30:16148 Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)));
fdorayeed5fa72016-07-26 22:28:45149
fdoraye2b19a12016-07-29 02:30:16150 EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
fdorayeed5fa72016-07-26 22:28:45151}
152
Francois Doray4914ec142018-02-22 12:48:38153TEST(SequenceCheckerMacroTest, Macros) {
154 auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
155 SequenceToken::Create());
156 SEQUENCE_CHECKER(my_sequence_checker);
fdorayeed5fa72016-07-26 22:28:45157
Francois Doray4914ec142018-02-22 12:48:38158 // Don't expect a DCHECK death when a SequenceChecker is used on the right
159 // sequence.
160 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
fdorayeed5fa72016-07-26 22:28:45161
Francois Doray4914ec142018-02-22 12:48:38162 scope.reset();
fdorayeed5fa72016-07-26 22:28:45163
gabd52c912a2017-05-11 04:15:59164#if DCHECK_IS_ON()
Francois Doray4914ec142018-02-22 12:48:38165 // Expect DCHECK death when used on a different sequence.
166 EXPECT_DCHECK_DEATH({
167 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
168 });
gabd52c912a2017-05-11 04:15:59169#else
170 // Happily no-ops on non-dcheck builds.
Francois Doray4914ec142018-02-22 12:48:38171 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
gabd52c912a2017-05-11 04:15:59172#endif
gabd52c912a2017-05-11 04:15:59173
Francois Doray4914ec142018-02-22 12:48:38174 DETACH_FROM_SEQUENCE(my_sequence_checker);
gabd52c912a2017-05-11 04:15:59175
Francois Doray4914ec142018-02-22 12:48:38176 // Don't expect a DCHECK death when a SequenceChecker is used for the first
177 // time after having been detached.
178 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
gabd52c912a2017-05-11 04:15:59179}
180
fdorayeed5fa72016-07-26 22:28:45181} // namespace base