OLD | NEW |
| (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/scheduler_worker_thread_stack.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/ptr_util.h" | |
9 #include "base/memory/ref_counted.h" | |
10 #include "base/task_scheduler/scheduler_worker_thread.h" | |
11 #include "base/task_scheduler/sequence.h" | |
12 #include "base/task_scheduler/task_tracker.h" | |
13 #include "base/task_scheduler/test_utils.h" | |
14 #include "base/threading/platform_thread.h" | |
15 #include "base/time/time.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 namespace base { | |
19 namespace internal { | |
20 | |
21 namespace { | |
22 | |
23 class MockSchedulerWorkerThreadDelegate | |
24 : public SchedulerWorkerThread::Delegate { | |
25 public: | |
26 void OnMainEntry(SchedulerWorkerThread* worker_thread) override {} | |
27 scoped_refptr<Sequence> GetWork( | |
28 SchedulerWorkerThread* worker_thread) override { | |
29 return nullptr; | |
30 } | |
31 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { | |
32 ADD_FAILURE() << "This delegate not expect to have sequences to reenqueue."; | |
33 } | |
34 TimeDelta GetSleepTimeout() override { | |
35 ADD_FAILURE() << | |
36 "The mock thread is not expected to be woken before it is shutdown"; | |
37 return TimeDelta::Max(); | |
38 } | |
39 }; | |
40 | |
41 class TaskSchedulerWorkerThreadStackTest : public testing::Test { | |
42 protected: | |
43 void SetUp() override { | |
44 thread_a_ = SchedulerWorkerThread::Create( | |
45 ThreadPriority::NORMAL, | |
46 WrapUnique(new MockSchedulerWorkerThreadDelegate), &task_tracker_); | |
47 ASSERT_TRUE(thread_a_); | |
48 thread_b_ = SchedulerWorkerThread::Create( | |
49 ThreadPriority::NORMAL, | |
50 WrapUnique(new MockSchedulerWorkerThreadDelegate), &task_tracker_); | |
51 ASSERT_TRUE(thread_b_); | |
52 thread_c_ = SchedulerWorkerThread::Create( | |
53 ThreadPriority::NORMAL, | |
54 WrapUnique(new MockSchedulerWorkerThreadDelegate), &task_tracker_); | |
55 ASSERT_TRUE(thread_c_); | |
56 } | |
57 | |
58 void TearDown() override { | |
59 thread_a_->JoinForTesting(); | |
60 thread_b_->JoinForTesting(); | |
61 thread_c_->JoinForTesting(); | |
62 } | |
63 | |
64 std::unique_ptr<SchedulerWorkerThread> thread_a_; | |
65 std::unique_ptr<SchedulerWorkerThread> thread_b_; | |
66 std::unique_ptr<SchedulerWorkerThread> thread_c_; | |
67 | |
68 private: | |
69 TaskTracker task_tracker_; | |
70 }; | |
71 | |
72 } // namespace | |
73 | |
74 // Verify that Push() and Pop() add/remove values in FIFO order. | |
75 TEST_F(TaskSchedulerWorkerThreadStackTest, PushPop) { | |
76 SchedulerWorkerThreadStack stack; | |
77 EXPECT_TRUE(stack.IsEmpty()); | |
78 EXPECT_EQ(0U, stack.Size()); | |
79 | |
80 stack.Push(thread_a_.get()); | |
81 EXPECT_FALSE(stack.IsEmpty()); | |
82 EXPECT_EQ(1U, stack.Size()); | |
83 | |
84 stack.Push(thread_b_.get()); | |
85 EXPECT_FALSE(stack.IsEmpty()); | |
86 EXPECT_EQ(2U, stack.Size()); | |
87 | |
88 stack.Push(thread_c_.get()); | |
89 EXPECT_FALSE(stack.IsEmpty()); | |
90 EXPECT_EQ(3U, stack.Size()); | |
91 | |
92 EXPECT_EQ(thread_c_.get(), stack.Pop()); | |
93 EXPECT_FALSE(stack.IsEmpty()); | |
94 EXPECT_EQ(2U, stack.Size()); | |
95 | |
96 stack.Push(thread_c_.get()); | |
97 EXPECT_FALSE(stack.IsEmpty()); | |
98 EXPECT_EQ(3U, stack.Size()); | |
99 | |
100 EXPECT_EQ(thread_c_.get(), stack.Pop()); | |
101 EXPECT_FALSE(stack.IsEmpty()); | |
102 EXPECT_EQ(2U, stack.Size()); | |
103 | |
104 EXPECT_EQ(thread_b_.get(), stack.Pop()); | |
105 EXPECT_FALSE(stack.IsEmpty()); | |
106 EXPECT_EQ(1U, stack.Size()); | |
107 | |
108 EXPECT_EQ(thread_a_.get(), stack.Pop()); | |
109 EXPECT_TRUE(stack.IsEmpty()); | |
110 EXPECT_EQ(0U, stack.Size()); | |
111 } | |
112 | |
113 // Verify that a value can be removed by Remove(). | |
114 TEST_F(TaskSchedulerWorkerThreadStackTest, Remove) { | |
115 SchedulerWorkerThreadStack stack; | |
116 EXPECT_TRUE(stack.IsEmpty()); | |
117 EXPECT_EQ(0U, stack.Size()); | |
118 | |
119 stack.Push(thread_a_.get()); | |
120 EXPECT_FALSE(stack.IsEmpty()); | |
121 EXPECT_EQ(1U, stack.Size()); | |
122 | |
123 stack.Push(thread_b_.get()); | |
124 EXPECT_FALSE(stack.IsEmpty()); | |
125 EXPECT_EQ(2U, stack.Size()); | |
126 | |
127 stack.Push(thread_c_.get()); | |
128 EXPECT_FALSE(stack.IsEmpty()); | |
129 EXPECT_EQ(3U, stack.Size()); | |
130 | |
131 stack.Remove(thread_b_.get()); | |
132 EXPECT_FALSE(stack.IsEmpty()); | |
133 EXPECT_EQ(2U, stack.Size()); | |
134 | |
135 EXPECT_EQ(thread_c_.get(), stack.Pop()); | |
136 EXPECT_FALSE(stack.IsEmpty()); | |
137 EXPECT_EQ(1U, stack.Size()); | |
138 | |
139 EXPECT_EQ(thread_a_.get(), stack.Pop()); | |
140 EXPECT_TRUE(stack.IsEmpty()); | |
141 EXPECT_EQ(0U, stack.Size()); | |
142 } | |
143 | |
144 // Verify that a value can be pushed again after it has been removed. | |
145 TEST_F(TaskSchedulerWorkerThreadStackTest, PushAfterRemove) { | |
146 SchedulerWorkerThreadStack stack; | |
147 EXPECT_EQ(0U, stack.Size()); | |
148 EXPECT_TRUE(stack.IsEmpty()); | |
149 | |
150 stack.Push(thread_a_.get()); | |
151 EXPECT_EQ(1U, stack.Size()); | |
152 EXPECT_FALSE(stack.IsEmpty()); | |
153 | |
154 stack.Remove(thread_a_.get()); | |
155 EXPECT_EQ(0U, stack.Size()); | |
156 EXPECT_TRUE(stack.IsEmpty()); | |
157 | |
158 stack.Push(thread_a_.get()); | |
159 EXPECT_EQ(1U, stack.Size()); | |
160 EXPECT_FALSE(stack.IsEmpty()); | |
161 } | |
162 | |
163 // Verify that Push() DCHECKs when a value is inserted twice. | |
164 TEST_F(TaskSchedulerWorkerThreadStackTest, PushTwice) { | |
165 SchedulerWorkerThreadStack stack; | |
166 stack.Push(thread_a_.get()); | |
167 EXPECT_DCHECK_DEATH({ stack.Push(thread_a_.get()); }, ""); | |
168 } | |
169 | |
170 } // namespace internal | |
171 } // namespace base | |
OLD | NEW |