| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011 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/bind.h" |
| 6 #include "base/message_loop.h" |
| 7 #include "base/platform_file.h" |
| 8 #include "base/time.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "webkit/chromeos/fileapi/memory_file_util.h" |
| 11 |
| 12 namespace { |
| 13 const FilePath::CharType kRootPath[] = "/mnt/memory"; |
| 14 const char kTestString[] = "A test string. A test string."; |
| 15 const char kTestStringLength = arraysize(kTestString) - 1; |
| 16 } // namespace |
| 17 |
| 18 namespace fileapi { |
| 19 |
| 20 // This test is actually testing MemoryFileUtil — an async in-memory file |
| 21 // system, based on FileUtilAsync. |
| 22 class MemoryFileUtilTest : public testing::Test { |
| 23 public: |
| 24 MemoryFileUtilTest() { |
| 25 } |
| 26 |
| 27 void SetUp() { |
| 28 file_util_.reset(new MemoryFileUtil(FilePath(kRootPath))); |
| 29 } |
| 30 |
| 31 MemoryFileUtil* file_util() { |
| 32 return file_util_.get(); |
| 33 } |
| 34 |
| 35 enum CallbackType { |
| 36 CALLBACK_TYPE_ERROR, |
| 37 CALLBACK_TYPE_STATUS, |
| 38 CALLBACK_TYPE_GET_FILE_INFO, |
| 39 CALLBACK_TYPE_OPEN, |
| 40 CALLBACK_TYPE_READ_WRITE, |
| 41 CALLBACK_TYPE_READ_DIRECTORY |
| 42 }; |
| 43 |
| 44 struct CallbackStatus { |
| 45 CallbackType type; |
| 46 base::PlatformFileError result; |
| 47 base::PlatformFileInfo file_info; |
| 48 // This object should be deleted in the test code. |
| 49 AsyncFileStream* file_stream; |
| 50 int64 length; |
| 51 |
| 52 // Following 4 fields only for ReadDirectory. |
| 53 FileUtilAsync::FileList entries; |
| 54 bool completed; |
| 55 bool called_after_completed; |
| 56 int called; |
| 57 }; |
| 58 |
| 59 FileUtilAsync::StatusCallback GetStatusCallback(int request_id) { |
| 60 max_request_id_ = std::max(request_id, max_request_id_); |
| 61 return base::Bind(&MemoryFileUtilTest::StatusCallbackImpl, |
| 62 base::Unretained(this), |
| 63 request_id); |
| 64 } |
| 65 |
| 66 FileUtilAsync::GetFileInfoCallback GetGetFileInfoCallback( |
| 67 int request_id) { |
| 68 max_request_id_ = std::max(request_id, max_request_id_); |
| 69 return base::Bind(&MemoryFileUtilTest::GetFileInfoCallback, |
| 70 base::Unretained(this), |
| 71 request_id); |
| 72 } |
| 73 |
| 74 FileUtilAsync::OpenCallback GetOpenCallback(int request_id) { |
| 75 max_request_id_ = std::max(request_id, max_request_id_); |
| 76 return base::Bind(&MemoryFileUtilTest::OpenCallback, |
| 77 base::Unretained(this), |
| 78 request_id); |
| 79 } |
| 80 |
| 81 AsyncFileStream::ReadWriteCallback GetReadWriteCallback(int request_id) { |
| 82 max_request_id_ = std::max(request_id, max_request_id_); |
| 83 return base::Bind(&MemoryFileUtilTest::ReadWriteCallbackImpl, |
| 84 base::Unretained(this), |
| 85 request_id); |
| 86 } |
| 87 |
| 88 FileUtilAsync::ReadDirectoryCallback GetReadDirectoryCallback( |
| 89 int request_id) { |
| 90 if (request_id > max_request_id_) { |
| 91 max_request_id_ = request_id; |
| 92 } |
| 93 return base::Bind(&MemoryFileUtilTest::ReadDirectoryCallback, |
| 94 base::Unretained(this), |
| 95 request_id); |
| 96 } |
| 97 |
| 98 int CreateEmptyFile(const FilePath& file_path) { |
| 99 int request_id = GetNextRequestId(); |
| 100 file_util_->Create(file_path, GetStatusCallback(request_id)); |
| 101 return request_id; |
| 102 } |
| 103 |
| 104 int CreateNonEmptyFile(const FilePath& file_path, |
| 105 const char* data, |
| 106 int length) { |
| 107 int request_id = GetNextRequestId(); |
| 108 file_util_->Open( |
| 109 file_path, |
| 110 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, |
| 111 base::Bind(&MemoryFileUtilTest::WriteToOpenedFile, |
| 112 base::Unretained(this), |
| 113 request_id, data, length)); |
| 114 return request_id; |
| 115 } |
| 116 |
| 117 CallbackType GetStatusType(int request_id) { |
| 118 if (status_map_.find(request_id) == status_map_.end()) |
| 119 return CALLBACK_TYPE_ERROR; |
| 120 return status_map_[request_id].type; |
| 121 } |
| 122 |
| 123 // Return the operation status. |
| 124 CallbackStatus& GetStatus(int request_id) { |
| 125 return status_map_[request_id]; |
| 126 } |
| 127 |
| 128 int StatusQueueSize() { |
| 129 return status_map_.size(); |
| 130 } |
| 131 |
| 132 int GetNextRequestId() { |
| 133 return ++max_request_id_; |
| 134 } |
| 135 |
| 136 void set_read_directory_buffer_size(int size) { |
| 137 file_util_->set_read_directory_buffer_size(size); |
| 138 } |
| 139 |
| 140 private: |
| 141 void StatusCallbackImpl(int request_id, PlatformFileError result) { |
| 142 CallbackStatus status; |
| 143 status.type = CALLBACK_TYPE_STATUS; |
| 144 status.result = result; |
| 145 status_map_[request_id] = status; |
| 146 } |
| 147 |
| 148 void GetFileInfoCallback(int request_id, |
| 149 PlatformFileError result, |
| 150 const base::PlatformFileInfo& file_info) { |
| 151 CallbackStatus status; |
| 152 status.type = CALLBACK_TYPE_GET_FILE_INFO; |
| 153 status.result = result; |
| 154 status.file_info = file_info; |
| 155 status_map_[request_id] = status; |
| 156 } |
| 157 |
| 158 void OpenCallback(int request_id, |
| 159 PlatformFileError result, |
| 160 AsyncFileStream* file_stream) { |
| 161 CallbackStatus status; |
| 162 status.type = CALLBACK_TYPE_OPEN; |
| 163 status.result = result; |
| 164 status.file_stream = file_stream; |
| 165 status_map_[request_id] = status; |
| 166 } |
| 167 |
| 168 void ReadWriteCallbackImpl(int request_id, |
| 169 PlatformFileError result, |
| 170 int64 length) { |
| 171 CallbackStatus status; |
| 172 status.type = CALLBACK_TYPE_READ_WRITE; |
| 173 status.result = result; |
| 174 status.length = length; |
| 175 status_map_[request_id] = status; |
| 176 } |
| 177 |
| 178 void ReadDirectoryCallback(int request_id, |
| 179 PlatformFileError result, |
| 180 const FileUtilAsync::FileList& entries, |
| 181 bool completed) { |
| 182 if (status_map_.find(request_id) == status_map_.end()) { |
| 183 CallbackStatus status; |
| 184 status.type = CALLBACK_TYPE_READ_DIRECTORY; |
| 185 status.called_after_completed = false; |
| 186 status.result = result; |
| 187 status.completed = completed; |
| 188 status.called = 1; |
| 189 status.entries = entries; |
| 190 status_map_[request_id] = status; |
| 191 } else { |
| 192 CallbackStatus& status = status_map_[request_id]; |
| 193 if (status.completed) |
| 194 status.called_after_completed = true; |
| 195 status.result = result; |
| 196 status.completed = completed; |
| 197 ++status.called; |
| 198 status.entries.insert(status.entries.begin(), entries.begin(), |
| 199 entries.end()); |
| 200 } |
| 201 } |
| 202 |
| 203 void WriteToOpenedFile(int request_id, |
| 204 const char* data, |
| 205 int length, |
| 206 PlatformFileError result, |
| 207 AsyncFileStream* stream) { |
| 208 CallbackStatus status; |
| 209 status.type = CALLBACK_TYPE_OPEN; |
| 210 status.result = result; |
| 211 status_map_[request_id] = status; |
| 212 stream->Write(data, length, GetReadWriteCallback(GetNextRequestId())); |
| 213 } |
| 214 |
| 215 scoped_ptr<MemoryFileUtil> file_util_; |
| 216 std::map<int, CallbackStatus> status_map_; |
| 217 int max_request_id_; |
| 218 |
| 219 DISALLOW_COPY_AND_ASSIGN(MemoryFileUtilTest); |
| 220 }; |
| 221 |
| 222 TEST_F(MemoryFileUtilTest, TestCreateGetFileInfo) { |
| 223 const int request_id1 = GetNextRequestId(); |
| 224 file_util()->GetFileInfo(FilePath("/mnt/memory/test.txt"), |
| 225 GetGetFileInfoCallback(request_id1)); |
| 226 |
| 227 // In case the file system is truely asynchronous, RunAllPending is not |
| 228 // enough to wait for answer. In that case the thread should be blocked |
| 229 // until the callback is called (ex. use Run() instead here, and call |
| 230 // Quit() from callback). |
| 231 MessageLoop::current()->RunAllPending(); |
| 232 |
| 233 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id1)); |
| 234 CallbackStatus status = GetStatus(request_id1); |
| 235 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status.result); |
| 236 |
| 237 base::Time start_create = base::Time::Now(); |
| 238 |
| 239 const int request_id2 = GetNextRequestId(); |
| 240 file_util()->Create(FilePath("/mnt/memory/test.txt"), |
| 241 GetStatusCallback(request_id2)); |
| 242 MessageLoop::current()->RunAllPending(); |
| 243 ASSERT_EQ(CALLBACK_TYPE_STATUS, GetStatusType(request_id2)); |
| 244 status = GetStatus(request_id2); |
| 245 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 246 |
| 247 file_util()->GetFileInfo(FilePath("/mnt/memory/test.txt"), |
| 248 GetGetFileInfoCallback(3)); |
| 249 MessageLoop::current()->RunAllPending(); |
| 250 |
| 251 base::Time end_create = base::Time::Now(); |
| 252 |
| 253 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(3)); |
| 254 status = GetStatus(3); |
| 255 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 256 ASSERT_EQ(0, status.file_info.size); |
| 257 ASSERT_FALSE(status.file_info.is_directory); |
| 258 ASSERT_FALSE(status.file_info.is_symbolic_link); |
| 259 ASSERT_GE(status.file_info.last_modified, start_create); |
| 260 ASSERT_LE(status.file_info.last_modified, end_create); |
| 261 ASSERT_GE(status.file_info.creation_time, start_create); |
| 262 ASSERT_LE(status.file_info.creation_time, end_create); |
| 263 } |
| 264 |
| 265 TEST_F(MemoryFileUtilTest, TestReadWrite) { |
| 266 // Check that the file does not exist. |
| 267 |
| 268 const int request_id1 = GetNextRequestId(); |
| 269 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 270 GetGetFileInfoCallback(request_id1)); |
| 271 |
| 272 MessageLoop::current()->RunAllPending(); |
| 273 |
| 274 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id1)); |
| 275 CallbackStatus status = GetStatus(request_id1); |
| 276 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status.result); |
| 277 |
| 278 // Create & open file for writing. |
| 279 |
| 280 base::Time start_create = base::Time::Now(); |
| 281 const int request_id2 = GetNextRequestId(); |
| 282 file_util()->Open(FilePath("/mnt/memory/test1.txt"), |
| 283 base::PLATFORM_FILE_CREATE_ALWAYS | |
| 284 base::PLATFORM_FILE_WRITE, |
| 285 GetOpenCallback(request_id2)); |
| 286 MessageLoop::current()->RunAllPending(); |
| 287 |
| 288 base::Time end_create = base::Time::Now(); |
| 289 |
| 290 ASSERT_EQ(CALLBACK_TYPE_OPEN, GetStatusType(request_id2)); |
| 291 status = GetStatus(request_id2); |
| 292 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 293 |
| 294 AsyncFileStream* write_file_stream = status.file_stream; |
| 295 |
| 296 // Check that file was created and has 0 size. |
| 297 |
| 298 const int request_id3 = GetNextRequestId(); |
| 299 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 300 GetGetFileInfoCallback(request_id3)); |
| 301 MessageLoop::current()->RunAllPending(); |
| 302 |
| 303 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id3)); |
| 304 status = GetStatus(request_id3); |
| 305 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 306 ASSERT_EQ(0, status.file_info.size); |
| 307 ASSERT_FALSE(status.file_info.is_directory); |
| 308 ASSERT_FALSE(status.file_info.is_symbolic_link); |
| 309 ASSERT_GE(status.file_info.last_modified, start_create); |
| 310 ASSERT_LE(status.file_info.last_modified, end_create); |
| 311 |
| 312 // Write 10 bytes to file. |
| 313 |
| 314 const int request_id4 = GetNextRequestId(); |
| 315 base::Time start_write = base::Time::Now(); |
| 316 write_file_stream->Write(kTestString, 10, |
| 317 GetReadWriteCallback(request_id4)); |
| 318 MessageLoop::current()->RunAllPending(); |
| 319 base::Time end_write = base::Time::Now(); |
| 320 |
| 321 ASSERT_EQ(CALLBACK_TYPE_READ_WRITE, GetStatusType(request_id4)); |
| 322 status = GetStatus(request_id4); |
| 323 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 324 ASSERT_EQ(10, status.length); |
| 325 |
| 326 // Check that the file has now size 10 and correct modification time. |
| 327 |
| 328 const int request_id5 = GetNextRequestId(); |
| 329 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 330 GetGetFileInfoCallback(request_id5)); |
| 331 MessageLoop::current()->RunAllPending(); |
| 332 |
| 333 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id5)); |
| 334 status = GetStatus(request_id5); |
| 335 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 336 ASSERT_EQ(10, status.file_info.size); |
| 337 ASSERT_GE(status.file_info.last_modified, start_write); |
| 338 ASSERT_LE(status.file_info.last_modified, end_write); |
| 339 |
| 340 // Write the rest of the string to file. |
| 341 |
| 342 const int request_id6 = GetNextRequestId(); |
| 343 start_write = base::Time::Now(); |
| 344 write_file_stream->Write(kTestString + 10, |
| 345 kTestStringLength - 10, |
| 346 GetReadWriteCallback(request_id6)); |
| 347 MessageLoop::current()->RunAllPending(); |
| 348 end_write = base::Time::Now(); |
| 349 |
| 350 ASSERT_EQ(CALLBACK_TYPE_READ_WRITE, GetStatusType(request_id6)); |
| 351 status = GetStatus(request_id6); |
| 352 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 353 ASSERT_EQ(static_cast<int64>(kTestStringLength) - 10, status.length); |
| 354 |
| 355 // Check the file size & modification time. |
| 356 |
| 357 const int request_id7 = GetNextRequestId(); |
| 358 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 359 GetGetFileInfoCallback(request_id7)); |
| 360 MessageLoop::current()->RunAllPending(); |
| 361 |
| 362 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id7)); |
| 363 status = GetStatus(request_id7); |
| 364 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 365 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.file_info.size); |
| 366 ASSERT_GE(status.file_info.last_modified, start_write); |
| 367 ASSERT_LE(status.file_info.last_modified, end_write); |
| 368 |
| 369 // Open file for reading. |
| 370 |
| 371 const int request_id8 = GetNextRequestId(); |
| 372 file_util()->Open(FilePath("/mnt/memory/test1.txt"), |
| 373 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, |
| 374 GetOpenCallback(request_id8)); |
| 375 MessageLoop::current()->RunAllPending(); |
| 376 |
| 377 ASSERT_EQ(CALLBACK_TYPE_OPEN, GetStatusType(request_id8)); |
| 378 status = GetStatus(request_id8); |
| 379 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 380 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 381 |
| 382 scoped_ptr<AsyncFileStream> read_file_stream(status.file_stream); |
| 383 |
| 384 // Read the whole file |
| 385 char buffer[1024]; |
| 386 const int request_id9 = GetNextRequestId(); |
| 387 read_file_stream->Read(buffer, 1023, GetReadWriteCallback(request_id9)); |
| 388 MessageLoop::current()->RunAllPending(); |
| 389 |
| 390 ASSERT_EQ(CALLBACK_TYPE_READ_WRITE, GetStatusType(request_id9)); |
| 391 status = GetStatus(request_id9); |
| 392 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 393 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.length); |
| 394 |
| 395 buffer[status.length] = '\0'; |
| 396 std::string result_string(buffer); |
| 397 ASSERT_EQ(kTestString, result_string); |
| 398 |
| 399 // Check that size & modification time have not changed. |
| 400 |
| 401 const int request_id10 = GetNextRequestId(); |
| 402 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 403 GetGetFileInfoCallback(request_id10)); |
| 404 MessageLoop::current()->RunAllPending(); |
| 405 |
| 406 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id10)); |
| 407 status = GetStatus(request_id10); |
| 408 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 409 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.file_info.size); |
| 410 ASSERT_GE(status.file_info.last_modified, start_write); |
| 411 ASSERT_LE(status.file_info.last_modified, end_write); |
| 412 |
| 413 // Open once more for writing. |
| 414 |
| 415 const int request_id11 = GetNextRequestId(); |
| 416 file_util()->Open(FilePath("/mnt/memory/test1.txt"), |
| 417 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, |
| 418 GetOpenCallback(request_id11)); |
| 419 MessageLoop::current()->RunAllPending(); |
| 420 |
| 421 ASSERT_EQ(CALLBACK_TYPE_OPEN, GetStatusType(request_id11)); |
| 422 status = GetStatus(request_id11); |
| 423 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 424 |
| 425 scoped_ptr<AsyncFileStream> write_file_stream2(status.file_stream); |
| 426 |
| 427 // Check that the size has not changed. |
| 428 |
| 429 const int request_id12 = GetNextRequestId(); |
| 430 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 431 GetGetFileInfoCallback(request_id12)); |
| 432 MessageLoop::current()->RunAllPending(); |
| 433 |
| 434 ASSERT_EQ(CALLBACK_TYPE_GET_FILE_INFO, GetStatusType(request_id12)); |
| 435 status = GetStatus(request_id12); |
| 436 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 437 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.file_info.size); |
| 438 |
| 439 // Seek beyond the end of file. Should return error. |
| 440 |
| 441 const int request_id13 = GetNextRequestId(); |
| 442 write_file_stream2->Seek(1000, GetStatusCallback(request_id13)); |
| 443 MessageLoop::current()->RunAllPending(); |
| 444 ASSERT_EQ(CALLBACK_TYPE_STATUS, GetStatusType(request_id13)); |
| 445 status = GetStatus(request_id13); |
| 446 ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status.result); |
| 447 |
| 448 // Try to write to read-only stream. |
| 449 |
| 450 const int request_id14 = GetNextRequestId(); |
| 451 read_file_stream->Write(kTestString, |
| 452 kTestStringLength, |
| 453 GetReadWriteCallback(request_id14)); |
| 454 MessageLoop::current()->RunAllPending(); |
| 455 status = GetStatus(request_id14); |
| 456 ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status.result); |
| 457 |
| 458 // Write data overlapping with already written. |
| 459 |
| 460 |
| 461 const int request_id15 = GetNextRequestId(); |
| 462 write_file_stream2->Seek(10, GetStatusCallback(request_id15)); |
| 463 MessageLoop::current()->RunAllPending(); |
| 464 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id15).result); |
| 465 |
| 466 const int request_id16 = GetNextRequestId(); |
| 467 write_file_stream2->Write(kTestString, |
| 468 kTestStringLength, |
| 469 GetReadWriteCallback(request_id16)); |
| 470 MessageLoop::current()->RunAllPending(); |
| 471 status = GetStatus(request_id16); |
| 472 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 473 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.length); |
| 474 |
| 475 // Check size. |
| 476 |
| 477 const int request_id17 = GetNextRequestId(); |
| 478 file_util()->GetFileInfo(FilePath("/mnt/memory/test1.txt"), |
| 479 GetGetFileInfoCallback(request_id17)); |
| 480 MessageLoop::current()->RunAllPending(); |
| 481 status = GetStatus(request_id17); |
| 482 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 483 ASSERT_EQ(static_cast<int64>(kTestStringLength) + 10, |
| 484 status.file_info.size); |
| 485 |
| 486 // Read from 10th byte. |
| 487 const int request_id18 = GetNextRequestId(); |
| 488 read_file_stream->Seek(10, GetStatusCallback(request_id18)); |
| 489 MessageLoop::current()->RunAllPending(); |
| 490 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id18).result); |
| 491 |
| 492 const int request_id19 = GetNextRequestId(); |
| 493 read_file_stream->Read(buffer, 1023, GetReadWriteCallback(request_id19)); |
| 494 MessageLoop::current()->RunAllPending(); |
| 495 status = GetStatus(request_id19); |
| 496 ASSERT_EQ(base::PLATFORM_FILE_OK, status.result); |
| 497 ASSERT_EQ(static_cast<int64>(kTestStringLength), status.length); |
| 498 buffer[status.length] = '\0'; |
| 499 std::string result_string2(buffer); |
| 500 ASSERT_EQ(kTestString, result_string2); |
| 501 } |
| 502 |
| 503 // The directory structure we'll be testing on: |
| 504 // path size |
| 505 // |
| 506 // /mnt/memory/a 0 |
| 507 // /mnt/memory/b/ |
| 508 // /mnt/memory/b/c kTestStringLength |
| 509 // /mnt/memory/b/d/ |
| 510 // /mnt/memory/b/e 0 |
| 511 // /mnt/memory/b/f kTestStringLength |
| 512 // /mnt/memory/b/g/ |
| 513 // /mnt/memory/b/g/h 0 |
| 514 // /mnt/memory/b/i kTestStringLength |
| 515 // /mnt/memory/c/ |
| 516 // /mnt/memory/longer_file_name.txt kTestStringLength |
| 517 TEST_F(MemoryFileUtilTest, TestDirectoryOperations) { |
| 518 // Check the directory is empty. |
| 519 const int request_id0 = GetNextRequestId(); |
| 520 file_util()->ReadDirectory(FilePath("/mnt/memory/"), |
| 521 GetReadDirectoryCallback(request_id0)); |
| 522 |
| 523 MessageLoop::current()->RunAllPending(); |
| 524 |
| 525 ASSERT_EQ(CALLBACK_TYPE_READ_DIRECTORY, GetStatusType(request_id0)); |
| 526 CallbackStatus& status = GetStatus(request_id0); |
| 527 ASSERT_TRUE(status.completed); |
| 528 ASSERT_FALSE(status.called_after_completed); |
| 529 ASSERT_EQ(1, status.called); |
| 530 ASSERT_EQ(0u, status.entries.size()); |
| 531 |
| 532 // Create /mnt/memory/a, /mnt/memory/b/, /mnt/memory/longer_file_name.txt, |
| 533 // /mnt/memory/c/ asyncronously (i.e. we do not wait for each operation to |
| 534 // complete before starting the next one. |
| 535 |
| 536 base::Time start_create = base::Time::Now(); |
| 537 CreateEmptyFile(FilePath("/mnt/memory/a")); |
| 538 |
| 539 int request_id1 = GetNextRequestId(); |
| 540 file_util()->CreateDirectory(FilePath("/mnt/memory/b"), |
| 541 GetStatusCallback(request_id1)); |
| 542 |
| 543 CreateNonEmptyFile(FilePath("/mnt/memory/longer_file_name.txt"), |
| 544 kTestString, |
| 545 kTestStringLength); |
| 546 |
| 547 int request_id2 = GetNextRequestId(); |
| 548 file_util()->CreateDirectory(FilePath("/mnt/memory/c"), |
| 549 GetStatusCallback(request_id2)); |
| 550 |
| 551 MessageLoop::current()->RunAllPending(); |
| 552 base::Time end_create = base::Time::Now(); |
| 553 |
| 554 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 555 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id2).result); |
| 556 |
| 557 // ReadDirectory /mnt/memory, /mnt/memory/a (not a dir), /mnt/memory/b/, |
| 558 // /mnt/memory/d (not found) |
| 559 |
| 560 set_read_directory_buffer_size(5); // Should complete in one go. |
| 561 |
| 562 request_id1 = GetNextRequestId(); |
| 563 file_util()->ReadDirectory(FilePath("/mnt/memory"), |
| 564 GetReadDirectoryCallback(request_id1)); |
| 565 request_id2 = GetNextRequestId(); |
| 566 file_util()->ReadDirectory(FilePath("/mnt/memory/a"), |
| 567 GetReadDirectoryCallback(request_id2)); |
| 568 const int request_id3 = GetNextRequestId(); |
| 569 file_util()->ReadDirectory(FilePath("/mnt/memory/b/"), |
| 570 GetReadDirectoryCallback(request_id3)); |
| 571 const int request_id4 = GetNextRequestId(); |
| 572 file_util()->ReadDirectory(FilePath("/mnt/memory/d/"), |
| 573 GetReadDirectoryCallback(request_id4)); |
| 574 |
| 575 MessageLoop::current()->RunAllPending(); |
| 576 |
| 577 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 578 status = GetStatus(request_id1); |
| 579 ASSERT_TRUE(status.completed); |
| 580 ASSERT_FALSE(status.called_after_completed); |
| 581 ASSERT_EQ(1, status.called); // Because the number of entries < 5. |
| 582 ASSERT_EQ(4u, status.entries.size()); |
| 583 |
| 584 std::set<FilePath::StringType> seen; |
| 585 |
| 586 for (FileUtilAsync::FileList::const_iterator it = status.entries.begin(); |
| 587 it != status.entries.end(); |
| 588 ++it) { |
| 589 ASSERT_LE(start_create, it->last_modified_time); |
| 590 ASSERT_GE(end_create, it->last_modified_time); |
| 591 |
| 592 ASSERT_EQ(seen.end(), seen.find(it->name)); |
| 593 seen.insert(it->name); |
| 594 |
| 595 if (it->name == "a") { |
| 596 ASSERT_FALSE(it->is_directory); |
| 597 ASSERT_EQ(0, it->size); |
| 598 } else if (it->name == "b") { |
| 599 ASSERT_TRUE(it->is_directory); |
| 600 } else if (it->name == "c") { |
| 601 ASSERT_TRUE(it->is_directory); |
| 602 } else if (it->name == "longer_file_name.txt") { |
| 603 ASSERT_FALSE(it->is_directory); |
| 604 ASSERT_EQ(static_cast<int64>(kTestStringLength), it->size); |
| 605 } else { |
| 606 LOG(ERROR) << "Unexpected file: " << it->name; |
| 607 ASSERT_TRUE(false); |
| 608 } |
| 609 } |
| 610 |
| 611 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, |
| 612 GetStatus(request_id2).result); |
| 613 |
| 614 status = GetStatus(request_id3); |
| 615 ASSERT_TRUE(status.completed); |
| 616 ASSERT_FALSE(status.called_after_completed); |
| 617 ASSERT_EQ(1, status.called); |
| 618 ASSERT_EQ(0u, status.entries.size()); |
| 619 |
| 620 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, GetStatus(request_id4).result); |
| 621 |
| 622 // Create files & dirs inside b/: |
| 623 // /mnt/memory/b/c kTestStringLength |
| 624 // /mnt/memory/b/d/ |
| 625 // /mnt/memory/b/e 0 |
| 626 // /mnt/memory/b/f kTestStringLength |
| 627 // /mnt/memory/b/g/ |
| 628 // /mnt/memory/b/i kTestStringLength |
| 629 // |
| 630 // /mnt/memory/b/g/h 0 |
| 631 |
| 632 start_create = base::Time::Now(); |
| 633 CreateNonEmptyFile(FilePath("/mnt/memory/b/c"), |
| 634 kTestString, |
| 635 kTestStringLength); |
| 636 request_id1 = GetNextRequestId(); |
| 637 file_util()->CreateDirectory(FilePath("/mnt/memory/b/d"), |
| 638 GetStatusCallback(request_id1)); |
| 639 CreateEmptyFile(FilePath("/mnt/memory/b/e")); |
| 640 CreateNonEmptyFile(FilePath("/mnt/memory/b/f"), |
| 641 kTestString, |
| 642 kTestStringLength); |
| 643 request_id2 = GetNextRequestId(); |
| 644 file_util()->CreateDirectory(FilePath("/mnt/memory/b/g"), |
| 645 GetStatusCallback(request_id1)); |
| 646 CreateNonEmptyFile(FilePath("/mnt/memory/b/i"), |
| 647 kTestString, |
| 648 kTestStringLength); |
| 649 |
| 650 MessageLoop::current()->RunAllPending(); |
| 651 |
| 652 CreateEmptyFile(FilePath("/mnt/memory/b/g/h")); |
| 653 |
| 654 MessageLoop::current()->RunAllPending(); |
| 655 end_create = base::Time::Now(); |
| 656 |
| 657 // Read /mnt/memory and check that the number of entries is unchanged. |
| 658 |
| 659 request_id1 = GetNextRequestId(); |
| 660 file_util()->ReadDirectory(FilePath("/mnt/memory"), |
| 661 GetReadDirectoryCallback(request_id1)); |
| 662 |
| 663 MessageLoop::current()->RunAllPending(); |
| 664 |
| 665 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 666 status = GetStatus(request_id1); |
| 667 ASSERT_TRUE(status.completed); |
| 668 ASSERT_FALSE(status.called_after_completed); |
| 669 ASSERT_EQ(1, status.called); // Because the number of entries < 5. |
| 670 ASSERT_EQ(4u, status.entries.size()); |
| 671 |
| 672 // Read /mnt/memory/b |
| 673 |
| 674 request_id1 = GetNextRequestId(); |
| 675 file_util()->ReadDirectory(FilePath("/mnt/memory/b"), |
| 676 GetReadDirectoryCallback(request_id1)); |
| 677 |
| 678 MessageLoop::current()->RunAllPending(); |
| 679 |
| 680 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 681 status = GetStatus(request_id1); |
| 682 ASSERT_TRUE(status.completed); |
| 683 ASSERT_FALSE(status.called_after_completed); |
| 684 ASSERT_EQ(2, status.called); // Because the number of entries > 5. |
| 685 ASSERT_EQ(6u, status.entries.size()); |
| 686 |
| 687 seen.clear(); |
| 688 |
| 689 for (FileUtilAsync::FileList::const_iterator it = status.entries.begin(); |
| 690 it != status.entries.end(); |
| 691 ++it) { |
| 692 ASSERT_LE(start_create, it->last_modified_time); |
| 693 ASSERT_GE(end_create, it->last_modified_time); |
| 694 |
| 695 ASSERT_EQ(seen.end(), seen.find(it->name)); |
| 696 seen.insert(it->name); |
| 697 |
| 698 // /mnt/memory/b/c kTestStringLength |
| 699 // /mnt/memory/b/d/ |
| 700 // /mnt/memory/b/e 0 |
| 701 // /mnt/memory/b/f kTestStringLength |
| 702 // /mnt/memory/b/g/ |
| 703 // /mnt/memory/b/i kTestStringLength |
| 704 |
| 705 if (it->name == "c") { |
| 706 ASSERT_FALSE(it->is_directory); |
| 707 ASSERT_EQ(static_cast<int64>(kTestStringLength), it->size); |
| 708 } else if (it->name == "d") { |
| 709 ASSERT_TRUE(it->is_directory); |
| 710 } else if (it->name == "e") { |
| 711 ASSERT_FALSE(it->is_directory); |
| 712 ASSERT_EQ(0, it->size); |
| 713 } else if (it->name == "f") { |
| 714 ASSERT_FALSE(it->is_directory); |
| 715 ASSERT_EQ(static_cast<int64>(kTestStringLength), it->size); |
| 716 } else if (it->name == "g") { |
| 717 ASSERT_TRUE(it->is_directory); |
| 718 } else if (it->name == "i") { |
| 719 ASSERT_FALSE(it->is_directory); |
| 720 ASSERT_EQ(static_cast<int64>(kTestStringLength), it->size); |
| 721 } else { |
| 722 LOG(ERROR) << "Unexpected file: " << it->name; |
| 723 ASSERT_TRUE(false); |
| 724 } |
| 725 } |
| 726 |
| 727 // Remove single file: /mnt/memory/b/f |
| 728 |
| 729 request_id1 = GetNextRequestId(); |
| 730 file_util()->Remove(FilePath("/mnt/memory/b/f"), false /* recursive */, |
| 731 GetStatusCallback(request_id1)); |
| 732 MessageLoop::current()->RunAllPending(); |
| 733 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 734 |
| 735 // Check the number of files in b/ |
| 736 |
| 737 request_id1 = GetNextRequestId(); |
| 738 file_util()->ReadDirectory(FilePath("/mnt/memory/b"), |
| 739 GetReadDirectoryCallback(request_id1)); |
| 740 |
| 741 MessageLoop::current()->RunAllPending(); |
| 742 |
| 743 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 744 status = GetStatus(request_id1); |
| 745 ASSERT_TRUE(status.completed); |
| 746 ASSERT_FALSE(status.called_after_completed); |
| 747 ASSERT_EQ(5u, status.entries.size()); |
| 748 |
| 749 // Try remove /mnt/memory/b non-recursively (error) |
| 750 |
| 751 request_id1 = GetNextRequestId(); |
| 752 file_util()->Remove(FilePath("/mnt/memory/b"), false /* recursive */, |
| 753 GetStatusCallback(request_id1)); |
| 754 MessageLoop::current()->RunAllPending(); |
| 755 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, |
| 756 GetStatus(request_id1).result); |
| 757 |
| 758 // Non-recursively remove empty directory. |
| 759 |
| 760 request_id1 = GetNextRequestId(); |
| 761 file_util()->Remove(FilePath("/mnt/memory/b/d"), false /* recursive */, |
| 762 GetStatusCallback(request_id1)); |
| 763 MessageLoop::current()->RunAllPending(); |
| 764 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 765 |
| 766 request_id1 = GetNextRequestId(); |
| 767 file_util()->GetFileInfo(FilePath("/mnt/memory/b/d"), |
| 768 GetGetFileInfoCallback(request_id1)); |
| 769 MessageLoop::current()->RunAllPending(); |
| 770 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, GetStatus(request_id1).result); |
| 771 |
| 772 // Remove /mnt/memory/b recursively. |
| 773 |
| 774 request_id1 = GetNextRequestId(); |
| 775 file_util()->Remove(FilePath("/mnt/memory/b"), true /* recursive */, |
| 776 GetStatusCallback(request_id1)); |
| 777 MessageLoop::current()->RunAllPending(); |
| 778 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 779 |
| 780 // ReadDirectory /mnt/memory/b -> not found |
| 781 |
| 782 request_id1 = GetNextRequestId(); |
| 783 file_util()->ReadDirectory(FilePath("/mnt/memory/b"), |
| 784 GetReadDirectoryCallback(request_id1)); |
| 785 MessageLoop::current()->RunAllPending(); |
| 786 ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, GetStatus(request_id1).result); |
| 787 |
| 788 // ReadDirectory /mnt/memory |
| 789 |
| 790 request_id1 = GetNextRequestId(); |
| 791 file_util()->ReadDirectory(FilePath("/mnt/memory"), |
| 792 GetReadDirectoryCallback(request_id1)); |
| 793 |
| 794 MessageLoop::current()->RunAllPending(); |
| 795 |
| 796 ASSERT_EQ(base::PLATFORM_FILE_OK, GetStatus(request_id1).result); |
| 797 status = GetStatus(request_id1); |
| 798 ASSERT_TRUE(status.completed); |
| 799 ASSERT_FALSE(status.called_after_completed); |
| 800 ASSERT_EQ(3u, status.entries.size()); |
| 801 |
| 802 seen.clear(); |
| 803 |
| 804 for (FileUtilAsync::FileList::const_iterator it = status.entries.begin(); |
| 805 it != status.entries.end(); |
| 806 ++it) { |
| 807 ASSERT_EQ(seen.end(), seen.find(it->name)); |
| 808 seen.insert(it->name); |
| 809 |
| 810 if (it->name == "a") { |
| 811 ASSERT_FALSE(it->is_directory); |
| 812 ASSERT_EQ(0, it->size); |
| 813 } else if (it->name == "c") { |
| 814 ASSERT_TRUE(it->is_directory); |
| 815 } else if (it->name == "longer_file_name.txt") { |
| 816 ASSERT_FALSE(it->is_directory); |
| 817 ASSERT_EQ(static_cast<int64>(kTestStringLength), it->size); |
| 818 } else { |
| 819 LOG(ERROR) << "Unexpected file: " << it->name; |
| 820 ASSERT_TRUE(false); |
| 821 } |
| 822 } |
| 823 } |
| 824 |
| 825 } // namespace fileapi |
| OLD | NEW |