OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/browser/download/byte_stream.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback.h" | |
9 #include "base/location.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/message_loop.h" | |
12 #include "base/task_runner.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "testing/gmock/include/gmock/gmock.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 using ::testing::_; | |
18 using ::testing::Return; | |
19 using ::testing::SaveArg; | |
20 using ::testing::StrictMock; | |
21 | |
22 namespace tracked_objects { | |
23 class Location; | |
24 } | |
25 | |
26 namespace { | |
27 | |
28 class MockTaskRunner : public base::SequencedTaskRunner { | |
29 public: | |
30 MockTaskRunner(); | |
31 | |
32 // TaskRunner functions. | |
33 MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&, | |
34 const base::Closure&, int64)); | |
35 MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&, | |
36 const base::Closure&, base::TimeDelta)); | |
37 | |
38 MOCK_METHOD3(PostNonNestableDelayedTask, bool( | |
39 const tracked_objects::Location&, | |
40 const base::Closure&, | |
41 int64 delay_ms)); | |
42 | |
43 MOCK_METHOD3(PostNonNestableDelayedTask, bool( | |
44 const tracked_objects::Location&, | |
45 const base::Closure&, | |
46 base::TimeDelta)); | |
47 | |
48 MOCK_CONST_METHOD0(RunsTasksOnCurrentThread, bool()); | |
49 | |
50 protected: | |
51 ~MockTaskRunner(); | |
52 }; | |
53 | |
54 MockTaskRunner::MockTaskRunner() { } | |
55 | |
56 MockTaskRunner::~MockTaskRunner() { } | |
57 | |
58 static int null_callback_call_count = 0; | |
59 static int alt_callback_call_count = 0; | |
60 | |
61 void NullCallback() { | |
benjhayden
2012/05/16 15:55:57
Would something like this work just as well with l
Randy Smith (Not in Mondays)
2012/05/16 20:30:16
D'oh. Good idea. Done.
| |
62 null_callback_call_count++; | |
63 } | |
64 | |
65 void AltCallback() { | |
66 alt_callback_call_count++; | |
67 } | |
68 | |
69 } // namespace | |
70 | |
71 class ByteStreamTest : public testing::Test { | |
72 public: | |
73 // Create a new IO buffer of the given |buffer_size|, with contents | |
74 // dependent on the |seed_key|. The |seed_key| is also used for comparing | |
75 // pointers between NewIOBuffer and ValidateIOBuffer; do not re-use any | |
76 // |seed_key| value within a single test. | |
benjhayden
2012/05/16 15:55:57
Can you use an internal automatic counter instead
Randy Smith (Not in Mondays)
2012/05/16 20:30:16
I'm a little reluctant to do that, as it implies t
| |
77 scoped_refptr<net::IOBuffer> NewIOBuffer(size_t buffer_size, int seed_key) { | |
78 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(buffer_size)); | |
79 char *bufferp = buffer->data(); | |
80 for (size_t i = 0; i < buffer_size; i++) | |
81 bufferp[i] = (i + seed_key) % (1 << sizeof(char)); | |
82 DCHECK(pointer_map_.find(seed_key) == pointer_map_.end()); | |
83 DCHECK(length_map_.find(seed_key) == length_map_.end()); | |
84 pointer_map_[seed_key] = bufferp; | |
85 length_map_[seed_key] = buffer_size; | |
86 return buffer; | |
87 } | |
88 | |
89 // Create an IOBuffer of the appropriate size and add it to the | |
90 // ByteStream, returning the result of the ByteStream::Write. | |
91 // Separate function to avoid duplication of buffer_size in test | |
92 // calls. | |
93 bool Write(content::ByteStreamInput* byte_stream_input, | |
94 int seed_key, size_t buffer_size) { | |
95 return byte_stream_input->Write(NewIOBuffer(buffer_size, seed_key), | |
96 buffer_size); | |
97 } | |
98 | |
99 // Validate that we have the IOBuffer we expect. This IOBuffer must | |
100 // have been created through NewIOBuffer with the given |buffer_size| | |
101 // and |seed_key|. | |
102 bool ValidateIOBuffer(scoped_refptr<net::IOBuffer> buffer, int seed_key, | |
103 size_t buffer_size) { | |
104 char *bufferp = buffer->data(); | |
105 EXPECT_TRUE(pointer_map_.find(seed_key) != pointer_map_.end()); | |
106 if (pointer_map_.find(seed_key) == pointer_map_.end()) | |
107 return false; | |
108 EXPECT_EQ(bufferp, pointer_map_[seed_key]); | |
109 EXPECT_TRUE(length_map_.find(seed_key) != length_map_.end()); | |
110 if (length_map_.find(seed_key) == length_map_.end()) | |
111 return false; | |
112 EXPECT_EQ(buffer_size, length_map_[seed_key]); | |
113 for (size_t i = 0; i < buffer_size; i++) { | |
114 EXPECT_EQ(static_cast<int>((i + seed_key) % (1 << sizeof(char))), | |
115 bufferp[i]); | |
116 if (static_cast<int>((i + seed_key) % (1 << sizeof(char))) != bufferp[i]) | |
117 return false; | |
118 } | |
119 return true; | |
120 } | |
121 | |
122 protected: | |
123 MessageLoop message_loop_; | |
124 private: | |
benjhayden
2012/05/16 19:17:21
Blank line between sections?
Randy Smith (Not in Mondays)
2012/05/16 20:30:16
Done.
| |
125 std::map<int, char*> pointer_map_; | |
126 std::map<int, size_t> length_map_; | |
127 }; | |
128 | |
129 // Confirm that filling and emptying the pipe works properly, and that | |
130 // we get full triggers when we expect. | |
131 TEST_F(ByteStreamTest, PushBack) { | |
benjhayden
2012/05/16 19:17:21
Would you mind prepending "ByteStream_" to all of
Randy Smith (Not in Mondays)
2012/05/16 20:30:16
It's annoyingly redundant :-{, but I hear your pai
| |
132 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
133 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
134 content::CreateByteStream( | |
135 &byte_stream_input, &byte_stream_output, | |
136 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
137 3 * 1024); | |
138 | |
139 // Push a series of IO buffers on; test pushback happening and | |
140 // that it's advisory. | |
141 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 1024)); | |
142 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 1024)); | |
143 EXPECT_TRUE(Write(byte_stream_input.get(), 2, 1024)); | |
144 EXPECT_FALSE(Write(byte_stream_input.get(), 3, 1)); | |
145 EXPECT_FALSE(Write(byte_stream_input.get(), 4, 1024)); | |
146 // Flush | |
147 byte_stream_input->Close(content::DOWNLOAD_INTERRUPT_REASON_NONE); | |
148 message_loop_.RunAllPending(); | |
149 | |
150 // Pull the IO buffers out; do we get the same buffers and do they | |
151 // have the same contents? | |
152 scoped_refptr<net::IOBuffer> output_io_buffer; | |
153 size_t output_length; | |
154 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
155 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
156 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
157 | |
158 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
159 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
160 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length)); | |
161 | |
162 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
163 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
164 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length)); | |
165 | |
166 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
167 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
168 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 3, output_length)); | |
169 | |
170 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
171 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
172 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 4, output_length)); | |
173 | |
174 EXPECT_EQ(content::ByteStreamOutput::STREAM_COMPLETE, | |
175 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
176 } | |
177 | |
178 // Same as above, only use knowledge of the internals to confirm | |
179 // that we're getting pushback even when data's split across the two | |
180 // objects | |
181 TEST_F(ByteStreamTest, PushBackSplit) { | |
182 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
183 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
184 content::CreateByteStream( | |
185 &byte_stream_input, &byte_stream_output, | |
186 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
187 9 * 1024); | |
188 | |
189 // Push a series of IO buffers on; test pushback happening and | |
190 // that it's advisory. | |
191 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 1024)); | |
192 message_loop_.RunAllPending(); | |
193 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 1024)); | |
194 message_loop_.RunAllPending(); | |
195 EXPECT_TRUE(Write(byte_stream_input.get(), 2, 1024)); | |
196 message_loop_.RunAllPending(); | |
197 EXPECT_TRUE(Write(byte_stream_input.get(), 3, 1024)); | |
198 message_loop_.RunAllPending(); | |
199 EXPECT_FALSE(Write(byte_stream_input.get(), 4, 6 * 1024)); | |
200 message_loop_.RunAllPending(); | |
201 | |
202 // Pull the IO buffers out; do we get the same buffers and do they | |
203 // have the same contents? | |
204 scoped_refptr<net::IOBuffer> output_io_buffer; | |
205 size_t output_length; | |
206 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
207 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
208 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
209 | |
210 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
211 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
212 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length)); | |
213 | |
214 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
215 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
216 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length)); | |
217 | |
218 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
219 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
220 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 3, output_length)); | |
221 | |
222 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
223 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
224 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 4, output_length)); | |
225 | |
226 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
227 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
228 } | |
229 | |
230 // Confirm that a Close() notification transmits in-order | |
231 // with data on the pipe. | |
232 TEST_F(ByteStreamTest, CompleteTransmits) { | |
233 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
234 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
235 | |
236 scoped_refptr<net::IOBuffer> output_io_buffer; | |
237 size_t output_length; | |
238 | |
239 // Empty stream, non-error case. | |
240 content::CreateByteStream( | |
241 &byte_stream_input, &byte_stream_output, | |
242 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
243 3 * 1024); | |
244 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
245 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
246 byte_stream_input->Close(content::DOWNLOAD_INTERRUPT_REASON_NONE); | |
247 message_loop_.RunAllPending(); | |
248 ASSERT_EQ(content::ByteStreamOutput::STREAM_COMPLETE, | |
249 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
250 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, | |
251 byte_stream_output->GetStatus()); | |
252 | |
253 // Non-empty stream, non-error case. | |
254 content::CreateByteStream( | |
255 &byte_stream_input, &byte_stream_output, | |
256 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
257 3 * 1024); | |
258 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
259 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
260 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 1024)); | |
261 byte_stream_input->Close(content::DOWNLOAD_INTERRUPT_REASON_NONE); | |
262 message_loop_.RunAllPending(); | |
263 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
264 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
265 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
266 ASSERT_EQ(content::ByteStreamOutput::STREAM_COMPLETE, | |
267 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
268 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, | |
269 byte_stream_output->GetStatus()); | |
270 | |
271 // Empty stream, non-error case. | |
272 content::CreateByteStream( | |
273 &byte_stream_input, &byte_stream_output, | |
274 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
275 3 * 1024); | |
276 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
277 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
278 byte_stream_input->Close( | |
279 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED); | |
280 message_loop_.RunAllPending(); | |
281 ASSERT_EQ(content::ByteStreamOutput::STREAM_COMPLETE, | |
282 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
283 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, | |
284 byte_stream_output->GetStatus()); | |
285 | |
286 // Non-empty stream, non-error case. | |
287 content::CreateByteStream( | |
288 &byte_stream_input, &byte_stream_output, | |
289 message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), | |
290 3 * 1024); | |
291 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
292 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
293 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 1024)); | |
294 byte_stream_input->Close( | |
295 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED); | |
296 message_loop_.RunAllPending(); | |
297 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
298 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
299 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length)); | |
300 ASSERT_EQ(content::ByteStreamOutput::STREAM_COMPLETE, | |
301 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
302 EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, | |
303 byte_stream_output->GetStatus()); | |
304 } | |
305 | |
306 // Confirm that callbacks on the sink side are triggered when they should be. | |
307 TEST_F(ByteStreamTest, SinkCallback) { | |
308 scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>()); | |
309 int null_callback_call_count_start = 0; | |
310 | |
311 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
312 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
313 content::CreateByteStream( | |
314 &byte_stream_input, &byte_stream_output, | |
315 message_loop_.message_loop_proxy(), task_runner, | |
316 10000); | |
317 | |
318 scoped_refptr<net::IOBuffer> output_io_buffer; | |
319 size_t output_length; | |
320 base::Closure intermediate_callback; | |
321 | |
322 // Note that the specifics of when the callbacks are called with regard | |
323 // to how much data is pushed onto the pipe is not (currently) part | |
324 // of the interface contract. If it becomes part of the contract, the | |
325 // tests below should get much more precise. | |
326 | |
327 // Confirm callback called when you add more than 33% of the buffer. | |
328 | |
329 // Setup callback | |
330 byte_stream_output->RegisterCallback(base::Bind(NullCallback)); | |
331 null_callback_call_count_start = null_callback_call_count; | |
332 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
333 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
334 Return(true))); | |
335 | |
336 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 4000)); | |
337 message_loop_.RunAllPending(); | |
338 | |
339 // Check callback results match expectations. | |
340 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
341 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
342 intermediate_callback.Run(); | |
343 EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count); | |
344 | |
345 // Check data and stream state. | |
346 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
347 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
348 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
349 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
350 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
351 | |
352 // Confirm callback *isn't* called at less than 33% | |
353 null_callback_call_count_start = null_callback_call_count; | |
354 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 3000)); | |
355 message_loop_.RunAllPending(); | |
356 | |
357 // This reflects an implementation artifact that data goes with callbacks, | |
358 // which should not be considered part of the interface guarantee. | |
359 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
360 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
361 } | |
362 | |
363 // Confirm that callbacks on the source side are triggered when they should | |
364 // be. | |
365 TEST_F(ByteStreamTest, SourceCallback) { | |
366 scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>()); | |
367 int null_callback_call_count_start = 0; | |
368 | |
369 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
370 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
371 content::CreateByteStream( | |
372 &byte_stream_input, &byte_stream_output, | |
373 task_runner, message_loop_.message_loop_proxy(), | |
374 10000); | |
375 | |
376 scoped_refptr<net::IOBuffer> output_io_buffer; | |
377 size_t output_length; | |
378 base::Closure intermediate_callback; | |
379 | |
380 // Note that the specifics of when the callbacks are called with regard | |
381 // to how much data is pulled from the pipe is not (currently) part | |
382 // of the interface contract. If it becomes part of the contract, the | |
383 // tests below should get much more precise. | |
384 | |
385 // Confirm callback called when about 33% space available, and not | |
386 // at other transitions. | |
387 | |
388 // Setup expectations and add data. | |
389 byte_stream_input->RegisterCallback(base::Bind(NullCallback)); | |
390 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 2000)); | |
391 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 2001)); | |
392 EXPECT_FALSE(Write(byte_stream_input.get(), 2, 6000)); | |
393 null_callback_call_count_start = null_callback_call_count; | |
394 | |
395 // Allow bytes to transition (needed for message passing implementation), | |
396 // and get and validate the data. | |
397 message_loop_.RunAllPending(); | |
398 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
399 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
400 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
401 | |
402 // Setup expectations. | |
403 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
404 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
405 Return(true))); | |
406 | |
407 // Grab data, triggering callback. Recorded on dispatch, but doesn't | |
408 // happen because it's caught by the mock. | |
409 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
410 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
411 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
412 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length)); | |
413 | |
414 // Confirm that the callback passed to the mock does what we expect. | |
415 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
416 intermediate_callback.Run(); | |
417 EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count); | |
418 | |
419 // Same drill with final buffer. | |
420 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
421 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
422 Return(true))); | |
423 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
424 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
425 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
426 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length)); | |
427 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
428 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
429 EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count); | |
430 intermediate_callback.Run(); | |
431 // Should have updated the internal structures but not called the | |
432 // callback. | |
433 EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count); | |
434 } | |
435 | |
436 // Confirm that racing a change to a sink callback with a post results | |
437 // in the new callback being called. | |
438 TEST_F(ByteStreamTest, SinkInterrupt) { | |
439 scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>()); | |
440 int null_callback_call_count_start = 0; | |
441 int alt_callback_call_count_start = 0; | |
442 | |
443 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
444 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
445 content::CreateByteStream( | |
446 &byte_stream_input, &byte_stream_output, | |
447 message_loop_.message_loop_proxy(), task_runner, | |
448 10000); | |
449 | |
450 scoped_refptr<net::IOBuffer> output_io_buffer; | |
451 size_t output_length; | |
452 base::Closure intermediate_callback; | |
453 | |
454 // Setup expectations and record initial state. | |
455 byte_stream_output->RegisterCallback(base::Bind(NullCallback)); | |
456 null_callback_call_count_start = null_callback_call_count; | |
457 alt_callback_call_count_start = alt_callback_call_count; | |
458 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
459 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
460 Return(true))); | |
461 | |
462 // Add data, and pass it across. | |
463 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 4000)); | |
464 message_loop_.RunAllPending(); | |
465 | |
466 // The task runner should have been hit, but the callback count | |
467 // isn't changed until we actually run the callback. | |
468 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
469 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
470 | |
471 // If we change the callback now, the new one should be run | |
472 // (simulates race with post task). | |
473 byte_stream_output->RegisterCallback(base::Bind(AltCallback)); | |
474 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
475 EXPECT_EQ(alt_callback_call_count_start, alt_callback_call_count); | |
476 intermediate_callback.Run(); | |
477 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
478 EXPECT_EQ(alt_callback_call_count_start+1, alt_callback_call_count); | |
479 | |
480 // Final cleanup. | |
481 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
482 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
483 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
484 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
485 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
486 | |
487 } | |
488 | |
489 // Confirm that racing a change to a source callback with a post results | |
490 // in the new callback being called. | |
491 TEST_F(ByteStreamTest, SourceInterrupt) { | |
492 scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>()); | |
493 int null_callback_call_count_start = 0; | |
494 int alt_callback_call_count_start = 0; | |
495 | |
496 scoped_ptr<content::ByteStreamInput> byte_stream_input; | |
497 scoped_ptr<content::ByteStreamOutput> byte_stream_output; | |
498 content::CreateByteStream( | |
499 &byte_stream_input, &byte_stream_output, | |
500 task_runner, message_loop_.message_loop_proxy(), | |
501 10000); | |
502 | |
503 scoped_refptr<net::IOBuffer> output_io_buffer; | |
504 size_t output_length; | |
505 base::Closure intermediate_callback; | |
506 | |
507 // Setup state for test and record initiali expectations | |
508 byte_stream_input->RegisterCallback(base::Bind(NullCallback)); | |
509 EXPECT_TRUE(Write(byte_stream_input.get(), 0, 2000)); | |
510 EXPECT_TRUE(Write(byte_stream_input.get(), 1, 2001)); | |
511 EXPECT_FALSE(Write(byte_stream_input.get(), 2, 6000)); | |
512 null_callback_call_count_start = null_callback_call_count; | |
513 alt_callback_call_count_start = alt_callback_call_count; | |
514 message_loop_.RunAllPending(); | |
515 | |
516 // Initial get should not trigger callback. | |
517 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
518 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
519 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length)); | |
520 message_loop_.RunAllPending(); | |
521 | |
522 // Setup expectations. | |
523 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
524 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
525 Return(true))); | |
526 | |
527 // Second get *should* trigger callback. | |
528 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
529 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
530 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
531 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length)); | |
532 | |
533 // Which should do the right thing when it's run. | |
534 byte_stream_input->RegisterCallback(base::Bind(AltCallback)); | |
535 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
536 EXPECT_EQ(alt_callback_call_count_start, alt_callback_call_count); | |
537 intermediate_callback.Run(); | |
538 EXPECT_EQ(null_callback_call_count_start, null_callback_call_count); | |
539 EXPECT_EQ(alt_callback_call_count_start+1, alt_callback_call_count); | |
540 | |
541 // Third get should also trigger callback. | |
542 EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0)) | |
543 .WillOnce(DoAll(SaveArg<1>(&intermediate_callback), | |
544 Return(true))); | |
545 EXPECT_EQ(content::ByteStreamOutput::STREAM_HAS_DATA, | |
546 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
547 ::testing::Mock::VerifyAndClearExpectations(task_runner.get()); | |
548 EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length)); | |
549 EXPECT_EQ(content::ByteStreamOutput::STREAM_EMPTY, | |
550 byte_stream_output->Read(&output_io_buffer, &output_length)); | |
551 } | |
OLD | NEW |