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 "android_webview/browser/input_stream.h"
6#include "android_webview/browser/net/input_stream_reader.h"
7#include "base/android/scoped_java_ref.h"
8#include "base/callback.h"
9#include "base/memory/ref_counted.h"
10#include "base/memory/scoped_ptr.h"
11#include "net/base/io_buffer.h"
12#include "net/http/http_byte_range.h"
13
14#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17using android_webview::InputStream;
18using android_webview::InputStreamReader;
19using testing::DoAll;
20using testing::Ge;
21using testing::InSequence;
22using testing::Lt;
23using testing::Ne;
24using testing::NotNull;
25using testing::Return;
26using testing::SetArgPointee;
27using testing::Test;
28using testing::_;
29
30class MockInputStream : public InputStream {
31 public:
32  MockInputStream() {}
33  virtual ~MockInputStream() {}
34
35  MOCK_CONST_METHOD1(BytesAvailable, bool(int* bytes_available));
36  MOCK_METHOD2(Skip, bool(int64_t n, int64_t* bytes_skipped));
37  MOCK_METHOD3(Read, bool(net::IOBuffer* dest, int length, int* bytes_read));
38};
39
40class InputStreamReaderTest : public Test {
41 public:
42  InputStreamReaderTest()
43      : input_stream_reader_(&input_stream_) {
44  }
45 protected:
46  int SeekRange(int first_byte, int last_byte) {
47    net::HttpByteRange byte_range;
48    byte_range.set_first_byte_position(first_byte);
49    byte_range.set_last_byte_position(last_byte);
50    return input_stream_reader_.Seek(byte_range);
51  }
52
53  int ReadRawData(scoped_refptr<net::IOBuffer> buffer, int bytesToRead) {
54    return input_stream_reader_.ReadRawData(buffer.get(), bytesToRead);
55  }
56
57  MockInputStream input_stream_;
58  InputStreamReader input_stream_reader_;
59};
60
61TEST_F(InputStreamReaderTest, BytesAvailableFailurePropagationOnSeek) {
62  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
63      .WillOnce(Return(false));
64
65  ASSERT_GT(0, SeekRange(0, 0));
66}
67
68TEST_F(InputStreamReaderTest, SkipFailurePropagationOnSeek) {
69  const int streamSize = 10;
70  const int bytesToSkip = 5;
71
72  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
73      .WillOnce(DoAll(SetArgPointee<0>(streamSize),
74                      Return(true)));
75
76  EXPECT_CALL(input_stream_, Skip(bytesToSkip, NotNull()))
77      .WillOnce(Return(false));
78
79  ASSERT_GT(0, SeekRange(bytesToSkip, streamSize - 1));
80}
81
82TEST_F(InputStreamReaderTest, SeekToMiddle) {
83  const int streamSize = 10;
84  const int bytesToSkip = 5;
85
86  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
87      .WillOnce(DoAll(SetArgPointee<0>(streamSize),
88                      Return(true)));
89
90  EXPECT_CALL(input_stream_, Skip(bytesToSkip, NotNull()))
91      .WillOnce(DoAll(SetArgPointee<1>(bytesToSkip),
92                      Return(true)));
93
94  ASSERT_EQ(bytesToSkip, SeekRange(bytesToSkip, streamSize - 1));
95}
96
97TEST_F(InputStreamReaderTest, SeekToMiddleInSteps) {
98  const int streamSize = 10;
99  const int bytesToSkip = 5;
100
101  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
102      .Times(1)
103      .WillOnce(DoAll(SetArgPointee<0>(streamSize),
104                      Return(true)));
105
106  EXPECT_CALL(input_stream_, Skip(_, _))
107      .Times(0);
108  {
109    InSequence s;
110    EXPECT_CALL(input_stream_, Skip(bytesToSkip, NotNull()))
111        .WillOnce(DoAll(SetArgPointee<1>(bytesToSkip - 3),
112                        Return(true)))
113        .RetiresOnSaturation();
114    EXPECT_CALL(input_stream_, Skip(3, NotNull()))
115        .WillOnce(DoAll(SetArgPointee<1>(1),
116                        Return(true)))
117        .RetiresOnSaturation();
118    EXPECT_CALL(input_stream_, Skip(2, NotNull()))
119        .WillOnce(DoAll(SetArgPointee<1>(2),
120                        Return(true)))
121        .RetiresOnSaturation();
122  }
123
124  ASSERT_EQ(bytesToSkip, SeekRange(bytesToSkip, streamSize - 1));
125}
126
127TEST_F(InputStreamReaderTest, SeekEmpty) {
128  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
129      .WillOnce(DoAll(SetArgPointee<0>(0),
130                      Return(true)));
131
132  ASSERT_EQ(0, SeekRange(0, 0));
133}
134
135TEST_F(InputStreamReaderTest, SeekMoreThanAvailable) {
136  const int bytesAvailable = 256;
137  EXPECT_CALL(input_stream_, BytesAvailable(NotNull()))
138      .WillOnce(DoAll(SetArgPointee<0>(bytesAvailable),
139                      Return(true)));
140
141  ASSERT_GT(0, SeekRange(bytesAvailable, 2 * bytesAvailable));
142}
143
144TEST_F(InputStreamReaderTest, ReadFailure) {
145  const int bytesToRead = 128;
146  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(bytesToRead);
147  EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull()))
148      .WillOnce(Return(false));
149
150  ASSERT_GT(0, ReadRawData(buffer, bytesToRead));
151}
152
153TEST_F(InputStreamReaderTest, ReadNothing) {
154  const int bytesToRead = 0;
155  // Size of net::IOBuffer can't be 0.
156  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(1);
157  EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull()))
158      .Times(0);
159
160  ASSERT_EQ(0, ReadRawData(buffer, bytesToRead));
161}
162
163TEST_F(InputStreamReaderTest, ReadSuccess) {
164  const int bytesToRead = 128;
165  scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(bytesToRead);
166
167  EXPECT_CALL(input_stream_, Read(buffer.get(), bytesToRead, NotNull()))
168      .WillOnce(DoAll(SetArgPointee<2>(bytesToRead),
169                      Return(true)));
170
171  ASSERT_EQ(bytesToRead, ReadRawData(buffer, bytesToRead));
172}
173