[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
[email protected] | 399ed42 | 2012-12-27 19:58:00 | [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 | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 5 | #include "base/sequence_checker.h" |
| 6 | |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
dcheng | 093de9b | 2016-04-04 21:25:51 | [diff] [blame] | 9 | #include <memory> |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 10 | #include <string> |
danakj | 0c8d4aa | 2015-11-25 05:29:58 | [diff] [blame] | 11 | |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 12 | #include "base/bind.h" |
| 13 | #include "base/bind_helpers.h" |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 14 | #include "base/callback_forward.h" |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 15 | #include "base/macros.h" |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 16 | #include "base/sequence_token.h" |
skyostil | 054861d | 2015-04-30 19:06:15 | [diff] [blame] | 17 | #include "base/single_thread_task_runner.h" |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 18 | #include "base/test/gtest_util.h" |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 19 | #include "base/threading/simple_thread.h" |
[email protected] | 8e76597 | 2013-07-26 17:10:02 | [diff] [blame] | 20 | #include "testing/gtest/include/gtest/gtest.h" |
[email protected] | 5c0b443 | 2013-07-26 14:23:56 | [diff] [blame] | 21 | |
[email protected] | 399ed42 | 2012-12-27 19:58:00 | [diff] [blame] | 22 | namespace base { |
| 23 | |
| 24 | namespace { |
| 25 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 26 | // Runs a callback on another thread. |
| 27 | class RunCallbackThread : public SimpleThread { |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 28 | public: |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 29 | explicit RunCallbackThread(const Closure& callback) |
| 30 | : SimpleThread("RunCallbackThread"), callback_(callback) { |
| 31 | Start(); |
| 32 | Join(); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | private: |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 36 | // SimpleThread: |
| 37 | void Run() override { callback_.Run(); } |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 38 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 39 | const Closure callback_; |
| 40 | |
| 41 | DISALLOW_COPY_AND_ASSIGN(RunCallbackThread); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 42 | }; |
| 43 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 44 | void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 45 | ASSERT_TRUE(sequence_checker); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 46 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 47 | // This should bind |sequence_checker| to the current sequence if it wasn't |
| 48 | // already bound to a sequence. |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 49 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 50 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 51 | // Since |sequence_checker| is now bound to the current sequence, another call |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 52 | // to CalledOnValidSequence() should return true. |
| 53 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
[email protected] | 399ed42 | 2012-12-27 19:58:00 | [diff] [blame] | 54 | } |
| 55 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 56 | void ExpectCalledOnValidSequenceWithSequenceToken( |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 57 | SequenceCheckerImpl* sequence_checker, |
| 58 | SequenceToken sequence_token) { |
| 59 | ScopedSetSequenceTokenForCurrentThread |
| 60 | scoped_set_sequence_token_for_current_thread(sequence_token); |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 61 | ExpectCalledOnValidSequence(sequence_checker); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 62 | } |
| 63 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 64 | void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 65 | ASSERT_TRUE(sequence_checker); |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 66 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 67 | } |
| 68 | |
[email protected] | 399ed42 | 2012-12-27 19:58:00 | [diff] [blame] | 69 | } // namespace |
| 70 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 71 | TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 72 | SequenceCheckerImpl sequence_checker; |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 73 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 74 | } |
[email protected] | d52426c | 2013-07-30 19:26:40 | [diff] [blame] | 75 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 76 | TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 77 | ScopedSetSequenceTokenForCurrentThread |
| 78 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
| 79 | SequenceCheckerImpl sequence_checker; |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 80 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 81 | } |
| 82 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 83 | TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 84 | SequenceCheckerImpl sequence_checker; |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 85 | RunCallbackThread thread( |
| 86 | Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker))); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 87 | } |
| 88 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 89 | TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 90 | const SequenceToken sequence_token(SequenceToken::Create()); |
| 91 | |
| 92 | ScopedSetSequenceTokenForCurrentThread |
| 93 | scoped_set_sequence_token_for_current_thread(sequence_token); |
| 94 | SequenceCheckerImpl sequence_checker; |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 95 | EXPECT_TRUE(sequence_checker.CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 96 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 97 | RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken, |
| 98 | Unretained(&sequence_checker), sequence_token)); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 99 | } |
| 100 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 101 | TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 102 | 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()); |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 114 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | // No SequenceToken. |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 118 | EXPECT_FALSE(sequence_checker->CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 119 | } |
| 120 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 121 | TEST(SequenceCheckerTest, DetachFromSequence) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 122 | 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 | { |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 133 | // Verify that CalledOnValidSequence() returns true when called with |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 134 | // a different sequence token after a call to DetachFromSequence(). |
| 135 | ScopedSetSequenceTokenForCurrentThread |
| 136 | scoped_set_sequence_token_for_current_thread(SequenceToken::Create()); |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 137 | EXPECT_TRUE(sequence_checker->CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 138 | } |
| 139 | } |
| 140 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 141 | TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) { |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 142 | SequenceCheckerImpl sequence_checker; |
| 143 | sequence_checker.DetachFromSequence(); |
| 144 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 145 | // Verify that CalledOnValidSequence() returns true when called on a |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 146 | // different thread after a call to DetachFromSequence(). |
| 147 | RunCallbackThread thread( |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 148 | Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker))); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 149 | |
fdoray | e2b19a1 | 2016-07-29 02:30:16 | [diff] [blame] | 150 | EXPECT_FALSE(sequence_checker.CalledOnValidSequence()); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 151 | } |
| 152 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 153 | TEST(SequenceCheckerMacroTest, Macros) { |
| 154 | auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>( |
| 155 | SequenceToken::Create()); |
| 156 | SEQUENCE_CHECKER(my_sequence_checker); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 157 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 158 | // 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."; |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 161 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 162 | scope.reset(); |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 163 | |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 164 | #if DCHECK_IS_ON() |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 165 | // 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 | }); |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 169 | #else |
| 170 | // Happily no-ops on non-dcheck builds. |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 171 | DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message."; |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 172 | #endif |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 173 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 174 | DETACH_FROM_SEQUENCE(my_sequence_checker); |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 175 | |
Francois Doray | 4914ec14 | 2018-02-22 12:48:38 | [diff] [blame] | 176 | // 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."; |
gab | d52c912a | 2017-05-11 04:15:59 | [diff] [blame] | 179 | } |
| 180 | |
fdoray | eed5fa7 | 2016-07-26 22:28:45 | [diff] [blame] | 181 | } // namespace base |