Fix race condition in gyp/ninja builds.
[chromium-blink-merge.git] / android_webview / browser / net / android_stream_reader_url_request_job_unittest.cc
blobe419dd1dfd64f179cef8aae00d051ac480b74814
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 "android_webview/browser/input_stream.h"
6 #include "android_webview/browser/net/android_stream_reader_url_request_job.h"
7 #include "android_webview/browser/net/aw_url_request_job_factory.h"
8 #include "android_webview/browser/net/input_stream_reader.h"
9 #include "base/format_macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/strings/stringprintf.h"
13 #include "net/base/request_priority.h"
14 #include "net/http/http_byte_range.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/url_request/url_request_job_factory_impl.h"
17 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using android_webview::InputStream;
23 using android_webview::InputStreamReader;
24 using net::TestDelegate;
25 using net::TestJobInterceptor;
26 using net::TestNetworkDelegate;
27 using net::TestURLRequestContext;
28 using net::TestURLRequest;
29 using testing::DoAll;
30 using testing::Ge;
31 using testing::Gt;
32 using testing::InSequence;
33 using testing::Invoke;
34 using testing::InvokeWithoutArgs;
35 using testing::NotNull;
36 using testing::Return;
37 using testing::SaveArg;
38 using testing::SetArgPointee;
39 using testing::StrictMock;
40 using testing::Test;
41 using testing::WithArg;
42 using testing::WithArgs;
43 using testing::_;
45 // Some of the classes will DCHECK on a null InputStream (which is desirable).
46 // The workaround is to use this class. None of the methods need to be
47 // implemented as the mock InputStreamReader should never forward calls to the
48 // InputStream.
49 class NotImplInputStream : public InputStream {
50 public:
51 NotImplInputStream() {}
52 virtual ~NotImplInputStream() {}
53 virtual bool BytesAvailable(int* bytes_available) const OVERRIDE {
54 NOTIMPLEMENTED();
55 return false;
57 virtual bool Skip(int64_t n, int64_t* bytes_skipped) OVERRIDE {
58 NOTIMPLEMENTED();
59 return false;
61 virtual bool Read(net::IOBuffer* dest, int length, int* bytes_read) OVERRIDE {
62 NOTIMPLEMENTED();
63 return false;
67 // Required in order to create an instance of AndroidStreamReaderURLRequestJob.
68 class StreamReaderDelegate :
69 public AndroidStreamReaderURLRequestJob::Delegate {
70 public:
71 StreamReaderDelegate() {}
73 virtual scoped_ptr<InputStream> OpenInputStream(
74 JNIEnv* env,
75 const GURL& url) OVERRIDE {
76 return make_scoped_ptr<InputStream>(new NotImplInputStream());
79 virtual void OnInputStreamOpenFailed(net::URLRequest* request,
80 bool* restart) OVERRIDE {
81 *restart = false;
84 virtual bool GetMimeType(JNIEnv* env,
85 net::URLRequest* request,
86 android_webview::InputStream* stream,
87 std::string* mime_type) OVERRIDE {
88 return false;
91 virtual bool GetCharset(JNIEnv* env,
92 net::URLRequest* request,
93 android_webview::InputStream* stream,
94 std::string* charset) OVERRIDE {
95 return false;
98 virtual void AppendResponseHeaders(
99 JNIEnv* env,
100 net::HttpResponseHeaders* headers) OVERRIDE {
101 // no-op
105 class NullStreamReaderDelegate : public StreamReaderDelegate {
106 public:
107 NullStreamReaderDelegate() {}
109 virtual scoped_ptr<InputStream> OpenInputStream(
110 JNIEnv* env,
111 const GURL& url) OVERRIDE {
112 return make_scoped_ptr<InputStream>(NULL);
116 class HeaderAlteringStreamReaderDelegate : public NullStreamReaderDelegate {
117 public:
118 HeaderAlteringStreamReaderDelegate() {}
120 virtual void AppendResponseHeaders(
121 JNIEnv* env,
122 net::HttpResponseHeaders* headers) OVERRIDE {
123 headers->ReplaceStatusLine(kStatusLine);
124 std::string headerLine(kCustomHeaderName);
125 headerLine.append(": ");
126 headerLine.append(kCustomHeaderValue);
127 headers->AddHeader(headerLine);
130 static const int kResponseCode;
131 static const char* kStatusLine;
132 static const char* kCustomHeaderName;
133 static const char* kCustomHeaderValue;
136 const int HeaderAlteringStreamReaderDelegate::kResponseCode = 401;
137 const char* HeaderAlteringStreamReaderDelegate::kStatusLine =
138 "HTTP/1.1 401 Gone";
139 const char* HeaderAlteringStreamReaderDelegate::kCustomHeaderName =
140 "X-Test-Header";
141 const char* HeaderAlteringStreamReaderDelegate::kCustomHeaderValue =
142 "TestHeaderValue";
144 class MockInputStreamReader : public InputStreamReader {
145 public:
146 MockInputStreamReader() : InputStreamReader(new NotImplInputStream()) {}
147 ~MockInputStreamReader() {}
149 MOCK_METHOD1(Seek, int(const net::HttpByteRange& byte_range));
150 MOCK_METHOD2(ReadRawData, int(net::IOBuffer* buffer, int buffer_size));
154 class TestStreamReaderJob : public AndroidStreamReaderURLRequestJob {
155 public:
156 TestStreamReaderJob(
157 net::URLRequest* request,
158 net::NetworkDelegate* network_delegate,
159 scoped_ptr<Delegate> delegate,
160 scoped_ptr<InputStreamReader> stream_reader)
161 : AndroidStreamReaderURLRequestJob(request,
162 network_delegate,
163 delegate.Pass()),
164 stream_reader_(stream_reader.Pass()) {
165 message_loop_proxy_ = base::MessageLoopProxy::current();
168 virtual scoped_ptr<InputStreamReader> CreateStreamReader(
169 InputStream* stream) OVERRIDE {
170 return stream_reader_.Pass();
172 protected:
173 virtual ~TestStreamReaderJob() {}
175 virtual base::TaskRunner* GetWorkerThreadRunner() OVERRIDE {
176 return message_loop_proxy_.get();
179 scoped_ptr<InputStreamReader> stream_reader_;
180 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
183 class AndroidStreamReaderURLRequestJobTest : public Test {
184 public:
185 AndroidStreamReaderURLRequestJobTest() {}
187 protected:
188 virtual void SetUp() {
189 context_.set_job_factory(&factory_);
190 context_.set_network_delegate(&network_delegate_);
191 req_.reset(new TestURLRequest(GURL("content://foo"),
192 net::DEFAULT_PRIORITY,
193 &url_request_delegate_,
194 &context_));
195 req_->set_method("GET");
198 void SetRange(net::URLRequest* req, int first_byte, int last_byte) {
199 net::HttpRequestHeaders headers;
200 headers.SetHeader(net::HttpRequestHeaders::kRange,
201 net::HttpByteRange::Bounded(
202 first_byte, last_byte).GetHeaderValue());
203 req->SetExtraRequestHeaders(headers);
206 void SetUpTestJob(scoped_ptr<InputStreamReader> stream_reader) {
207 SetUpTestJob(stream_reader.Pass(),
208 make_scoped_ptr(new StreamReaderDelegate())
209 .PassAs<AndroidStreamReaderURLRequestJob::Delegate>());
212 void SetUpTestJob(scoped_ptr<InputStreamReader> stream_reader,
213 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>
214 stream_reader_delegate) {
215 TestStreamReaderJob* test_stream_reader_job =
216 new TestStreamReaderJob(
217 req_.get(),
218 &network_delegate_,
219 stream_reader_delegate.Pass(),
220 stream_reader.Pass());
221 // The Interceptor is owned by the |factory_|.
222 TestJobInterceptor* protocol_handler = new TestJobInterceptor;
223 protocol_handler->set_main_intercept_job(test_stream_reader_job);
224 bool set_protocol = factory_.SetProtocolHandler("http", protocol_handler);
225 DCHECK(set_protocol);
227 protocol_handler = new TestJobInterceptor;
228 protocol_handler->set_main_intercept_job(test_stream_reader_job);
229 set_protocol = factory_.SetProtocolHandler("content", protocol_handler);
230 DCHECK(set_protocol);
233 base::MessageLoopForIO loop_;
234 TestURLRequestContext context_;
235 android_webview::AwURLRequestJobFactory factory_;
236 TestDelegate url_request_delegate_;
237 TestNetworkDelegate network_delegate_;
238 scoped_ptr<TestURLRequest> req_;
241 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadEmptyStream) {
242 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
243 new StrictMock<MockInputStreamReader>());
245 InSequence s;
246 EXPECT_CALL(*stream_reader, Seek(_))
247 .WillOnce(Return(0));
248 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Gt(0)))
249 .WillOnce(Return(0));
252 SetUpTestJob(stream_reader.PassAs<InputStreamReader>());
254 req_->Start();
256 // The TestDelegate will quit the message loop on request completion.
257 base::MessageLoop::current()->Run();
259 EXPECT_FALSE(url_request_delegate_.request_failed());
260 EXPECT_EQ(1, network_delegate_.completed_requests());
261 EXPECT_EQ(0, network_delegate_.error_count());
262 EXPECT_EQ(200, req_->GetResponseCode());
265 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadWithNullStream) {
266 SetUpTestJob(scoped_ptr<InputStreamReader>(),
267 make_scoped_ptr(new NullStreamReaderDelegate())
268 .PassAs<AndroidStreamReaderURLRequestJob::Delegate>());
269 req_->Start();
271 // The TestDelegate will quit the message loop on request completion.
272 base::MessageLoop::current()->Run();
274 // The request_failed() method is named confusingly but all it checks is
275 // whether the request got as far as calling NotifyHeadersComplete.
276 EXPECT_FALSE(url_request_delegate_.request_failed());
277 EXPECT_EQ(1, network_delegate_.completed_requests());
278 // A null input stream shouldn't result in an error. See crbug.com/180950.
279 EXPECT_EQ(0, network_delegate_.error_count());
280 EXPECT_EQ(404, req_->GetResponseCode());
283 TEST_F(AndroidStreamReaderURLRequestJobTest, ModifyHeadersAndStatus) {
284 SetUpTestJob(scoped_ptr<InputStreamReader>(),
285 make_scoped_ptr(new HeaderAlteringStreamReaderDelegate())
286 .PassAs<AndroidStreamReaderURLRequestJob::Delegate>());
287 req_->Start();
289 // The TestDelegate will quit the message loop on request completion.
290 base::MessageLoop::current()->Run();
292 // The request_failed() method is named confusingly but all it checks is
293 // whether the request got as far as calling NotifyHeadersComplete.
294 EXPECT_FALSE(url_request_delegate_.request_failed());
295 EXPECT_EQ(1, network_delegate_.completed_requests());
296 // A null input stream shouldn't result in an error. See crbug.com/180950.
297 EXPECT_EQ(0, network_delegate_.error_count());
298 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kResponseCode,
299 req_->GetResponseCode());
300 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kStatusLine,
301 req_->response_headers()->GetStatusLine());
302 EXPECT_TRUE(req_->response_headers()->HasHeader(
303 HeaderAlteringStreamReaderDelegate::kCustomHeaderName));
304 std::string header_value;
305 EXPECT_TRUE(req_->response_headers()->EnumerateHeader(
306 NULL, HeaderAlteringStreamReaderDelegate::kCustomHeaderName,
307 &header_value));
308 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kCustomHeaderValue,
309 header_value);
312 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadPartOfStream) {
313 const int bytes_available = 128;
314 const int offset = 32;
315 const int bytes_to_read = bytes_available - offset;
316 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
317 new StrictMock<MockInputStreamReader>());
319 InSequence s;
320 EXPECT_CALL(*stream_reader, Seek(_))
321 .WillOnce(Return(bytes_available));
322 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
323 .WillOnce(Return(bytes_to_read/2));
324 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
325 .WillOnce(Return(bytes_to_read/2));
326 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
327 .WillOnce(Return(0));
330 SetUpTestJob(stream_reader.PassAs<InputStreamReader>());
332 SetRange(req_.get(), offset, bytes_available);
333 req_->Start();
335 base::MessageLoop::current()->Run();
337 EXPECT_FALSE(url_request_delegate_.request_failed());
338 EXPECT_EQ(bytes_to_read, url_request_delegate_.bytes_received());
339 EXPECT_EQ(1, network_delegate_.completed_requests());
340 EXPECT_EQ(0, network_delegate_.error_count());
343 TEST_F(AndroidStreamReaderURLRequestJobTest,
344 ReadStreamWithMoreAvailableThanActual) {
345 const int bytes_available_reported = 190;
346 const int bytes_available = 128;
347 const int offset = 0;
348 const int bytes_to_read = bytes_available - offset;
349 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
350 new StrictMock<MockInputStreamReader>());
352 InSequence s;
353 EXPECT_CALL(*stream_reader, Seek(_))
354 .WillOnce(Return(bytes_available_reported));
355 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
356 .WillOnce(Return(bytes_available));
357 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
358 .WillOnce(Return(0));
361 SetUpTestJob(stream_reader.PassAs<InputStreamReader>());
363 SetRange(req_.get(), offset, bytes_available_reported);
364 req_->Start();
366 base::MessageLoop::current()->Run();
368 EXPECT_FALSE(url_request_delegate_.request_failed());
369 EXPECT_EQ(bytes_to_read, url_request_delegate_.bytes_received());
370 EXPECT_EQ(1, network_delegate_.completed_requests());
371 EXPECT_EQ(0, network_delegate_.error_count());
374 TEST_F(AndroidStreamReaderURLRequestJobTest, DeleteJobMidWaySeek) {
375 const int offset = 20;
376 const int bytes_available = 128;
377 base::RunLoop loop;
378 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
379 new StrictMock<MockInputStreamReader>());
380 EXPECT_CALL(*stream_reader, Seek(_))
381 .WillOnce(DoAll(InvokeWithoutArgs(&loop, &base::RunLoop::Quit),
382 Return(bytes_available)));
383 ON_CALL(*stream_reader, ReadRawData(_, _))
384 .WillByDefault(Return(0));
386 SetUpTestJob(stream_reader.PassAs<InputStreamReader>());
388 SetRange(req_.get(), offset, bytes_available);
389 req_->Start();
391 loop.Run();
393 EXPECT_EQ(0, network_delegate_.completed_requests());
394 req_->Cancel();
395 EXPECT_EQ(1, network_delegate_.completed_requests());
398 TEST_F(AndroidStreamReaderURLRequestJobTest, DeleteJobMidWayRead) {
399 const int offset = 20;
400 const int bytes_available = 128;
401 base::RunLoop loop;
402 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
403 new StrictMock<MockInputStreamReader>());
404 net::CompletionCallback read_completion_callback;
405 EXPECT_CALL(*stream_reader, Seek(_))
406 .WillOnce(Return(bytes_available));
407 EXPECT_CALL(*stream_reader, ReadRawData(_, _))
408 .WillOnce(DoAll(InvokeWithoutArgs(&loop, &base::RunLoop::Quit),
409 Return(bytes_available)));
411 SetUpTestJob(stream_reader.PassAs<InputStreamReader>());
413 SetRange(req_.get(), offset, bytes_available);
414 req_->Start();
416 loop.Run();
418 EXPECT_EQ(0, network_delegate_.completed_requests());
419 req_->Cancel();
420 EXPECT_EQ(1, network_delegate_.completed_requests());