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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_stream_reader_unittest.cc

Issue 318563002: [fsp] Introduce BufferingFileStreamReader to read files in bigger chunks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 6 years, 5 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 | Annotate | Revision Log
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 <string>
6 #include <vector>
7
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/run_loop.h"
12 #include "chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_st ream_reader.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace chromeos {
19 namespace file_system_provider {
20 namespace {
21
22 // Size of the fake file in bytes.
23 const int kFileSize = 1024;
24
25 // Size of the preloading buffer in bytes.
26 const int kBufferSize = 8;
27
28 // Number of bytes requested per BufferingFileStreamReader::Read().
29 const int kChunkSize = 3;
30
31 // Pushes a value to the passed log vector.
32 template <typename T>
33 void LogValue(std::vector<T>* log, T value) {
34 log->push_back(value);
35 }
36
37 // Fake internal file stream reader.
38 class FakeFileStreamReader : public webkit_blob::FileStreamReader {
39 public:
40 FakeFileStreamReader(std::vector<int>* log, net::Error return_error)
41 : log_(log), return_error_(return_error) {}
42 virtual ~FakeFileStreamReader() {}
43
44 // webkit_blob::FileStreamReader overrides.
45 virtual int Read(net::IOBuffer* buf,
46 int buf_len,
47 const net::CompletionCallback& callback) OVERRIDE {
48 DCHECK(log_);
49 log_->push_back(buf_len);
50
51 if (return_error_ != net::OK) {
52 base::MessageLoopProxy::current()->PostTask(
53 FROM_HERE, base::Bind(callback, return_error_));
54 return net::ERR_IO_PENDING;
55 }
56
57 const std::string fake_data('X', buf_len);
58 memcpy(buf->data(), fake_data.c_str(), buf_len);
59
60 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
61 base::Bind(callback, buf_len));
62 return net::ERR_IO_PENDING;
63 }
64
65 virtual int64 GetLength(
66 const net::Int64CompletionCallback& callback) OVERRIDE {
67 DCHECK_EQ(net::OK, return_error_);
68 base::MessageLoopProxy::current()->PostTask(
69 FROM_HERE, base::Bind(callback, kFileSize));
70 return net::ERR_IO_PENDING;
71 }
72
73 private:
74 std::vector<int>* log_; // Not owned.
75 net::Error return_error_;
76 DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
77 };
78
79 } // namespace
80
81 class FileSystemProviderBufferingFileStreamReaderTest : public testing::Test {
82 protected:
83 FileSystemProviderBufferingFileStreamReaderTest() {}
84 virtual ~FileSystemProviderBufferingFileStreamReaderTest() {}
85
86 content::TestBrowserThreadBundle thread_bundle_;
87 };
88
89 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read) {
90 std::vector<int> inner_read_log;
91 BufferingFileStreamReader reader(
92 scoped_ptr<webkit_blob::FileStreamReader>(
93 new FakeFileStreamReader(&inner_read_log, net::OK)),
94 kBufferSize);
95
96 // For the first read, the internal file stream reader is fired, as there is
97 // no data in the preloading buffer.
98 {
99 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
100 std::vector<int> read_log;
101 const int result =
102 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
103 base::RunLoop().RunUntilIdle();
104
105 EXPECT_EQ(net::ERR_IO_PENDING, result);
106 ASSERT_EQ(1u, inner_read_log.size());
107 EXPECT_EQ(kBufferSize, inner_read_log[0]);
108 ASSERT_EQ(1u, read_log.size());
109 EXPECT_EQ(kChunkSize, read_log[0]);
110 }
111
112 // Second read should return data from the preloading buffer, without calling
113 // the internal file stream reader.
114 {
115 inner_read_log.clear();
116 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
117 std::vector<int> read_log;
118 const int result =
119 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
120 base::RunLoop().RunUntilIdle();
121
122 EXPECT_EQ(kChunkSize, result);
123 EXPECT_EQ(0u, inner_read_log.size());
124 // Results returned synchronously, so no new read result events.
125 EXPECT_EQ(0u, read_log.size());
126 }
127
128 // Third read should return partial result from the preloading buffer. It is
129 // valid to return less bytes than requested.
130 {
131 inner_read_log.clear();
132 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
133 std::vector<int> read_log;
134 const int result =
135 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
136 base::RunLoop().RunUntilIdle();
137
138 EXPECT_EQ(kBufferSize - 2 * kChunkSize, result);
139 EXPECT_EQ(0u, inner_read_log.size());
140 // Results returned synchronously, so no new read result events.
141 EXPECT_EQ(0u, read_log.size());
142 }
143
144 // The preloading buffer is now empty, so reading should invoke the internal
145 // file stream reader.
146 {
147 inner_read_log.clear();
148 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
149 std::vector<int> read_log;
150 const int result =
151 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
152 base::RunLoop().RunUntilIdle();
153
154 EXPECT_EQ(net::ERR_IO_PENDING, result);
155 ASSERT_EQ(1u, inner_read_log.size());
156 EXPECT_EQ(kBufferSize, inner_read_log[0]);
157 ASSERT_EQ(1u, read_log.size());
158 EXPECT_EQ(kChunkSize, read_log[0]);
159 }
160 }
161
162 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_Directly) {
163 std::vector<int> inner_read_log;
164 BufferingFileStreamReader reader(
165 scoped_ptr<webkit_blob::FileStreamReader>(
166 new FakeFileStreamReader(&inner_read_log, net::OK)),
167 kBufferSize);
168
169 // First read couple of bytes, so the internal buffer is filled out.
170 {
171 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
172 std::vector<int> read_log;
173 const int result =
174 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
175 base::RunLoop().RunUntilIdle();
176
177 EXPECT_EQ(net::ERR_IO_PENDING, result);
178 ASSERT_EQ(1u, inner_read_log.size());
179 EXPECT_EQ(kBufferSize, inner_read_log[0]);
180 ASSERT_EQ(1u, read_log.size());
181 EXPECT_EQ(kChunkSize, read_log[0]);
182 }
183
184 const int read_bytes = kBufferSize * 2;
185 ASSERT_GT(kFileSize, read_bytes);
186
187 // Reading more than the internal buffer size would cause fetching only
188 // as much as available in the internal buffer.
189 {
190 inner_read_log.clear();
191 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
192 std::vector<int> read_log;
193 const int result =
194 reader.Read(buffer, read_bytes, base::Bind(&LogValue<int>, &read_log));
195 base::RunLoop().RunUntilIdle();
196
197 EXPECT_EQ(kBufferSize - kChunkSize, result);
198 EXPECT_EQ(0u, inner_read_log.size());
199 EXPECT_EQ(0u, read_log.size());
200 }
201
202 // The internal buffer is clean. Fetching more than the internal buffer size
203 // would cause fetching data directly from the inner reader, with skipping
204 // the internal buffer.
205 {
206 inner_read_log.clear();
207 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
208 std::vector<int> read_log;
209 const int result =
210 reader.Read(buffer, read_bytes, base::Bind(&LogValue<int>, &read_log));
211 base::RunLoop().RunUntilIdle();
212
213 EXPECT_EQ(net::ERR_IO_PENDING, result);
214 ASSERT_EQ(1u, inner_read_log.size());
215 EXPECT_EQ(read_bytes, inner_read_log[0]);
216 ASSERT_EQ(1u, read_log.size());
217 EXPECT_EQ(read_bytes, read_log[0]);
218 }
219 }
220
221 TEST_F(FileSystemProviderBufferingFileStreamReaderTest,
222 Read_MoreThanBufferSize) {
223 std::vector<int> inner_read_log;
224 BufferingFileStreamReader reader(
225 scoped_ptr<webkit_blob::FileStreamReader>(
226 new FakeFileStreamReader(&inner_read_log, net::OK)),
227 kBufferSize);
228 // First read couple of bytes, so the internal buffer is filled out.
229 {
230 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
231 std::vector<int> read_log;
232 const int result =
233 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
234 base::RunLoop().RunUntilIdle();
235
236 EXPECT_EQ(net::ERR_IO_PENDING, result);
237 ASSERT_EQ(1u, inner_read_log.size());
238 EXPECT_EQ(kBufferSize, inner_read_log[0]);
239 ASSERT_EQ(1u, read_log.size());
240 EXPECT_EQ(kChunkSize, read_log[0]);
241 }
242
243 // Returning less than requested number of bytes is valid, and should not
244 // fail.
245 {
246 inner_read_log.clear();
247 const int chunk_size = 20;
248 ASSERT_LT(kBufferSize, chunk_size);
249 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(chunk_size));
250 std::vector<int> read_log;
251 const int result =
252 reader.Read(buffer, chunk_size, base::Bind(&LogValue<int>, &read_log));
253 base::RunLoop().RunUntilIdle();
254
255 EXPECT_EQ(5, result);
256 EXPECT_EQ(0u, inner_read_log.size());
257 EXPECT_EQ(0u, read_log.size());
258 }
259 }
260
261 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_WithError) {
262 std::vector<int> inner_read_log;
263 BufferingFileStreamReader reader(
264 scoped_ptr<webkit_blob::FileStreamReader>(
265 new FakeFileStreamReader(&inner_read_log, net::ERR_ACCESS_DENIED)),
266 kBufferSize);
267
268 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
269 std::vector<int> read_log;
270 const int result =
271 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
272 base::RunLoop().RunUntilIdle();
273
274 EXPECT_EQ(net::ERR_IO_PENDING, result);
275 ASSERT_EQ(1u, inner_read_log.size());
276 EXPECT_EQ(kBufferSize, inner_read_log[0]);
277 ASSERT_EQ(1u, read_log.size());
278 EXPECT_EQ(net::ERR_ACCESS_DENIED, read_log[0]);
279 }
280
281 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, GetLength) {
282 BufferingFileStreamReader reader(scoped_ptr<webkit_blob::FileStreamReader>(
283 new FakeFileStreamReader(NULL, net::OK)),
284 kBufferSize);
285
286 std::vector<int64> get_length_log;
287 const int64 result =
288 reader.GetLength(base::Bind(&LogValue<int64>, &get_length_log));
289 base::RunLoop().RunUntilIdle();
290
291 EXPECT_EQ(net::ERR_IO_PENDING, result);
292 ASSERT_EQ(1u, get_length_log.size());
293 EXPECT_EQ(kFileSize, get_length_log[0]);
294 }
295
296 } // namespace file_system_provider
297 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698