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

Side by Side Diff: base/task_scheduler/priority_queue_unittest.cc

Issue 1709713002: TaskScheduler [4/9] Priority Queue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s_2_sequence_and_task
Patch Set: CR danakj #31 Created 4 years, 9 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 unified diff | Download patch
« no previous file with comments | « base/task_scheduler/priority_queue.cc ('k') | base/task_scheduler/scheduler_lock_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/task_scheduler/priority_queue.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/task_scheduler/sequence.h"
14 #include "base/task_scheduler/task.h"
15 #include "base/task_scheduler/task_traits.h"
16 #include "base/task_scheduler/test_utils.h"
17 #include "base/threading/platform_thread.h"
18 #include "base/threading/simple_thread.h"
19 #include "base/time/time.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace base {
24 namespace internal {
25
26 namespace {
27
28 class PriorityQueueCallbackMock {
29 public:
30 PriorityQueueCallbackMock() = default;
31 MOCK_METHOD0(SequenceInsertedInPriorityQueue, void());
32
33 private:
34 DISALLOW_COPY_AND_ASSIGN(PriorityQueueCallbackMock);
35 };
36
37 class ThreadBeginningTransaction : public SimpleThread {
38 public:
39 explicit ThreadBeginningTransaction(PriorityQueue* priority_queue)
40 : SimpleThread("ThreadBeginningTransaction"),
41 priority_queue_(priority_queue),
42 transaction_began_(true, false) {}
43
44 // SimpleThread:
45 void Run() override {
46 scoped_ptr<PriorityQueue::Transaction> transaction =
47 priority_queue_->BeginTransaction();
48 transaction_began_.Signal();
49 }
50
51 void ExpectTransactionDoesNotBegin() {
52 // After a few milliseconds, the call to BeginTransaction() should not have
53 // returned.
54 EXPECT_FALSE(
55 transaction_began_.TimedWait(TimeDelta::FromMilliseconds(250)));
56 }
57
58 private:
59 PriorityQueue* const priority_queue_;
60 WaitableEvent transaction_began_;
61
62 DISALLOW_COPY_AND_ASSIGN(ThreadBeginningTransaction);
63 };
64
65 void ExpectSequenceAndSortKeyEq(
66 const PriorityQueue::SequenceAndSortKey& expected,
67 const PriorityQueue::SequenceAndSortKey& actual) {
68 EXPECT_EQ(expected.sequence, actual.sequence);
69 EXPECT_EQ(expected.sort_key.priority, actual.sort_key.priority);
70 EXPECT_EQ(expected.sort_key.next_task_sequenced_time,
71 actual.sort_key.next_task_sequenced_time);
72 }
73
74 #define EXPECT_SEQUENCE_AND_SORT_KEY_EQ(expected, actual) \
75 do { \
76 SCOPED_TRACE(""); \
77 ExpectSequenceAndSortKeyEq(expected, actual); \
78 } while (false)
79
80 } // namespace
81
82 TEST(TaskSchedulerPriorityQueueTest, PushPopPeek) {
83 // Create test sequences.
84 scoped_refptr<Sequence> sequence_a(new Sequence);
85 sequence_a->PushTask(make_scoped_ptr(
86 new Task(FROM_HERE, Closure(),
87 TaskTraits().WithPriority(TaskPriority::USER_VISIBLE))));
88 SequenceSortKey sort_key_a = sequence_a->GetSortKey();
89
90 scoped_refptr<Sequence> sequence_b(new Sequence);
91 sequence_b->PushTask(make_scoped_ptr(
92 new Task(FROM_HERE, Closure(),
93 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING))));
94 SequenceSortKey sort_key_b = sequence_b->GetSortKey();
95
96 scoped_refptr<Sequence> sequence_c(new Sequence);
97 sequence_c->PushTask(make_scoped_ptr(
98 new Task(FROM_HERE, Closure(),
99 TaskTraits().WithPriority(TaskPriority::USER_BLOCKING))));
100 SequenceSortKey sort_key_c = sequence_c->GetSortKey();
101
102 scoped_refptr<Sequence> sequence_d(new Sequence);
103 sequence_d->PushTask(make_scoped_ptr(
104 new Task(FROM_HERE, Closure(),
105 TaskTraits().WithPriority(TaskPriority::BACKGROUND))));
106 SequenceSortKey sort_key_d = sequence_d->GetSortKey();
107
108 // Create a PriorityQueue and a Transaction.
109 testing::StrictMock<PriorityQueueCallbackMock> mock;
110 PriorityQueue pq(
111 Bind(&PriorityQueueCallbackMock::SequenceInsertedInPriorityQueue,
112 Unretained(&mock)));
113 scoped_ptr<PriorityQueue::Transaction> transaction(pq.BeginTransaction());
114 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(),
115 transaction->Peek());
116
117 // Push |sequence_a| in the PriorityQueue. It becomes the sequence with the
118 // highest priority.
119 transaction->Push(make_scoped_ptr(
120 new PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a)));
121 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
122 PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a),
123 transaction->Peek());
124
125 // Push |sequence_b| in the PriorityQueue. It becomes the sequence with the
126 // highest priority.
127 transaction->Push(make_scoped_ptr(
128 new PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b)));
129 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
130 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b),
131 transaction->Peek());
132
133 // Push |sequence_c| in the PriorityQueue. |sequence_b| is still the sequence
134 // with the highest priority.
135 transaction->Push(make_scoped_ptr(
136 new PriorityQueue::SequenceAndSortKey(sequence_c, sort_key_c)));
137 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
138 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b),
139 transaction->Peek());
140
141 // Push |sequence_d| in the PriorityQueue. |sequence_b| is still the sequence
142 // with the highest priority.
143 transaction->Push(make_scoped_ptr(
144 new PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d)));
145 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
146 PriorityQueue::SequenceAndSortKey(sequence_b, sort_key_b),
147 transaction->Peek());
148
149 // Pop |sequence_b| from the PriorityQueue. |sequence_c| becomes the sequence
150 // with the highest priority.
151 transaction->Pop();
152 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
153 PriorityQueue::SequenceAndSortKey(sequence_c, sort_key_c),
154 transaction->Peek());
155
156 // Pop |sequence_c| from the PriorityQueue. |sequence_a| becomes the sequence
157 // with the highest priority.
158 transaction->Pop();
159 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
160 PriorityQueue::SequenceAndSortKey(sequence_a, sort_key_a),
161 transaction->Peek());
162
163 // Pop |sequence_a| from the PriorityQueue. |sequence_d| becomes the sequence
164 // with the highest priority.
165 transaction->Pop();
166 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(
167 PriorityQueue::SequenceAndSortKey(sequence_d, sort_key_d),
168 transaction->Peek());
169
170 // Pop |sequence_d| from the PriorityQueue. It is now empty.
171 transaction->Pop();
172 EXPECT_SEQUENCE_AND_SORT_KEY_EQ(PriorityQueue::SequenceAndSortKey(),
173 transaction->Peek());
174
175 // Expect 4 calls to mock.SequenceInsertedInPriorityQueue() when the
176 // Transaction is destroyed.
177 EXPECT_CALL(mock, SequenceInsertedInPriorityQueue()).Times(4);
178 transaction.reset();
179 }
180
181 // Check that creating Transactions on the same thread for 2 unrelated
182 // PriorityQueues causes a crash.
183 TEST(TaskSchedulerPriorityQueueTest, IllegalTwoTransactionsSameThread) {
184 PriorityQueue pq_a(Bind(&DoNothing));
185 PriorityQueue pq_b(Bind(&DoNothing));
186
187 EXPECT_DCHECK_DEATH(
188 {
189 scoped_ptr<PriorityQueue::Transaction> transaction_a =
190 pq_a.BeginTransaction();
191 scoped_ptr<PriorityQueue::Transaction> transaction_b =
192 pq_b.BeginTransaction();
193 },
194 "");
195 }
196
197 // Check that there is no crash when Transactions are created on the same thread
198 // for 2 PriorityQueues which have a predecessor relationship.
199 TEST(TaskSchedulerPriorityQueueTest, LegalTwoTransactionsSameThread) {
200 PriorityQueue pq_a(Bind(&DoNothing));
201 PriorityQueue pq_b(Bind(&DoNothing), &pq_a);
202
203 // This shouldn't crash.
204 scoped_ptr<PriorityQueue::Transaction> transaction_a =
205 pq_a.BeginTransaction();
206 scoped_ptr<PriorityQueue::Transaction> transaction_b =
207 pq_b.BeginTransaction();
208 }
209
210 // Check that it is possible to begin multiple Transactions for the same
211 // PriorityQueue on different threads. The call to BeginTransaction() on the
212 // second thread should block until the Transaction has ended on the first
213 // thread.
214 TEST(TaskSchedulerPriorityQueueTest, TwoTransactionsTwoThreads) {
215 PriorityQueue pq(Bind(&DoNothing));
216
217 // Call BeginTransaction() on this thread and keep the Transaction alive.
218 scoped_ptr<PriorityQueue::Transaction> transaction = pq.BeginTransaction();
219
220 // Call BeginTransaction() on another thread.
221 ThreadBeginningTransaction thread_beginning_transaction(&pq);
222 thread_beginning_transaction.Start();
223
224 // After a few milliseconds, the call to BeginTransaction() on the other
225 // thread should not have returned.
226 thread_beginning_transaction.ExpectTransactionDoesNotBegin();
227
228 // End the Transaction on the current thread.
229 transaction.reset();
230
231 // The other thread should exit after its call to BeginTransaction() returns.
232 thread_beginning_transaction.Join();
233 }
234
235 TEST(TaskSchedulerPriorityQueueTest, SequenceAndSortKeyIsNull) {
236 EXPECT_TRUE(PriorityQueue::SequenceAndSortKey().is_null());
237
238 const PriorityQueue::SequenceAndSortKey non_null_sequence_andsort_key(
239 make_scoped_refptr(new Sequence),
240 SequenceSortKey(TaskPriority::USER_VISIBLE, TimeTicks()));
241 EXPECT_FALSE(non_null_sequence_andsort_key.is_null());
242 }
243
244 } // namespace internal
245 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/priority_queue.cc ('k') | base/task_scheduler/scheduler_lock_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698