Roll WebRTC 9745:9761, Libjingle 9742:9761
[chromium-blink-merge.git] / android_webview / browser / net / android_stream_reader_url_request_job_unittest.cc
blobc7e3c688782a81ac6dfbe2334cc07def04d978e2
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/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "net/base/request_priority.h"
16 #include "net/http/http_byte_range.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_job_factory_impl.h"
20 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using android_webview::InputStream;
26 using android_webview::InputStreamReader;
27 using net::TestDelegate;
28 using net::TestJobInterceptor;
29 using net::TestNetworkDelegate;
30 using net::TestURLRequestContext;
31 using net::URLRequest;
32 using testing::DoAll;
33 using testing::Ge;
34 using testing::Gt;
35 using testing::InSequence;
36 using testing::Invoke;
37 using testing::InvokeWithoutArgs;
38 using testing::NotNull;
39 using testing::Return;
40 using testing::SaveArg;
41 using testing::SetArgPointee;
42 using testing::StrictMock;
43 using testing::Test;
44 using testing::WithArg;
45 using testing::WithArgs;
46 using testing::_;
48 // Some of the classes will DCHECK on a null InputStream (which is desirable).
49 // The workaround is to use this class. None of the methods need to be
50 // implemented as the mock InputStreamReader should never forward calls to the
51 // InputStream.
52 class NotImplInputStream : public InputStream {
53 public:
54 NotImplInputStream() {}
55 ~NotImplInputStream() override {}
56 bool BytesAvailable(int* bytes_available) const override {
57 NOTIMPLEMENTED();
58 return false;
60 bool Skip(int64_t n, int64_t* bytes_skipped) override {
61 NOTIMPLEMENTED();
62 return false;
64 bool Read(net::IOBuffer* dest, int length, int* bytes_read) override {
65 NOTIMPLEMENTED();
66 return false;
70 // Required in order to create an instance of AndroidStreamReaderURLRequestJob.
71 class StreamReaderDelegate :
72 public AndroidStreamReaderURLRequestJob::Delegate {
73 public:
74 StreamReaderDelegate() {}
76 scoped_ptr<InputStream> OpenInputStream(JNIEnv* env,
77 const GURL& url) override {
78 return make_scoped_ptr<InputStream>(new NotImplInputStream());
81 void OnInputStreamOpenFailed(net::URLRequest* request,
82 bool* restart) override {
83 *restart = false;
86 bool GetMimeType(JNIEnv* env,
87 net::URLRequest* request,
88 android_webview::InputStream* stream,
89 std::string* mime_type) override {
90 return false;
93 bool GetCharset(JNIEnv* env,
94 net::URLRequest* request,
95 android_webview::InputStream* stream,
96 std::string* charset) override {
97 return false;
100 void AppendResponseHeaders(JNIEnv* env,
101 net::HttpResponseHeaders* headers) override {
102 // no-op
106 class NullStreamReaderDelegate : public StreamReaderDelegate {
107 public:
108 NullStreamReaderDelegate() {}
110 scoped_ptr<InputStream> OpenInputStream(JNIEnv* env,
111 const GURL& url) override {
112 return make_scoped_ptr<InputStream>(NULL);
116 class HeaderAlteringStreamReaderDelegate : public NullStreamReaderDelegate {
117 public:
118 HeaderAlteringStreamReaderDelegate() {}
120 void AppendResponseHeaders(JNIEnv* env,
121 net::HttpResponseHeaders* headers) override {
122 headers->ReplaceStatusLine(kStatusLine);
123 std::string headerLine(kCustomHeaderName);
124 headerLine.append(": ");
125 headerLine.append(kCustomHeaderValue);
126 headers->AddHeader(headerLine);
129 static const int kResponseCode;
130 static const char* kStatusLine;
131 static const char* kCustomHeaderName;
132 static const char* kCustomHeaderValue;
135 const int HeaderAlteringStreamReaderDelegate::kResponseCode = 401;
136 const char* HeaderAlteringStreamReaderDelegate::kStatusLine =
137 "HTTP/1.1 401 Gone";
138 const char* HeaderAlteringStreamReaderDelegate::kCustomHeaderName =
139 "X-Test-Header";
140 const char* HeaderAlteringStreamReaderDelegate::kCustomHeaderValue =
141 "TestHeaderValue";
143 class MockInputStreamReader : public InputStreamReader {
144 public:
145 MockInputStreamReader() : InputStreamReader(new NotImplInputStream()) {}
146 ~MockInputStreamReader() {}
148 MOCK_METHOD1(Seek, int(const net::HttpByteRange& byte_range));
149 MOCK_METHOD2(ReadRawData, int(net::IOBuffer* buffer, int buffer_size));
153 class TestStreamReaderJob : public AndroidStreamReaderURLRequestJob {
154 public:
155 TestStreamReaderJob(
156 net::URLRequest* request,
157 net::NetworkDelegate* network_delegate,
158 scoped_ptr<Delegate> delegate,
159 scoped_ptr<InputStreamReader> stream_reader)
160 : AndroidStreamReaderURLRequestJob(request,
161 network_delegate,
162 delegate.Pass()),
163 stream_reader_(stream_reader.Pass()) {
164 task_runner_ = base::ThreadTaskRunnerHandle::Get();
167 scoped_ptr<InputStreamReader> CreateStreamReader(
168 InputStream* stream) override {
169 return stream_reader_.Pass();
171 protected:
172 ~TestStreamReaderJob() override {}
174 base::TaskRunner* GetWorkerThreadRunner() override {
175 return task_runner_.get();
178 scoped_ptr<InputStreamReader> stream_reader_;
179 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
182 class AndroidStreamReaderURLRequestJobTest : public Test {
183 public:
184 AndroidStreamReaderURLRequestJobTest() {}
186 protected:
187 void SetUp() override {
188 context_.set_job_factory(&factory_);
189 context_.set_network_delegate(&network_delegate_);
190 req_ = context_.CreateRequest(GURL("content://foo"),
191 net::DEFAULT_PRIORITY,
192 &url_request_delegate_);
193 req_->set_method("GET");
196 void SetRange(net::URLRequest* req, int first_byte, int last_byte) {
197 net::HttpRequestHeaders headers;
198 headers.SetHeader(net::HttpRequestHeaders::kRange,
199 net::HttpByteRange::Bounded(
200 first_byte, last_byte).GetHeaderValue());
201 req->SetExtraRequestHeaders(headers);
204 void SetUpTestJob(scoped_ptr<InputStreamReader> stream_reader) {
205 SetUpTestJob(stream_reader.Pass(),
206 make_scoped_ptr(new StreamReaderDelegate()));
209 void SetUpTestJob(scoped_ptr<InputStreamReader> stream_reader,
210 scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>
211 stream_reader_delegate) {
212 TestStreamReaderJob* test_stream_reader_job =
213 new TestStreamReaderJob(
214 req_.get(),
215 &network_delegate_,
216 stream_reader_delegate.Pass(),
217 stream_reader.Pass());
218 // The Interceptor is owned by the |factory_|.
219 TestJobInterceptor* protocol_handler = new TestJobInterceptor;
220 protocol_handler->set_main_intercept_job(test_stream_reader_job);
221 bool set_protocol = factory_.SetProtocolHandler("http", protocol_handler);
222 DCHECK(set_protocol);
224 protocol_handler = new TestJobInterceptor;
225 protocol_handler->set_main_intercept_job(test_stream_reader_job);
226 set_protocol = factory_.SetProtocolHandler("content", protocol_handler);
227 DCHECK(set_protocol);
230 base::MessageLoopForIO loop_;
231 TestURLRequestContext context_;
232 android_webview::AwURLRequestJobFactory factory_;
233 TestDelegate url_request_delegate_;
234 TestNetworkDelegate network_delegate_;
235 scoped_ptr<URLRequest> req_;
238 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadEmptyStream) {
239 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
240 new StrictMock<MockInputStreamReader>());
242 InSequence s;
243 EXPECT_CALL(*stream_reader, Seek(_))
244 .WillOnce(Return(0));
245 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Gt(0)))
246 .WillOnce(Return(0));
249 SetUpTestJob(stream_reader.Pass());
251 req_->Start();
253 // The TestDelegate will quit the message loop on request completion.
254 base::MessageLoop::current()->Run();
256 EXPECT_FALSE(url_request_delegate_.request_failed());
257 EXPECT_EQ(1, network_delegate_.completed_requests());
258 EXPECT_EQ(0, network_delegate_.error_count());
259 EXPECT_EQ(200, req_->GetResponseCode());
262 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadWithNullStream) {
263 SetUpTestJob(nullptr, make_scoped_ptr(new NullStreamReaderDelegate()));
264 req_->Start();
266 // The TestDelegate will quit the message loop on request completion.
267 base::MessageLoop::current()->Run();
269 // The request_failed() method is named confusingly but all it checks is
270 // whether the request got as far as calling NotifyHeadersComplete.
271 EXPECT_FALSE(url_request_delegate_.request_failed());
272 EXPECT_EQ(1, network_delegate_.completed_requests());
273 // A null input stream shouldn't result in an error. See crbug.com/180950.
274 EXPECT_EQ(0, network_delegate_.error_count());
275 EXPECT_EQ(404, req_->GetResponseCode());
278 TEST_F(AndroidStreamReaderURLRequestJobTest, ModifyHeadersAndStatus) {
279 SetUpTestJob(nullptr,
280 make_scoped_ptr(new HeaderAlteringStreamReaderDelegate()));
281 req_->Start();
283 // The TestDelegate will quit the message loop on request completion.
284 base::MessageLoop::current()->Run();
286 // The request_failed() method is named confusingly but all it checks is
287 // whether the request got as far as calling NotifyHeadersComplete.
288 EXPECT_FALSE(url_request_delegate_.request_failed());
289 EXPECT_EQ(1, network_delegate_.completed_requests());
290 // A null input stream shouldn't result in an error. See crbug.com/180950.
291 EXPECT_EQ(0, network_delegate_.error_count());
292 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kResponseCode,
293 req_->GetResponseCode());
294 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kStatusLine,
295 req_->response_headers()->GetStatusLine());
296 EXPECT_TRUE(req_->response_headers()->HasHeader(
297 HeaderAlteringStreamReaderDelegate::kCustomHeaderName));
298 std::string header_value;
299 EXPECT_TRUE(req_->response_headers()->EnumerateHeader(
300 NULL, HeaderAlteringStreamReaderDelegate::kCustomHeaderName,
301 &header_value));
302 EXPECT_EQ(HeaderAlteringStreamReaderDelegate::kCustomHeaderValue,
303 header_value);
306 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadPartOfStream) {
307 const int bytes_available = 128;
308 const int offset = 32;
309 const int bytes_to_read = bytes_available - offset;
310 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
311 new StrictMock<MockInputStreamReader>());
313 InSequence s;
314 EXPECT_CALL(*stream_reader, Seek(_))
315 .WillOnce(Return(bytes_available));
316 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
317 .WillOnce(Return(bytes_to_read/2));
318 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
319 .WillOnce(Return(bytes_to_read/2));
320 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
321 .WillOnce(Return(0));
324 SetUpTestJob(stream_reader.Pass());
326 SetRange(req_.get(), offset, bytes_available);
327 req_->Start();
329 base::MessageLoop::current()->Run();
331 EXPECT_FALSE(url_request_delegate_.request_failed());
332 EXPECT_EQ(bytes_to_read, url_request_delegate_.bytes_received());
333 EXPECT_EQ(1, network_delegate_.completed_requests());
334 EXPECT_EQ(0, network_delegate_.error_count());
337 TEST_F(AndroidStreamReaderURLRequestJobTest,
338 ReadStreamWithMoreAvailableThanActual) {
339 const int bytes_available_reported = 190;
340 const int bytes_available = 128;
341 const int offset = 0;
342 const int bytes_to_read = bytes_available - offset;
343 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
344 new StrictMock<MockInputStreamReader>());
346 InSequence s;
347 EXPECT_CALL(*stream_reader, Seek(_))
348 .WillOnce(Return(bytes_available_reported));
349 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
350 .WillOnce(Return(bytes_available));
351 EXPECT_CALL(*stream_reader, ReadRawData(NotNull(), Ge(bytes_to_read)))
352 .WillOnce(Return(0));
355 SetUpTestJob(stream_reader.Pass());
357 SetRange(req_.get(), offset, bytes_available_reported);
358 req_->Start();
360 base::MessageLoop::current()->Run();
362 EXPECT_FALSE(url_request_delegate_.request_failed());
363 EXPECT_EQ(bytes_to_read, url_request_delegate_.bytes_received());
364 EXPECT_EQ(1, network_delegate_.completed_requests());
365 EXPECT_EQ(0, network_delegate_.error_count());
368 TEST_F(AndroidStreamReaderURLRequestJobTest, DeleteJobMidWaySeek) {
369 const int offset = 20;
370 const int bytes_available = 128;
371 base::RunLoop loop;
372 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
373 new StrictMock<MockInputStreamReader>());
374 EXPECT_CALL(*stream_reader, Seek(_))
375 .WillOnce(DoAll(InvokeWithoutArgs(&loop, &base::RunLoop::Quit),
376 Return(bytes_available)));
377 ON_CALL(*stream_reader, ReadRawData(_, _))
378 .WillByDefault(Return(0));
380 SetUpTestJob(stream_reader.Pass());
382 SetRange(req_.get(), offset, bytes_available);
383 req_->Start();
385 loop.Run();
387 EXPECT_EQ(0, network_delegate_.completed_requests());
388 req_->Cancel();
389 EXPECT_EQ(1, network_delegate_.completed_requests());
392 TEST_F(AndroidStreamReaderURLRequestJobTest, DeleteJobMidWayRead) {
393 const int offset = 20;
394 const int bytes_available = 128;
395 base::RunLoop loop;
396 scoped_ptr<StrictMock<MockInputStreamReader> > stream_reader(
397 new StrictMock<MockInputStreamReader>());
398 net::CompletionCallback read_completion_callback;
399 EXPECT_CALL(*stream_reader, Seek(_))
400 .WillOnce(Return(bytes_available));
401 EXPECT_CALL(*stream_reader, ReadRawData(_, _))
402 .WillOnce(DoAll(InvokeWithoutArgs(&loop, &base::RunLoop::Quit),
403 Return(bytes_available)));
405 SetUpTestJob(stream_reader.Pass());
407 SetRange(req_.get(), offset, bytes_available);
408 req_->Start();
410 loop.Run();
412 EXPECT_EQ(0, network_delegate_.completed_requests());
413 req_->Cancel();
414 EXPECT_EQ(1, network_delegate_.completed_requests());