1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/run_loop.h"
13 #include "base/threading/thread.h"
14 #include "chrome/browser/chromeos/drive/fake_file_system.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/local_file_reader.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/google_apis/test_util.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/test_completion_callback.h"
24 #include "net/http/http_byte_range.h"
25 #include "testing/gtest/include/gtest/gtest.h"
31 // Increments the |num_called|, when this method is invoked.
32 void IncrementCallback(int* num_called) {
39 class LocalReaderProxyTest : public ::testing::Test {
41 LocalReaderProxyTest()
42 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
45 virtual void SetUp() OVERRIDE {
46 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
47 ASSERT_TRUE(google_apis::test_util::CreateFileOfSpecifiedSize(
48 temp_dir_.path(), 1024, &file_path_, &file_content_));
50 worker_thread_.reset(new base::Thread("ReaderProxyTest"));
51 ASSERT_TRUE(worker_thread_->Start());
54 content::TestBrowserThreadBundle thread_bundle_;
56 base::ScopedTempDir temp_dir_;
57 base::FilePath file_path_;
58 std::string file_content_;
60 scoped_ptr<base::Thread> worker_thread_;
63 TEST_F(LocalReaderProxyTest, Read) {
64 // Open the file first.
65 scoped_ptr<util::LocalFileReader> file_reader(
66 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
67 net::TestCompletionCallback callback;
68 file_reader->Open(file_path_, 0, callback.callback());
69 ASSERT_EQ(net::OK, callback.WaitForResult());
72 LocalReaderProxy proxy(file_reader.Pass(), file_content_.size());
74 // Make sure the read content is as same as the file.
76 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
77 EXPECT_EQ(file_content_, content);
80 TEST_F(LocalReaderProxyTest, ReadWithLimit) {
81 // This test case, we only read first half of the file.
82 const std::string expected_content =
83 file_content_.substr(0, file_content_.size() / 2);
85 // Open the file first.
86 scoped_ptr<util::LocalFileReader> file_reader(
87 new util::LocalFileReader(worker_thread_->message_loop_proxy().get()));
88 net::TestCompletionCallback callback;
89 file_reader->Open(file_path_, 0, callback.callback());
90 ASSERT_EQ(net::OK, callback.WaitForResult());
93 LocalReaderProxy proxy(file_reader.Pass(), expected_content.size());
95 // Make sure the read content is as same as the file.
97 ASSERT_EQ(net::OK, test_util::ReadAllData(&proxy, &content));
98 EXPECT_EQ(expected_content, content);
101 class NetworkReaderProxyTest : public ::testing::Test {
103 NetworkReaderProxyTest()
104 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
107 content::TestBrowserThreadBundle thread_bundle_;
110 TEST_F(NetworkReaderProxyTest, EmptyFile) {
111 NetworkReaderProxy proxy(0, 0, base::Bind(&base::DoNothing));
113 net::TestCompletionCallback callback;
114 const int kBufferSize = 10;
115 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
116 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
118 // For empty file, Read() should return 0 immediately.
119 EXPECT_EQ(0, result);
122 TEST_F(NetworkReaderProxyTest, Read) {
123 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
125 net::TestCompletionCallback callback;
126 const int kBufferSize = 3;
127 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
129 // If no data is available yet, ERR_IO_PENDING should be returned.
130 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
131 EXPECT_EQ(net::ERR_IO_PENDING, result);
133 // And when the data is supplied, the callback will be called.
134 scoped_ptr<std::string> data(new std::string("abcde"));
135 proxy.OnGetContent(data.Pass());
137 // The returned data should be fit to the buffer size.
138 result = callback.GetResult(result);
139 EXPECT_EQ(3, result);
140 EXPECT_EQ("abc", std::string(buffer->data(), result));
142 // The next Read should return immediately because there is pending data
143 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
144 EXPECT_EQ(2, result);
145 EXPECT_EQ("de", std::string(buffer->data(), result));
147 // Supply the data before calling Read operation.
148 data.reset(new std::string("fg"));
149 proxy.OnGetContent(data.Pass());
150 data.reset(new std::string("hij"));
151 proxy.OnGetContent(data.Pass()); // Now 10 bytes are supplied.
153 // The data should be concatenated if possible.
154 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
155 EXPECT_EQ(3, result);
156 EXPECT_EQ("fgh", std::string(buffer->data(), result));
158 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
159 EXPECT_EQ(2, result);
160 EXPECT_EQ("ij", std::string(buffer->data(), result));
162 // The whole data is read, so Read() should return 0 immediately by then.
163 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
164 EXPECT_EQ(0, result);
167 TEST_F(NetworkReaderProxyTest, ReadWithLimit) {
168 NetworkReaderProxy proxy(10, 10, base::Bind(&base::DoNothing));
170 net::TestCompletionCallback callback;
171 const int kBufferSize = 3;
172 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
174 // If no data is available yet, ERR_IO_PENDING should be returned.
175 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
176 EXPECT_EQ(net::ERR_IO_PENDING, result);
178 // And when the data is supplied, the callback will be called.
179 scoped_ptr<std::string> data(new std::string("abcde"));
180 proxy.OnGetContent(data.Pass());
181 data.reset(new std::string("fgh"));
182 proxy.OnGetContent(data.Pass());
183 data.reset(new std::string("ijklmno"));
184 proxy.OnGetContent(data.Pass());
186 // The returned data should be fit to the buffer size.
187 result = callback.GetResult(result);
188 EXPECT_EQ(3, result);
189 EXPECT_EQ("klm", std::string(buffer->data(), result));
191 // The next Read should return immediately because there is pending data
192 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
193 EXPECT_EQ(2, result);
194 EXPECT_EQ("no", std::string(buffer->data(), result));
196 // Supply the data before calling Read operation.
197 data.reset(new std::string("pqrs"));
198 proxy.OnGetContent(data.Pass());
199 data.reset(new std::string("tuvwxyz"));
200 proxy.OnGetContent(data.Pass()); // 't' is the 20-th byte.
202 // The data should be concatenated if possible.
203 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
204 EXPECT_EQ(3, result);
205 EXPECT_EQ("pqr", std::string(buffer->data(), result));
207 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
208 EXPECT_EQ(2, result);
209 EXPECT_EQ("st", std::string(buffer->data(), result));
211 // The whole data is read, so Read() should return 0 immediately by then.
212 result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
213 EXPECT_EQ(0, result);
216 TEST_F(NetworkReaderProxyTest, ErrorWithPendingCallback) {
217 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
219 net::TestCompletionCallback callback;
220 const int kBufferSize = 3;
221 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
223 // Set pending callback.
224 int result = proxy.Read(buffer.get(), kBufferSize, callback.callback());
225 EXPECT_EQ(net::ERR_IO_PENDING, result);
227 // Emulate that an error is found. The callback should be called internally.
228 proxy.OnCompleted(FILE_ERROR_FAILED);
229 result = callback.GetResult(result);
230 EXPECT_EQ(net::ERR_FAILED, result);
232 // The next Read call should also return the same error code.
233 EXPECT_EQ(net::ERR_FAILED,
234 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
237 TEST_F(NetworkReaderProxyTest, ErrorWithPendingData) {
238 NetworkReaderProxy proxy(0, 10, base::Bind(&base::DoNothing));
240 net::TestCompletionCallback callback;
241 const int kBufferSize = 3;
242 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
244 // Supply the data before an error.
245 scoped_ptr<std::string> data(new std::string("abcde"));
246 proxy.OnGetContent(data.Pass());
248 // Emulate that an error is found.
249 proxy.OnCompleted(FILE_ERROR_FAILED);
251 // The next Read call should return the error code, even if there is
252 // pending data (the pending data should be released in OnCompleted.
253 EXPECT_EQ(net::ERR_FAILED,
254 proxy.Read(buffer.get(), kBufferSize, callback.callback()));
257 TEST_F(NetworkReaderProxyTest, CancelJob) {
260 NetworkReaderProxy proxy(
261 0, 0, base::Bind(&IncrementCallback, &num_called));
262 proxy.OnCompleted(FILE_ERROR_OK);
263 // Destroy the instance after the network operation is completed.
264 // The cancelling callback shouldn't be called.
266 EXPECT_EQ(0, num_called);
270 NetworkReaderProxy proxy(
271 0, 0, base::Bind(&IncrementCallback, &num_called));
272 // Destroy the instance before the network operation is completed.
273 // The cancelling callback should be called.
275 EXPECT_EQ(1, num_called);
278 } // namespace internal
280 class DriveFileStreamReaderTest : public ::testing::Test {
282 DriveFileStreamReaderTest()
283 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
286 virtual void SetUp() OVERRIDE {
287 worker_thread_.reset(new base::Thread("DriveFileStreamReaderTest"));
288 ASSERT_TRUE(worker_thread_->Start());
290 // Initialize FakeDriveService.
291 fake_drive_service_.reset(new FakeDriveService);
292 fake_drive_service_->LoadResourceListForWapi(
293 "gdata/root_feed.json");
294 fake_drive_service_->LoadAccountMetadataForWapi(
295 "gdata/account_metadata.json");
297 // Create a testee instance.
298 fake_file_system_.reset(
299 new test_util::FakeFileSystem(fake_drive_service_.get()));
302 FileSystemInterface* GetFileSystem() {
303 return fake_file_system_.get();
306 DriveFileStreamReader::FileSystemGetter GetFileSystemGetter() {
307 return base::Bind(&DriveFileStreamReaderTest::GetFileSystem,
308 base::Unretained(this));
311 content::TestBrowserThreadBundle thread_bundle_;
313 scoped_ptr<base::Thread> worker_thread_;
315 scoped_ptr<FakeDriveService> fake_drive_service_;
316 scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
319 TEST_F(DriveFileStreamReaderTest, Read) {
320 const base::FilePath kDriveFile =
321 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
322 // Create the reader, and initialize it.
323 // In this case, the file is not yet locally cached.
324 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
325 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
326 EXPECT_FALSE(reader->IsInitialized());
328 int error = net::ERR_FAILED;
329 scoped_ptr<ResourceEntry> entry;
331 base::RunLoop run_loop;
334 net::HttpByteRange(),
335 google_apis::test_util::CreateQuitCallback(
337 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
340 EXPECT_EQ(net::OK, error);
342 EXPECT_TRUE(reader->IsInitialized());
343 size_t content_size = entry->file_info().size();
345 // Read data from the reader.
346 std::string first_content;
347 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
348 EXPECT_EQ(content_size, first_content.size());
350 // Create second instance and initialize it.
351 // In this case, the file should be cached one.
352 reader.reset(new DriveFileStreamReader(
353 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
354 EXPECT_FALSE(reader->IsInitialized());
356 error = net::ERR_FAILED;
359 base::RunLoop run_loop;
362 net::HttpByteRange(),
363 google_apis::test_util::CreateQuitCallback(
365 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
368 EXPECT_EQ(net::OK, error);
370 EXPECT_TRUE(reader->IsInitialized());
372 // The size should be same.
373 EXPECT_EQ(content_size, static_cast<size_t>(entry->file_info().size()));
375 // Read data from the reader, again.
376 std::string second_content;
377 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
379 // The same content is expected.
380 EXPECT_EQ(first_content, second_content);
383 TEST_F(DriveFileStreamReaderTest, ReadRange) {
384 // In this test case, we just confirm that the part of file is read.
385 const int64 kRangeOffset = 3;
386 const int64 kRangeLength = 4;
388 const base::FilePath kDriveFile =
389 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
390 // Create the reader, and initialize it.
391 // In this case, the file is not yet locally cached.
392 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
393 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
394 EXPECT_FALSE(reader->IsInitialized());
396 int error = net::ERR_FAILED;
397 scoped_ptr<ResourceEntry> entry;
398 net::HttpByteRange byte_range;
399 byte_range.set_first_byte_position(kRangeOffset);
400 // Last byte position is inclusive.
401 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
403 base::RunLoop run_loop;
407 google_apis::test_util::CreateQuitCallback(
409 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
412 EXPECT_EQ(net::OK, error);
414 EXPECT_TRUE(reader->IsInitialized());
416 // Read data from the reader.
417 std::string first_content;
418 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &first_content));
420 // The length should be equal to range length.
421 EXPECT_EQ(kRangeLength, static_cast<int64>(first_content.size()));
423 // Create second instance and initialize it.
424 // In this case, the file should be cached one.
425 reader.reset(new DriveFileStreamReader(
426 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
427 EXPECT_FALSE(reader->IsInitialized());
429 error = net::ERR_FAILED;
432 base::RunLoop run_loop;
436 google_apis::test_util::CreateQuitCallback(
438 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
441 EXPECT_EQ(net::OK, error);
443 EXPECT_TRUE(reader->IsInitialized());
445 // Read data from the reader, again.
446 std::string second_content;
447 ASSERT_EQ(net::OK, test_util::ReadAllData(reader.get(), &second_content));
449 // The same content is expected.
450 EXPECT_EQ(first_content, second_content);
453 TEST_F(DriveFileStreamReaderTest, OutOfRangeError) {
454 const int64 kRangeOffset = 1000000; // Out of range.
455 const int64 kRangeLength = 4;
457 const base::FilePath kDriveFile =
458 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
459 // Create the reader, and initialize it.
460 // In this case, the file is not yet locally cached.
461 scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
462 GetFileSystemGetter(), worker_thread_->message_loop_proxy().get()));
463 EXPECT_FALSE(reader->IsInitialized());
465 int error = net::ERR_FAILED;
466 scoped_ptr<ResourceEntry> entry;
467 net::HttpByteRange byte_range;
468 byte_range.set_first_byte_position(kRangeOffset);
469 // Last byte position is inclusive.
470 byte_range.set_last_byte_position(kRangeOffset + kRangeLength - 1);
472 base::RunLoop run_loop;
476 google_apis::test_util::CreateQuitCallback(
478 google_apis::test_util::CreateCopyResultCallback(&error, &entry)));
481 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, error);