tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
akalin@chromium.org | 4fb2deb | 2012-12-28 04:58:00 +0900 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 5 | #include "base/sequence_checker.h" |
| 6 | |
avi | a6a6a68 | 2015-12-27 07:15:14 +0900 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
dcheng | cc8e4d8 | 2016-04-05 06:25:51 +0900 | [diff] [blame] | 9 | #include <memory> |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 10 | #include <string> |
danakj | 800d2ea | 2015-11-25 14:29:58 +0900 | [diff] [blame] | 11 | |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 12 | #include "base/bind.h" |
| 13 | #include "base/bind_helpers.h" |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 14 | #include "base/callback_forward.h" |
avi | a6a6a68 | 2015-12-27 07:15:14 +0900 | [diff] [blame] | 15 | #include "base/macros.h" |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 16 | #include "base/message_loop/message_loop.h" |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 17 | #include "base/sequence_token.h" |
skyostil | 97aefe1 | 2015-05-01 04:06:15 +0900 | [diff] [blame] | 18 | #include "base/single_thread_task_runner.h" |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 19 | #include "base/test/gtest_util.h" |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 20 | #include "base/threading/simple_thread.h" |
dewittj@chromium.org | fadd934 | 2013-07-27 02:10:02 +0900 | [diff] [blame] | 21 | #include "testing/gtest/include/gtest/gtest.h" |
tommycli@chromium.org | 755085a | 2013-07-26 23:23:56 +0900 | [diff] [blame] | 22 | |
akalin@chromium.org | 4fb2deb | 2012-12-28 04:58:00 +0900 | [diff] [blame] | 23 | namespace base { |
| 24 | |
| 25 | namespace { |
| 26 | |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 27 | // Runs a callback on another thread. |
| 28 | class RunCallbackThread : public SimpleThread { |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 29 | public: |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 30 | explicit RunCallbackThread(const Closure& callback) |
| 31 | : SimpleThread("RunCallbackThread"), callback_(callback) { |
| 32 | Start(); |
| 33 | Join(); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 34 | } |
| 35 | |
| 36 | private: |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 37 | // SimpleThread: |
| 38 | void Run() override { callback_.Run(); } |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 39 | |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 40 | const Closure callback_; |
| 41 | |
| 42 | DISALLOW_COPY_AND_ASSIGN(RunCallbackThread); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 43 | }; |
| 44 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 45 | void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 46 | ASSERT_TRUE(sequence_checker); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 47 | |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 48 | // This should bind |sequence_checker| to the current sequence if it wasn't |
| 49 | // already bound to a sequence. |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 50 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 51 | |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 52 | // Since |sequence_checker| is now bound to the current sequence, another call |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 53 | // to CalledOnValidSequence() should return true. |
| 54 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
akalin@chromium.org | 4fb2deb | 2012-12-28 04:58:00 +0900 | [diff] [blame] | 55 | } |
| 56 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 57 | void ExpectCalledOnValidSequenceWithSequenceToken( |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 58 | SequenceCheckerImpl* sequence_checker, |
| 59 | SequenceToken sequence_token) { |
| 60 | ScopedSetSequenceTokenForCurrentThread |
| 61 | scoped_set_sequence_token_for_current_thread(sequence_token); |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 62 | ExpectCalledOnValidSequence(sequence_checker); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 63 | } |
| 64 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 65 | void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 66 | ASSERT_TRUE(sequence_checker); |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 67 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 68 | } |
| 69 | |
akalin@chromium.org | 4fb2deb | 2012-12-28 04:58:00 +0900 | [diff] [blame] | 70 | } // namespace |
| 71 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 72 | TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 73 | SequenceCheckerImpl sequence_checker; |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 74 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 75 | } |
tommycli@chromium.org | 623e16c | 2013-07-31 04:26:40 +0900 | [diff] [blame] | 76 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 77 | TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 78 | ScopedSetSequenceTokenForCurrentThread |
| 79 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
| 80 | SequenceCheckerImpl sequence_checker; |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 81 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 82 | } |
| 83 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 84 | TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 85 | SequenceCheckerImpl sequence_checker; |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 86 | RunCallbackThread thread( |
| 87 | Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker))); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 88 | } |
| 89 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 90 | TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 91 | const SequenceToken sequence_token(SequenceToken::Create()); |
| 92 | |
| 93 | ScopedSetSequenceTokenForCurrentThread |
| 94 | scoped_set_sequence_token_for_current_thread(sequence_token); |
| 95 | SequenceCheckerImpl sequence_checker; |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 96 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 97 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 98 | RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken, |
| 99 | Unretained(&sequence_checker), sequence_token)); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 100 | } |
| 101 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 102 | TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 103 | std::unique_ptr<SequenceCheckerImpl> sequence_checker; |
| 104 | |
| 105 | { |
| 106 | ScopedSetSequenceTokenForCurrentThread |
| 107 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
| 108 | sequence_checker.reset(new SequenceCheckerImpl); |
| 109 | } |
| 110 | |
| 111 | { |
| 112 | // Different SequenceToken. |
| 113 | ScopedSetSequenceTokenForCurrentThread |
| 114 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 115 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | // No SequenceToken. |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 119 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 120 | } |
| 121 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 122 | TEST(SequenceCheckerTest, DetachFromSequence) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 123 | std::unique_ptr<SequenceCheckerImpl> sequence_checker; |
| 124 | |
| 125 | { |
| 126 | ScopedSetSequenceTokenForCurrentThread |
| 127 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
| 128 | sequence_checker.reset(new SequenceCheckerImpl); |
| 129 | } |
| 130 | |
| 131 | sequence_checker->DetachFromSequence(); |
| 132 | |
| 133 | { |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 134 | // Verify that CalledOnValidSequence() returns true when called with |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 135 | // a different sequence token after a call to DetachFromSequence(). |
| 136 | ScopedSetSequenceTokenForCurrentThread |
| 137 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 138 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 139 | } |
| 140 | } |
| 141 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 142 | TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) { |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 143 | SequenceCheckerImpl sequence_checker; |
| 144 | sequence_checker.DetachFromSequence(); |
| 145 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 146 | // Verify that CalledOnValidSequence() returns true when called on a |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 147 | // different thread after a call to DetachFromSequence(). |
| 148 | RunCallbackThread thread( |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 149 | Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker))); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 150 | |
fdoray | e4a5827 | 2016-07-29 11:30:16 +0900 | [diff] [blame] | 151 | EXPECT_FALSE(sequence_checker.CalledOnValidSequence()); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 152 | } |
| 153 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 154 | TEST(SequenceCheckerMacroTest, Macros) { |
| 155 | auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>( |
| 156 | SequenceToken::Create()); |
| 157 | SEQUENCE_CHECKER(my_sequence_checker); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 158 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 159 | // Don't expect a DCHECK death when a SequenceChecker is used on the right |
| 160 | // sequence. |
| 161 | DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message."; |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 162 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 163 | scope.reset(); |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 164 | |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 165 | #if DCHECK_IS_ON() |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 166 | // Expect DCHECK death when used on a different sequence. |
| 167 | EXPECT_DCHECK_DEATH({ |
| 168 | DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message."; |
| 169 | }); |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 170 | #else |
| 171 | // Happily no-ops on non-dcheck builds. |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 172 | DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message."; |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 173 | #endif |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 174 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 175 | DETACH_FROM_SEQUENCE(my_sequence_checker); |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 176 | |
Francois Doray | 3c2d2fd | 2018-02-22 21:48:38 +0900 | [diff] [blame] | 177 | // Don't expect a DCHECK death when a SequenceChecker is used for the first |
| 178 | // time after having been detached. |
| 179 | DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message."; |
gab | be9beea | 2017-05-11 13:15:59 +0900 | [diff] [blame] | 180 | } |
| 181 | |
fdoray | 4bcf108 | 2016-07-27 07:28:45 +0900 | [diff] [blame] | 182 | } // namespace base |