Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_system_provider / fileapi / buffering_file_stream_reader_unittest.cc
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_stream_reader.h"
13 #include "chrome/browser/chromeos/fileapi/file_system_backend.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 kPreloadingBufferLength = 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 storage::FileStreamReader {
40  public:
41   FakeFileStreamReader(std::vector<int>* log, net::Error return_error)
42       : log_(log), return_error_(return_error) {}
43   virtual ~FakeFileStreamReader() {}
44
45   // storage::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_ != net::OK) {
53       base::MessageLoopProxy::current()->PostTask(
54           FROM_HERE, base::Bind(callback, return_error_));
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     DCHECK_EQ(net::OK, return_error_);
69     base::MessageLoopProxy::current()->PostTask(
70         FROM_HERE, base::Bind(callback, kFileSize));
71     return net::ERR_IO_PENDING;
72   }
73
74  private:
75   std::vector<int>* log_;  // Not owned.
76   net::Error return_error_;
77   DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
78 };
79
80 }  // namespace
81
82 class FileSystemProviderBufferingFileStreamReaderTest : public testing::Test {
83  protected:
84   FileSystemProviderBufferingFileStreamReaderTest() {}
85   virtual ~FileSystemProviderBufferingFileStreamReaderTest() {}
86
87   content::TestBrowserThreadBundle thread_bundle_;
88 };
89
90 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read) {
91   std::vector<int> inner_read_log;
92   BufferingFileStreamReader reader(
93       scoped_ptr<storage::FileStreamReader>(
94           new FakeFileStreamReader(&inner_read_log, net::OK)),
95       kPreloadingBufferLength,
96       kFileSize);
97
98   // For the first read, the internal file stream reader is fired, as there is
99   // no data in the preloading buffer.
100   {
101     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
102     std::vector<int> read_log;
103     const int result = reader.Read(
104         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
105     base::RunLoop().RunUntilIdle();
106
107     EXPECT_EQ(net::ERR_IO_PENDING, result);
108     ASSERT_EQ(1u, inner_read_log.size());
109     EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
110     ASSERT_EQ(1u, read_log.size());
111     EXPECT_EQ(kChunkSize, read_log[0]);
112   }
113
114   // Second read should return data from the preloading buffer, without calling
115   // the internal file stream reader.
116   {
117     inner_read_log.clear();
118     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
119     std::vector<int> read_log;
120     const int result = reader.Read(
121         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
122     base::RunLoop().RunUntilIdle();
123
124     EXPECT_EQ(kChunkSize, result);
125     EXPECT_EQ(0u, inner_read_log.size());
126     // Results returned synchronously, so no new read result events.
127     EXPECT_EQ(0u, read_log.size());
128   }
129
130   // Third read should return partial result from the preloading buffer. It is
131   // valid to return less bytes than requested.
132   {
133     inner_read_log.clear();
134     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
135     std::vector<int> read_log;
136     const int result = reader.Read(
137         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
138     base::RunLoop().RunUntilIdle();
139
140     EXPECT_EQ(kPreloadingBufferLength - 2 * kChunkSize, result);
141     EXPECT_EQ(0u, inner_read_log.size());
142     // Results returned synchronously, so no new read result events.
143     EXPECT_EQ(0u, read_log.size());
144   }
145
146   // The preloading buffer is now empty, so reading should invoke the internal
147   // file stream reader.
148   {
149     inner_read_log.clear();
150     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
151     std::vector<int> read_log;
152     const int result = reader.Read(
153         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
154     base::RunLoop().RunUntilIdle();
155
156     EXPECT_EQ(net::ERR_IO_PENDING, result);
157     ASSERT_EQ(1u, inner_read_log.size());
158     EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
159     ASSERT_EQ(1u, read_log.size());
160     EXPECT_EQ(kChunkSize, read_log[0]);
161   }
162 }
163
164 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_Directly) {
165   std::vector<int> inner_read_log;
166   BufferingFileStreamReader reader(
167       scoped_ptr<storage::FileStreamReader>(
168           new FakeFileStreamReader(&inner_read_log, net::OK)),
169       kPreloadingBufferLength,
170       kFileSize);
171
172   // First read couple of bytes, so the internal buffer is filled out.
173   {
174     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
175     std::vector<int> read_log;
176     const int result = reader.Read(
177         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
178     base::RunLoop().RunUntilIdle();
179
180     EXPECT_EQ(net::ERR_IO_PENDING, result);
181     ASSERT_EQ(1u, inner_read_log.size());
182     EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
183     ASSERT_EQ(1u, read_log.size());
184     EXPECT_EQ(kChunkSize, read_log[0]);
185   }
186
187   const int read_bytes = kPreloadingBufferLength * 2;
188   ASSERT_GT(kFileSize, read_bytes);
189
190   // Reading more than the internal buffer size would cause fetching only
191   // as much as available in the internal buffer.
192   {
193     inner_read_log.clear();
194     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
195     std::vector<int> read_log;
196     const int result = reader.Read(
197         buffer.get(), read_bytes, base::Bind(&LogValue<int>, &read_log));
198     base::RunLoop().RunUntilIdle();
199
200     EXPECT_EQ(kPreloadingBufferLength - kChunkSize, result);
201     EXPECT_EQ(0u, inner_read_log.size());
202     EXPECT_EQ(0u, read_log.size());
203   }
204
205   // The internal buffer is clean. Fetching more than the internal buffer size
206   // would cause fetching data directly from the inner reader, with skipping
207   // the internal buffer.
208   {
209     inner_read_log.clear();
210     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
211     std::vector<int> read_log;
212     const int result = reader.Read(
213         buffer.get(), read_bytes, base::Bind(&LogValue<int>, &read_log));
214     base::RunLoop().RunUntilIdle();
215
216     EXPECT_EQ(net::ERR_IO_PENDING, result);
217     ASSERT_EQ(1u, inner_read_log.size());
218     EXPECT_EQ(read_bytes, inner_read_log[0]);
219     ASSERT_EQ(1u, read_log.size());
220     EXPECT_EQ(read_bytes, read_log[0]);
221   }
222 }
223
224 TEST_F(FileSystemProviderBufferingFileStreamReaderTest,
225        Read_MoreThanBufferSize) {
226   std::vector<int> inner_read_log;
227   BufferingFileStreamReader reader(
228       scoped_ptr<storage::FileStreamReader>(
229           new FakeFileStreamReader(&inner_read_log, net::OK)),
230       kPreloadingBufferLength,
231       kFileSize);
232   // First read couple of bytes, so the internal buffer is filled out.
233   {
234     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
235     std::vector<int> read_log;
236     const int result = reader.Read(
237         buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
238     base::RunLoop().RunUntilIdle();
239
240     EXPECT_EQ(net::ERR_IO_PENDING, result);
241     ASSERT_EQ(1u, inner_read_log.size());
242     EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
243     ASSERT_EQ(1u, read_log.size());
244     EXPECT_EQ(kChunkSize, read_log[0]);
245   }
246
247   // Returning less than requested number of bytes is valid, and should not
248   // fail.
249   {
250     inner_read_log.clear();
251     const int chunk_size = 20;
252     ASSERT_LT(kPreloadingBufferLength, chunk_size);
253     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(chunk_size));
254     std::vector<int> read_log;
255     const int result = reader.Read(
256         buffer.get(), chunk_size, base::Bind(&LogValue<int>, &read_log));
257     base::RunLoop().RunUntilIdle();
258
259     EXPECT_EQ(5, result);
260     EXPECT_EQ(0u, inner_read_log.size());
261     EXPECT_EQ(0u, read_log.size());
262   }
263 }
264
265 TEST_F(FileSystemProviderBufferingFileStreamReaderTest,
266        Read_LessThanBufferSize) {
267   std::vector<int> inner_read_log;
268   const int total_bytes_to_read = 3;
269   ASSERT_LT(total_bytes_to_read, kPreloadingBufferLength);
270   BufferingFileStreamReader reader(
271       scoped_ptr<storage::FileStreamReader>(
272           new FakeFileStreamReader(&inner_read_log, net::OK)),
273       kPreloadingBufferLength,
274       total_bytes_to_read);
275
276   // For the first read, the internal file stream reader is fired, as there is
277   // no data in the preloading buffer.
278   const int read_bytes = 2;
279   ASSERT_LT(read_bytes, kPreloadingBufferLength);
280   ASSERT_LE(read_bytes, total_bytes_to_read);
281
282   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
283   std::vector<int> read_log;
284   const int result = reader.Read(
285       buffer.get(), read_bytes, base::Bind(&LogValue<int>, &read_log));
286   base::RunLoop().RunUntilIdle();
287
288   EXPECT_EQ(net::ERR_IO_PENDING, result);
289   ASSERT_EQ(1u, inner_read_log.size());
290   EXPECT_EQ(total_bytes_to_read, inner_read_log[0]);
291   ASSERT_EQ(1u, read_log.size());
292   EXPECT_EQ(read_bytes, read_log[0]);
293 }
294
295 TEST_F(FileSystemProviderBufferingFileStreamReaderTest,
296        Read_LessThanBufferSize_WithoutSpecifiedLength) {
297   std::vector<int> inner_read_log;
298   BufferingFileStreamReader reader(
299       scoped_ptr<storage::FileStreamReader>(
300           new FakeFileStreamReader(&inner_read_log, net::OK)),
301       kPreloadingBufferLength,
302       storage::kMaximumLength);
303
304   // For the first read, the internal file stream reader is fired, as there is
305   // no data in the preloading buffer.
306   const int read_bytes = 2;
307   ASSERT_LT(read_bytes, kPreloadingBufferLength);
308
309   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(read_bytes));
310   std::vector<int> read_log;
311   const int result = reader.Read(
312       buffer.get(), read_bytes, base::Bind(&LogValue<int>, &read_log));
313   base::RunLoop().RunUntilIdle();
314
315   EXPECT_EQ(net::ERR_IO_PENDING, result);
316   ASSERT_EQ(1u, inner_read_log.size());
317   EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
318   ASSERT_EQ(1u, read_log.size());
319   EXPECT_EQ(read_bytes, read_log[0]);
320 }
321
322 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, Read_WithError) {
323   std::vector<int> inner_read_log;
324   BufferingFileStreamReader reader(
325       scoped_ptr<storage::FileStreamReader>(
326           new FakeFileStreamReader(&inner_read_log, net::ERR_ACCESS_DENIED)),
327       kPreloadingBufferLength,
328       kFileSize);
329
330   scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kChunkSize));
331   std::vector<int> read_log;
332   const int result = reader.Read(
333       buffer.get(), kChunkSize, base::Bind(&LogValue<int>, &read_log));
334   base::RunLoop().RunUntilIdle();
335
336   EXPECT_EQ(net::ERR_IO_PENDING, result);
337   ASSERT_EQ(1u, inner_read_log.size());
338   EXPECT_EQ(kPreloadingBufferLength, inner_read_log[0]);
339   ASSERT_EQ(1u, read_log.size());
340   EXPECT_EQ(net::ERR_ACCESS_DENIED, read_log[0]);
341 }
342
343 TEST_F(FileSystemProviderBufferingFileStreamReaderTest, GetLength) {
344   BufferingFileStreamReader reader(scoped_ptr<storage::FileStreamReader>(
345                                        new FakeFileStreamReader(NULL, net::OK)),
346                                    kPreloadingBufferLength,
347                                    kFileSize);
348
349   std::vector<int64> get_length_log;
350   const int64 result =
351       reader.GetLength(base::Bind(&LogValue<int64>, &get_length_log));
352   base::RunLoop().RunUntilIdle();
353
354   EXPECT_EQ(net::ERR_IO_PENDING, result);
355   ASSERT_EQ(1u, get_length_log.size());
356   EXPECT_EQ(kFileSize, get_length_log[0]);
357 }
358
359 }  // namespace file_system_provider
360 }  // namespace chromeos