OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 // TODO(vtl): Split this file. |
| 6 |
| 7 #include <map> |
| 8 #include <string> |
5 #include <vector> | 9 #include <vector> |
6 | 10 |
7 #include "base/macros.h" | 11 #include "base/macros.h" |
8 #include "mojo/public/cpp/application/application_impl.h" | 12 #include "mojo/public/cpp/application/application_impl.h" |
9 #include "mojo/public/cpp/application/application_test_base.h" | 13 #include "mojo/public/cpp/application/application_test_base.h" |
10 #include "mojo/public/cpp/bindings/interface_request.h" | 14 #include "mojo/public/cpp/bindings/interface_request.h" |
11 #include "mojo/public/cpp/bindings/type_converter.h" | 15 #include "mojo/public/cpp/bindings/type_converter.h" |
12 #include "services/files/directory.mojom.h" | 16 #include "services/files/directory.mojom.h" |
13 #include "services/files/file.mojom.h" | 17 #include "services/files/file.mojom.h" |
14 #include "services/files/files.mojom.h" | 18 #include "services/files/files.mojom.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 class FilesAppTest : public test::ApplicationTestBase { | 91 class FilesAppTest : public test::ApplicationTestBase { |
88 public: | 92 public: |
89 FilesAppTest() {} | 93 FilesAppTest() {} |
90 ~FilesAppTest() override {} | 94 ~FilesAppTest() override {} |
91 | 95 |
92 void SetUp() override { | 96 void SetUp() override { |
93 test::ApplicationTestBase::SetUp(); | 97 test::ApplicationTestBase::SetUp(); |
94 application_impl()->ConnectToService("mojo:files", &files_); | 98 application_impl()->ConnectToService("mojo:files", &files_); |
95 } | 99 } |
96 | 100 |
| 101 protected: |
| 102 void GetTemporaryRoot(DirectoryPtr* directory) { |
| 103 Error error = ERROR_INTERNAL; |
| 104 files()->OpenFileSystem(FILE_SYSTEM_TEMPORARY, GetProxy(directory), |
| 105 Capture(&error)); |
| 106 ASSERT_TRUE(files().WaitForIncomingMethodCall()); |
| 107 ASSERT_EQ(ERROR_OK, error); |
| 108 } |
| 109 |
97 FilesPtr& files() { return files_; } | 110 FilesPtr& files() { return files_; } |
98 | 111 |
99 private: | 112 private: |
100 FilesPtr files_; | 113 FilesPtr files_; |
101 | 114 |
102 DISALLOW_COPY_AND_ASSIGN(FilesAppTest); | 115 DISALLOW_COPY_AND_ASSIGN(FilesAppTest); |
103 }; | 116 }; |
104 | 117 |
105 TEST_F(FilesAppTest, CreateWriteCloseRenameOpenRead) { | 118 // FileImpl -------------------------------------------------------------------- |
106 // Get a temporary root directory. | 119 |
| 120 typedef FilesAppTest FileImplTest; |
| 121 |
| 122 TEST_F(FileImplTest, CreateWriteCloseRenameOpenRead) { |
107 DirectoryPtr directory; | 123 DirectoryPtr directory; |
108 Error error = ERROR_INTERNAL; | 124 GetTemporaryRoot(&directory); |
109 files()->OpenFileSystem(FILE_SYSTEM_TEMPORARY, GetProxy(&directory), | 125 Error error; |
110 Capture(&error)); | |
111 ASSERT_TRUE(files().WaitForIncomingMethodCall()); | |
112 EXPECT_EQ(ERROR_OK, error); | |
113 | 126 |
114 { | 127 { |
115 // Create my_file. | 128 // Create my_file. |
116 FilePtr file; | 129 FilePtr file; |
117 error = ERROR_INTERNAL; | 130 error = ERROR_INTERNAL; |
118 directory->OpenFile("my_file", GetProxy(&file), | 131 directory->OpenFile("my_file", GetProxy(&file), |
119 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); | 132 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); |
120 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); | 133 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
121 EXPECT_EQ(ERROR_OK, error); | 134 EXPECT_EQ(ERROR_OK, error); |
122 | 135 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[1]); | 181 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[1]); |
169 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[2]); | 182 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[2]); |
170 } | 183 } |
171 | 184 |
172 // TODO(vtl): Test various open options. | 185 // TODO(vtl): Test various open options. |
173 // TODO(vtl): Test read/write offset options. | 186 // TODO(vtl): Test read/write offset options. |
174 } | 187 } |
175 | 188 |
176 // Note: Ignore nanoseconds, since it may not always be supported. We expect at | 189 // Note: Ignore nanoseconds, since it may not always be supported. We expect at |
177 // least second-resolution support though. | 190 // least second-resolution support though. |
178 TEST_F(FilesAppTest, StatTouch) { | 191 TEST_F(FileImplTest, StatTouch) { |
179 // Get a temporary root directory. | |
180 DirectoryPtr directory; | 192 DirectoryPtr directory; |
181 Error error = ERROR_INTERNAL; | 193 GetTemporaryRoot(&directory); |
182 files()->OpenFileSystem(FILE_SYSTEM_TEMPORARY, GetProxy(&directory), | 194 Error error; |
183 Capture(&error)); | |
184 ASSERT_TRUE(files().WaitForIncomingMethodCall()); | |
185 EXPECT_EQ(ERROR_OK, error); | |
186 | 195 |
187 // Create my_file. | 196 // Create my_file. |
188 FilePtr file; | 197 FilePtr file; |
189 error = ERROR_INTERNAL; | 198 error = ERROR_INTERNAL; |
190 directory->OpenFile("my_file", GetProxy(&file), | 199 directory->OpenFile("my_file", GetProxy(&file), |
191 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); | 200 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); |
192 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); | 201 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
193 EXPECT_EQ(ERROR_OK, error); | 202 EXPECT_EQ(ERROR_OK, error); |
194 | 203 |
195 // Stat it. | 204 // Stat it. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 // TODO(vtl): Also test Touch() "now" options. | 264 // TODO(vtl): Also test Touch() "now" options. |
256 // TODO(vtl): Also test touching both atime and mtime. | 265 // TODO(vtl): Also test touching both atime and mtime. |
257 | 266 |
258 // Close it. | 267 // Close it. |
259 error = ERROR_INTERNAL; | 268 error = ERROR_INTERNAL; |
260 file->Close(Capture(&error)); | 269 file->Close(Capture(&error)); |
261 ASSERT_TRUE(file.WaitForIncomingMethodCall()); | 270 ASSERT_TRUE(file.WaitForIncomingMethodCall()); |
262 EXPECT_EQ(ERROR_OK, error); | 271 EXPECT_EQ(ERROR_OK, error); |
263 } | 272 } |
264 | 273 |
265 TEST_F(FilesAppTest, TellSeek) { | 274 TEST_F(FileImplTest, TellSeek) { |
266 // Get a temporary root directory. | |
267 DirectoryPtr directory; | 275 DirectoryPtr directory; |
268 Error error = ERROR_INTERNAL; | 276 GetTemporaryRoot(&directory); |
269 files()->OpenFileSystem(FILE_SYSTEM_TEMPORARY, GetProxy(&directory), | 277 Error error; |
270 Capture(&error)); | |
271 ASSERT_TRUE(files().WaitForIncomingMethodCall()); | |
272 EXPECT_EQ(ERROR_OK, error); | |
273 | 278 |
274 // Create my_file. | 279 // Create my_file. |
275 FilePtr file; | 280 FilePtr file; |
276 error = ERROR_INTERNAL; | 281 error = ERROR_INTERNAL; |
277 directory->OpenFile("my_file", GetProxy(&file), | 282 directory->OpenFile("my_file", GetProxy(&file), |
278 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); | 283 kOpenFlagWrite | kOpenFlagCreate, Capture(&error)); |
279 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); | 284 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
280 EXPECT_EQ(ERROR_OK, error); | 285 EXPECT_EQ(ERROR_OK, error); |
281 | 286 |
282 // Write to it. | 287 // Write to it. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // TODO(vtl): Check that seeking actually affects reading/writing. | 355 // TODO(vtl): Check that seeking actually affects reading/writing. |
351 // TODO(vtl): Check that seeking can extend the file? | 356 // TODO(vtl): Check that seeking can extend the file? |
352 | 357 |
353 // Close it. | 358 // Close it. |
354 error = ERROR_INTERNAL; | 359 error = ERROR_INTERNAL; |
355 file->Close(Capture(&error)); | 360 file->Close(Capture(&error)); |
356 ASSERT_TRUE(file.WaitForIncomingMethodCall()); | 361 ASSERT_TRUE(file.WaitForIncomingMethodCall()); |
357 EXPECT_EQ(ERROR_OK, error); | 362 EXPECT_EQ(ERROR_OK, error); |
358 } | 363 } |
359 | 364 |
360 TEST_F(FilesAppTest, Dup) { | 365 TEST_F(FileImplTest, Dup) { |
361 // Get a temporary root directory. | |
362 DirectoryPtr directory; | 366 DirectoryPtr directory; |
363 Error error = ERROR_INTERNAL; | 367 GetTemporaryRoot(&directory); |
364 files()->OpenFileSystem(FILE_SYSTEM_TEMPORARY, GetProxy(&directory), | 368 Error error; |
365 Capture(&error)); | |
366 ASSERT_TRUE(files().WaitForIncomingMethodCall()); | |
367 EXPECT_EQ(ERROR_OK, error); | |
368 | 369 |
369 // Create my_file. | 370 // Create my_file. |
370 FilePtr file1; | 371 FilePtr file1; |
371 error = ERROR_INTERNAL; | 372 error = ERROR_INTERNAL; |
372 directory->OpenFile("my_file", GetProxy(&file1), | 373 directory->OpenFile("my_file", GetProxy(&file1), |
373 kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate, | 374 kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate, |
374 Capture(&error)); | 375 Capture(&error)); |
375 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); | 376 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
376 EXPECT_EQ(ERROR_OK, error); | 377 EXPECT_EQ(ERROR_OK, error); |
377 | 378 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 450 |
450 // Close |file2|. | 451 // Close |file2|. |
451 error = ERROR_INTERNAL; | 452 error = ERROR_INTERNAL; |
452 file2->Close(Capture(&error)); | 453 file2->Close(Capture(&error)); |
453 ASSERT_TRUE(file2.WaitForIncomingMethodCall()); | 454 ASSERT_TRUE(file2.WaitForIncomingMethodCall()); |
454 EXPECT_EQ(ERROR_OK, error); | 455 EXPECT_EQ(ERROR_OK, error); |
455 | 456 |
456 // TODO(vtl): Test that |file2| has the same open options as |file1|. | 457 // TODO(vtl): Test that |file2| has the same open options as |file1|. |
457 } | 458 } |
458 | 459 |
| 460 // DirectoryImpl --------------------------------------------------------------- |
| 461 |
| 462 typedef FilesAppTest DirectoryImplTest; |
| 463 |
| 464 TEST_F(FileImplTest, Read) { |
| 465 DirectoryPtr directory; |
| 466 GetTemporaryRoot(&directory); |
| 467 Error error; |
| 468 |
| 469 // Make some files. |
| 470 const struct { |
| 471 const char* name; |
| 472 uint32_t open_flags; |
| 473 } files_to_create[] = { |
| 474 {"my_file1", kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate}, |
| 475 {"my_file2", kOpenFlagWrite | kOpenFlagCreate | kOpenFlagExclusive}, |
| 476 {"my_file3", kOpenFlagWrite | kOpenFlagCreate | kOpenFlagAppend}, |
| 477 {"my_file4", kOpenFlagWrite | kOpenFlagCreate | kOpenFlagTruncate}}; |
| 478 for (size_t i = 0; i < arraysize(files_to_create); i++) { |
| 479 error = ERROR_INTERNAL; |
| 480 directory->OpenFile(files_to_create[i].name, nullptr, |
| 481 files_to_create[i].open_flags, Capture(&error)); |
| 482 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 483 EXPECT_EQ(ERROR_OK, error); |
| 484 } |
| 485 // Make a directory. |
| 486 error = ERROR_INTERNAL; |
| 487 directory->OpenDirectory("my_dir", nullptr, |
| 488 kOpenFlagRead | kOpenFlagWrite | kOpenFlagCreate, |
| 489 Capture(&error)); |
| 490 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 491 EXPECT_EQ(ERROR_OK, error); |
| 492 |
| 493 error = ERROR_INTERNAL; |
| 494 Array<DirectoryEntryPtr> directory_contents; |
| 495 directory->Read(Capture(&error, &directory_contents)); |
| 496 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 497 EXPECT_EQ(ERROR_OK, error); |
| 498 |
| 499 // Expected contents of the directory. |
| 500 std::map<std::string, FileType> expected_contents; |
| 501 expected_contents["my_file1"] = FILE_TYPE_REGULAR_FILE; |
| 502 expected_contents["my_file2"] = FILE_TYPE_REGULAR_FILE; |
| 503 expected_contents["my_file3"] = FILE_TYPE_REGULAR_FILE; |
| 504 expected_contents["my_file4"] = FILE_TYPE_REGULAR_FILE; |
| 505 expected_contents["my_dir"] = FILE_TYPE_DIRECTORY; |
| 506 expected_contents["."] = FILE_TYPE_DIRECTORY; |
| 507 expected_contents[".."] = FILE_TYPE_DIRECTORY; |
| 508 |
| 509 EXPECT_EQ(expected_contents.size(), directory_contents.size()); |
| 510 for (size_t i = 0; i < directory_contents.size(); i++) { |
| 511 ASSERT_TRUE(directory_contents[i]); |
| 512 ASSERT_TRUE(directory_contents[i]->name); |
| 513 auto it = expected_contents.find(directory_contents[i]->name.get()); |
| 514 ASSERT_TRUE(it != expected_contents.end()); |
| 515 EXPECT_EQ(it->second, directory_contents[i]->type); |
| 516 expected_contents.erase(it); |
| 517 } |
| 518 } |
| 519 |
| 520 // Note: Ignore nanoseconds, since it may not always be supported. We expect at |
| 521 // least second-resolution support though. |
| 522 // TODO(vtl): Maybe share this with |FileImplTest.StatTouch| ... but then it'd |
| 523 // be harder to split this file. |
| 524 TEST_F(DirectoryImplTest, StatTouch) { |
| 525 DirectoryPtr directory; |
| 526 GetTemporaryRoot(&directory); |
| 527 Error error; |
| 528 |
| 529 // Stat it. |
| 530 error = ERROR_INTERNAL; |
| 531 FileInformationPtr file_info; |
| 532 directory->Stat(Capture(&error, &file_info)); |
| 533 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 534 EXPECT_EQ(ERROR_OK, error); |
| 535 ASSERT_FALSE(file_info.is_null()); |
| 536 EXPECT_EQ(0, file_info->size); |
| 537 ASSERT_FALSE(file_info->atime.is_null()); |
| 538 EXPECT_GT(file_info->atime->seconds, 0); // Expect that it's not 1970-01-01. |
| 539 ASSERT_FALSE(file_info->mtime.is_null()); |
| 540 EXPECT_GT(file_info->mtime->seconds, 0); |
| 541 int64_t first_mtime = file_info->mtime->seconds; |
| 542 |
| 543 // Touch only the atime. |
| 544 error = ERROR_INTERNAL; |
| 545 TimespecOrNowPtr t(TimespecOrNow::New()); |
| 546 t->now = false; |
| 547 t->timespec = Timespec::New(); |
| 548 const int64_t kPartyTime1 = 1234567890; // Party like it's 2009-02-13. |
| 549 t->timespec->seconds = kPartyTime1; |
| 550 directory->Touch(t.Pass(), nullptr, Capture(&error)); |
| 551 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 552 EXPECT_EQ(ERROR_OK, error); |
| 553 |
| 554 // Stat again. |
| 555 error = ERROR_INTERNAL; |
| 556 file_info.reset(); |
| 557 directory->Stat(Capture(&error, &file_info)); |
| 558 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 559 EXPECT_EQ(ERROR_OK, error); |
| 560 ASSERT_FALSE(file_info.is_null()); |
| 561 ASSERT_FALSE(file_info->atime.is_null()); |
| 562 EXPECT_EQ(kPartyTime1, file_info->atime->seconds); |
| 563 ASSERT_FALSE(file_info->mtime.is_null()); |
| 564 EXPECT_EQ(first_mtime, file_info->mtime->seconds); |
| 565 |
| 566 // Touch only the mtime. |
| 567 t = TimespecOrNow::New(); |
| 568 t->now = false; |
| 569 t->timespec = Timespec::New(); |
| 570 const int64_t kPartyTime2 = 1425059525; // No time like the present. |
| 571 t->timespec->seconds = kPartyTime2; |
| 572 directory->Touch(nullptr, t.Pass(), Capture(&error)); |
| 573 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 574 EXPECT_EQ(ERROR_OK, error); |
| 575 |
| 576 // Stat again. |
| 577 error = ERROR_INTERNAL; |
| 578 file_info.reset(); |
| 579 directory->Stat(Capture(&error, &file_info)); |
| 580 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 581 EXPECT_EQ(ERROR_OK, error); |
| 582 ASSERT_FALSE(file_info.is_null()); |
| 583 ASSERT_FALSE(file_info->atime.is_null()); |
| 584 EXPECT_EQ(kPartyTime1, file_info->atime->seconds); |
| 585 ASSERT_FALSE(file_info->mtime.is_null()); |
| 586 EXPECT_EQ(kPartyTime2, file_info->mtime->seconds); |
| 587 |
| 588 // TODO(vtl): Also test Touch() "now" options. |
| 589 // TODO(vtl): Also test touching both atime and mtime. |
| 590 } |
| 591 |
| 592 // TODO(vtl): Properly test OpenFile() and OpenDirectory() (including flags). |
| 593 |
| 594 TEST_F(DirectoryImplTest, BasicRenameDelete) { |
| 595 DirectoryPtr directory; |
| 596 GetTemporaryRoot(&directory); |
| 597 Error error; |
| 598 |
| 599 // Create my_file. |
| 600 error = ERROR_INTERNAL; |
| 601 directory->OpenFile("my_file", nullptr, kOpenFlagWrite | kOpenFlagCreate, |
| 602 Capture(&error)); |
| 603 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 604 EXPECT_EQ(ERROR_OK, error); |
| 605 |
| 606 // Opening my_file should succeed. |
| 607 error = ERROR_INTERNAL; |
| 608 directory->OpenFile("my_file", nullptr, kOpenFlagRead, Capture(&error)); |
| 609 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 610 EXPECT_EQ(ERROR_OK, error); |
| 611 |
| 612 // Rename my_file to my_new_file. |
| 613 directory->Rename("my_file", "my_new_file", Capture(&error)); |
| 614 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 615 EXPECT_EQ(ERROR_OK, error); |
| 616 |
| 617 // Opening my_file should fail. |
| 618 error = ERROR_INTERNAL; |
| 619 directory->OpenFile("my_file", nullptr, kOpenFlagRead, Capture(&error)); |
| 620 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 621 EXPECT_EQ(ERROR_UNKNOWN, error); |
| 622 |
| 623 // Opening my_new_file should succeed. |
| 624 error = ERROR_INTERNAL; |
| 625 directory->OpenFile("my_new_file", nullptr, kOpenFlagRead, Capture(&error)); |
| 626 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 627 EXPECT_EQ(ERROR_OK, error); |
| 628 |
| 629 // Delete my_new_file (no flags). |
| 630 directory->Delete("my_new_file", 0, Capture(&error)); |
| 631 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 632 EXPECT_EQ(ERROR_OK, error); |
| 633 |
| 634 // Opening my_new_file should fail. |
| 635 error = ERROR_INTERNAL; |
| 636 directory->OpenFile("my_new_file", nullptr, kOpenFlagRead, Capture(&error)); |
| 637 ASSERT_TRUE(directory.WaitForIncomingMethodCall()); |
| 638 EXPECT_EQ(ERROR_UNKNOWN, error); |
| 639 } |
| 640 |
| 641 // TODO(vtl): Test that an open file can be moved (by someone else) without |
| 642 // operations on it being affected. |
| 643 // TODO(vtl): Test delete flags. |
| 644 |
459 } // namespace | 645 } // namespace |
460 } // namespace files | 646 } // namespace files |
461 } // namespace mojo | 647 } // namespace mojo |
OLD | NEW |