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

Side by Side Diff: content/renderer/resource_dispatch_throttler_unittest.cc

Issue 847883002: Reland "Throttle resource message requests during user interaction" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup Created 5 years, 11 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
OLDNEW
(Empty)
1 // Copyright 2014 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 "content/renderer/resource_dispatch_throttler.h"
6
7 #include "base/memory/scoped_vector.h"
8 #include "content/common/resource_messages.h"
9 #include "content/test/fake_renderer_scheduler.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace content {
13 namespace {
14
15 const uint32 kRequestsPerFlush = 4;
16 const double kFlushPeriodSeconds = 1.f / 60;
17 const int kRoutingId = 1;
18
19 typedef ScopedVector<IPC::Message> ScopedMessages;
20
21 class SenderSink : public IPC::Sender {
22 public:
23 SenderSink(ScopedMessages* sent_messages) : sent_messages_(sent_messages) {}
24
25 // IPC::Sender implementation:
26 bool Send(IPC::Message* msg) override {
27 sent_messages_->push_back(msg);
28 return true;
29 }
30
31 private:
32 ScopedMessages* sent_messages_;
33 };
34
35 } // namespace
36
37 class ResourceDispatchThrottlerTest : public testing::Test,
38 public FakeRendererScheduler,
39 public ResourceDispatchThrottler {
40 public:
41 ResourceDispatchThrottlerTest()
42 : ResourceDispatchThrottler(
43 &sender_sink_,
44 this,
45 base::TimeDelta::FromSecondsD(kFlushPeriodSeconds),
46 kRequestsPerFlush),
47 sender_sink_(&sent_messages_),
48 flush_scheduled_(false),
49 anticipate_(false),
50 last_request_id_(0) {}
51 ~ResourceDispatchThrottlerTest() override {}
52
53 // RendererScheduler implementation:
54 bool ShouldAnticipateHighPriorityWork() override { return anticipate_; }
55
56 protected:
57 base::TimeTicks Now() const override { return now_; }
58
59 void ScheduleFlush() override { flush_scheduled_ = true; }
60
61 void SetShouldAnticipateHighPriorityWork(bool anticipate) {
62 anticipate_ = anticipate;
63 }
64
65 void Advance(base::TimeDelta delta) { now_ += delta; }
66
67 bool RunScheduledFlush() {
68 if (!flush_scheduled_)
69 return false;
70
71 flush_scheduled_ = false;
72 Flush();
73 return true;
74 }
75
76 bool RequestResource() {
77 ResourceHostMsg_Request request;
78 request.download_to_file = true;
79 return Send(new ResourceHostMsg_RequestResource(
80 kRoutingId, ++last_request_id_, request));
81 }
82
83 void RequestResourcesUntilThrottled() {
84 SetShouldAnticipateHighPriorityWork(true);
85 GetAndResetSentMessageCount();
86 for (RequestResource(); GetAndResetSentMessageCount(); RequestResource()) {
87 }
88 }
89
90 bool UpdateRequestPriority(int request_id, net::RequestPriority priority) {
91 return Send(new ResourceHostMsg_DidChangePriority(request_id, priority, 0));
92 }
93
94 bool ReleaseDownloadedFile(int request_id) {
95 return Send(new ResourceHostMsg_ReleaseDownloadedFile(request_id));
96 }
97
98 bool CancelRequest(int request_id) {
99 return Send(new ResourceHostMsg_CancelRequest(request_id));
100 }
101
102 bool RequestResourceSync() {
103 SyncLoadResult result;
104 return Send(new ResourceHostMsg_SyncLoad(
105 kRoutingId, ++last_request_id_, ResourceHostMsg_Request(), &result));
106 }
107
108 size_t GetAndResetSentMessageCount() {
109 size_t sent_message_count = sent_messages_.size();
110 sent_messages_.clear();
111 return sent_message_count;
112 }
113
114 const IPC::Message* LastSentMessage() const {
115 return sent_messages_.empty() ? nullptr : sent_messages_.back();
116 }
117
118 int LastSentRequestId() const {
119 const IPC::Message* msg = LastSentMessage();
120 if (!msg)
121 return -1;
122
123 int routing_id = -1;
124 int request_id = -1;
125 PickleIterator iter(*msg);
126 CHECK(IPC::ReadParam(msg, &iter, &routing_id));
127 CHECK(IPC::ReadParam(msg, &iter, &request_id));
128 return request_id;
129 }
130
131 int last_request_id() const { return last_request_id_; }
132
133 ScopedMessages sent_messages_;
134
135 private:
136 SenderSink sender_sink_;
137 base::MessageLoopForUI message_loop_;
138 base::TimeTicks now_;
139 bool flush_scheduled_;
140 bool anticipate_;
141 int last_request_id_;
142
143 DISALLOW_COPY_AND_ASSIGN(ResourceDispatchThrottlerTest);
144 };
145
146 TEST_F(ResourceDispatchThrottlerTest, NotThrottledByDefault) {
147 SetShouldAnticipateHighPriorityWork(false);
148 for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
149 RequestResource();
150 EXPECT_EQ(i + 1, sent_messages_.size());
151 }
152 }
153
154 TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendLimitNotReached) {
155 SetShouldAnticipateHighPriorityWork(true);
156 for (size_t i = 0; i < kRequestsPerFlush; ++i) {
157 RequestResource();
158 EXPECT_EQ(i + 1, sent_messages_.size());
159 }
160 }
161
162 TEST_F(ResourceDispatchThrottlerTest, ThrottledWhenHighPriorityWork) {
163 SetShouldAnticipateHighPriorityWork(true);
164 for (size_t i = 0; i < kRequestsPerFlush; ++i)
165 RequestResource();
166 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
167
168 RequestResource();
169 EXPECT_EQ(0U, sent_messages_.size());
170
171 EXPECT_TRUE(RunScheduledFlush());
172 EXPECT_EQ(1U, sent_messages_.size());
173 }
174
175 TEST_F(ResourceDispatchThrottlerTest,
176 ThrottledWhenDeferredMessageQueueNonEmpty) {
177 SetShouldAnticipateHighPriorityWork(true);
178 for (size_t i = 0; i < kRequestsPerFlush; ++i)
179 RequestResource();
180 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
181
182 RequestResource();
183 EXPECT_EQ(0U, sent_messages_.size());
184 SetShouldAnticipateHighPriorityWork(false);
185 RequestResource();
186 EXPECT_EQ(0U, sent_messages_.size());
187
188 EXPECT_TRUE(RunScheduledFlush());
189 EXPECT_EQ(2U, sent_messages_.size());
190 }
191
192 TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSufficientTimePassed) {
193 SetShouldAnticipateHighPriorityWork(true);
194
195 for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
196 Advance(base::TimeDelta::FromSecondsD(kFlushPeriodSeconds * 2));
197 RequestResource();
198 EXPECT_EQ(1U, GetAndResetSentMessageCount());
199 EXPECT_FALSE(RunScheduledFlush());
200 }
201 }
202
203 TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfUnthrottledMessageType) {
204 SetShouldAnticipateHighPriorityWork(true);
205
206 RequestResourceSync();
207 EXPECT_EQ(1U, GetAndResetSentMessageCount());
208
209 // Saturate the queue.
210 for (size_t i = 0; i < kRequestsPerFlush * 2; ++i)
211 RequestResource();
212 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
213
214 // Unthrottled message types should pass through untouched.
215 RequestResourceSync();
216 EXPECT_EQ(1U, GetAndResetSentMessageCount());
217 RequestResourceSync();
218 EXPECT_EQ(1U, GetAndResetSentMessageCount());
219
220 // Deferred messages should flush as usual.
221 EXPECT_TRUE(RunScheduledFlush());
222 EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
223 }
224
225 TEST_F(ResourceDispatchThrottlerTest, MultipleFlushes) {
226 SetShouldAnticipateHighPriorityWork(true);
227 for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
228 RequestResource();
229 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
230
231 for (size_t i = 0; i < 3; ++i) {
232 EXPECT_TRUE(RunScheduledFlush());
233 EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount()) << i;
234 }
235
236 EXPECT_FALSE(RunScheduledFlush());
237 EXPECT_EQ(0U, sent_messages_.size());
238 }
239
240 TEST_F(ResourceDispatchThrottlerTest, MultipleFlushesWhileReceiving) {
241 SetShouldAnticipateHighPriorityWork(true);
242 for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
243 RequestResource();
244 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
245
246 for (size_t i = 0; i < 3; ++i) {
247 EXPECT_TRUE(RunScheduledFlush());
248 EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount()) << i;
249 for (size_t j = 0; j < kRequestsPerFlush; ++j)
250 RequestResource();
251 EXPECT_EQ(0U, sent_messages_.size()) << i;
252 }
253
254 for (size_t i = 0; i < 3; ++i) {
255 EXPECT_TRUE(RunScheduledFlush());
256 EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
257 }
258
259 EXPECT_FALSE(RunScheduledFlush());
260 EXPECT_EQ(0U, sent_messages_.size());
261 }
262
263 TEST_F(ResourceDispatchThrottlerTest, CancelRequest) {
264 RequestResource();
265 ASSERT_EQ(1U, GetAndResetSentMessageCount());
266
267 // Cancel messages for an unthrottled request will be forwarded immediately.
268 CancelRequest(last_request_id());
269 ASSERT_EQ(1U, sent_messages_.size());
270 EXPECT_EQ(ResourceHostMsg_CancelRequest::ID, LastSentMessage()->type());
271
272 RequestResourcesUntilThrottled();
273
274 // The cancelled request should never be sent.
275 CancelRequest(last_request_id());
276 ASSERT_EQ(0U, sent_messages_.size());
277 EXPECT_TRUE(RunScheduledFlush());
278 EXPECT_EQ(0U, sent_messages_.size());
279 }
280
281 TEST_F(ResourceDispatchThrottlerTest, CancelRequestOutOfOrder) {
282 SetShouldAnticipateHighPriorityWork(true);
283 for (size_t i = 0; i < kRequestsPerFlush; ++i)
284 RequestResource();
285 ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
286
287 for (size_t i = 0; i < kRequestsPerFlush; ++i)
288 RequestResource();
289 ASSERT_EQ(0U, sent_messages_.size());
290
291 // Cancel the first and last throttled request, ensuring they're not flushed.
292 CancelRequest(last_request_id());
293 CancelRequest(last_request_id() - 2);
294 EXPECT_TRUE(RunScheduledFlush());
295 ASSERT_EQ(kRequestsPerFlush - 2, sent_messages_.size());
296 EXPECT_EQ(LastSentRequestId(), last_request_id() - 1);
297 }
298
299 TEST_F(ResourceDispatchThrottlerTest, PriorityUpdate) {
300 RequestResource();
301 ASSERT_EQ(1U, GetAndResetSentMessageCount());
302
303 // Priority updates for an unthrottled request will be forwarded immediately.
304 UpdateRequestPriority(last_request_id(), net::HIGHEST);
305 ASSERT_EQ(1U, sent_messages_.size());
306 EXPECT_EQ(ResourceHostMsg_DidChangePriority::ID, LastSentMessage()->type());
307
308 RequestResourcesUntilThrottled();
309
310 // The updated priority should be reflected in the flushed message.
311 UpdateRequestPriority(last_request_id(), net::HIGHEST);
312 ASSERT_EQ(0U, sent_messages_.size());
313 EXPECT_TRUE(RunScheduledFlush());
314 ASSERT_EQ(1U, sent_messages_.size());
315 ResourceHostMsg_RequestResource::Param request_params;
316 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(LastSentMessage(),
317 &request_params));
318 EXPECT_EQ(net::HIGHEST, get<2>(request_params).priority);
319 }
320
321 TEST_F(ResourceDispatchThrottlerTest, ReleaseDownloadFileUpdate) {
322 RequestResource();
323 ASSERT_EQ(1U, GetAndResetSentMessageCount());
324
325 // Download request updates for an unthrottled request will be
326 // immediately.
327 ReleaseDownloadedFile(last_request_id());
328 ASSERT_EQ(1U, sent_messages_.size());
329 EXPECT_EQ(ResourceHostMsg_ReleaseDownloadedFile::ID,
330 LastSentMessage()->type());
331
332 RequestResourcesUntilThrottled();
333
334 // The download request update should be reflected in the flushed message.
335 ReleaseDownloadedFile(last_request_id());
336 ASSERT_EQ(0U, sent_messages_.size());
337 EXPECT_TRUE(RunScheduledFlush());
338 ASSERT_EQ(1U, sent_messages_.size());
339 ResourceHostMsg_RequestResource::Param request_params;
340 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(LastSentMessage(),
341 &request_params));
342 EXPECT_FALSE(get<2>(request_params).download_to_file);
343 }
344
345 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698