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. 4 5 #include "base/basictypes.h" 6 #include "base/files/file_path.h" 7 #include "base/files/scoped_temp_dir.h" 8 #include "base/run_loop.h" 9 #include "content/public/test/test_file_system_context.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "webkit/browser/fileapi/file_system_context.h" 12 #include "webkit/browser/fileapi/file_system_operation_runner.h" 13 14 using fileapi::FileSystemContext; 15 using fileapi::FileSystemOperationRunner; 16 using fileapi::FileSystemType; 17 using fileapi::FileSystemURL; 18 19 namespace content { 20 21 void GetStatus(bool* done, 22 base::File::Error *status_out, 23 base::File::Error status) { 24 ASSERT_FALSE(*done); 25 *done = true; 26 *status_out = status; 27 } 28 29 void GetCancelStatus(bool* operation_done, 30 bool* cancel_done, 31 base::File::Error *status_out, 32 base::File::Error status) { 33 // Cancel callback must be always called after the operation's callback. 34 ASSERT_TRUE(*operation_done); 35 ASSERT_FALSE(*cancel_done); 36 *cancel_done = true; 37 *status_out = status; 38 } 39 40 class FileSystemOperationRunnerTest : public testing::Test { 41 protected: 42 FileSystemOperationRunnerTest() {} 43 virtual ~FileSystemOperationRunnerTest() {} 44 45 virtual void SetUp() OVERRIDE { 46 ASSERT_TRUE(base_.CreateUniqueTempDir()); 47 base::FilePath base_dir = base_.path(); 48 file_system_context_ = 49 CreateFileSystemContextForTesting(NULL, base_dir); 50 } 51 52 virtual void TearDown() OVERRIDE { 53 file_system_context_ = NULL; 54 base::RunLoop().RunUntilIdle(); 55 } 56 57 FileSystemURL URL(const std::string& path) { 58 return file_system_context_->CreateCrackedFileSystemURL( 59 GURL("http://example.com"), fileapi::kFileSystemTypeTemporary, 60 base::FilePath::FromUTF8Unsafe(path)); 61 } 62 63 FileSystemOperationRunner* operation_runner() { 64 return file_system_context_->operation_runner(); 65 } 66 67 private: 68 base::ScopedTempDir base_; 69 base::MessageLoop message_loop_; 70 scoped_refptr<FileSystemContext> file_system_context_; 71 72 DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunnerTest); 73 }; 74 75 TEST_F(FileSystemOperationRunnerTest, NotFoundError) { 76 bool done = false; 77 base::File::Error status = base::File::FILE_ERROR_FAILED; 78 79 // Regular NOT_FOUND error, which is called asynchronously. 80 operation_runner()->Truncate(URL("foo"), 0, 81 base::Bind(&GetStatus, &done, &status)); 82 ASSERT_FALSE(done); 83 base::RunLoop().RunUntilIdle(); 84 ASSERT_TRUE(done); 85 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, status); 86 } 87 88 TEST_F(FileSystemOperationRunnerTest, InvalidURLError) { 89 bool done = false; 90 base::File::Error status = base::File::FILE_ERROR_FAILED; 91 92 // Invalid URL error, which calls DidFinish synchronously. 93 operation_runner()->Truncate(FileSystemURL(), 0, 94 base::Bind(&GetStatus, &done, &status)); 95 // The error call back shouldn't be fired synchronously. 96 ASSERT_FALSE(done); 97 98 base::RunLoop().RunUntilIdle(); 99 ASSERT_TRUE(done); 100 ASSERT_EQ(base::File::FILE_ERROR_INVALID_URL, status); 101 } 102 103 TEST_F(FileSystemOperationRunnerTest, NotFoundErrorAndCancel) { 104 bool done = false; 105 bool cancel_done = false; 106 base::File::Error status = base::File::FILE_ERROR_FAILED; 107 base::File::Error cancel_status = base::File::FILE_ERROR_FAILED; 108 109 // Call Truncate with non-existent URL, and try to cancel it immediately 110 // after that (before its callback is fired). 111 FileSystemOperationRunner::OperationID id = 112 operation_runner()->Truncate(URL("foo"), 0, 113 base::Bind(&GetStatus, &done, &status)); 114 operation_runner()->Cancel(id, base::Bind(&GetCancelStatus, 115 &done, &cancel_done, 116 &cancel_status)); 117 118 ASSERT_FALSE(done); 119 ASSERT_FALSE(cancel_done); 120 base::RunLoop().RunUntilIdle(); 121 122 ASSERT_TRUE(done); 123 ASSERT_TRUE(cancel_done); 124 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, status); 125 ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status); 126 } 127 128 TEST_F(FileSystemOperationRunnerTest, InvalidURLErrorAndCancel) { 129 bool done = false; 130 bool cancel_done = false; 131 base::File::Error status = base::File::FILE_ERROR_FAILED; 132 base::File::Error cancel_status = base::File::FILE_ERROR_FAILED; 133 134 // Call Truncate with invalid URL, and try to cancel it immediately 135 // after that (before its callback is fired). 136 FileSystemOperationRunner::OperationID id = 137 operation_runner()->Truncate(FileSystemURL(), 0, 138 base::Bind(&GetStatus, &done, &status)); 139 operation_runner()->Cancel(id, base::Bind(&GetCancelStatus, 140 &done, &cancel_done, 141 &cancel_status)); 142 143 ASSERT_FALSE(done); 144 ASSERT_FALSE(cancel_done); 145 base::RunLoop().RunUntilIdle(); 146 147 ASSERT_TRUE(done); 148 ASSERT_TRUE(cancel_done); 149 ASSERT_EQ(base::File::FILE_ERROR_INVALID_URL, status); 150 ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status); 151 } 152 153 TEST_F(FileSystemOperationRunnerTest, CancelWithInvalidId) { 154 const FileSystemOperationRunner::OperationID kInvalidId = -1; 155 bool done = true; // The operation is not running. 156 bool cancel_done = false; 157 base::File::Error cancel_status = base::File::FILE_ERROR_FAILED; 158 operation_runner()->Cancel(kInvalidId, base::Bind(&GetCancelStatus, 159 &done, &cancel_done, 160 &cancel_status)); 161 162 ASSERT_TRUE(cancel_done); 163 ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status); 164 } 165 166 } // namespace content 167