roll skia to 4276
[chromium-blink-merge.git] / net / base / prioritized_dispatcher_unittest.cc
blob41a09c5cb920b7967e3eece5756352ea7743f557
1 // Copyright (c) 2012 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.
5 #include <ctype.h>
6 #include <string>
8 #include "base/compiler_specific.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_vector.h"
12 #include "net/base/prioritized_dispatcher.h"
13 #include "net/base/request_priority.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace net {
18 namespace {
20 // We rely on the priority enum values being sequential having starting at 0,
21 // and increasing for higher priorities.
22 COMPILE_ASSERT(MINIMUM_PRIORITY == 0u &&
23 MINIMUM_PRIORITY == IDLE &&
24 IDLE < LOWEST &&
25 LOWEST < HIGHEST &&
26 HIGHEST < NUM_PRIORITIES,
27 priority_indexes_incompatible);
29 class PrioritizedDispatcherTest : public testing::Test {
30 public:
31 typedef PrioritizedDispatcher::Priority Priority;
32 // A job that appends |tag| to |log| when started and '.' when finished.
33 // This is intended to confirm the execution order of a sequence of jobs added
34 // to the dispatcher. Note that finishing order of jobs does not matter.
35 class TestJob : public PrioritizedDispatcher::Job {
36 public:
37 TestJob(PrioritizedDispatcher* dispatcher,
38 char tag,
39 Priority priority,
40 std::string* log)
41 : dispatcher_(dispatcher),
42 tag_(tag),
43 priority_(priority),
44 running_(false),
45 log_(log) {}
47 bool running() const {
48 return running_;
51 const PrioritizedDispatcher::Handle handle() const {
52 return handle_;
55 void Add() {
56 CHECK(handle_.is_null());
57 CHECK(!running_);
58 size_t num_queued = dispatcher_->num_queued_jobs();
59 size_t num_running = dispatcher_->num_running_jobs();
61 handle_ = dispatcher_->Add(this, priority_);
63 if (handle_.is_null()) {
64 EXPECT_EQ(num_queued, dispatcher_->num_queued_jobs());
65 EXPECT_TRUE(running_);
66 EXPECT_EQ(num_running + 1, dispatcher_->num_running_jobs());
67 } else {
68 EXPECT_FALSE(running_);
69 EXPECT_EQ(priority_, handle_.priority());
70 EXPECT_EQ(tag_, reinterpret_cast<TestJob*>(handle_.value())->tag_);
71 EXPECT_EQ(num_running, dispatcher_->num_running_jobs());
75 void ChangePriority(Priority priority) {
76 CHECK(!handle_.is_null());
77 CHECK(!running_);
78 size_t num_queued = dispatcher_->num_queued_jobs();
79 size_t num_running = dispatcher_->num_running_jobs();
81 handle_ = dispatcher_->ChangePriority(handle_, priority);
83 if (handle_.is_null()) {
84 EXPECT_TRUE(running_);
85 EXPECT_EQ(num_queued - 1, dispatcher_->num_queued_jobs());
86 EXPECT_EQ(num_running + 1, dispatcher_->num_running_jobs());
87 } else {
88 EXPECT_FALSE(running_);
89 EXPECT_EQ(priority, handle_.priority());
90 EXPECT_EQ(tag_, reinterpret_cast<TestJob*>(handle_.value())->tag_);
91 EXPECT_EQ(num_queued, dispatcher_->num_queued_jobs());
92 EXPECT_EQ(num_running, dispatcher_->num_running_jobs());
96 void Cancel() {
97 CHECK(!handle_.is_null());
98 CHECK(!running_);
99 size_t num_queued = dispatcher_->num_queued_jobs();
101 dispatcher_->Cancel(handle_);
103 EXPECT_EQ(num_queued - 1, dispatcher_->num_queued_jobs());
104 handle_ = PrioritizedDispatcher::Handle();
107 void Finish() {
108 CHECK(running_);
109 running_ = false;
110 log_->append(1u, '.');
112 dispatcher_->OnJobFinished();
115 // PriorityDispatch::Job interface
116 virtual void Start() OVERRIDE {
117 EXPECT_FALSE(running_);
118 handle_ = PrioritizedDispatcher::Handle();
119 running_ = true;
120 log_->append(1u, tag_);
123 private:
124 PrioritizedDispatcher* dispatcher_;
126 char tag_;
127 Priority priority_;
129 PrioritizedDispatcher::Handle handle_;
130 bool running_;
132 std::string* log_;
135 protected:
136 void Prepare(const PrioritizedDispatcher::Limits& limits) {
137 dispatcher_.reset(new PrioritizedDispatcher(limits));
140 TestJob* AddJob(char data, Priority priority) {
141 TestJob* job = new TestJob(dispatcher_.get(), data, priority, &log_);
142 jobs_.push_back(job);
143 job->Add();
144 return job;
147 void Expect(std::string log) {
148 EXPECT_EQ(0u, dispatcher_->num_queued_jobs());
149 EXPECT_EQ(0u, dispatcher_->num_running_jobs());
150 EXPECT_EQ(log, log_);
151 log_.clear();
154 std::string log_;
155 scoped_ptr<PrioritizedDispatcher> dispatcher_;
156 ScopedVector<TestJob> jobs_;
159 TEST_F(PrioritizedDispatcherTest, AddAFIFO) {
160 // Allow only one running job.
161 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
162 Prepare(limits);
164 TestJob* job_a = AddJob('a', IDLE);
165 TestJob* job_b = AddJob('b', IDLE);
166 TestJob* job_c = AddJob('c', IDLE);
167 TestJob* job_d = AddJob('d', IDLE);
169 ASSERT_TRUE(job_a->running());
170 job_a->Finish();
171 ASSERT_TRUE(job_b->running());
172 job_b->Finish();
173 ASSERT_TRUE(job_c->running());
174 job_c->Finish();
175 ASSERT_TRUE(job_d->running());
176 job_d->Finish();
178 Expect("a.b.c.d.");
181 TEST_F(PrioritizedDispatcherTest, AddPriority) {
182 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
183 Prepare(limits);
185 TestJob* job_a = AddJob('a', IDLE);
186 TestJob* job_b = AddJob('b', MEDIUM);
187 TestJob* job_c = AddJob('c', HIGHEST);
188 TestJob* job_d = AddJob('d', HIGHEST);
189 TestJob* job_e = AddJob('e', MEDIUM);
191 ASSERT_TRUE(job_a->running());
192 job_a->Finish();
193 ASSERT_TRUE(job_c->running());
194 job_c->Finish();
195 ASSERT_TRUE(job_d->running());
196 job_d->Finish();
197 ASSERT_TRUE(job_b->running());
198 job_b->Finish();
199 ASSERT_TRUE(job_e->running());
200 job_e->Finish();
202 Expect("a.c.d.b.e.");
205 TEST_F(PrioritizedDispatcherTest, EnforceLimits) {
206 // Reserve 2 for HIGHEST and 1 for LOW or higher.
207 // This leaves 2 for LOWEST or lower.
208 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 5);
209 limits.reserved_slots[HIGHEST] = 2;
210 limits.reserved_slots[LOW] = 1;
211 Prepare(limits);
213 TestJob* job_a = AddJob('a', IDLE); // Uses unreserved slot.
214 TestJob* job_b = AddJob('b', IDLE); // Uses unreserved slot.
215 TestJob* job_c = AddJob('c', LOWEST); // Must wait.
216 TestJob* job_d = AddJob('d', LOW); // Uses reserved slot.
217 TestJob* job_e = AddJob('e', MEDIUM); // Must wait.
218 TestJob* job_f = AddJob('f', HIGHEST); // Uses reserved slot.
219 TestJob* job_g = AddJob('g', HIGHEST); // Uses reserved slot.
220 TestJob* job_h = AddJob('h', HIGHEST); // Must wait.
222 EXPECT_EQ(5u, dispatcher_->num_running_jobs());
223 EXPECT_EQ(3u, dispatcher_->num_queued_jobs());
225 ASSERT_TRUE(job_a->running());
226 ASSERT_TRUE(job_b->running());
227 ASSERT_TRUE(job_d->running());
228 ASSERT_TRUE(job_f->running());
229 ASSERT_TRUE(job_g->running());
230 // a, b, d, f, g are running. Finish them in any order.
231 job_b->Finish(); // Releases h.
232 job_f->Finish();
233 job_a->Finish();
234 job_g->Finish(); // Releases e.
235 job_d->Finish();
236 ASSERT_TRUE(job_e->running());
237 ASSERT_TRUE(job_h->running());
238 // h, e are running.
239 job_e->Finish(); // Releases c.
240 ASSERT_TRUE(job_c->running());
241 job_c->Finish();
242 job_h->Finish();
244 Expect("abdfg.h...e..c..");
247 TEST_F(PrioritizedDispatcherTest, ChangePriority) {
248 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
249 Prepare(limits);
251 TestJob* job_a = AddJob('a', IDLE);
252 TestJob* job_b = AddJob('b', MEDIUM);
253 TestJob* job_c = AddJob('c', HIGHEST);
254 TestJob* job_d = AddJob('d', HIGHEST);
256 ASSERT_FALSE(job_b->running());
257 ASSERT_FALSE(job_c->running());
258 job_b->ChangePriority(HIGHEST);
259 job_c->ChangePriority(MEDIUM);
261 ASSERT_TRUE(job_a->running());
262 job_a->Finish();
263 ASSERT_TRUE(job_d->running());
264 job_d->Finish();
265 ASSERT_TRUE(job_b->running());
266 job_b->Finish();
267 ASSERT_TRUE(job_c->running());
268 job_c->Finish();
270 Expect("a.d.b.c.");
273 TEST_F(PrioritizedDispatcherTest, Cancel) {
274 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
275 Prepare(limits);
277 TestJob* job_a = AddJob('a', IDLE);
278 TestJob* job_b = AddJob('b', IDLE);
279 TestJob* job_c = AddJob('c', IDLE);
280 TestJob* job_d = AddJob('d', IDLE);
281 TestJob* job_e = AddJob('e', IDLE);
283 ASSERT_FALSE(job_b->running());
284 ASSERT_FALSE(job_d->running());
285 job_b->Cancel();
286 job_d->Cancel();
288 ASSERT_TRUE(job_a->running());
289 job_a->Finish();
290 ASSERT_TRUE(job_c->running());
291 job_c->Finish();
292 ASSERT_TRUE(job_e->running());
293 job_e->Finish();
295 Expect("a.c.e.");
298 TEST_F(PrioritizedDispatcherTest, Evict) {
299 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
300 Prepare(limits);
302 TestJob* job_a = AddJob('a', IDLE);
303 TestJob* job_b = AddJob('b', LOW);
304 TestJob* job_c = AddJob('c', HIGHEST);
305 TestJob* job_d = AddJob('d', LOW);
306 TestJob* job_e = AddJob('e', HIGHEST);
308 EXPECT_EQ(job_b, dispatcher_->EvictOldestLowest());
309 EXPECT_EQ(job_d, dispatcher_->EvictOldestLowest());
311 ASSERT_TRUE(job_a->running());
312 job_a->Finish();
313 ASSERT_TRUE(job_c->running());
314 job_c->Finish();
315 ASSERT_TRUE(job_e->running());
316 job_e->Finish();
318 Expect("a.c.e.");
321 TEST_F(PrioritizedDispatcherTest, EvictFromEmpty) {
322 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
323 Prepare(limits);
324 EXPECT_TRUE(dispatcher_->EvictOldestLowest() == NULL);
327 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
328 TEST_F(PrioritizedDispatcherTest, CancelNull) {
329 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
330 Prepare(limits);
331 EXPECT_DEBUG_DEATH(dispatcher_->Cancel(PrioritizedDispatcher::Handle()), "");
334 TEST_F(PrioritizedDispatcherTest, CancelMissing) {
335 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
336 Prepare(limits);
337 AddJob('a', IDLE);
338 TestJob* job_b = AddJob('b', IDLE);
339 PrioritizedDispatcher::Handle handle = job_b->handle();
340 ASSERT_FALSE(handle.is_null());
341 dispatcher_->Cancel(handle);
342 EXPECT_DEBUG_DEATH(dispatcher_->Cancel(handle), "");
345 // TODO(szym): Fix the PriorityQueue::Pointer check to die here.
346 // http://crbug.com/130846
347 TEST_F(PrioritizedDispatcherTest, DISABLED_CancelIncompatible) {
348 PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1);
349 Prepare(limits);
350 AddJob('a', IDLE);
351 TestJob* job_b = AddJob('b', IDLE);
352 PrioritizedDispatcher::Handle handle = job_b->handle();
353 ASSERT_FALSE(handle.is_null());
355 // New dispatcher.
356 Prepare(limits);
357 AddJob('a', IDLE);
358 AddJob('b', IDLE);
359 EXPECT_DEBUG_DEATH(dispatcher_->Cancel(handle), "");
361 #endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
363 } // namespace
365 } // namespace net