| OLD | NEW |
| (Empty) |
| 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 "storage/browser/fileapi/file_system_file_stream_reader.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <limits> | |
| 11 #include <memory> | |
| 12 #include <string> | |
| 13 | |
| 14 #include "base/files/scoped_temp_dir.h" | |
| 15 #include "base/macros.h" | |
| 16 #include "base/run_loop.h" | |
| 17 #include "content/public/test/async_file_test_helper.h" | |
| 18 #include "content/public/test/test_file_system_context.h" | |
| 19 #include "net/base/io_buffer.h" | |
| 20 #include "net/base/net_errors.h" | |
| 21 #include "net/base/test_completion_callback.h" | |
| 22 #include "storage/browser/fileapi/external_mount_points.h" | |
| 23 #include "storage/browser/fileapi/file_system_context.h" | |
| 24 #include "storage/browser/fileapi/file_system_file_util.h" | |
| 25 #include "testing/gtest/include/gtest/gtest.h" | |
| 26 | |
| 27 using content::AsyncFileTestHelper; | |
| 28 using storage::FileSystemContext; | |
| 29 using storage::FileSystemFileStreamReader; | |
| 30 using storage::FileSystemType; | |
| 31 using storage::FileSystemURL; | |
| 32 | |
| 33 namespace content { | |
| 34 | |
| 35 namespace { | |
| 36 | |
| 37 const char kURLOrigin[] = "http://remote/"; | |
| 38 const char kTestFileName[] = "test.dat"; | |
| 39 const char kTestData[] = "0123456789"; | |
| 40 const int kTestDataSize = arraysize(kTestData) - 1; | |
| 41 | |
| 42 void ReadFromReader(storage::FileSystemFileStreamReader* reader, | |
| 43 std::string* data, | |
| 44 size_t size, | |
| 45 int* result) { | |
| 46 ASSERT_TRUE(reader != NULL); | |
| 47 ASSERT_TRUE(result != NULL); | |
| 48 *result = net::OK; | |
| 49 net::TestCompletionCallback callback; | |
| 50 size_t total_bytes_read = 0; | |
| 51 while (total_bytes_read < size) { | |
| 52 scoped_refptr<net::IOBufferWithSize> buf( | |
| 53 new net::IOBufferWithSize(size - total_bytes_read)); | |
| 54 int rv = reader->Read(buf.get(), buf->size(), callback.callback()); | |
| 55 if (rv == net::ERR_IO_PENDING) | |
| 56 rv = callback.WaitForResult(); | |
| 57 if (rv < 0) | |
| 58 *result = rv; | |
| 59 if (rv <= 0) | |
| 60 break; | |
| 61 total_bytes_read += rv; | |
| 62 data->append(buf->data(), rv); | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 void NeverCalled(int unused) { ADD_FAILURE(); } | |
| 67 | |
| 68 } // namespace | |
| 69 | |
| 70 class FileSystemFileStreamReaderTest : public testing::Test { | |
| 71 public: | |
| 72 FileSystemFileStreamReaderTest() {} | |
| 73 | |
| 74 void SetUp() override { | |
| 75 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 76 | |
| 77 file_system_context_ = | |
| 78 CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath()); | |
| 79 | |
| 80 file_system_context_->OpenFileSystem( | |
| 81 GURL(kURLOrigin), | |
| 82 storage::kFileSystemTypeTemporary, | |
| 83 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, | |
| 84 base::Bind(&OnOpenFileSystem)); | |
| 85 base::RunLoop().RunUntilIdle(); | |
| 86 | |
| 87 WriteFile(kTestFileName, kTestData, kTestDataSize, | |
| 88 &test_file_modification_time_); | |
| 89 } | |
| 90 | |
| 91 void TearDown() override { base::RunLoop().RunUntilIdle(); } | |
| 92 | |
| 93 protected: | |
| 94 storage::FileSystemFileStreamReader* CreateFileReader( | |
| 95 const std::string& file_name, | |
| 96 int64_t initial_offset, | |
| 97 const base::Time& expected_modification_time) { | |
| 98 return new FileSystemFileStreamReader(file_system_context_.get(), | |
| 99 GetFileSystemURL(file_name), | |
| 100 initial_offset, | |
| 101 expected_modification_time); | |
| 102 } | |
| 103 | |
| 104 base::Time test_file_modification_time() const { | |
| 105 return test_file_modification_time_; | |
| 106 } | |
| 107 | |
| 108 void WriteFile(const std::string& file_name, | |
| 109 const char* buf, | |
| 110 int buf_size, | |
| 111 base::Time* modification_time) { | |
| 112 FileSystemURL url = GetFileSystemURL(file_name); | |
| 113 | |
| 114 ASSERT_EQ(base::File::FILE_OK, | |
| 115 content::AsyncFileTestHelper::CreateFileWithData( | |
| 116 file_system_context_.get(), url, buf, buf_size)); | |
| 117 | |
| 118 base::File::Info file_info; | |
| 119 ASSERT_EQ(base::File::FILE_OK, | |
| 120 AsyncFileTestHelper::GetMetadata( | |
| 121 file_system_context_.get(), url, &file_info)); | |
| 122 if (modification_time) | |
| 123 *modification_time = file_info.last_modified; | |
| 124 } | |
| 125 | |
| 126 private: | |
| 127 static void OnOpenFileSystem(const GURL& root_url, | |
| 128 const std::string& name, | |
| 129 base::File::Error result) { | |
| 130 ASSERT_EQ(base::File::FILE_OK, result); | |
| 131 } | |
| 132 | |
| 133 FileSystemURL GetFileSystemURL(const std::string& file_name) { | |
| 134 return file_system_context_->CreateCrackedFileSystemURL( | |
| 135 GURL(kURLOrigin), | |
| 136 storage::kFileSystemTypeTemporary, | |
| 137 base::FilePath().AppendASCII(file_name)); | |
| 138 } | |
| 139 | |
| 140 base::MessageLoopForIO message_loop_; | |
| 141 base::ScopedTempDir temp_dir_; | |
| 142 scoped_refptr<FileSystemContext> file_system_context_; | |
| 143 base::Time test_file_modification_time_; | |
| 144 }; | |
| 145 | |
| 146 TEST_F(FileSystemFileStreamReaderTest, NonExistent) { | |
| 147 const char kFileName[] = "nonexistent"; | |
| 148 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 149 CreateFileReader(kFileName, 0, base::Time())); | |
| 150 int result = 0; | |
| 151 std::string data; | |
| 152 ReadFromReader(reader.get(), &data, 10, &result); | |
| 153 ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result); | |
| 154 ASSERT_EQ(0U, data.size()); | |
| 155 } | |
| 156 | |
| 157 TEST_F(FileSystemFileStreamReaderTest, Empty) { | |
| 158 const char kFileName[] = "empty"; | |
| 159 WriteFile(kFileName, NULL, 0, NULL); | |
| 160 | |
| 161 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 162 CreateFileReader(kFileName, 0, base::Time())); | |
| 163 int result = 0; | |
| 164 std::string data; | |
| 165 ReadFromReader(reader.get(), &data, 10, &result); | |
| 166 ASSERT_EQ(net::OK, result); | |
| 167 ASSERT_EQ(0U, data.size()); | |
| 168 | |
| 169 net::TestInt64CompletionCallback callback; | |
| 170 int64_t length_result = reader->GetLength(callback.callback()); | |
| 171 if (length_result == net::ERR_IO_PENDING) | |
| 172 length_result = callback.WaitForResult(); | |
| 173 ASSERT_EQ(0, length_result); | |
| 174 } | |
| 175 | |
| 176 TEST_F(FileSystemFileStreamReaderTest, GetLengthNormal) { | |
| 177 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 178 CreateFileReader(kTestFileName, 0, test_file_modification_time())); | |
| 179 net::TestInt64CompletionCallback callback; | |
| 180 int64_t result = reader->GetLength(callback.callback()); | |
| 181 if (result == net::ERR_IO_PENDING) | |
| 182 result = callback.WaitForResult(); | |
| 183 ASSERT_EQ(kTestDataSize, result); | |
| 184 } | |
| 185 | |
| 186 TEST_F(FileSystemFileStreamReaderTest, GetLengthAfterModified) { | |
| 187 // Pass a fake expected modifictaion time so that the expectation fails. | |
| 188 base::Time fake_expected_modification_time = | |
| 189 test_file_modification_time() - base::TimeDelta::FromSeconds(10); | |
| 190 | |
| 191 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 192 CreateFileReader(kTestFileName, 0, fake_expected_modification_time)); | |
| 193 net::TestInt64CompletionCallback callback; | |
| 194 int64_t result = reader->GetLength(callback.callback()); | |
| 195 if (result == net::ERR_IO_PENDING) | |
| 196 result = callback.WaitForResult(); | |
| 197 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); | |
| 198 | |
| 199 // With NULL expected modification time this should work. | |
| 200 reader.reset(CreateFileReader(kTestFileName, 0, base::Time())); | |
| 201 result = reader->GetLength(callback.callback()); | |
| 202 if (result == net::ERR_IO_PENDING) | |
| 203 result = callback.WaitForResult(); | |
| 204 ASSERT_EQ(kTestDataSize, result); | |
| 205 } | |
| 206 | |
| 207 TEST_F(FileSystemFileStreamReaderTest, GetLengthWithOffset) { | |
| 208 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 209 CreateFileReader(kTestFileName, 3, base::Time())); | |
| 210 net::TestInt64CompletionCallback callback; | |
| 211 int64_t result = reader->GetLength(callback.callback()); | |
| 212 if (result == net::ERR_IO_PENDING) | |
| 213 result = callback.WaitForResult(); | |
| 214 // Initial offset does not affect the result of GetLength. | |
| 215 ASSERT_EQ(kTestDataSize, result); | |
| 216 } | |
| 217 | |
| 218 TEST_F(FileSystemFileStreamReaderTest, ReadNormal) { | |
| 219 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 220 CreateFileReader(kTestFileName, 0, test_file_modification_time())); | |
| 221 int result = 0; | |
| 222 std::string data; | |
| 223 ReadFromReader(reader.get(), &data, kTestDataSize, &result); | |
| 224 ASSERT_EQ(net::OK, result); | |
| 225 ASSERT_EQ(kTestData, data); | |
| 226 } | |
| 227 | |
| 228 TEST_F(FileSystemFileStreamReaderTest, ReadAfterModified) { | |
| 229 // Pass a fake expected modifictaion time so that the expectation fails. | |
| 230 base::Time fake_expected_modification_time = | |
| 231 test_file_modification_time() - base::TimeDelta::FromSeconds(10); | |
| 232 | |
| 233 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 234 CreateFileReader(kTestFileName, 0, fake_expected_modification_time)); | |
| 235 int result = 0; | |
| 236 std::string data; | |
| 237 ReadFromReader(reader.get(), &data, kTestDataSize, &result); | |
| 238 ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); | |
| 239 ASSERT_EQ(0U, data.size()); | |
| 240 | |
| 241 // With NULL expected modification time this should work. | |
| 242 data.clear(); | |
| 243 reader.reset(CreateFileReader(kTestFileName, 0, base::Time())); | |
| 244 ReadFromReader(reader.get(), &data, kTestDataSize, &result); | |
| 245 ASSERT_EQ(net::OK, result); | |
| 246 ASSERT_EQ(kTestData, data); | |
| 247 } | |
| 248 | |
| 249 TEST_F(FileSystemFileStreamReaderTest, ReadWithOffset) { | |
| 250 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 251 CreateFileReader(kTestFileName, 3, base::Time())); | |
| 252 int result = 0; | |
| 253 std::string data; | |
| 254 ReadFromReader(reader.get(), &data, kTestDataSize, &result); | |
| 255 ASSERT_EQ(net::OK, result); | |
| 256 ASSERT_EQ(&kTestData[3], data); | |
| 257 } | |
| 258 | |
| 259 TEST_F(FileSystemFileStreamReaderTest, DeleteWithUnfinishedRead) { | |
| 260 std::unique_ptr<FileSystemFileStreamReader> reader( | |
| 261 CreateFileReader(kTestFileName, 0, base::Time())); | |
| 262 | |
| 263 net::TestCompletionCallback callback; | |
| 264 scoped_refptr<net::IOBufferWithSize> buf( | |
| 265 new net::IOBufferWithSize(kTestDataSize)); | |
| 266 int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled)); | |
| 267 ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0); | |
| 268 | |
| 269 // Delete immediately. | |
| 270 // Should not crash; nor should NeverCalled be callback. | |
| 271 reader.reset(); | |
| 272 } | |
| 273 | |
| 274 } // namespace content | |
| OLD | NEW |