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

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: Fixed naming. 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/memory/weak_ptr.h"
hashimoto 2014/07/08 11:12:55 nit: No need to include this.
mtomasz 2014/07/09 02:05:22 Done.
11 #include "base/message_loop/message_loop.h"
hashimoto 2014/07/08 11:12:55 nit: This should be message_loop_proxy
mtomasz 2014/07/09 02:05:22 Done.
12 #include "base/run_loop.h"
13 #include "chrome/browser/chromeos/file_system_provider/fileapi/buffering_file_st ream_reader.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace chromeos {
20 namespace file_system_provider {
21 namespace {
22
23 // Size of the fake file in bytes.
24 const int kFileSize = 1024;
25
26 // Size of the preloading buffer in bytes.
27 const int kBufferSize = 8;
28
29 // Number of bytes requested per BufferingFileStreamReader::Read().
30 const int kChunkSize = 3;
31
32 // Pushes a value to the passed log vector.
33 template <typename T>
34 void LogValue(std::vector<T>* log, T value) {
35 log->push_back(value);
36 }
37
38 // Fake internal file stream reader.
39 class FakeFileStreamReader : public webkit_blob::FileStreamReader {
40 public:
41 FakeFileStreamReader(std::vector<int>* log, bool return_error)
hashimoto 2014/07/08 11:12:55 How about replacing |return_error| with net::Error
mtomasz 2014/07/09 02:05:22 Done.
42 : log_(log), return_error_(return_error) {}
43 virtual ~FakeFileStreamReader() {}
44
45 // webkit_blob::FileStreamReader overrides.
46 virtual int Read(net::IOBuffer* buf,
47 int buf_len,
48 const net::CompletionCallback& callback) OVERRIDE {
49 DCHECK(log_);
50 log_->push_back(buf_len);
51
52 if (return_error_) {
53 base::MessageLoopProxy::current()->PostTask(
54 FROM_HERE, base::Bind(callback, net::ERR_ACCESS_DENIED));
55 return net::ERR_IO_PENDING;
56 }
57
58 const std::string fake_data('X', buf_len);
59 memcpy(buf->data(), fake_data.c_str(), buf_len);
60
61 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
62 base::Bind(callback, buf_len));
63 return net::ERR_IO_PENDING;
64 }
65
66 virtual int64 GetLength(
67 const net::Int64CompletionCallback& callback) OVERRIDE {
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 bool 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, false /* return_error */)),
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 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
116 std::vector<int> read_log;
117 const int result =
118 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
119 base::RunLoop().RunUntilIdle();
120
121 EXPECT_EQ(kChunkSize, result);
122 EXPECT_EQ(1u, inner_read_log.size());
123 // Results returned synchronously, so no new read result events.
124 EXPECT_EQ(0u, read_log.size());
125 }
126
127 // Third read should return partial result from the preloading buffer. It is
128 // valid to return less bytes than requested.
129 {
130 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
131 std::vector<int> read_log;
132 const int result =
133 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
134 base::RunLoop().RunUntilIdle();
135
136 EXPECT_EQ(kBufferSize - 2 * kChunkSize, result);
137 EXPECT_EQ(1u, inner_read_log.size());
138 // Results returned synchronously, so no new read result events.
139 EXPECT_EQ(0u, read_log.size());
140 }
141
142 // The preloading buffer is now empty, so reading should invoke the internal
143 // file stream reader.
144 {
145 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
146 std::vector<int> read_log;
147 const int result =
148 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
149 base::RunLoop().RunUntilIdle();
150
151 EXPECT_EQ(net::ERR_IO_PENDING, result);
152 ASSERT_EQ(2u, inner_read_log.size());
153 EXPECT_EQ(kBufferSize, inner_read_log[0]);
hashimoto 2014/07/08 11:12:55 Shouldn't this be inner_read_log[1]? BTW, how abo
mtomasz 2014/07/09 02:05:22 Good idea. Done.
154 ASSERT_EQ(1u, read_log.size());
155 EXPECT_EQ(kChunkSize, read_log[0]);
156 }
157 }
158
159 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_Directly) {
160 std::vector<int> inner_read_log;
161 BufferingFileStreamReader reader(
162 scoped_ptr<webkit_blob::FileStreamReader>(
163 new FakeFileStreamReader(&inner_read_log, false /* return_error */)),
164 kBufferSize);
165
166 // First read couple of bytes, so the internal buffer is filled out.
167 {
168 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
169 std::vector<int> read_log;
170 const int result =
171 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
172 base::RunLoop().RunUntilIdle();
173
174 EXPECT_EQ(net::ERR_IO_PENDING, result);
175 ASSERT_EQ(1u, inner_read_log.size());
176 EXPECT_EQ(kBufferSize, inner_read_log[0]);
177 ASSERT_EQ(1u, read_log.size());
178 EXPECT_EQ(kChunkSize, read_log[0]);
179 }
180
181 const int read_bytes = kBufferSize * 2;
182 ASSERT_GT(kFileSize, read_bytes);
183
184 // Reading more than the internal buffer size would cause fetching only
185 // as much as available in the internal buffer.
186 {
187 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
188 std::vector<int> read_log;
189 const int result =
190 reader.Read(buffer, read_bytes, base::Bind(&LogValue<int>, &read_log));
191 base::RunLoop().RunUntilIdle();
192
193 EXPECT_EQ(kBufferSize - kChunkSize, result);
194 ASSERT_EQ(1u, inner_read_log.size());
195 EXPECT_EQ(kBufferSize, inner_read_log[0]);
196 EXPECT_EQ(0u, read_log.size());
197 }
198
199 // The internal buffer is clean. Fetching more than the internal buffer size
200 // would cause fetching data directly from the inner reader, with skipping
201 // the internal buffer.
202 {
203 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
204 std::vector<int> read_log;
205 const int result =
206 reader.Read(buffer, read_bytes, base::Bind(&LogValue<int>, &read_log));
207 base::RunLoop().RunUntilIdle();
208
209 EXPECT_EQ(net::ERR_IO_PENDING, result);
210 ASSERT_EQ(2u, inner_read_log.size());
211 EXPECT_EQ(read_bytes, inner_read_log[1]);
212 ASSERT_EQ(1u, read_log.size());
213 EXPECT_EQ(read_bytes, read_log[0]);
214 }
215 }
216
217 TEST_F(FileSystemProviderBufferingFileStreamReaderTest,
218 Read_MoreThanBufferSize) {
219 std::vector<int> inner_read_log;
220 BufferingFileStreamReader reader(
221 scoped_ptr<webkit_blob::FileStreamReader>(
222 new FakeFileStreamReader(&inner_read_log, false /* return_error */)),
223 kBufferSize);
224 // First read couple of bytes, so the internal buffer is filled out.
225 {
226 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
227 std::vector<int> read_log;
228 const int result =
229 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
230 base::RunLoop().RunUntilIdle();
231
232 EXPECT_EQ(net::ERR_IO_PENDING, result);
233 ASSERT_EQ(1u, inner_read_log.size());
234 EXPECT_EQ(kBufferSize, inner_read_log[0]);
235 ASSERT_EQ(1u, read_log.size());
236 EXPECT_EQ(kChunkSize, read_log[0]);
237 }
238
239 // Returning less than requested number of bytes is valid, and should not
240 // fail.
241 {
242 const int chunk_size = 20;
243 ASSERT_LT(kBufferSize, chunk_size);
244 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(chunk_size));
245 std::vector<int> read_log;
246 const int result =
247 reader.Read(buffer, chunk_size, base::Bind(&LogValue<int>, &read_log));
248 base::RunLoop().RunUntilIdle();
249
250 EXPECT_EQ(5, result);
251 EXPECT_EQ(1u, inner_read_log.size());
252 EXPECT_EQ(0u, read_log.size());
253 }
254 }
255
256 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_WithError) {
257 std::vector<int> inner_read_log;
258 BufferingFileStreamReader reader(
259 scoped_ptr<webkit_blob::FileStreamReader>(
260 new FakeFileStreamReader(&inner_read_log, true /* return_error */)),
261 kBufferSize);
262
263 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
264 std::vector<int> read_log;
265 const int result =
266 reader.Read(buffer, kChunkSize, base::Bind(&LogValue<int>, &read_log));
267 base::RunLoop().RunUntilIdle();
268
269 EXPECT_EQ(net::ERR_IO_PENDING, result);
270 ASSERT_EQ(1u, inner_read_log.size());
271 EXPECT_EQ(kBufferSize, inner_read_log[0]);
272 ASSERT_EQ(1u, read_log.size());
273 EXPECT_EQ(net::ERR_ACCESS_DENIED, read_log[0]);
274 }
275
276 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, GetLength) {
277 BufferingFileStreamReader reader(
278 scoped_ptr<webkit_blob::FileStreamReader>(
279 new FakeFileStreamReader(NULL, false /* return_error */)),
280 kBufferSize);
281
282 std::vector<int64> get_length_log;
283 const int64 result =
284 reader.GetLength(base::Bind(&LogValue<int64>, &get_length_log));
285 base::RunLoop().RunUntilIdle();
286
287 EXPECT_EQ(net::ERR_IO_PENDING, result);
288 ASSERT_EQ(1u, get_length_log.size());
289 EXPECT_EQ(kFileSize, get_length_log[0]);
290 }
291
292 } // namespace file_system_provider
293 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698