OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/task_scheduler/priority_queue.h" | 5 #include "base/task_scheduler/priority_queue.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
24 | 24 |
25 namespace base { | 25 namespace base { |
26 namespace internal { | 26 namespace internal { |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 class PriorityQueueCallbackMock { | 30 class PriorityQueueCallbackMock { |
31 public: | 31 public: |
32 PriorityQueueCallbackMock() = default; | 32 PriorityQueueCallbackMock() = default; |
33 MOCK_METHOD0(SequenceInsertedInPriorityQueue, void()); | 33 MOCK_METHOD0(WakeUp, void()); |
34 | 34 |
35 private: | 35 private: |
36 DISALLOW_COPY_AND_ASSIGN(PriorityQueueCallbackMock); | 36 DISALLOW_COPY_AND_ASSIGN(PriorityQueueCallbackMock); |
37 }; | 37 }; |
38 | 38 |
39 class ThreadBeginningTransaction : public SimpleThread { | 39 class ThreadBeginningTransaction : public SimpleThread { |
40 public: | 40 public: |
41 explicit ThreadBeginningTransaction(PriorityQueue* priority_queue) | 41 explicit ThreadBeginningTransaction(PriorityQueue* priority_queue) |
42 : SimpleThread("ThreadBeginningTransaction"), | 42 : SimpleThread("ThreadBeginningTransaction"), |
43 priority_queue_(priority_queue), | 43 priority_queue_(priority_queue), |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 SequenceSortKey sort_key_c = sequence_c->GetSortKey(); | 102 SequenceSortKey sort_key_c = sequence_c->GetSortKey(); |
103 | 103 |
104 scoped_refptr<Sequence> sequence_d(new Sequence); | 104 scoped_refptr<Sequence> sequence_d(new Sequence); |
105 sequence_d->PushTask(WrapUnique( | 105 sequence_d->PushTask(WrapUnique( |
106 new Task(FROM_HERE, Closure(), | 106 new Task(FROM_HERE, Closure(), |
107 TaskTraits().WithPriority(TaskPriority::BACKGROUND)))); | 107 TaskTraits().WithPriority(TaskPriority::BACKGROUND)))); |
108 SequenceSortKey sort_key_d = sequence_d->GetSortKey(); | 108 SequenceSortKey sort_key_d = sequence_d->GetSortKey(); |
109 | 109 |
110 // Create a PriorityQueue and a Transaction. | 110 // Create a PriorityQueue and a Transaction. |
111 testing::StrictMock<PriorityQueueCallbackMock> mock; | 111 testing::StrictMock<PriorityQueueCallbackMock> mock; |
112 PriorityQueue pq( | 112 PriorityQueue pq(Bind(&PriorityQueueCallbackMock::WakeUp, Unretained(&mock))); |
113 Bind(&PriorityQueueCallbackMock::SequenceInsertedInPriorityQueue, | |
114 Unretained(&mock))); | |
115 std::unique_ptr<PriorityQueue::Transaction> transaction( | 113 std::unique_ptr<PriorityQueue::Transaction> transaction( |
116 pq.BeginTransaction()); | 114 pq.BeginTransaction()); |
117 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), | 115 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), |
118 transaction->Peek()); | 116 transaction->Peek()); |
119 | 117 |
120 // Push |sequence_a| in the PriorityQueue. It becomes the sequence with the | 118 // Push |sequence_a| in the PriorityQueue. It becomes the sequence with the |
121 // highest priority. | 119 // highest priority. |
122 transaction->Push(WrapUnique( | 120 transaction->Push(WrapUnique( |
123 new PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a))); | 121 new PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a))); |
124 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( | 122 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 transaction->Pop(); | 166 transaction->Pop(); |
169 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( | 167 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
170 PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d), | 168 PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d), |
171 transaction->Peek()); | 169 transaction->Peek()); |
172 | 170 |
173 // Pop |sequence_d| from the PriorityQueue. It is now empty. | 171 // Pop |sequence_d| from the PriorityQueue. It is now empty. |
174 transaction->Pop(); | 172 transaction->Pop(); |
175 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), | 173 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), |
176 transaction->Peek()); | 174 transaction->Peek()); |
177 | 175 |
178 // Expect 4 calls to mock.SequenceInsertedInPriorityQueue() when the | 176 // Expect 4 calls to mock.WakeUp() when the Transaction is destroyed. |
179 // Transaction is destroyed. | 177 EXPECT_CALL(mock, WakeUp()).Times(4); |
180 EXPECT_CALL(mock, SequenceInsertedInPriorityQueue()).Times(4); | |
181 transaction.reset(); | 178 transaction.reset(); |
182 } | 179 } |
183 | 180 |
| 181 TEST(TaskSchedulerPriorityQueueTest, PushNoWakeUpPopPeek) { |
| 182 // Create test sequences. |
| 183 scoped_refptr<Sequence> sequence_a(new Sequence); |
| 184 sequence_a->PushTask(WrapUnique( |
| 185 new Task(FROM_HERE, Closure(), |
| 186 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE)))); |
| 187 SequenceSortKey sort_key_a = sequence_a->GetSortKey(); |
| 188 |
| 189 scoped_refptr<Sequence> sequence_b(new Sequence); |
| 190 sequence_b->PushTask(WrapUnique( |
| 191 new Task(FROM_HERE, Closure(), |
| 192 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING)))); |
| 193 SequenceSortKey sort_key_b = sequence_b->GetSortKey(); |
| 194 |
| 195 scoped_refptr<Sequence> sequence_c(new Sequence); |
| 196 sequence_c->PushTask(WrapUnique( |
| 197 new Task(FROM_HERE, Closure(), |
| 198 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING)))); |
| 199 SequenceSortKey sort_key_c = sequence_c->GetSortKey(); |
| 200 |
| 201 scoped_refptr<Sequence> sequence_d(new Sequence); |
| 202 sequence_d->PushTask(WrapUnique( |
| 203 new Task(FROM_HERE, Closure(), |
| 204 TaskTraits().WithPriority(TaskPriority::BACKGROUND)))); |
| 205 SequenceSortKey sort_key_d = sequence_d->GetSortKey(); |
| 206 |
| 207 // Create a PriorityQueue and a Transaction. |
| 208 testing::StrictMock<PriorityQueueCallbackMock> mock; |
| 209 PriorityQueue pq(Bind(&PriorityQueueCallbackMock::WakeUp, Unretained(&mock))); |
| 210 std::unique_ptr<PriorityQueue::Transaction> transaction( |
| 211 pq.BeginTransaction()); |
| 212 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), |
| 213 transaction->Peek()); |
| 214 |
| 215 // Push |sequence_a| in the PriorityQueue. It becomes the sequence with the |
| 216 // highest priority. |
| 217 transaction->PushNoWakeUp(WrapUnique( |
| 218 new PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a))); |
| 219 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 220 PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a), |
| 221 transaction->Peek()); |
| 222 |
| 223 // Push |sequence_b| in the PriorityQueue. It becomes the sequence with the |
| 224 // highest priority. |
| 225 transaction->PushNoWakeUp(WrapUnique( |
| 226 new PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b))); |
| 227 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 228 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b), |
| 229 transaction->Peek()); |
| 230 |
| 231 // Push |sequence_c| in the PriorityQueue. |sequence_b| is still the sequence |
| 232 // with the highest priority. |
| 233 transaction->PushNoWakeUp(WrapUnique( |
| 234 new PriorityQueue::SequenceAndSortKey(sequence_c, sort_key_c))); |
| 235 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 236 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b), |
| 237 transaction->Peek()); |
| 238 |
| 239 // Push |sequence_d| in the PriorityQueue. |sequence_b| is still the sequence |
| 240 // with the highest priority. |
| 241 transaction->PushNoWakeUp(WrapUnique( |
| 242 new PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d))); |
| 243 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 244 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b), |
| 245 transaction->Peek()); |
| 246 |
| 247 // Pop |sequence_b| from the PriorityQueue. |sequence_c| becomes the sequence |
| 248 // with the highest priority. |
| 249 transaction->Pop(); |
| 250 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 251 PriorityQueue::SequenceAndSortKey(sequence_c, sort_key_c), |
| 252 transaction->Peek()); |
| 253 |
| 254 // Pop |sequence_c| from the PriorityQueue. |sequence_a| becomes the sequence |
| 255 // with the highest priority. |
| 256 transaction->Pop(); |
| 257 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 258 PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a), |
| 259 transaction->Peek()); |
| 260 |
| 261 // Pop |sequence_a| from the PriorityQueue. |sequence_d| becomes the sequence |
| 262 // with the highest priority. |
| 263 transaction->Pop(); |
| 264 EXPECT_SEQUENCE_AND_SORT_KEY_EQ( |
| 265 PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d), |
| 266 transaction->Peek()); |
| 267 |
| 268 // Pop |sequence_d| from the PriorityQueue. It is now empty. |
| 269 transaction->Pop(); |
| 270 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(), |
| 271 transaction->Peek()); |
| 272 |
| 273 // Expect no call to mock.WakeUp() when the Transaction is destroyed. |
| 274 EXPECT_CALL(mock, WakeUp()).Times(0); |
| 275 transaction.reset(); |
| 276 } |
| 277 |
184 // Check that creating Transactions on the same thread for 2 unrelated | 278 // Check that creating Transactions on the same thread for 2 unrelated |
185 // PriorityQueues causes a crash. | 279 // PriorityQueues causes a crash. |
186 TEST(TaskSchedulerPriorityQueueTest, IllegalTwoTransactionsSameThread) { | 280 TEST(TaskSchedulerPriorityQueueTest, IllegalTwoTransactionsSameThread) { |
187 PriorityQueue pq_a(Bind(&DoNothing)); | 281 PriorityQueue pq_a(Bind(&DoNothing)); |
188 PriorityQueue pq_b(Bind(&DoNothing)); | 282 PriorityQueue pq_b(Bind(&DoNothing)); |
189 | 283 |
190 EXPECT_DCHECK_DEATH( | 284 EXPECT_DCHECK_DEATH( |
191 { | 285 { |
192 std::unique_ptr<PriorityQueue::Transaction> transaction_a = | 286 std::unique_ptr<PriorityQueue::Transaction> transaction_a = |
193 pq_a.BeginTransaction(); | 287 pq_a.BeginTransaction(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 EXPECT_TRUE(PriorityQueue::SequenceAndSortKey().is_null()); | 334 EXPECT_TRUE(PriorityQueue::SequenceAndSortKey().is_null()); |
241 | 335 |
242 const PriorityQueue::SequenceAndSortKey non_null_sequence_andsort_key( | 336 const PriorityQueue::SequenceAndSortKey non_null_sequence_andsort_key( |
243 make_scoped_refptr(new Sequence), | 337 make_scoped_refptr(new Sequence), |
244 SequenceSortKey(TaskPriority::USER_VISIBLE, TimeTicks())); | 338 SequenceSortKey(TaskPriority::USER_VISIBLE, TimeTicks())); |
245 EXPECT_FALSE(non_null_sequence_andsort_key.is_null()); | 339 EXPECT_FALSE(non_null_sequence_andsort_key.is_null()); |
246 } | 340 } |
247 | 341 |
248 } // namespace internal | 342 } // namespace internal |
249 } // namespace base | 343 } // namespace base |
OLD | NEW |