Upstream version 9.38.198.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 "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