saved_files_service_unittest.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #include <algorithm>
  5. #include "apps/saved_files_service.h"
  6. #include "base/files/file_path.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/test/values_test_util.h"
  10. #include "base/values.h"
  11. #include "chrome/browser/extensions/test_extension_environment.h"
  12. #include "chrome/test/base/testing_profile.h"
  13. #include "extensions/browser/api/file_system/saved_file_entry.h"
  14. #include "extensions/browser/extension_prefs.h"
  15. #include "extensions/browser/extension_system.h"
  16. #include "extensions/common/extension.h"
  17. #include "testing/gtest/include/gtest/gtest.h"
  18. #define TRACE_CALL(expression) \
  19. do { \
  20. SCOPED_TRACE(#expression); \
  21. expression; \
  22. } while (0)
  23. using apps::SavedFilesService;
  24. using extensions::SavedFileEntry;
  25. namespace {
  26. std::string GenerateId(int i) {
  27. return base::NumberToString(i) + ":filename.ext";
  28. }
  29. } // namespace
  30. class SavedFilesServiceUnitTest : public testing::Test {
  31. protected:
  32. void SetUp() override {
  33. testing::Test::SetUp();
  34. extension_ = env_.MakeExtension(*base::test::ParseJsonDeprecated(
  35. "{"
  36. " \"app\": {"
  37. " \"background\": {"
  38. " \"scripts\": [\"background.js\"]"
  39. " }"
  40. " },"
  41. " \"permissions\": ["
  42. " {\"fileSystem\": [\"retainEntries\"]}"
  43. " ]"
  44. "}"));
  45. service_ = SavedFilesService::Get(env_.profile());
  46. path_ = base::FilePath(FILE_PATH_LITERAL("filename.ext"));
  47. }
  48. void TearDown() override {
  49. SavedFilesService::ClearMaxSequenceNumberForTest();
  50. SavedFilesService::ClearLruSizeForTest();
  51. testing::Test::TearDown();
  52. }
  53. // Check that a registered file entry has the correct value.
  54. void CheckEntrySequenceNumber(int id, int sequence_number) {
  55. std::string id_string = GenerateId(id);
  56. SCOPED_TRACE(id_string);
  57. EXPECT_TRUE(service_->IsRegistered(extension_->id(), id_string));
  58. const SavedFileEntry* entry =
  59. service_->GetFileEntry(extension_->id(), id_string);
  60. ASSERT_TRUE(entry);
  61. EXPECT_EQ(id_string, entry->id);
  62. EXPECT_EQ(path_, entry->path);
  63. EXPECT_TRUE(entry->is_directory);
  64. EXPECT_EQ(sequence_number, entry->sequence_number);
  65. }
  66. // Check that a range of registered file entries have the correct values.
  67. void CheckRangeEnqueuedInOrder(int start, int end) {
  68. SavedFileEntry entry;
  69. for (int i = start; i < end; i++) {
  70. CheckEntrySequenceNumber(i, i + 1);
  71. }
  72. }
  73. extensions::TestExtensionEnvironment env_;
  74. raw_ptr<const extensions::Extension> extension_;
  75. raw_ptr<SavedFilesService> service_;
  76. base::FilePath path_;
  77. };
  78. TEST_F(SavedFilesServiceUnitTest, RetainTwoFilesTest) {
  79. service_->RegisterFileEntry(extension_->id(), GenerateId(1), path_, true);
  80. service_->RegisterFileEntry(extension_->id(), GenerateId(2), path_, true);
  81. service_->RegisterFileEntry(extension_->id(), GenerateId(3), path_, true);
  82. // Test that no entry has a sequence number.
  83. TRACE_CALL(CheckEntrySequenceNumber(1, 0));
  84. TRACE_CALL(CheckEntrySequenceNumber(2, 0));
  85. TRACE_CALL(CheckEntrySequenceNumber(3, 0));
  86. // Test that only entry #1 has a sequence number.
  87. service_->EnqueueFileEntry(extension_->id(), GenerateId(1));
  88. TRACE_CALL(CheckEntrySequenceNumber(1, 1));
  89. TRACE_CALL(CheckEntrySequenceNumber(2, 0));
  90. // Test that entry #1 has not changed sequence number because it is the most
  91. // recently enqueued entry.
  92. service_->EnqueueFileEntry(extension_->id(), GenerateId(1));
  93. TRACE_CALL(CheckEntrySequenceNumber(1, 1));
  94. TRACE_CALL(CheckEntrySequenceNumber(2, 0));
  95. // Test that entry #1 is unchanged and entry #2 has been assigned the next
  96. // sequence number.
  97. service_->EnqueueFileEntry(extension_->id(), GenerateId(2));
  98. TRACE_CALL(CheckEntrySequenceNumber(1, 1));
  99. TRACE_CALL(CheckEntrySequenceNumber(2, 2));
  100. // Test that both entries #1 and #2 are unchanged because #2 is the most
  101. // recently enqueued entry.
  102. service_->EnqueueFileEntry(extension_->id(), GenerateId(2));
  103. TRACE_CALL(CheckEntrySequenceNumber(1, 1));
  104. TRACE_CALL(CheckEntrySequenceNumber(2, 2));
  105. // Test that entry #1 has been assigned the next sequence number.
  106. service_->EnqueueFileEntry(extension_->id(), GenerateId(1));
  107. TRACE_CALL(CheckEntrySequenceNumber(1, 3));
  108. TRACE_CALL(CheckEntrySequenceNumber(2, 2));
  109. TRACE_CALL(CheckEntrySequenceNumber(3, 0));
  110. EXPECT_FALSE(service_->IsRegistered(extension_->id(), "another id"));
  111. SavedFileEntry entry;
  112. EXPECT_FALSE(service_->GetFileEntry(extension_->id(), "another id"));
  113. // ClearQueueIfNoRetainPermission should be a no-op because the app has the
  114. // fileSystem.retainEntries permission.
  115. service_->ClearQueueIfNoRetainPermission(extension_);
  116. TRACE_CALL(CheckEntrySequenceNumber(1, 3));
  117. TRACE_CALL(CheckEntrySequenceNumber(2, 2));
  118. TRACE_CALL(CheckEntrySequenceNumber(3, 0));
  119. // Test that after a clear, retained file entries are unchanged, but file
  120. // entries that have been registered but not retained are no longer
  121. // registered.
  122. service_->Clear(extension_->id());
  123. TRACE_CALL(CheckEntrySequenceNumber(1, 3));
  124. TRACE_CALL(CheckEntrySequenceNumber(2, 2));
  125. EXPECT_FALSE(service_->IsRegistered(extension_->id(), GenerateId(3)));
  126. }
  127. TEST_F(SavedFilesServiceUnitTest, NoRetainEntriesPermissionTest) {
  128. extension_ = env_.MakeExtension(*base::test::ParseJsonDeprecated(
  129. "{\"app\": {\"background\": {\"scripts\": [\"background.js\"]}},"
  130. "\"permissions\": [\"fileSystem\"]}"));
  131. service_->RegisterFileEntry(extension_->id(), GenerateId(1), path_, true);
  132. TRACE_CALL(CheckEntrySequenceNumber(1, 0));
  133. SavedFileEntry entry;
  134. service_->EnqueueFileEntry(extension_->id(), GenerateId(1));
  135. TRACE_CALL(CheckEntrySequenceNumber(1, 1));
  136. EXPECT_FALSE(service_->IsRegistered(extension_->id(), "another id"));
  137. EXPECT_FALSE(service_->GetFileEntry(extension_->id(), "another id"));
  138. // ClearQueueIfNoRetainPermission should clear the queue, since the app does
  139. // not have the "retainEntries" permission.
  140. service_->ClearQueueIfNoRetainPermission(extension_);
  141. std::vector<SavedFileEntry> entries =
  142. service_->GetAllFileEntries(extension_->id());
  143. EXPECT_TRUE(entries.empty());
  144. }
  145. TEST_F(SavedFilesServiceUnitTest, EvictionTest) {
  146. SavedFilesService::SetLruSizeForTest(10);
  147. for (int i = 0; i < 10; i++) {
  148. service_->RegisterFileEntry(extension_->id(), GenerateId(i), path_, true);
  149. service_->EnqueueFileEntry(extension_->id(), GenerateId(i));
  150. }
  151. service_->RegisterFileEntry(extension_->id(), GenerateId(10), path_, true);
  152. // Expect that entries 0 to 9 are in the queue, but 10 is not.
  153. TRACE_CALL(CheckRangeEnqueuedInOrder(0, 10));
  154. TRACE_CALL(CheckEntrySequenceNumber(10, 0));
  155. service_->EnqueueFileEntry(extension_->id(), GenerateId(10));
  156. // Expect that entries 1 to 10 are in the queue, but entry 0 is not.
  157. TRACE_CALL(CheckEntrySequenceNumber(0, 0));
  158. TRACE_CALL(CheckRangeEnqueuedInOrder(1, 11));
  159. // Check that retained entries are unchanged after a clear.
  160. service_->Clear(extension_->id());
  161. SavedFileEntry entry;
  162. EXPECT_FALSE(service_->GetFileEntry(extension_->id(), GenerateId(0)));
  163. TRACE_CALL(CheckRangeEnqueuedInOrder(1, 11));
  164. // Expect that entry 2 is now at the back of the queue, and no further entries
  165. // have been evicted.
  166. service_->EnqueueFileEntry(extension_->id(), GenerateId(2));
  167. TRACE_CALL(CheckEntrySequenceNumber(2, 12));
  168. TRACE_CALL(CheckRangeEnqueuedInOrder(1, 1));
  169. TRACE_CALL(CheckRangeEnqueuedInOrder(3, 11));
  170. // Check that retained entries are unchanged after a clear.
  171. service_->Clear(extension_->id());
  172. TRACE_CALL(CheckEntrySequenceNumber(2, 12));
  173. TRACE_CALL(CheckRangeEnqueuedInOrder(1, 1));
  174. TRACE_CALL(CheckRangeEnqueuedInOrder(3, 11));
  175. }
  176. TEST_F(SavedFilesServiceUnitTest, SequenceNumberCompactionTest) {
  177. SavedFilesService::SetMaxSequenceNumberForTest(8);
  178. SavedFilesService::SetLruSizeForTest(8);
  179. for (int i = 0; i < 4; i++) {
  180. service_->RegisterFileEntry(extension_->id(), GenerateId(i), path_, true);
  181. service_->EnqueueFileEntry(extension_->id(), GenerateId(i));
  182. }
  183. service_->EnqueueFileEntry(extension_->id(), GenerateId(2));
  184. service_->EnqueueFileEntry(extension_->id(), GenerateId(3));
  185. service_->EnqueueFileEntry(extension_->id(), GenerateId(2));
  186. // The sequence numbers should be sparse, as they have not gone over the
  187. // limit.
  188. TRACE_CALL(CheckEntrySequenceNumber(0, 1));
  189. TRACE_CALL(CheckEntrySequenceNumber(1, 2));
  190. TRACE_CALL(CheckEntrySequenceNumber(2, 7));
  191. TRACE_CALL(CheckEntrySequenceNumber(3, 6));
  192. service_->Clear(extension_->id());
  193. TRACE_CALL(CheckEntrySequenceNumber(0, 1));
  194. TRACE_CALL(CheckEntrySequenceNumber(1, 2));
  195. TRACE_CALL(CheckEntrySequenceNumber(2, 7));
  196. TRACE_CALL(CheckEntrySequenceNumber(3, 6));
  197. // This should push the sequence number to the limit of 8, and trigger a
  198. // sequence number compaction. Expect that the sequence numbers are
  199. // contiguous from 1 to 4.
  200. service_->EnqueueFileEntry(extension_->id(), GenerateId(3));
  201. TRACE_CALL(CheckRangeEnqueuedInOrder(0, 4));
  202. service_->Clear(extension_->id());
  203. TRACE_CALL(CheckRangeEnqueuedInOrder(0, 4));
  204. }