OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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 <ctype.h> | |
6 #include <string> | |
7 | |
8 #include "base/compiler_specific.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/memory/scoped_vector.h" | |
11 #include "net/base/priority_dispatch.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace net { | |
15 | |
16 namespace { | |
17 | |
18 class PriorityDispatchTest : public testing::Test { | |
19 public: | |
20 // A job that appends |data| to |log| when started, toupper(|data|) when | |
21 // evicted, and '.' when finished. | |
mmenke
2011/12/21 16:22:58
nit: log_
mmenke
2011/12/21 16:22:58
I think a bit more of an explanation is in order.
szym
2011/12/28 01:24:10
Done.
| |
22 class TestJob : public PriorityDispatch::Job { | |
23 public: | |
24 TestJob(PriorityDispatchTest* test, char data, RequestPriority priority) | |
25 : test_(test), data_(data), priority_(priority), running_(false) {} | |
26 | |
27 // win does not accept EXPECT_EQ(this, ...) so wrap it up. | |
mmenke
2011/12/21 16:22:58
nit: "Windows does not"
szym
2011/12/28 01:24:10
Done.
| |
28 PriorityDispatch::Job* this_job() { | |
29 return this; | |
30 } | |
31 | |
32 void Add() { | |
33 EXPECT_TRUE(handle_.is_null()); | |
34 EXPECT_FALSE(running_); | |
35 size_t num_queued = dispatch().num_queued_jobs(); | |
36 size_t num_running = dispatch().num_running_jobs(); | |
37 | |
38 handle_ = dispatch().Add(this, priority_); | |
39 | |
40 if (handle_.is_null()) { | |
41 EXPECT_EQ(num_queued, dispatch().num_queued_jobs()); | |
42 if (running_) { | |
43 EXPECT_EQ(num_running + 1, dispatch().num_running_jobs()); | |
44 } else { | |
45 // This job got evicted on Add. | |
46 EXPECT_EQ(num_running, dispatch().num_running_jobs()); | |
47 } | |
48 } else { | |
49 EXPECT_FALSE(running_); | |
50 EXPECT_EQ(priority_, handle_.priority()); | |
51 EXPECT_EQ(this_job(), handle_.value()); | |
52 EXPECT_EQ(num_running, dispatch().num_running_jobs()); | |
53 } | |
54 } | |
55 | |
56 void Update(RequestPriority priority) { | |
57 EXPECT_FALSE(running_); | |
58 ASSERT_FALSE(handle_.is_null()); | |
59 size_t num_queued = dispatch().num_queued_jobs(); | |
60 size_t num_running = dispatch().num_running_jobs(); | |
61 | |
62 handle_ = dispatch().Update(handle_, priority); | |
63 | |
64 if (handle_.is_null()) { | |
65 EXPECT_TRUE(running_); | |
66 EXPECT_EQ(num_queued - 1, dispatch().num_queued_jobs()); | |
67 EXPECT_EQ(num_running + 1, dispatch().num_running_jobs()); | |
68 } else { | |
69 EXPECT_FALSE(running_); | |
70 EXPECT_EQ(priority, handle_.priority()); | |
71 EXPECT_EQ(this_job(), handle_.value()); | |
72 EXPECT_EQ(num_queued, dispatch().num_queued_jobs()); | |
73 EXPECT_EQ(num_running, dispatch().num_running_jobs()); | |
74 } | |
75 } | |
76 | |
77 void Cancel() { | |
78 EXPECT_FALSE(running_); | |
79 ASSERT_FALSE(handle_.is_null()); | |
80 size_t num_queued = dispatch().num_queued_jobs(); | |
81 | |
82 dispatch().Cancel(handle_); | |
83 | |
84 EXPECT_EQ(num_queued - 1, dispatch().num_queued_jobs()); | |
85 handle_ = PriorityDispatch::Handle(); | |
86 } | |
87 | |
88 void Finish() { | |
89 EXPECT_TRUE(running_); | |
90 running_ = false; | |
91 test_->log_.append(1u, '.'); | |
92 | |
93 dispatch().OnJobFinished(); | |
94 } | |
95 | |
96 // PriorityDispatch::Job interface | |
97 virtual void Start() OVERRIDE { | |
98 EXPECT_FALSE(running_); | |
99 handle_ = PriorityDispatch::Handle(); | |
100 running_ = true; | |
101 test_->log_.append(1u, data_); | |
102 } | |
103 | |
104 virtual void OnEvicted() OVERRIDE { | |
105 EXPECT_FALSE(running_); | |
106 handle_ = PriorityDispatch::Handle(); | |
107 test_->log_.append(1u, toupper(data_)); | |
108 } | |
109 | |
110 private: | |
111 PriorityDispatch& dispatch() { return *(test_->dispatch_); } | |
112 | |
113 PriorityDispatchTest* test_; | |
114 | |
115 char data_; | |
116 RequestPriority priority_; | |
117 | |
118 PriorityDispatch::Handle handle_; | |
119 bool running_; | |
120 }; | |
121 | |
122 protected: | |
123 friend class TestJob; | |
mmenke
2011/12/21 16:22:58
nit: Don't believe this is needed. Inner classes
szym
2011/12/28 01:24:10
Done.
| |
124 | |
125 void Prepare(const PriorityDispatch::Limits& limits, size_t max_queued) { | |
126 dispatch_.reset(new PriorityDispatch(limits, max_queued)); | |
127 } | |
128 | |
129 TestJob* AddJob(char data, RequestPriority priority) { | |
130 TestJob* job = new TestJob(this, data, priority); | |
131 jobs_.push_back(job); | |
132 job->Add(); | |
133 return job; | |
134 } | |
135 | |
136 void Expect(std::string log) { | |
137 EXPECT_EQ(0u, dispatch_->num_queued_jobs()); | |
138 EXPECT_EQ(0u, dispatch_->num_running_jobs()); | |
139 EXPECT_EQ(log, log_); | |
140 log_.clear(); | |
141 } | |
142 | |
143 std::string log_; | |
144 scoped_ptr<PriorityDispatch> dispatch_; | |
145 ScopedVector<TestJob> jobs_; | |
146 }; | |
147 | |
148 TEST_F(PriorityDispatchTest, AddAFIFO) { | |
149 // Allow only one running job. | |
150 PriorityDispatch::Limits limits = {{0, 0, 0, 0, 1}}; | |
151 Prepare(limits, 1000u); | |
152 | |
153 TestJob* job_a = AddJob('a', IDLE); | |
154 TestJob* job_b = AddJob('b', IDLE); | |
155 TestJob* job_c = AddJob('c', IDLE); | |
156 TestJob* job_d = AddJob('d', IDLE); | |
157 | |
158 job_a->Finish(); | |
159 job_b->Finish(); | |
160 job_c->Finish(); | |
161 job_d->Finish(); | |
162 | |
163 Expect("a.b.c.d."); | |
164 } | |
165 | |
166 TEST_F(PriorityDispatchTest, AddPriority) { | |
167 PriorityDispatch::Limits limits = {{0, 0, 0, 0, 1}}; | |
168 Prepare(limits, 1000u); | |
169 | |
170 TestJob* job_a = AddJob('a', IDLE); | |
171 TestJob* job_b = AddJob('b', MEDIUM); | |
172 TestJob* job_c = AddJob('c', HIGHEST); | |
173 TestJob* job_d = AddJob('d', HIGHEST); | |
174 TestJob* job_e = AddJob('e', MEDIUM); | |
175 | |
176 job_a->Finish(); | |
177 job_c->Finish(); | |
178 job_d->Finish(); | |
179 job_b->Finish(); | |
180 job_e->Finish(); | |
181 | |
182 Expect("a.c.d.b.e."); | |
183 } | |
184 | |
185 TEST_F(PriorityDispatchTest, EnforceLimits) { | |
186 PriorityDispatch::Limits limits = {{2, 0, 1, 0, 2}}; | |
187 Prepare(limits, 1000u); | |
188 | |
189 TestJob* job_a = AddJob('a', IDLE); | |
190 TestJob* job_b = AddJob('b', IDLE); | |
191 TestJob* job_c = AddJob('c', LOWEST); | |
192 TestJob* job_d = AddJob('d', LOW); | |
193 TestJob* job_e = AddJob('e', MEDIUM); | |
194 TestJob* job_f = AddJob('f', HIGHEST); | |
195 TestJob* job_g = AddJob('g', HIGHEST); | |
196 TestJob* job_h = AddJob('h', HIGHEST); | |
197 | |
198 EXPECT_EQ(5u, dispatch_->num_running_jobs()); | |
199 EXPECT_EQ(3u, dispatch_->num_queued_jobs()); | |
200 | |
201 job_a->Finish(); // Releases h. | |
202 job_b->Finish(); | |
203 job_d->Finish(); | |
204 job_f->Finish(); // Releases e. | |
205 job_g->Finish(); | |
206 job_h->Finish(); // Releases c. | |
207 job_e->Finish(); | |
208 job_c->Finish(); | |
209 | |
210 Expect("abdfg.h...e..c.."); | |
211 } | |
212 | |
213 TEST_F(PriorityDispatchTest, Update) { | |
214 PriorityDispatch::Limits limits = {{0, 0, 0, 0, 1}}; | |
215 Prepare(limits, 1000u); | |
216 | |
217 TestJob* job_a = AddJob('a', IDLE); | |
218 TestJob* job_b = AddJob('b', MEDIUM); | |
219 TestJob* job_c = AddJob('c', HIGHEST); | |
220 TestJob* job_d = AddJob('d', HIGHEST); | |
221 | |
222 job_b->Update(HIGHEST); | |
223 job_c->Update(MEDIUM); | |
224 | |
225 job_a->Finish(); | |
226 job_d->Finish(); | |
227 job_b->Finish(); | |
228 job_c->Finish(); | |
229 | |
230 Expect("a.d.b.c."); | |
231 } | |
232 | |
233 TEST_F(PriorityDispatchTest, Cancel) { | |
234 PriorityDispatch::Limits limits = {{0, 0, 0, 0, 1}}; | |
235 Prepare(limits, 1000u); | |
236 | |
237 TestJob* job_a = AddJob('a', IDLE); | |
238 TestJob* job_b = AddJob('b', IDLE); | |
239 TestJob* job_c = AddJob('c', IDLE); | |
240 TestJob* job_d = AddJob('d', IDLE); | |
241 TestJob* job_e = AddJob('e', IDLE); | |
242 | |
243 job_b->Cancel(); | |
244 job_d->Cancel(); | |
245 | |
246 job_a->Finish(); | |
247 job_c->Finish(); | |
248 job_e->Finish(); | |
249 | |
250 Expect("a.c.e."); | |
251 } | |
252 | |
253 TEST_F(PriorityDispatchTest, Evict) { | |
254 PriorityDispatch::Limits limits = {{0, 0, 0, 0, 1}}; | |
255 Prepare(limits, 2u); | |
256 | |
257 // Note that the eviction order is by OldestLowest. | |
258 TestJob* job_a = AddJob('a', LOW); | |
259 AddJob('b', LOW); | |
260 AddJob('c', LOW); | |
261 TestJob* job_d = AddJob('d', LOW); // Evicts b. | |
262 TestJob* job_e = AddJob('e', HIGHEST); // Evicts c. | |
263 AddJob('f', IDLE); // Evicts self. | |
264 | |
265 job_a->Finish(); | |
266 job_e->Finish(); | |
267 job_d->Finish(); | |
268 | |
269 Expect("aBCF.e.d."); | |
270 } | |
271 | |
272 } // namespace | |
273 | |
274 } // namespace net | |
275 | |
OLD | NEW |