• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Chromium Authors
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 "net/extras/sqlite/sqlite_persistent_shared_dictionary_store.h"
6 
7 #include <tuple>
8 
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_refptr.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/task/sequenced_task_runner.h"
15 #include "base/task/thread_pool.h"
16 #include "base/test/bind.h"
17 #include "base/test/test_file_util.h"
18 #include "build/build_config.h"
19 #include "net/base/schemeful_site.h"
20 #include "net/extras/shared_dictionary/shared_dictionary_info.h"
21 #include "net/extras/shared_dictionary/shared_dictionary_isolation_key.h"
22 #include "net/test/test_with_task_environment.h"
23 #include "sql/database.h"
24 #include "sql/meta_table.h"
25 #include "sql/test/test_helpers.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/abseil-cpp/absl/types/optional.h"
29 
30 using ::testing::ElementsAre;
31 using ::testing::ElementsAreArray;
32 using ::testing::Pair;
33 using ::testing::UnorderedElementsAreArray;
34 
35 namespace net {
36 
37 namespace {
38 
39 const int kCurrentVersionNumber = 1;
40 
41 const base::FilePath::CharType kSharedDictionaryStoreFilename[] =
42     FILE_PATH_LITERAL("SharedDictionary");
43 
44 SQLitePersistentSharedDictionaryStore::RegisterDictionaryResult
RegisterDictionaryImpl(SQLitePersistentSharedDictionaryStore * store,const SharedDictionaryIsolationKey & isolation_key,SharedDictionaryInfo dictionary_info,uint64_t max_size_per_site=1000000,uint64_t max_count_per_site=1000)45 RegisterDictionaryImpl(SQLitePersistentSharedDictionaryStore* store,
46                        const SharedDictionaryIsolationKey& isolation_key,
47                        SharedDictionaryInfo dictionary_info,
48                        uint64_t max_size_per_site = 1000000,
49                        uint64_t max_count_per_site = 1000) {
50   absl::optional<
51       SQLitePersistentSharedDictionaryStore::RegisterDictionaryResult>
52       result_out;
53   base::RunLoop run_loop;
54   store->RegisterDictionary(
55       isolation_key, std::move(dictionary_info), max_size_per_site,
56       max_count_per_site,
57       base::BindLambdaForTesting(
58           [&](SQLitePersistentSharedDictionaryStore::
59                   RegisterDictionaryResultOrError result) {
60             ASSERT_TRUE(result.has_value());
61             result_out = result.value();
62             run_loop.Quit();
63           }));
64   run_loop.Run();
65   CHECK(result_out);
66   return *result_out;
67 }
68 
69 // Register following 4 dictionaries for ProcessEviction tests.
70 //   dict1: size=1000 last_used_time=now
71 //   dict2: size=3000 last_used_time=now+4
72 //   dict3: size=5000 last_used_time=now+2
73 //   dict4: size=7000 last_used_time=now+3
74 std::tuple<SharedDictionaryInfo,
75            SharedDictionaryInfo,
76            SharedDictionaryInfo,
77            SharedDictionaryInfo>
RegisterSharedDictionariesForProcessEvictionTest(SQLitePersistentSharedDictionaryStore * store,const SharedDictionaryIsolationKey & isolation_key)78 RegisterSharedDictionariesForProcessEvictionTest(
79     SQLitePersistentSharedDictionaryStore* store,
80     const SharedDictionaryIsolationKey& isolation_key) {
81   const base::Time now = base::Time::Now();
82   auto token1 = base::UnguessableToken::Create();
83   SharedDictionaryInfo dict1 =
84       SharedDictionaryInfo(GURL("https://a.example/dict"),
85                            /*response_time=*/now,
86                            /*expiration*/ base::Seconds(100), "/pattern*",
87                            /*last_used_time*/ now,
88                            /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
89                            /*disk_cache_key_token=*/token1,
90                            /*primary_key_in_database=*/absl::nullopt);
91   auto result1 = RegisterDictionaryImpl(store, isolation_key, dict1);
92   dict1.set_primary_key_in_database(result1.primary_key_in_database());
93 
94   auto token2 = base::UnguessableToken::Create();
95   SharedDictionaryInfo dict2 =
96       SharedDictionaryInfo(GURL("https://b.example/dict"),
97                            /*response_time=*/now,
98                            /*expiration*/ base::Seconds(100), "/pattern*",
99                            /*last_used_time*/ now + base::Seconds(1),
100                            /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
101                            /*disk_cache_key_token=*/token2,
102                            /*primary_key_in_database=*/absl::nullopt);
103   auto result2 = RegisterDictionaryImpl(store, isolation_key, dict2);
104   dict2.set_primary_key_in_database(result2.primary_key_in_database());
105 
106   auto token3 = base::UnguessableToken::Create();
107   SharedDictionaryInfo dict3 =
108       SharedDictionaryInfo(GURL("https://c.example/dict"),
109                            /*response_time=*/now,
110                            /*expiration*/ base::Seconds(100), "/pattern*",
111                            /*last_used_time*/ now + base::Seconds(2),
112                            /*size=*/5000, SHA256HashValue({{0x00, 0x03}}),
113                            /*disk_cache_key_token=*/token3,
114                            /*primary_key_in_database=*/absl::nullopt);
115   auto result3 = RegisterDictionaryImpl(store, isolation_key, dict3);
116   dict3.set_primary_key_in_database(result3.primary_key_in_database());
117 
118   auto token4 = base::UnguessableToken::Create();
119   SharedDictionaryInfo dict4 =
120       SharedDictionaryInfo(GURL("https://d.example/dict"),
121                            /*response_time=*/now,
122                            /*expiration*/ base::Seconds(100), "/pattern*",
123                            /*last_used_time*/ now + base::Seconds(3),
124                            /*size=*/7000, SHA256HashValue({{0x00, 0x04}}),
125                            /*disk_cache_key_token=*/token4,
126                            /*primary_key_in_database=*/absl::nullopt);
127   auto result4 = RegisterDictionaryImpl(store, isolation_key, dict4);
128   dict4.set_primary_key_in_database(result4.primary_key_in_database());
129 
130   // Call UpdateDictionaryLastUsedTime to update the last used time of dict2.
131   store->UpdateDictionaryLastUsedTime(*dict2.primary_key_in_database(),
132                                       now + base::Seconds(4));
133 
134   SharedDictionaryInfo updated_dict2 = SharedDictionaryInfo(
135       dict2.url(), dict2.response_time(), dict2.expiration(), dict2.match(),
136       now + base::Seconds(4), dict2.size(), dict2.hash(),
137       dict2.disk_cache_key_token(), dict2.primary_key_in_database());
138 
139   return {dict1, updated_dict2, dict3, dict4};
140 }
141 
142 }  // namespace
143 
CreateIsolationKey(const std::string & frame_origin_str,const absl::optional<std::string> & top_frame_site_str=absl::nullopt)144 SharedDictionaryIsolationKey CreateIsolationKey(
145     const std::string& frame_origin_str,
146     const absl::optional<std::string>& top_frame_site_str = absl::nullopt) {
147   return SharedDictionaryIsolationKey(
148       url::Origin::Create(GURL(frame_origin_str)),
149       top_frame_site_str ? SchemefulSite(GURL(*top_frame_site_str))
150                          : SchemefulSite(GURL(frame_origin_str)));
151 }
152 
153 class SQLitePersistentSharedDictionaryStoreTest : public ::testing::Test,
154                                                   public WithTaskEnvironment {
155  public:
SQLitePersistentSharedDictionaryStoreTest()156   SQLitePersistentSharedDictionaryStoreTest()
157       : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
158         isolation_key_(CreateIsolationKey("https://origin.test/")),
159         dictionary_info_(
160             GURL("https://origin.test/dict"),
161             /*response_time=*/base::Time::Now() - base::Seconds(10),
162             /*expiration*/ base::Seconds(100),
163             "/pattern*",
164             /*last_used_time*/ base::Time::Now(),
165             /*size=*/1000,
166             SHA256HashValue({{0x00, 0x01}}),
167             /*disk_cache_key_token=*/base::UnguessableToken::Create(),
168             /*primary_key_in_database=*/absl::nullopt) {}
169 
170   SQLitePersistentSharedDictionaryStoreTest(
171       const SQLitePersistentSharedDictionaryStoreTest&) = delete;
172   SQLitePersistentSharedDictionaryStoreTest& operator=(
173       const SQLitePersistentSharedDictionaryStoreTest&) = delete;
174 
SetUp()175   void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
176 
TearDown()177   void TearDown() override { DestroyStore(); }
178 
179  protected:
GetStroeFilePath() const180   base::FilePath GetStroeFilePath() const {
181     return temp_dir_.GetPath().Append(kSharedDictionaryStoreFilename);
182   }
183 
CreateStore()184   void CreateStore() {
185     CHECK(!store_);
186     store_ = std::make_unique<SQLitePersistentSharedDictionaryStore>(
187         GetStroeFilePath(), client_task_runner_, background_task_runner_);
188   }
189 
DestroyStore()190   void DestroyStore() {
191     store_.reset();
192     // Make sure we wait until the destructor has run by running all
193     // TaskEnvironment tasks.
194     RunUntilIdle();
195   }
196 
GetTotalDictionarySize()197   uint64_t GetTotalDictionarySize() {
198     base::RunLoop run_loop;
199     uint64_t total_dictionary_size_out = 0;
200     store_->GetTotalDictionarySize(base::BindLambdaForTesting(
201         [&](base::expected<
202             uint64_t, SQLitePersistentSharedDictionaryStore::Error> result) {
203           ASSERT_TRUE(result.has_value());
204           total_dictionary_size_out = result.value();
205           run_loop.Quit();
206         }));
207     run_loop.Run();
208     return total_dictionary_size_out;
209   }
210 
211   SQLitePersistentSharedDictionaryStore::RegisterDictionaryResult
RegisterDictionary(const SharedDictionaryIsolationKey & isolation_key,SharedDictionaryInfo dictionary_info)212   RegisterDictionary(const SharedDictionaryIsolationKey& isolation_key,
213                      SharedDictionaryInfo dictionary_info) {
214     return RegisterDictionaryImpl(store_.get(), isolation_key,
215                                   std::move(dictionary_info));
216   }
217 
GetDictionaries(const SharedDictionaryIsolationKey & isolation_key)218   std::vector<SharedDictionaryInfo> GetDictionaries(
219       const SharedDictionaryIsolationKey& isolation_key) {
220     std::vector<SharedDictionaryInfo> result_dictionaries;
221     base::RunLoop run_loop;
222     store_->GetDictionaries(
223         isolation_key,
224         base::BindLambdaForTesting(
225             [&](SQLitePersistentSharedDictionaryStore::DictionaryListOrError
226                     result) {
227               ASSERT_TRUE(result.has_value());
228               result_dictionaries = std::move(result.value());
229               run_loop.Quit();
230             }));
231     run_loop.Run();
232     return result_dictionaries;
233   }
234 
235   std::map<SharedDictionaryIsolationKey, std::vector<SharedDictionaryInfo>>
GetAllDictionaries()236   GetAllDictionaries() {
237     std::map<SharedDictionaryIsolationKey, std::vector<SharedDictionaryInfo>>
238         result_all_dictionaries;
239     base::RunLoop run_loop;
240     store_->GetAllDictionaries(base::BindLambdaForTesting(
241         [&](SQLitePersistentSharedDictionaryStore::DictionaryMapOrError
242                 result) {
243           ASSERT_TRUE(result.has_value());
244           result_all_dictionaries = std::move(result.value());
245           run_loop.Quit();
246         }));
247     run_loop.Run();
248     return result_all_dictionaries;
249   }
250 
GetUsageInfo()251   std::vector<SharedDictionaryUsageInfo> GetUsageInfo() {
252     std::vector<SharedDictionaryUsageInfo> result_usage_info;
253     base::RunLoop run_loop;
254     store_->GetUsageInfo(base::BindLambdaForTesting(
255         [&](SQLitePersistentSharedDictionaryStore::UsageInfoOrError result) {
256           ASSERT_TRUE(result.has_value());
257           result_usage_info = std::move(result.value());
258           run_loop.Quit();
259         }));
260     run_loop.Run();
261     return result_usage_info;
262   }
263 
GetOriginsBetween(const base::Time start_time,const base::Time end_time)264   std::vector<url::Origin> GetOriginsBetween(const base::Time start_time,
265                                              const base::Time end_time) {
266     std::vector<url::Origin> origins;
267     base::RunLoop run_loop;
268     store_->GetOriginsBetween(
269         start_time, end_time,
270         base::BindLambdaForTesting(
271             [&](SQLitePersistentSharedDictionaryStore::OriginListOrError
272                     result) {
273               ASSERT_TRUE(result.has_value());
274               origins = std::move(result.value());
275               run_loop.Quit();
276             }));
277     run_loop.Run();
278     return origins;
279   }
280 
ClearAllDictionaries()281   std::set<base::UnguessableToken> ClearAllDictionaries() {
282     base::RunLoop run_loop;
283     std::set<base::UnguessableToken> tokens;
284     store_->ClearAllDictionaries(base::BindLambdaForTesting(
285         [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
286                 result) {
287           ASSERT_TRUE(result.has_value());
288           tokens = std::move(result.value());
289           run_loop.Quit();
290         }));
291     run_loop.Run();
292     return tokens;
293   }
294 
ClearDictionaries(const base::Time start_time,const base::Time end_time,base::RepeatingCallback<bool (const GURL &)> url_matcher)295   std::set<base::UnguessableToken> ClearDictionaries(
296       const base::Time start_time,
297       const base::Time end_time,
298       base::RepeatingCallback<bool(const GURL&)> url_matcher) {
299     base::RunLoop run_loop;
300     std::set<base::UnguessableToken> tokens;
301     store_->ClearDictionaries(
302         start_time, end_time, std::move(url_matcher),
303         base::BindLambdaForTesting([&](SQLitePersistentSharedDictionaryStore::
304                                            UnguessableTokenSetOrError result) {
305           ASSERT_TRUE(result.has_value());
306           tokens = std::move(result.value());
307           run_loop.Quit();
308         }));
309     run_loop.Run();
310     return tokens;
311   }
312 
ClearDictionariesForIsolationKey(const SharedDictionaryIsolationKey & isolation_key)313   std::set<base::UnguessableToken> ClearDictionariesForIsolationKey(
314       const SharedDictionaryIsolationKey& isolation_key) {
315     base::RunLoop run_loop;
316     std::set<base::UnguessableToken> tokens;
317     store_->ClearDictionariesForIsolationKey(
318         isolation_key,
319         base::BindLambdaForTesting([&](SQLitePersistentSharedDictionaryStore::
320                                            UnguessableTokenSetOrError result) {
321           ASSERT_TRUE(result.has_value());
322           tokens = std::move(result.value());
323           run_loop.Quit();
324         }));
325     run_loop.Run();
326     return tokens;
327   }
328 
DeleteExpiredDictionaries(const base::Time now)329   std::set<base::UnguessableToken> DeleteExpiredDictionaries(
330       const base::Time now) {
331     base::RunLoop run_loop;
332     std::set<base::UnguessableToken> tokens;
333     store_->DeleteExpiredDictionaries(
334         now,
335         base::BindLambdaForTesting([&](SQLitePersistentSharedDictionaryStore::
336                                            UnguessableTokenSetOrError result) {
337           ASSERT_TRUE(result.has_value());
338           tokens = std::move(result.value());
339           run_loop.Quit();
340         }));
341     run_loop.Run();
342     return tokens;
343   }
344 
ProcessEviction(uint64_t cache_max_size,uint64_t size_low_watermark,uint64_t cache_max_count,uint64_t count_low_watermark)345   std::set<base::UnguessableToken> ProcessEviction(
346       uint64_t cache_max_size,
347       uint64_t size_low_watermark,
348       uint64_t cache_max_count,
349       uint64_t count_low_watermark) {
350     base::RunLoop run_loop;
351     std::set<base::UnguessableToken> tokens;
352     store_->ProcessEviction(
353         cache_max_size, size_low_watermark, cache_max_count,
354         count_low_watermark,
355         base::BindLambdaForTesting([&](SQLitePersistentSharedDictionaryStore::
356                                            UnguessableTokenSetOrError result) {
357           ASSERT_TRUE(result.has_value());
358           tokens = std::move(result.value());
359           run_loop.Quit();
360         }));
361     run_loop.Run();
362     return tokens;
363   }
364 
GetAllDiskCacheKeyTokens()365   std::set<base::UnguessableToken> GetAllDiskCacheKeyTokens() {
366     base::RunLoop run_loop;
367     std::set<base::UnguessableToken> tokens;
368     store_->GetAllDiskCacheKeyTokens(base::BindLambdaForTesting(
369         [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
370                 result) {
371           ASSERT_TRUE(result.has_value());
372           tokens = std::move(result.value());
373           run_loop.Quit();
374         }));
375     run_loop.Run();
376     return tokens;
377   }
378 
379   SQLitePersistentSharedDictionaryStore::Error
DeleteDictionariesByDiskCacheKeyTokens(std::set<base::UnguessableToken> disk_cache_key_tokens)380   DeleteDictionariesByDiskCacheKeyTokens(
381       std::set<base::UnguessableToken> disk_cache_key_tokens) {
382     base::RunLoop run_loop;
383     SQLitePersistentSharedDictionaryStore::Error error_out;
384     store_->DeleteDictionariesByDiskCacheKeyTokens(
385         std::move(disk_cache_key_tokens),
386         base::BindLambdaForTesting(
387             [&](SQLitePersistentSharedDictionaryStore::Error result_error) {
388               error_out = result_error;
389               run_loop.Quit();
390             }));
391     run_loop.Run();
392     return error_out;
393   }
394 
CorruptDatabaseFile()395   void CorruptDatabaseFile() {
396     // Execute CreateStore(), ClearAllDictionaries() and DestroyStore() to
397     // create a database file.
398     CreateStore();
399     ClearAllDictionaries();
400     DestroyStore();
401 
402     // Corrupt the database.
403     CHECK(sql::test::CorruptSizeInHeader(GetStroeFilePath()));
404   }
405 
ManipulateDatabase(const std::vector<std::string> & queries)406   void ManipulateDatabase(const std::vector<std::string>& queries) {
407     // We don't allow manipulating the database while `store_` exists.
408     ASSERT_FALSE(store_);
409 
410     std::unique_ptr<sql::Database> db =
411         std::make_unique<sql::Database>(sql::DatabaseOptions{});
412     ASSERT_TRUE(db->Open(GetStroeFilePath()));
413 
414     sql::MetaTable meta_table;
415     ASSERT_TRUE(meta_table.Init(db.get(), kCurrentVersionNumber,
416                                 kCurrentVersionNumber));
417     for (const std::string& query : queries) {
418       ASSERT_TRUE(db->Execute(query.c_str()));
419     }
420     db->Close();
421   }
422 
MakeFileUnwritable()423   void MakeFileUnwritable() {
424     file_permissions_restorer_ =
425         std::make_unique<base::FilePermissionRestorer>(GetStroeFilePath());
426     ASSERT_TRUE(base::MakeFileUnwritable(GetStroeFilePath()));
427   }
428 
CheckStoreRecovered()429   void CheckStoreRecovered() {
430     CreateStore();
431     EXPECT_TRUE(GetDictionaries(isolation_key_).empty());
432     EXPECT_TRUE(GetAllDictionaries().empty());
433     DestroyStore();
434   }
435 
436   void RunMultipleDictionariesTest(
437       const SharedDictionaryIsolationKey isolation_key1,
438       const SharedDictionaryInfo dictionary_info1,
439       const SharedDictionaryIsolationKey isolation_key2,
440       const SharedDictionaryInfo dictionary_info2,
441       bool expect_merged);
442 
443   void RunGetTotalDictionarySizeFailureTest(
444       SQLitePersistentSharedDictionaryStore::Error expected_error);
445   void RunRegisterDictionaryFailureTest(
446       SQLitePersistentSharedDictionaryStore::Error expected_error);
447   void RunGetDictionariesFailureTest(
448       SQLitePersistentSharedDictionaryStore::Error expected_error);
449   void RunGetAllDictionariesFailureTest(
450       SQLitePersistentSharedDictionaryStore::Error expected_error);
451   void RunGetUsageInfoFailureTest(
452       SQLitePersistentSharedDictionaryStore::Error expected_error);
453   void RunGetOriginsBetweenFailureTest(
454       SQLitePersistentSharedDictionaryStore::Error expected_error);
455   void RunClearAllDictionariesFailureTest(
456       SQLitePersistentSharedDictionaryStore::Error expected_error);
457   void RunClearDictionariesFailureTest(
458       base::RepeatingCallback<bool(const GURL&)> url_matcher,
459       SQLitePersistentSharedDictionaryStore::Error expected_error);
460   void RunClearDictionariesForIsolationKeyFailureTest(
461       SQLitePersistentSharedDictionaryStore::Error expected_error);
462   void RunDeleteExpiredDictionariesFailureTest(
463       SQLitePersistentSharedDictionaryStore::Error expected_error);
464   void RunProcessEvictionFailureTest(
465       SQLitePersistentSharedDictionaryStore::Error expected_error);
466   void RunGetAllDiskCacheKeyTokensFailureTest(
467       SQLitePersistentSharedDictionaryStore::Error expected_error);
468 
469   base::ScopedTempDir temp_dir_;
470   std::unique_ptr<SQLitePersistentSharedDictionaryStore> store_;
471   const scoped_refptr<base::SequencedTaskRunner> client_task_runner_ =
472       base::SingleThreadTaskRunner::GetCurrentDefault();
473   const scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
474       base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
475   // `file_permissions_restorer_` must be below `temp_dir_` to restore the
476   // file permission correctly.
477   std::unique_ptr<base::FilePermissionRestorer> file_permissions_restorer_;
478 
479   const SharedDictionaryIsolationKey isolation_key_;
480   const SharedDictionaryInfo dictionary_info_;
481 };
482 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,SingleDictionary)483 TEST_F(SQLitePersistentSharedDictionaryStoreTest, SingleDictionary) {
484   CreateStore();
485 
486   EXPECT_EQ(0u, GetTotalDictionarySize());
487 
488   auto register_dictionary_result =
489       RegisterDictionary(isolation_key_, dictionary_info_);
490   EXPECT_EQ(dictionary_info_.size(),
491             register_dictionary_result.total_dictionary_size());
492   EXPECT_EQ(1u, register_dictionary_result.total_dictionary_count());
493 
494   SharedDictionaryInfo expected_info = dictionary_info_;
495   expected_info.set_primary_key_in_database(
496       register_dictionary_result.primary_key_in_database());
497 
498   EXPECT_EQ(dictionary_info_.size(), GetTotalDictionarySize());
499   EXPECT_THAT(GetDictionaries(isolation_key_),
500               ElementsAreArray({expected_info}));
501   EXPECT_THAT(
502       GetAllDictionaries(),
503       ElementsAre(Pair(isolation_key_, ElementsAreArray({expected_info}))));
504   EXPECT_THAT(GetUsageInfo(),
505               ElementsAre(SharedDictionaryUsageInfo{
506                   .isolation_key = isolation_key_,
507                   .total_size_bytes = dictionary_info_.size()}));
508   EXPECT_TRUE(
509       GetOriginsBetween(dictionary_info_.response_time() - base::Seconds(1),
510                         dictionary_info_.response_time())
511           .empty());
512   EXPECT_THAT(
513       GetOriginsBetween(dictionary_info_.response_time(),
514                         dictionary_info_.response_time() + base::Seconds(1)),
515       ElementsAreArray({isolation_key_.frame_origin()}));
516 
517   EXPECT_THAT(
518       ClearAllDictionaries(),
519       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
520 
521   EXPECT_EQ(0u, GetTotalDictionarySize());
522   EXPECT_TRUE(GetDictionaries(isolation_key_).empty());
523   EXPECT_TRUE(GetAllDictionaries().empty());
524   EXPECT_TRUE(GetUsageInfo().empty());
525 }
526 
RunMultipleDictionariesTest(const SharedDictionaryIsolationKey isolation_key1,const SharedDictionaryInfo dictionary_info1,const SharedDictionaryIsolationKey isolation_key2,const SharedDictionaryInfo dictionary_info2,bool expect_merged)527 void SQLitePersistentSharedDictionaryStoreTest::RunMultipleDictionariesTest(
528     const SharedDictionaryIsolationKey isolation_key1,
529     const SharedDictionaryInfo dictionary_info1,
530     const SharedDictionaryIsolationKey isolation_key2,
531     const SharedDictionaryInfo dictionary_info2,
532     bool expect_merged) {
533   CreateStore();
534 
535   auto register_dictionary_result1 =
536       RegisterDictionary(isolation_key1, dictionary_info1);
537   EXPECT_EQ(dictionary_info1.size(),
538             register_dictionary_result1.total_dictionary_size());
539   EXPECT_EQ(1u, register_dictionary_result1.total_dictionary_count());
540   auto register_dictionary_result2 =
541       RegisterDictionary(isolation_key2, dictionary_info2);
542   EXPECT_EQ(expect_merged ? 1u : 2u,
543             register_dictionary_result2.total_dictionary_count());
544 
545   EXPECT_NE(register_dictionary_result1.primary_key_in_database(),
546             register_dictionary_result2.primary_key_in_database());
547 
548   SharedDictionaryInfo expected_info1 = dictionary_info1;
549   SharedDictionaryInfo expected_info2 = dictionary_info2;
550   expected_info1.set_primary_key_in_database(
551       register_dictionary_result1.primary_key_in_database());
552   expected_info2.set_primary_key_in_database(
553       register_dictionary_result2.primary_key_in_database());
554   base::Time oldest_response_time = std::min(dictionary_info1.response_time(),
555                                              dictionary_info2.response_time());
556   base::Time latest_response_time = std::max(dictionary_info1.response_time(),
557                                              dictionary_info2.response_time());
558 
559   std::set<base::UnguessableToken> registered_tokens;
560 
561   if (isolation_key1 == isolation_key2) {
562     if (expect_merged) {
563       registered_tokens.insert(expected_info2.disk_cache_key_token());
564       EXPECT_EQ(dictionary_info2.size(),
565                 register_dictionary_result2.total_dictionary_size());
566       EXPECT_THAT(GetDictionaries(isolation_key1),
567                   ElementsAreArray({expected_info2}));
568       EXPECT_THAT(GetAllDictionaries(),
569                   ElementsAre(Pair(isolation_key1,
570                                    ElementsAreArray({expected_info2}))));
571       ASSERT_TRUE(register_dictionary_result2.replaced_disk_cache_key_token());
572       EXPECT_EQ(dictionary_info1.disk_cache_key_token(),
573                 *register_dictionary_result2.replaced_disk_cache_key_token());
574       EXPECT_THAT(GetUsageInfo(),
575                   ElementsAre(SharedDictionaryUsageInfo{
576                       .isolation_key = isolation_key1,
577                       .total_size_bytes = dictionary_info2.size()}));
578       EXPECT_THAT(GetOriginsBetween(oldest_response_time,
579                                     latest_response_time + base::Seconds(1)),
580                   ElementsAreArray({isolation_key2.frame_origin()}));
581     } else {
582       registered_tokens.insert(expected_info1.disk_cache_key_token());
583       registered_tokens.insert(expected_info2.disk_cache_key_token());
584 
585       EXPECT_EQ(dictionary_info1.size() + dictionary_info2.size(),
586                 register_dictionary_result2.total_dictionary_size());
587       EXPECT_THAT(GetDictionaries(isolation_key1),
588                   UnorderedElementsAreArray({expected_info1, expected_info2}));
589       EXPECT_THAT(GetAllDictionaries(),
590                   ElementsAre(Pair(isolation_key1,
591                                    UnorderedElementsAreArray(
592                                        {expected_info1, expected_info2}))));
593       EXPECT_THAT(GetUsageInfo(),
594                   ElementsAre(SharedDictionaryUsageInfo{
595                       .isolation_key = isolation_key1,
596                       .total_size_bytes =
597                           dictionary_info1.size() + dictionary_info2.size()}));
598       EXPECT_THAT(GetOriginsBetween(oldest_response_time,
599                                     latest_response_time + base::Seconds(1)),
600                   UnorderedElementsAreArray({isolation_key1.frame_origin()}));
601     }
602   } else {
603     registered_tokens.insert(expected_info1.disk_cache_key_token());
604     registered_tokens.insert(expected_info2.disk_cache_key_token());
605     EXPECT_EQ(dictionary_info1.size() + dictionary_info2.size(),
606               register_dictionary_result2.total_dictionary_size());
607     EXPECT_THAT(GetDictionaries(isolation_key1),
608                 ElementsAreArray({expected_info1}));
609     EXPECT_THAT(GetDictionaries(isolation_key2),
610                 ElementsAreArray({expected_info2}));
611     EXPECT_THAT(
612         GetAllDictionaries(),
613         ElementsAre(Pair(isolation_key1, ElementsAreArray({expected_info1})),
614                     Pair(isolation_key2, ElementsAreArray({expected_info2}))));
615     EXPECT_THAT(GetUsageInfo(),
616                 UnorderedElementsAreArray(
617                     {SharedDictionaryUsageInfo{
618                          .isolation_key = isolation_key1,
619                          .total_size_bytes = dictionary_info1.size()},
620                      SharedDictionaryUsageInfo{
621                          .isolation_key = isolation_key2,
622                          .total_size_bytes = dictionary_info2.size()}}));
623     EXPECT_THAT(GetOriginsBetween(oldest_response_time,
624                                   latest_response_time + base::Seconds(1)),
625                 UnorderedElementsAreArray({isolation_key1.frame_origin(),
626                                            isolation_key2.frame_origin()}));
627   }
628 
629   EXPECT_THAT(ClearAllDictionaries(),
630               UnorderedElementsAreArray(registered_tokens));
631   EXPECT_TRUE(GetDictionaries(isolation_key_).empty());
632   EXPECT_TRUE(GetAllDictionaries().empty());
633   EXPECT_TRUE(GetUsageInfo().empty());
634   EXPECT_TRUE(GetOriginsBetween(oldest_response_time,
635                                 latest_response_time + base::Seconds(1))
636                   .empty());
637 }
638 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,MultipleDictionariesDifferentOriginSameSite)639 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
640        MultipleDictionariesDifferentOriginSameSite) {
641   SharedDictionaryIsolationKey isolation_key1 =
642       CreateIsolationKey("https://www1.origin.test/");
643   SharedDictionaryIsolationKey isolation_key2 =
644       CreateIsolationKey("https://www2.origin.test/");
645   EXPECT_NE(isolation_key1, isolation_key2);
646   EXPECT_NE(isolation_key1.frame_origin(), isolation_key2.frame_origin());
647   EXPECT_EQ(isolation_key1.top_frame_site(), isolation_key2.top_frame_site());
648   RunMultipleDictionariesTest(isolation_key1, dictionary_info_, isolation_key2,
649                               dictionary_info_, /*expect_merged=*/false);
650 }
651 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,MultipleDictionariesDifferentSite)652 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
653        MultipleDictionariesDifferentSite) {
654   SharedDictionaryIsolationKey isolation_key1 =
655       CreateIsolationKey("https://origin1.test/");
656   SharedDictionaryIsolationKey isolation_key2 =
657       CreateIsolationKey("https://origin2.test/");
658   EXPECT_NE(isolation_key1, isolation_key2);
659   EXPECT_NE(isolation_key1.frame_origin(), isolation_key2.frame_origin());
660   EXPECT_NE(isolation_key1.top_frame_site(), isolation_key2.top_frame_site());
661   RunMultipleDictionariesTest(isolation_key1, dictionary_info_, isolation_key2,
662                               dictionary_info_, /*expect_merged=*/false);
663 }
664 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,MultipleDictionariesDifferentHostAndPathPattern)665 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
666        MultipleDictionariesDifferentHostAndPathPattern) {
667   RunMultipleDictionariesTest(
668       isolation_key_,
669       SharedDictionaryInfo(
670           GURL("https://origin1.test/dict"),
671           /*response_time=*/base::Time::Now() - base::Seconds(10),
672           /*expiration*/ base::Seconds(100), "/pattern1*",
673           /*last_used_time*/ base::Time::Now(),
674           /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
675           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
676           /*primary_key_in_database=*/absl::nullopt),
677       isolation_key_,
678       SharedDictionaryInfo(
679           GURL("https://origin2.test/dict"),
680           /*response_time=*/base::Time::Now() - base::Seconds(20),
681           /*expiration*/ base::Seconds(200), "/pattern2*",
682           /*last_used_time*/ base::Time::Now(),
683           /*size=*/2000, SHA256HashValue({{0x00, 0x02}}),
684           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
685           /*primary_key_in_database=*/absl::nullopt),
686       /*expect_merged=*/false);
687 }
688 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,SameIsolationKeySameHostDifferentPathPattern)689 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
690        SameIsolationKeySameHostDifferentPathPattern) {
691   RunMultipleDictionariesTest(
692       isolation_key_,
693       SharedDictionaryInfo(
694           GURL("https://origin.test/dict"),
695           /*response_time=*/base::Time::Now() - base::Seconds(10),
696           /*expiration*/ base::Seconds(100), "/pattern1*",
697           /*last_used_time*/ base::Time::Now(),
698           /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
699           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
700           /*primary_key_in_database=*/absl::nullopt),
701       isolation_key_,
702       SharedDictionaryInfo(
703           GURL("https://origin.test/dict"),
704           /*response_time=*/base::Time::Now() - base::Seconds(20),
705           /*expiration*/ base::Seconds(200), "/pattern2*",
706           /*last_used_time*/ base::Time::Now(),
707           /*size=*/2000, SHA256HashValue({{0x00, 0x02}}),
708           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
709           /*primary_key_in_database=*/absl::nullopt),
710       /*expect_merged=*/false);
711 }
712 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,SameIsolationKeySameHostSamePathPattern)713 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
714        SameIsolationKeySameHostSamePathPattern) {
715   RunMultipleDictionariesTest(
716       isolation_key_,
717       SharedDictionaryInfo(
718           GURL("https://origin.test/dict"),
719           /*response_time=*/base::Time::Now() - base::Seconds(10),
720           /*expiration*/ base::Seconds(100), "/pattern*",
721           /*last_used_time*/ base::Time::Now(),
722           /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
723           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
724           /*primary_key_in_database=*/absl::nullopt),
725       isolation_key_,
726       SharedDictionaryInfo(
727           GURL("https://origin.test/dict"),
728           /*response_time=*/base::Time::Now() - base::Seconds(20),
729           /*expiration*/ base::Seconds(200), "/pattern*",
730           /*last_used_time*/ base::Time::Now(),
731           /*size=*/2000, SHA256HashValue({{0x00, 0x02}}),
732           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
733           /*primary_key_in_database=*/absl::nullopt),
734       /*expect_merged=*/true);
735 }
736 
737 void SQLitePersistentSharedDictionaryStoreTest::
RunGetTotalDictionarySizeFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)738     RunGetTotalDictionarySizeFailureTest(
739         SQLitePersistentSharedDictionaryStore::Error expected_error) {
740   CreateStore();
741   base::RunLoop run_loop;
742   store_->GetTotalDictionarySize(base::BindLambdaForTesting(
743       [&](base::expected<uint64_t, SQLitePersistentSharedDictionaryStore::Error>
744               result) {
745         ASSERT_FALSE(result.has_value());
746         EXPECT_EQ(expected_error, result.error());
747         run_loop.Quit();
748       }));
749   run_loop.Run();
750   DestroyStore();
751 }
752 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetTotalDictionarySizeErrorInitializationFailure)753 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
754        GetTotalDictionarySizeErrorInitializationFailure) {
755   CorruptDatabaseFile();
756   RunGetTotalDictionarySizeFailureTest(SQLitePersistentSharedDictionaryStore::
757                                            Error::kFailedToInitializeDatabase);
758   CheckStoreRecovered();
759 }
760 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetTotalDictionarySizeErrorFailedToGetTotalDictSize)761 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
762        GetTotalDictionarySizeErrorFailedToGetTotalDictSize) {
763   CreateStore();
764   EXPECT_TRUE(ClearAllDictionaries().empty());
765   DestroyStore();
766   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
767 
768   RunGetTotalDictionarySizeFailureTest(
769       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
770 
771   CreateStore();
772   // ClearAllDictionaries() resets total_dict_size in metadata.
773   EXPECT_TRUE(ClearAllDictionaries().empty());
774   // So GetTotalDictionarySize() should succeed.
775   EXPECT_EQ(0u, GetTotalDictionarySize());
776 }
777 
778 void SQLitePersistentSharedDictionaryStoreTest::
RunRegisterDictionaryFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)779     RunRegisterDictionaryFailureTest(
780         SQLitePersistentSharedDictionaryStore::Error expected_error) {
781   CreateStore();
782   base::RunLoop run_loop;
783   store_->RegisterDictionary(
784       isolation_key_, dictionary_info_, /*max_size_per_site=*/1000000,
785       /*max_count_per_site=*/1000,
786       base::BindLambdaForTesting(
787           [&](SQLitePersistentSharedDictionaryStore::
788                   RegisterDictionaryResultOrError result) {
789             ASSERT_FALSE(result.has_value());
790             EXPECT_EQ(expected_error, result.error());
791             run_loop.Quit();
792           }));
793   run_loop.Run();
794   DestroyStore();
795 }
796 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorDatabaseInitializationFailure)797 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
798        RegisterDictionaryErrorDatabaseInitializationFailure) {
799   CorruptDatabaseFile();
800   RunRegisterDictionaryFailureTest(SQLitePersistentSharedDictionaryStore::
801                                        Error::kFailedToInitializeDatabase);
802   CheckStoreRecovered();
803 }
804 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorInvalidSql)805 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
806        RegisterDictionaryErrorInvalidSql) {
807   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
808   RunRegisterDictionaryFailureTest(
809       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
810 }
811 
812 #if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
813 // MakeFileUnwritable() doesn't cause the failure on Fuchsia and Windows. So
814 // disabling the test on Fuchsia and Windows.
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorSqlExecutionFailure)815 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
816        RegisterDictionaryErrorSqlExecutionFailure) {
817   CreateStore();
818   ClearAllDictionaries();
819   DestroyStore();
820   MakeFileUnwritable();
821   RunRegisterDictionaryFailureTest(
822       SQLitePersistentSharedDictionaryStore::Error::kFailedToExecuteSql);
823 }
824 #endif  // !BUILDFLAG(IS_FUCHSIA)
825 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorFailedToGetTotalDictSize)826 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
827        RegisterDictionaryErrorFailedToGetTotalDictSize) {
828   CreateStore();
829   ClearAllDictionaries();
830   DestroyStore();
831   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
832 
833   RunRegisterDictionaryFailureTest(
834       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
835 
836   CreateStore();
837   // ClearAllDictionaries() resets total_dict_size in metadata.
838   EXPECT_TRUE(ClearAllDictionaries().empty());
839   // So RegisterDictionary() should succeed.
840   RegisterDictionary(isolation_key_, dictionary_info_);
841 }
842 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorInvalidTotalDictSize)843 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
844        RegisterDictionaryErrorInvalidTotalDictSize) {
845   CreateStore();
846 
847   SharedDictionaryInfo dictionary_info(
848       dictionary_info_.url(),
849       /*response_time*/ base::Time::Now(), dictionary_info_.expiration(),
850       dictionary_info_.match(),
851       /*last_used_time*/ base::Time::Now(), dictionary_info_.size() + 1,
852       SHA256HashValue({{0x00, 0x02}}),
853       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
854       /*primary_key_in_database=*/absl::nullopt);
855 
856   // Register the dictionary which size is dictionary_info_.size() + 1.
857   base::RunLoop run_loop;
858   store_->RegisterDictionary(
859       isolation_key_, dictionary_info, /*max_size_per_site=*/1000000,
860       /*max_count_per_site=*/1000,
861       base::BindLambdaForTesting(
862           [&](SQLitePersistentSharedDictionaryStore::
863                   RegisterDictionaryResultOrError result) {
864             EXPECT_TRUE(result.has_value());
865             run_loop.Quit();
866           }));
867   run_loop.Run();
868 
869   DestroyStore();
870 
871   // Set total_dict_size in metadata to 0.
872   ManipulateDatabase({"UPDATE meta SET value=0 WHERE key='total_dict_size'"});
873 
874   // Registering `dictionary_info_` which size is smaller than the previous
875   // dictionary cause InvalidTotalDictSize error because the calculated total
876   // size will be negative.
877   RunRegisterDictionaryFailureTest(
878       SQLitePersistentSharedDictionaryStore::Error::kInvalidTotalDictSize);
879 }
880 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryErrorTooBigDictionary)881 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
882        RegisterDictionaryErrorTooBigDictionary) {
883   CreateStore();
884   uint64_t max_size_per_site = 10000;
885   base::RunLoop run_loop;
886   store_->RegisterDictionary(
887       isolation_key_,
888       SharedDictionaryInfo(
889           GURL("https://a.example/dict"),
890           /*response_time=*/base::Time::Now(),
891           /*expiration*/ base::Seconds(100), "/pattern*",
892           /*last_used_time*/ base::Time::Now(),
893           /*size=*/max_size_per_site + 1, SHA256HashValue({{0x00, 0x01}}),
894           /*disk_cache_key_token=*/base::UnguessableToken::Create(),
895           /*primary_key_in_database=*/absl::nullopt),
896       max_size_per_site,
897       /*max_count_per_site=*/1000,
898       base::BindLambdaForTesting(
899           [&](SQLitePersistentSharedDictionaryStore::
900                   RegisterDictionaryResultOrError result) {
901             ASSERT_FALSE(result.has_value());
902             EXPECT_EQ(
903                 SQLitePersistentSharedDictionaryStore::Error::kTooBigDictionary,
904                 result.error());
905             run_loop.Quit();
906           }));
907   run_loop.Run();
908   EXPECT_EQ(0u, GetTotalDictionarySize());
909 }
910 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryPerSiteEvictionWhenExceededSizeLimit)911 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
912        RegisterDictionaryPerSiteEvictionWhenExceededSizeLimit) {
913   CreateStore();
914 
915   uint64_t max_size_per_site = 10000;
916   uint64_t max_count_per_site = 100;
917 
918   auto isolation_key1 = CreateIsolationKey("https://origin1.test",
919                                            "https://top-frame-site1.test");
920   auto dict1 = SharedDictionaryInfo(
921       GURL("https://a.example/dict"),
922       /*response_time=*/base::Time::Now(),
923       /*expiration*/ base::Seconds(100), "/pattern*",
924       /*last_used_time*/ base::Time::Now(),
925       /*size=*/max_size_per_site, SHA256HashValue({{0x00, 0x01}}),
926       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
927       /*primary_key_in_database=*/absl::nullopt);
928   auto result1 = RegisterDictionaryImpl(store_.get(), isolation_key1, dict1,
929                                         max_size_per_site, max_count_per_site);
930   dict1.set_primary_key_in_database(result1.primary_key_in_database());
931   EXPECT_TRUE(result1.evicted_disk_cache_key_tokens().empty());
932   EXPECT_THAT(GetAllDictionaries(),
933               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1}))));
934 
935   FastForwardBy(base::Seconds(1));
936 
937   auto isolation_key2 = CreateIsolationKey("https://origin1.test",
938                                            "https://top-frame-site2.test");
939   auto dict2 = SharedDictionaryInfo(
940       GURL("https://b.example/dict"),
941       /*response_time=*/base::Time::Now(),
942       /*expiration*/ base::Seconds(100), "/pattern*",
943       /*last_used_time*/ base::Time::Now(),
944       /*size=*/max_size_per_site / 2, SHA256HashValue({{0x00, 0x02}}),
945       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
946       /*primary_key_in_database=*/absl::nullopt);
947   auto result2 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict2,
948                                         max_size_per_site, max_count_per_site);
949   dict2.set_primary_key_in_database(result2.primary_key_in_database());
950   EXPECT_TRUE(result2.evicted_disk_cache_key_tokens().empty());
951   EXPECT_THAT(GetAllDictionaries(),
952               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
953                           Pair(isolation_key2, ElementsAreArray({dict2}))));
954 
955   FastForwardBy(base::Seconds(1));
956 
957   auto dict3 = SharedDictionaryInfo(
958       GURL("https://c.example/dict"),
959       /*response_time=*/base::Time::Now(),
960       /*expiration*/ base::Seconds(100), "/pattern*",
961       /*last_used_time*/ base::Time::Now(),
962       /*size=*/max_size_per_site / 2, SHA256HashValue({{0x00, 0x03}}),
963       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
964       /*primary_key_in_database=*/absl::nullopt);
965   auto result3 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict3,
966                                         max_size_per_site, max_count_per_site);
967   dict3.set_primary_key_in_database(result3.primary_key_in_database());
968   EXPECT_TRUE(result3.evicted_disk_cache_key_tokens().empty());
969   EXPECT_THAT(GetAllDictionaries(),
970               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
971                           Pair(isolation_key2,
972                                UnorderedElementsAreArray({dict2, dict3}))));
973 
974   FastForwardBy(base::Seconds(1));
975 
976   // The top frame site of `isolation_key3` is same as the top frame site of
977   // `isolation_key2`.
978   auto isolation_key3 = CreateIsolationKey("https://origin2.test",
979                                            "https://top-frame-site2.test");
980   auto dict4 = SharedDictionaryInfo(
981       GURL("https://d.example/dict"),
982       /*response_time=*/base::Time::Now(),
983       /*expiration*/ base::Seconds(100), "/pattern*",
984       /*last_used_time*/ base::Time::Now(),
985       /*size=*/1, SHA256HashValue({{0x00, 0x04}}),
986       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
987       /*primary_key_in_database=*/absl::nullopt);
988   auto result4 = RegisterDictionaryImpl(store_.get(), isolation_key3, dict4,
989                                         max_size_per_site, max_count_per_site);
990   dict4.set_primary_key_in_database(result4.primary_key_in_database());
991   // dict2.size() + dict3.size() + dict4.size() exceeds `max_size_per_site`. So
992   // the oldest dictionary `dict2` must be evicted.
993   EXPECT_THAT(result4.evicted_disk_cache_key_tokens(),
994               ElementsAreArray({dict2.disk_cache_key_token()}));
995   EXPECT_THAT(GetAllDictionaries(),
996               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
997                           Pair(isolation_key2, ElementsAreArray({dict3})),
998                           Pair(isolation_key3, ElementsAreArray({dict4}))));
999   EXPECT_EQ(dict1.size() + dict3.size() + dict4.size(),
1000             GetTotalDictionarySize());
1001 }
1002 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryPerSiteEvictionWhenExceededCountLimit)1003 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1004        RegisterDictionaryPerSiteEvictionWhenExceededCountLimit) {
1005   CreateStore();
1006 
1007   uint64_t max_size_per_site = 10000;
1008   uint64_t max_count_per_site = 2;
1009 
1010   auto isolation_key1 = CreateIsolationKey("https://origin1.test",
1011                                            "https://top-frame-site1.test");
1012   auto dict1 = SharedDictionaryInfo(
1013       GURL("https://a.example/dict"),
1014       /*response_time=*/base::Time::Now(),
1015       /*expiration*/ base::Seconds(100), "/pattern*",
1016       /*last_used_time*/ base::Time::Now(),
1017       /*size=*/100, SHA256HashValue({{0x00, 0x01}}),
1018       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1019       /*primary_key_in_database=*/absl::nullopt);
1020   auto result1 = RegisterDictionaryImpl(store_.get(), isolation_key1, dict1,
1021                                         max_size_per_site, max_count_per_site);
1022   dict1.set_primary_key_in_database(result1.primary_key_in_database());
1023   EXPECT_TRUE(result1.evicted_disk_cache_key_tokens().empty());
1024   EXPECT_THAT(GetAllDictionaries(),
1025               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1}))));
1026 
1027   FastForwardBy(base::Seconds(1));
1028 
1029   auto isolation_key2 = CreateIsolationKey("https://origin1.test",
1030                                            "https://top-frame-site2.test");
1031   auto dict2 = SharedDictionaryInfo(
1032       GURL("https://b.example/dict"),
1033       /*response_time=*/base::Time::Now(),
1034       /*expiration*/ base::Seconds(100), "/pattern*",
1035       /*last_used_time*/ base::Time::Now(),
1036       /*size=*/200, SHA256HashValue({{0x00, 0x02}}),
1037       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1038       /*primary_key_in_database=*/absl::nullopt);
1039   auto result2 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict2,
1040                                         max_size_per_site, max_count_per_site);
1041   dict2.set_primary_key_in_database(result2.primary_key_in_database());
1042   EXPECT_TRUE(result2.evicted_disk_cache_key_tokens().empty());
1043   EXPECT_THAT(GetAllDictionaries(),
1044               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1045                           Pair(isolation_key2, ElementsAreArray({dict2}))));
1046 
1047   FastForwardBy(base::Seconds(1));
1048 
1049   auto dict3 = SharedDictionaryInfo(
1050       GURL("https://c.example/dict"),
1051       /*response_time=*/base::Time::Now(),
1052       /*expiration*/ base::Seconds(100), "/pattern*",
1053       /*last_used_time*/ base::Time::Now(),
1054       /*size=*/400, SHA256HashValue({{0x00, 0x03}}),
1055       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1056       /*primary_key_in_database=*/absl::nullopt);
1057   auto result3 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict3,
1058                                         max_size_per_site, max_count_per_site);
1059   dict3.set_primary_key_in_database(result3.primary_key_in_database());
1060   EXPECT_TRUE(result3.evicted_disk_cache_key_tokens().empty());
1061   EXPECT_THAT(GetAllDictionaries(),
1062               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1063                           Pair(isolation_key2,
1064                                UnorderedElementsAreArray({dict2, dict3}))));
1065 
1066   FastForwardBy(base::Seconds(1));
1067 
1068   // The top frame site of `isolation_key3` is same as the top frame site of
1069   // `isolation_key2`.
1070   auto isolation_key3 = CreateIsolationKey("https://origin2.test",
1071                                            "https://top-frame-site2.test");
1072   auto dict4 = SharedDictionaryInfo(
1073       GURL("https://d.example/dict"),
1074       /*response_time=*/base::Time::Now(),
1075       /*expiration*/ base::Seconds(100), "/pattern*",
1076       /*last_used_time*/ base::Time::Now(),
1077       /*size=*/800, SHA256HashValue({{0x00, 0x04}}),
1078       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1079       /*primary_key_in_database=*/absl::nullopt);
1080   auto result4 = RegisterDictionaryImpl(store_.get(), isolation_key3, dict4,
1081                                         max_size_per_site, max_count_per_site);
1082   dict4.set_primary_key_in_database(result4.primary_key_in_database());
1083   // The dictionary count on "https://top-frame-site2.test" exceeds
1084   // `max_count_per_site`. So the oldest dictionary `dict2` must be evicted.
1085   EXPECT_THAT(result4.evicted_disk_cache_key_tokens(),
1086               ElementsAreArray({dict2.disk_cache_key_token()}));
1087   EXPECT_THAT(GetAllDictionaries(),
1088               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1089                           Pair(isolation_key2, ElementsAreArray({dict3})),
1090                           Pair(isolation_key3, ElementsAreArray({dict4}))));
1091   EXPECT_EQ(dict1.size() + dict3.size() + dict4.size(),
1092             GetTotalDictionarySize());
1093 }
1094 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryPerSiteEvictionWhenExceededCountLimitWithoutSizeLimit)1095 TEST_F(
1096     SQLitePersistentSharedDictionaryStoreTest,
1097     RegisterDictionaryPerSiteEvictionWhenExceededCountLimitWithoutSizeLimit) {
1098   CreateStore();
1099 
1100   uint64_t max_size_per_site = 0;
1101   uint64_t max_count_per_site = 2;
1102 
1103   auto isolation_key1 = CreateIsolationKey("https://origin1.test",
1104                                            "https://top-frame-site1.test");
1105   auto dict1 = SharedDictionaryInfo(
1106       GURL("https://a.example/dict"),
1107       /*response_time=*/base::Time::Now(),
1108       /*expiration*/ base::Seconds(100), "/pattern*",
1109       /*last_used_time*/ base::Time::Now(),
1110       /*size=*/100, SHA256HashValue({{0x00, 0x01}}),
1111       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1112       /*primary_key_in_database=*/absl::nullopt);
1113   auto result1 = RegisterDictionaryImpl(store_.get(), isolation_key1, dict1,
1114                                         max_size_per_site, max_count_per_site);
1115   dict1.set_primary_key_in_database(result1.primary_key_in_database());
1116   EXPECT_TRUE(result1.evicted_disk_cache_key_tokens().empty());
1117   EXPECT_THAT(GetAllDictionaries(),
1118               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1}))));
1119 
1120   FastForwardBy(base::Seconds(1));
1121 
1122   auto isolation_key2 = CreateIsolationKey("https://origin1.test",
1123                                            "https://top-frame-site2.test");
1124   auto dict2 = SharedDictionaryInfo(
1125       GURL("https://b.example/dict"),
1126       /*response_time=*/base::Time::Now(),
1127       /*expiration*/ base::Seconds(100), "/pattern*",
1128       /*last_used_time*/ base::Time::Now(),
1129       /*size=*/200, SHA256HashValue({{0x00, 0x02}}),
1130       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1131       /*primary_key_in_database=*/absl::nullopt);
1132   auto result2 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict2,
1133                                         max_size_per_site, max_count_per_site);
1134   dict2.set_primary_key_in_database(result2.primary_key_in_database());
1135   EXPECT_TRUE(result2.evicted_disk_cache_key_tokens().empty());
1136   EXPECT_THAT(GetAllDictionaries(),
1137               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1138                           Pair(isolation_key2, ElementsAreArray({dict2}))));
1139 
1140   FastForwardBy(base::Seconds(1));
1141 
1142   auto dict3 = SharedDictionaryInfo(
1143       GURL("https://c.example/dict"),
1144       /*response_time=*/base::Time::Now(),
1145       /*expiration*/ base::Seconds(100), "/pattern*",
1146       /*last_used_time*/ base::Time::Now(),
1147       /*size=*/400, SHA256HashValue({{0x00, 0x03}}),
1148       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1149       /*primary_key_in_database=*/absl::nullopt);
1150   auto result3 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict3,
1151                                         max_size_per_site, max_count_per_site);
1152   dict3.set_primary_key_in_database(result3.primary_key_in_database());
1153   EXPECT_TRUE(result3.evicted_disk_cache_key_tokens().empty());
1154   EXPECT_THAT(GetAllDictionaries(),
1155               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1156                           Pair(isolation_key2,
1157                                UnorderedElementsAreArray({dict2, dict3}))));
1158 
1159   FastForwardBy(base::Seconds(1));
1160 
1161   // The top frame site of `isolation_key3` is same as the top frame site of
1162   // `isolation_key2`.
1163   auto isolation_key3 = CreateIsolationKey("https://origin2.test",
1164                                            "https://top-frame-site2.test");
1165   auto dict4 = SharedDictionaryInfo(
1166       GURL("https://d.example/dict"),
1167       /*response_time=*/base::Time::Now(),
1168       /*expiration*/ base::Seconds(100), "/pattern*",
1169       /*last_used_time*/ base::Time::Now(),
1170       /*size=*/800, SHA256HashValue({{0x00, 0x04}}),
1171       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1172       /*primary_key_in_database=*/absl::nullopt);
1173   auto result4 = RegisterDictionaryImpl(store_.get(), isolation_key3, dict4,
1174                                         max_size_per_site, max_count_per_site);
1175   dict4.set_primary_key_in_database(result4.primary_key_in_database());
1176   // The dictionary count on "https://top-frame-site2.test" exceeds
1177   // `max_count_per_site`. So the oldest dictionary `dict2` must be evicted.
1178   EXPECT_THAT(result4.evicted_disk_cache_key_tokens(),
1179               ElementsAreArray({dict2.disk_cache_key_token()}));
1180   EXPECT_THAT(GetAllDictionaries(),
1181               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1182                           Pair(isolation_key2, ElementsAreArray({dict3})),
1183                           Pair(isolation_key3, ElementsAreArray({dict4}))));
1184   EXPECT_EQ(dict1.size() + dict3.size() + dict4.size(),
1185             GetTotalDictionarySize());
1186 }
1187 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryPerSiteEvictionWhenExceededBothSizeAndCountLimit)1188 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1189        RegisterDictionaryPerSiteEvictionWhenExceededBothSizeAndCountLimit) {
1190   CreateStore();
1191 
1192   uint64_t max_size_per_site = 800;
1193   uint64_t max_count_per_site = 2;
1194 
1195   auto isolation_key1 = CreateIsolationKey("https://origin1.test",
1196                                            "https://top-frame-site1.test");
1197   auto dict1 = SharedDictionaryInfo(
1198       GURL("https://a.example/dict"),
1199       /*response_time=*/base::Time::Now(),
1200       /*expiration*/ base::Seconds(100), "/pattern*",
1201       /*last_used_time*/ base::Time::Now(),
1202       /*size=*/100, SHA256HashValue({{0x00, 0x01}}),
1203       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1204       /*primary_key_in_database=*/absl::nullopt);
1205   auto result1 = RegisterDictionaryImpl(store_.get(), isolation_key1, dict1,
1206                                         max_size_per_site, max_count_per_site);
1207   dict1.set_primary_key_in_database(result1.primary_key_in_database());
1208   EXPECT_TRUE(result1.evicted_disk_cache_key_tokens().empty());
1209   EXPECT_THAT(GetAllDictionaries(),
1210               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1}))));
1211 
1212   FastForwardBy(base::Seconds(1));
1213 
1214   auto isolation_key2 = CreateIsolationKey("https://origin1.test",
1215                                            "https://top-frame-site2.test");
1216   auto dict2 = SharedDictionaryInfo(
1217       GURL("https://b.example/dict"),
1218       /*response_time=*/base::Time::Now(),
1219       /*expiration*/ base::Seconds(100), "/pattern*",
1220       /*last_used_time*/ base::Time::Now(),
1221       /*size=*/200, SHA256HashValue({{0x00, 0x02}}),
1222       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1223       /*primary_key_in_database=*/absl::nullopt);
1224   auto result2 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict2,
1225                                         max_size_per_site, max_count_per_site);
1226   dict2.set_primary_key_in_database(result2.primary_key_in_database());
1227   EXPECT_TRUE(result2.evicted_disk_cache_key_tokens().empty());
1228   EXPECT_THAT(GetAllDictionaries(),
1229               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1230                           Pair(isolation_key2, ElementsAreArray({dict2}))));
1231 
1232   FastForwardBy(base::Seconds(1));
1233 
1234   auto dict3 = SharedDictionaryInfo(
1235       GURL("https://c.example/dict"),
1236       /*response_time=*/base::Time::Now(),
1237       /*expiration*/ base::Seconds(100), "/pattern*",
1238       /*last_used_time*/ base::Time::Now(),
1239       /*size=*/400, SHA256HashValue({{0x00, 0x03}}),
1240       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1241       /*primary_key_in_database=*/absl::nullopt);
1242   auto result3 = RegisterDictionaryImpl(store_.get(), isolation_key2, dict3,
1243                                         max_size_per_site, max_count_per_site);
1244   dict3.set_primary_key_in_database(result3.primary_key_in_database());
1245   EXPECT_TRUE(result3.evicted_disk_cache_key_tokens().empty());
1246   EXPECT_THAT(GetAllDictionaries(),
1247               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1248                           Pair(isolation_key2,
1249                                UnorderedElementsAreArray({dict2, dict3}))));
1250 
1251   FastForwardBy(base::Seconds(1));
1252 
1253   // The top frame site of `isolation_key3` is same as the top frame site of
1254   // `isolation_key2`.
1255   auto isolation_key3 = CreateIsolationKey("https://origin2.test",
1256                                            "https://top-frame-site2.test");
1257   auto dict4 = SharedDictionaryInfo(
1258       GURL("https://d.example/dict"),
1259       /*response_time=*/base::Time::Now(),
1260       /*expiration*/ base::Seconds(100), "/pattern*",
1261       /*last_used_time*/ base::Time::Now(),
1262       /*size=*/800, SHA256HashValue({{0x00, 0x04}}),
1263       /*disk_cache_key_token=*/base::UnguessableToken::Create(),
1264       /*primary_key_in_database=*/absl::nullopt);
1265   auto result4 = RegisterDictionaryImpl(store_.get(), isolation_key3, dict4,
1266                                         max_size_per_site, max_count_per_site);
1267   dict4.set_primary_key_in_database(result4.primary_key_in_database());
1268   // The dictionary count on "https://top-frame-site2.test" exceeds
1269   // `max_count_per_site`. Also dictionary size on
1270   // "https://top-frame-site2.test" exceeds `max_size_per_site`.
1271   // So both `dict2` and `dict3` must be evicted.
1272   EXPECT_THAT(result4.evicted_disk_cache_key_tokens(),
1273               UnorderedElementsAreArray({dict2.disk_cache_key_token(),
1274                                          dict3.disk_cache_key_token()}));
1275   EXPECT_THAT(GetAllDictionaries(),
1276               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
1277                           Pair(isolation_key3, ElementsAreArray({dict4}))));
1278   EXPECT_EQ(dict1.size() + dict4.size(), GetTotalDictionarySize());
1279 }
1280 
RunGetDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1281 void SQLitePersistentSharedDictionaryStoreTest::RunGetDictionariesFailureTest(
1282     SQLitePersistentSharedDictionaryStore::Error expected_error) {
1283   CreateStore();
1284   base::RunLoop run_loop;
1285   store_->GetDictionaries(
1286       isolation_key_,
1287       base::BindLambdaForTesting(
1288           [&](SQLitePersistentSharedDictionaryStore::DictionaryListOrError
1289                   result) {
1290             ASSERT_FALSE(result.has_value());
1291             EXPECT_EQ(expected_error, result.error());
1292             run_loop.Quit();
1293           }));
1294   run_loop.Run();
1295   DestroyStore();
1296 }
1297 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetDictionariesErrorDatabaseInitializationFailure)1298 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1299        GetDictionariesErrorDatabaseInitializationFailure) {
1300   CorruptDatabaseFile();
1301   RunGetDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::Error::
1302                                     kFailedToInitializeDatabase);
1303   CheckStoreRecovered();
1304 }
1305 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetDictionariesErrorInvalidSql)1306 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1307        GetDictionariesErrorInvalidSql) {
1308   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1309   RunGetDictionariesFailureTest(
1310       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1311 }
1312 
1313 void SQLitePersistentSharedDictionaryStoreTest::
RunGetAllDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1314     RunGetAllDictionariesFailureTest(
1315         SQLitePersistentSharedDictionaryStore::Error expected_error) {
1316   CreateStore();
1317   base::RunLoop run_loop;
1318   store_->GetAllDictionaries(base::BindLambdaForTesting(
1319       [&](SQLitePersistentSharedDictionaryStore::DictionaryMapOrError result) {
1320         ASSERT_FALSE(result.has_value());
1321         EXPECT_EQ(expected_error, result.error());
1322         run_loop.Quit();
1323       }));
1324   run_loop.Run();
1325   DestroyStore();
1326 }
1327 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDictionariesErrorDatabaseInitializationFailure)1328 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1329        GetAllDictionariesErrorDatabaseInitializationFailure) {
1330   CorruptDatabaseFile();
1331   RunGetAllDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::
1332                                        Error::kFailedToInitializeDatabase);
1333   CheckStoreRecovered();
1334 }
1335 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDictionariesErrorInvalidSql)1336 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1337        GetAllDictionariesErrorInvalidSql) {
1338   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1339   RunGetAllDictionariesFailureTest(
1340       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1341 }
1342 
RunGetUsageInfoFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1343 void SQLitePersistentSharedDictionaryStoreTest::RunGetUsageInfoFailureTest(
1344     SQLitePersistentSharedDictionaryStore::Error expected_error) {
1345   CreateStore();
1346   base::RunLoop run_loop;
1347   store_->GetUsageInfo(base::BindLambdaForTesting(
1348       [&](SQLitePersistentSharedDictionaryStore::UsageInfoOrError result) {
1349         ASSERT_FALSE(result.has_value());
1350         EXPECT_EQ(expected_error, result.error());
1351         run_loop.Quit();
1352       }));
1353   run_loop.Run();
1354   DestroyStore();
1355 }
1356 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RunGetUsageInfoErrorDatabaseInitializationFailure)1357 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1358        RunGetUsageInfoErrorDatabaseInitializationFailure) {
1359   CorruptDatabaseFile();
1360   RunGetUsageInfoFailureTest(SQLitePersistentSharedDictionaryStore::Error::
1361                                  kFailedToInitializeDatabase);
1362   CheckStoreRecovered();
1363 }
1364 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RunGetUsageInfoErrorInvalidSql)1365 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1366        RunGetUsageInfoErrorInvalidSql) {
1367   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1368   RunGetUsageInfoFailureTest(
1369       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1370 }
1371 
RunGetOriginsBetweenFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1372 void SQLitePersistentSharedDictionaryStoreTest::RunGetOriginsBetweenFailureTest(
1373     SQLitePersistentSharedDictionaryStore::Error expected_error) {
1374   CreateStore();
1375   base::RunLoop run_loop;
1376   store_->GetOriginsBetween(
1377       base::Time::Now(), base::Time::Now() + base::Seconds(1),
1378       base::BindLambdaForTesting(
1379           [&](SQLitePersistentSharedDictionaryStore::OriginListOrError result) {
1380             ASSERT_FALSE(result.has_value());
1381             EXPECT_EQ(expected_error, result.error());
1382             run_loop.Quit();
1383           }));
1384   run_loop.Run();
1385   DestroyStore();
1386 }
1387 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RunGetOriginsBetweenErrorDatabaseInitializationFailure)1388 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1389        RunGetOriginsBetweenErrorDatabaseInitializationFailure) {
1390   CorruptDatabaseFile();
1391   RunGetOriginsBetweenFailureTest(SQLitePersistentSharedDictionaryStore::Error::
1392                                       kFailedToInitializeDatabase);
1393   CheckStoreRecovered();
1394 }
1395 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RunGetOriginsBetweenErrorInvalidSql)1396 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1397        RunGetOriginsBetweenErrorInvalidSql) {
1398   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1399   RunGetOriginsBetweenFailureTest(
1400       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1401 }
1402 
1403 void SQLitePersistentSharedDictionaryStoreTest::
RunClearAllDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1404     RunClearAllDictionariesFailureTest(
1405         SQLitePersistentSharedDictionaryStore::Error expected_error) {
1406   CreateStore();
1407   base::RunLoop run_loop;
1408   store_->ClearAllDictionaries(base::BindLambdaForTesting(
1409       [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1410               result) {
1411         ASSERT_FALSE(result.has_value());
1412         EXPECT_EQ(expected_error, result.error());
1413         run_loop.Quit();
1414       }));
1415   run_loop.Run();
1416   DestroyStore();
1417 }
1418 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearAllDictionariesErrorDatabaseInitializationFailure)1419 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1420        ClearAllDictionariesErrorDatabaseInitializationFailure) {
1421   CorruptDatabaseFile();
1422   RunClearAllDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::
1423                                          Error::kFailedToInitializeDatabase);
1424   CheckStoreRecovered();
1425 }
1426 
1427 #if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
1428 // MakeFileUnwritable() doesn't cause the failure on Fuchsia and Windows. So
1429 // disabling the test on Fuchsia and Windows.
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearAllDictionariesErrorSqlExecutionFailure)1430 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1431        ClearAllDictionariesErrorSqlExecutionFailure) {
1432   CreateStore();
1433   ClearAllDictionaries();
1434   DestroyStore();
1435   MakeFileUnwritable();
1436   RunClearAllDictionariesFailureTest(
1437       SQLitePersistentSharedDictionaryStore::Error::kFailedToSetTotalDictSize);
1438 }
1439 #endif  // !BUILDFLAG(IS_FUCHSIA)
1440 
RunClearDictionariesFailureTest(base::RepeatingCallback<bool (const GURL &)> url_matcher,SQLitePersistentSharedDictionaryStore::Error expected_error)1441 void SQLitePersistentSharedDictionaryStoreTest::RunClearDictionariesFailureTest(
1442     base::RepeatingCallback<bool(const GURL&)> url_matcher,
1443     SQLitePersistentSharedDictionaryStore::Error expected_error) {
1444   CreateStore();
1445   base::RunLoop run_loop;
1446   store_->ClearDictionaries(
1447       base::Time::Now() - base::Seconds(10), base::Time::Now(),
1448       std::move(url_matcher),
1449       base::BindLambdaForTesting(
1450           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1451                   result) {
1452             ASSERT_FALSE(result.has_value());
1453             EXPECT_EQ(expected_error, result.error());
1454             run_loop.Quit();
1455           }));
1456   run_loop.Run();
1457   DestroyStore();
1458 }
1459 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesErrorDatabaseInitializationFailure)1460 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1461        ClearDictionariesErrorDatabaseInitializationFailure) {
1462   CorruptDatabaseFile();
1463   RunClearDictionariesFailureTest(base::RepeatingCallback<bool(const GURL&)>(),
1464                                   SQLitePersistentSharedDictionaryStore::Error::
1465                                       kFailedToInitializeDatabase);
1466   CheckStoreRecovered();
1467 }
1468 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesErrorInvalidSql)1469 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1470        ClearDictionariesErrorInvalidSql) {
1471   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1472   RunClearDictionariesFailureTest(
1473       base::RepeatingCallback<bool(const GURL&)>(),
1474       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1475 }
1476 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesWithUrlMatcherErrorInvalidSql)1477 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1478        ClearDictionariesWithUrlMatcherErrorInvalidSql) {
1479   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1480   RunClearDictionariesFailureTest(
1481       base::BindRepeating([](const GURL&) { return true; }),
1482       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1483 }
1484 
1485 #if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
1486 // MakeFileUnwritable() doesn't cause the failure on Fuchsia and Windows. So
1487 // disabling the test on Fuchsia and Windows.
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesErrorSqlExecutionFailure)1488 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1489        ClearDictionariesErrorSqlExecutionFailure) {
1490   CreateStore();
1491   RegisterDictionary(isolation_key_, dictionary_info_);
1492   DestroyStore();
1493   MakeFileUnwritable();
1494   RunClearDictionariesFailureTest(
1495       base::RepeatingCallback<bool(const GURL&)>(),
1496       SQLitePersistentSharedDictionaryStore::Error::kFailedToExecuteSql);
1497 }
1498 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesWithUrlMatcherErrorSqlExecutionFailure)1499 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1500        ClearDictionariesWithUrlMatcherErrorSqlExecutionFailure) {
1501   CreateStore();
1502   RegisterDictionary(isolation_key_, dictionary_info_);
1503   DestroyStore();
1504   MakeFileUnwritable();
1505   RunClearDictionariesFailureTest(
1506       base::BindRepeating([](const GURL&) { return true; }),
1507       SQLitePersistentSharedDictionaryStore::Error::kFailedToExecuteSql);
1508 }
1509 #endif  // !BUILDFLAG(IS_FUCHSIA)
1510 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesErrorFailedToGetTotalDictSize)1511 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1512        ClearDictionariesErrorFailedToGetTotalDictSize) {
1513   CreateStore();
1514   RegisterDictionary(isolation_key_, dictionary_info_);
1515   DestroyStore();
1516   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
1517 
1518   RunClearDictionariesFailureTest(
1519       base::RepeatingCallback<bool(const GURL&)>(),
1520       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
1521 
1522   CreateStore();
1523   // ClearAllDictionaries() resets total_dict_size in metadata.
1524   EXPECT_THAT(
1525       ClearAllDictionaries(),
1526       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
1527   // So ClearDictionaries() should succeed.
1528   EXPECT_TRUE(ClearDictionaries(base::Time::Now() - base::Seconds(10),
1529                                 base::Time::Now(),
1530                                 base::RepeatingCallback<bool(const GURL&)>())
1531                   .empty());
1532 }
1533 
1534 void SQLitePersistentSharedDictionaryStoreTest::
RunClearDictionariesForIsolationKeyFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1535     RunClearDictionariesForIsolationKeyFailureTest(
1536         SQLitePersistentSharedDictionaryStore::Error expected_error) {
1537   CreateStore();
1538   base::RunLoop run_loop;
1539   store_->ClearDictionariesForIsolationKey(
1540       isolation_key_,
1541       base::BindLambdaForTesting(
1542           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1543                   result) {
1544             ASSERT_FALSE(result.has_value());
1545             EXPECT_EQ(expected_error, result.error());
1546             run_loop.Quit();
1547           }));
1548   run_loop.Run();
1549   DestroyStore();
1550 }
1551 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolationKeyErrorDatabaseInitializationFailure)1552 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1553        ClearDictionariesForIsolationKeyErrorDatabaseInitializationFailure) {
1554   CorruptDatabaseFile();
1555   RunClearDictionariesForIsolationKeyFailureTest(
1556       SQLitePersistentSharedDictionaryStore::Error::
1557           kFailedToInitializeDatabase);
1558   CheckStoreRecovered();
1559 }
1560 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolationKeyErrorInvalidSql)1561 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1562        ClearDictionariesForIsolationKeyErrorInvalidSql) {
1563   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1564   RunClearDictionariesForIsolationKeyFailureTest(
1565       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1566 }
1567 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolationKeyErrorFailedToGetTotalDictSize)1568 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1569        ClearDictionariesForIsolationKeyErrorFailedToGetTotalDictSize) {
1570   CreateStore();
1571   RegisterDictionary(isolation_key_, dictionary_info_);
1572   DestroyStore();
1573   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
1574 
1575   RunClearDictionariesForIsolationKeyFailureTest(
1576       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
1577 
1578   CreateStore();
1579   // ClearAllDictionaries() resets total_dict_size in metadata.
1580   EXPECT_THAT(
1581       ClearAllDictionaries(),
1582       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
1583   // So ClearDictionariesForIsolationKey() should succeed.
1584   EXPECT_TRUE(ClearDictionariesForIsolationKey(isolation_key_).empty());
1585 }
1586 
1587 void SQLitePersistentSharedDictionaryStoreTest::
RunDeleteExpiredDictionariesFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1588     RunDeleteExpiredDictionariesFailureTest(
1589         SQLitePersistentSharedDictionaryStore::Error expected_error) {
1590   CreateStore();
1591   base::RunLoop run_loop;
1592   store_->DeleteExpiredDictionaries(
1593       base::Time::Now(),
1594       base::BindLambdaForTesting(
1595           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1596                   result) {
1597             ASSERT_FALSE(result.has_value());
1598             EXPECT_EQ(expected_error, result.error());
1599             run_loop.Quit();
1600           }));
1601   run_loop.Run();
1602   DestroyStore();
1603 }
1604 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteExpiredDictionariesErrorDatabaseInitializationFailure)1605 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1606        DeleteExpiredDictionariesErrorDatabaseInitializationFailure) {
1607   CorruptDatabaseFile();
1608   RunDeleteExpiredDictionariesFailureTest(
1609       SQLitePersistentSharedDictionaryStore::Error::
1610           kFailedToInitializeDatabase);
1611   CheckStoreRecovered();
1612 }
1613 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteExpiredDictionariesErrorInvalidSql)1614 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1615        DeleteExpiredDictionariesErrorInvalidSql) {
1616   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1617   RunDeleteExpiredDictionariesFailureTest(
1618       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1619 }
1620 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteExpiredDictionariesErrorFailedToGetTotalDictSize)1621 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1622        DeleteExpiredDictionariesErrorFailedToGetTotalDictSize) {
1623   CreateStore();
1624   RegisterDictionary(isolation_key_, dictionary_info_);
1625   DestroyStore();
1626   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
1627 
1628   // Move the clock forward by 90 seconds to make `dictionary_info_` expired.
1629   FastForwardBy(base::Seconds(90));
1630 
1631   RunDeleteExpiredDictionariesFailureTest(
1632       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
1633 
1634   CreateStore();
1635   // ClearAllDictionaries() resets total_dict_size in metadata.
1636   EXPECT_THAT(
1637       ClearAllDictionaries(),
1638       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
1639   // So DeleteExpiredDictionaries() should succeed.
1640   EXPECT_TRUE(DeleteExpiredDictionaries(base::Time::Now()).empty());
1641 }
1642 
RunProcessEvictionFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1643 void SQLitePersistentSharedDictionaryStoreTest::RunProcessEvictionFailureTest(
1644     SQLitePersistentSharedDictionaryStore::Error expected_error) {
1645   CreateStore();
1646   base::RunLoop run_loop;
1647   store_->ProcessEviction(
1648       /*cache_max_size=*/1, /*size_low_watermark=*/1,
1649       /*cache_max_count=*/1, /*count_low_watermark=*/1,
1650       base::BindLambdaForTesting(
1651           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1652                   result) {
1653             ASSERT_FALSE(result.has_value());
1654             EXPECT_EQ(expected_error, result.error());
1655             run_loop.Quit();
1656           }));
1657   run_loop.Run();
1658   DestroyStore();
1659 }
1660 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionErrorDatabaseInitializationFailure)1661 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1662        ProcessEvictionErrorDatabaseInitializationFailure) {
1663   CorruptDatabaseFile();
1664   RunProcessEvictionFailureTest(SQLitePersistentSharedDictionaryStore::Error::
1665                                     kFailedToInitializeDatabase);
1666   CheckStoreRecovered();
1667 }
1668 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionErrorInvalidSql)1669 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1670        ProcessEvictionErrorInvalidSql) {
1671   CreateStore();
1672   RegisterDictionary(isolation_key_, dictionary_info_);
1673   DestroyStore();
1674   // Delete the existing `dictionaries` table, and create a broken
1675   // `dictionaries` table.
1676   ManipulateDatabase({"DROP TABLE dictionaries",
1677                       "CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1678   RunProcessEvictionFailureTest(
1679       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1680 }
1681 
1682 #if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN)
1683 // MakeFileUnwritable() doesn't cause the failure on Fuchsia and Windows. So
1684 // disabling the test on Fuchsia and Windows.
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionErrorSqlExecutionFailure)1685 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1686        ProcessEvictionErrorSqlExecutionFailure) {
1687   CreateStore();
1688   RegisterDictionary(isolation_key_, dictionary_info_);
1689   DestroyStore();
1690   MakeFileUnwritable();
1691 
1692   RunProcessEvictionFailureTest(
1693       SQLitePersistentSharedDictionaryStore::Error::kFailedToExecuteSql);
1694 }
1695 #endif  // !BUILDFLAG(IS_FUCHSIA)
1696 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionErrorFailedToGetTotalDictSize)1697 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1698        ProcessEvictionErrorFailedToGetTotalDictSize) {
1699   CreateStore();
1700   RegisterDictionary(isolation_key_, dictionary_info_);
1701   DestroyStore();
1702   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
1703 
1704   RunProcessEvictionFailureTest(
1705       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize);
1706 
1707   CreateStore();
1708   // ClearAllDictionaries() resets total_dict_size in metadata.
1709   EXPECT_THAT(
1710       ClearAllDictionaries(),
1711       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
1712   // So ProcessEviction() should succeed.
1713   EXPECT_TRUE(ProcessEviction(
1714                   /*cache_max_size=*/1, /*size_low_watermark=*/1,
1715                   /*cache_max_count=*/1, /*count_low_watermark=*/1)
1716                   .empty());
1717 }
1718 
1719 void SQLitePersistentSharedDictionaryStoreTest::
RunGetAllDiskCacheKeyTokensFailureTest(SQLitePersistentSharedDictionaryStore::Error expected_error)1720     RunGetAllDiskCacheKeyTokensFailureTest(
1721         SQLitePersistentSharedDictionaryStore::Error expected_error) {
1722   CreateStore();
1723   base::RunLoop run_loop;
1724   store_->GetAllDiskCacheKeyTokens(base::BindLambdaForTesting(
1725       [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1726               result) {
1727         ASSERT_FALSE(result.has_value());
1728         EXPECT_EQ(expected_error, result.error());
1729         run_loop.Quit();
1730       }));
1731   run_loop.Run();
1732   DestroyStore();
1733 }
1734 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDiskCacheKeyTokensErrorDatabaseInitializationFailure)1735 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1736        GetAllDiskCacheKeyTokensErrorDatabaseInitializationFailure) {
1737   CorruptDatabaseFile();
1738   RunGetAllDiskCacheKeyTokensFailureTest(
1739       SQLitePersistentSharedDictionaryStore::Error::
1740           kFailedToInitializeDatabase);
1741   CheckStoreRecovered();
1742 }
1743 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDiskCacheKeyTokensErrorInvalidSql)1744 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1745        GetAllDiskCacheKeyTokensErrorInvalidSql) {
1746   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1747   RunGetAllDiskCacheKeyTokensFailureTest(
1748       SQLitePersistentSharedDictionaryStore::Error::kInvalidSql);
1749 }
1750 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteDictionariesByDiskCacheKeyTokensErrorDatabaseInitializationFailure)1751 TEST_F(
1752     SQLitePersistentSharedDictionaryStoreTest,
1753     DeleteDictionariesByDiskCacheKeyTokensErrorDatabaseInitializationFailure) {
1754   CorruptDatabaseFile();
1755   CreateStore();
1756   EXPECT_EQ(
1757       SQLitePersistentSharedDictionaryStore::Error::kFailedToInitializeDatabase,
1758       DeleteDictionariesByDiskCacheKeyTokens(
1759           {dictionary_info_.disk_cache_key_token()}));
1760   DestroyStore();
1761   CheckStoreRecovered();
1762 }
1763 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteDictionariesByDiskCacheKeyTokensErrorInvalidSql)1764 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1765        DeleteDictionariesByDiskCacheKeyTokensErrorInvalidSql) {
1766   ManipulateDatabase({"CREATE TABLE dictionaries (dummy TEST NOT NULL)"});
1767   CreateStore();
1768   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kInvalidSql,
1769             DeleteDictionariesByDiskCacheKeyTokens(
1770                 {dictionary_info_.disk_cache_key_token()}));
1771 }
1772 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteDictionariesByDiskCacheKeyTokensErrorFailedToGetTotalDictSize)1773 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1774        DeleteDictionariesByDiskCacheKeyTokensErrorFailedToGetTotalDictSize) {
1775   CreateStore();
1776   RegisterDictionary(isolation_key_, dictionary_info_);
1777   DestroyStore();
1778   ManipulateDatabase({"DELETE FROM meta WHERE key='total_dict_size'"});
1779   CreateStore();
1780   EXPECT_EQ(
1781       SQLitePersistentSharedDictionaryStore::Error::kFailedToGetTotalDictSize,
1782       DeleteDictionariesByDiskCacheKeyTokens(
1783           {dictionary_info_.disk_cache_key_token()}));
1784 
1785   // ClearAllDictionaries() resets total_dict_size in metadata.
1786   EXPECT_THAT(
1787       ClearAllDictionaries(),
1788       UnorderedElementsAreArray({dictionary_info_.disk_cache_key_token()}));
1789   // So DeleteDictionariesByDiskCacheKeyTokens() should succeed.
1790   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
1791             DeleteDictionariesByDiskCacheKeyTokens(
1792                 {base::UnguessableToken::Create()}));
1793 }
1794 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,InvalidHash)1795 TEST_F(SQLitePersistentSharedDictionaryStoreTest, InvalidHash) {
1796   CreateStore();
1797   auto register_dictionary_result =
1798       RegisterDictionary(isolation_key_, dictionary_info_);
1799   SharedDictionaryInfo expected_info = dictionary_info_;
1800   expected_info.set_primary_key_in_database(
1801       register_dictionary_result.primary_key_in_database());
1802   EXPECT_THAT(GetDictionaries(isolation_key_),
1803               ElementsAreArray({expected_info}));
1804   DestroyStore();
1805 
1806   ManipulateDatabase({"UPDATE dictionaries set sha256='DUMMY'"});
1807 
1808   CreateStore();
1809   EXPECT_TRUE(GetDictionaries(isolation_key_).empty());
1810   EXPECT_TRUE(GetAllDictionaries().empty());
1811 }
1812 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,InvalidToken)1813 TEST_F(SQLitePersistentSharedDictionaryStoreTest, InvalidToken) {
1814   CreateStore();
1815   auto register_dictionary_result =
1816       RegisterDictionary(isolation_key_, dictionary_info_);
1817   SharedDictionaryInfo expected_info = dictionary_info_;
1818   expected_info.set_primary_key_in_database(
1819       register_dictionary_result.primary_key_in_database());
1820   EXPECT_THAT(GetDictionaries(isolation_key_),
1821               ElementsAreArray({expected_info}));
1822   DestroyStore();
1823 
1824   // {token_low=0, token_high=0} token is treated as invalid.
1825   ManipulateDatabase({"UPDATE dictionaries set token_low=0, token_high=0"});
1826 
1827   CreateStore();
1828   EXPECT_TRUE(GetDictionaries(isolation_key_).empty());
1829   EXPECT_TRUE(GetAllDictionaries().empty());
1830 }
1831 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetTotalDictionarySizeCallbackNotCalledAfterStoreDeleted)1832 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1833        GetTotalDictionarySizeCallbackNotCalledAfterStoreDeleted) {
1834   CreateStore();
1835   store_->GetTotalDictionarySize(base::BindLambdaForTesting(
1836       [](base::expected<uint64_t,
1837                         SQLitePersistentSharedDictionaryStore::Error>) {
1838         EXPECT_TRUE(false) << "Should not be reached.";
1839       }));
1840   store_.reset();
1841   RunUntilIdle();
1842 }
1843 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,RegisterDictionaryCallbackNotCalledAfterStoreDeleted)1844 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1845        RegisterDictionaryCallbackNotCalledAfterStoreDeleted) {
1846   CreateStore();
1847   store_->RegisterDictionary(
1848       isolation_key_, dictionary_info_,
1849       /*max_size_per_site=*/1000000,
1850       /*max_count_per_site=*/1000,
1851       base::BindLambdaForTesting(
1852           [](SQLitePersistentSharedDictionaryStore::
1853                  RegisterDictionaryResultOrError result) {
1854             EXPECT_TRUE(false) << "Should not be reached.";
1855           }));
1856   store_.reset();
1857   RunUntilIdle();
1858 }
1859 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetDictionariesCallbackNotCalledAfterStoreDeleted)1860 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1861        GetDictionariesCallbackNotCalledAfterStoreDeleted) {
1862   CreateStore();
1863   store_->GetDictionaries(
1864       isolation_key_,
1865       base::BindLambdaForTesting(
1866           [](SQLitePersistentSharedDictionaryStore::DictionaryListOrError) {
1867             EXPECT_TRUE(false) << "Should not be reached.";
1868           }));
1869   store_.reset();
1870   RunUntilIdle();
1871 }
1872 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDictionariesCallbackNotCalledAfterStoreDeleted)1873 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1874        GetAllDictionariesCallbackNotCalledAfterStoreDeleted) {
1875   CreateStore();
1876   store_->GetAllDictionaries(base::BindLambdaForTesting(
1877       [](SQLitePersistentSharedDictionaryStore::DictionaryMapOrError result) {
1878         EXPECT_TRUE(false) << "Should not be reached.";
1879       }));
1880   store_.reset();
1881   RunUntilIdle();
1882 }
1883 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearAllDictionariesCallbackNotCalledAfterStoreDeleted)1884 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1885        ClearAllDictionariesCallbackNotCalledAfterStoreDeleted) {
1886   CreateStore();
1887   store_->ClearAllDictionaries(base::BindLambdaForTesting(
1888       [](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1889              result) { EXPECT_TRUE(false) << "Should not be reached."; }));
1890   store_.reset();
1891   RunUntilIdle();
1892 }
1893 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesCallbackNotCalledAfterStoreDeleted)1894 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1895        ClearDictionariesCallbackNotCalledAfterStoreDeleted) {
1896   CreateStore();
1897   store_->ClearDictionaries(
1898       base::Time::Now() - base::Seconds(1), base::Time::Now(),
1899       base::RepeatingCallback<bool(const GURL&)>(),
1900       base::BindLambdaForTesting(
1901           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1902                   result) { EXPECT_TRUE(false) << "Should not be reached."; }));
1903   store_.reset();
1904   RunUntilIdle();
1905 }
1906 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteExpiredDictionariesCallbackNotCalledAfterStoreDeleted)1907 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1908        DeleteExpiredDictionariesCallbackNotCalledAfterStoreDeleted) {
1909   CreateStore();
1910   store_->DeleteExpiredDictionaries(
1911       base::Time::Now(),
1912       base::BindLambdaForTesting(
1913           [&](SQLitePersistentSharedDictionaryStore::UnguessableTokenSetOrError
1914                   result) { EXPECT_TRUE(false) << "Should not be reached."; }));
1915   store_.reset();
1916   RunUntilIdle();
1917 }
1918 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionaries)1919 TEST_F(SQLitePersistentSharedDictionaryStoreTest, ClearDictionaries) {
1920   CreateStore();
1921 
1922   auto token1 = base::UnguessableToken::Create();
1923   SharedDictionaryInfo dict1 = SharedDictionaryInfo(
1924       GURL("https://a.example/dict"),
1925       /*response_time=*/base::Time::Now() - base::Seconds(4),
1926       /*expiration*/ base::Seconds(100), "/pattern*",
1927       /*last_used_time*/ base::Time::Now(),
1928       /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
1929       /*disk_cache_key_token=*/token1,
1930       /*primary_key_in_database=*/absl::nullopt);
1931   auto result1 = RegisterDictionary(isolation_key_, dict1);
1932   dict1.set_primary_key_in_database(result1.primary_key_in_database());
1933 
1934   auto token2 = base::UnguessableToken::Create();
1935   SharedDictionaryInfo dict2 = SharedDictionaryInfo(
1936       GURL("https://b.example/dict"),
1937       /*response_time=*/base::Time::Now() - base::Seconds(3),
1938       /*expiration*/ base::Seconds(100), "/pattern*",
1939       /*last_used_time*/ base::Time::Now(),
1940       /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
1941       /*disk_cache_key_token=*/token2,
1942       /*primary_key_in_database=*/absl::nullopt);
1943   auto result2 = RegisterDictionary(isolation_key_, dict2);
1944   dict2.set_primary_key_in_database(result2.primary_key_in_database());
1945 
1946   auto token3 = base::UnguessableToken::Create();
1947   SharedDictionaryInfo dict3 = SharedDictionaryInfo(
1948       GURL("https://c.example/dict"),
1949       /*response_time=*/base::Time::Now() - base::Seconds(2),
1950       /*expiration*/ base::Seconds(100), "/pattern*",
1951       /*last_used_time*/ base::Time::Now(),
1952       /*size=*/5000, SHA256HashValue({{0x00, 0x03}}),
1953       /*disk_cache_key_token=*/token3,
1954       /*primary_key_in_database=*/absl::nullopt);
1955   auto result3 = RegisterDictionary(isolation_key_, dict3);
1956   dict3.set_primary_key_in_database(result3.primary_key_in_database());
1957 
1958   auto token4 = base::UnguessableToken::Create();
1959   SharedDictionaryInfo dict4 = SharedDictionaryInfo(
1960       GURL("https://d.example/dict"),
1961       /*response_time=*/base::Time::Now() - base::Seconds(1),
1962       /*expiration*/ base::Seconds(100), "/pattern*",
1963       /*last_used_time*/ base::Time::Now(),
1964       /*size=*/7000, SHA256HashValue({{0x00, 0x04}}),
1965       /*disk_cache_key_token=*/token4,
1966       /*primary_key_in_database=*/absl::nullopt);
1967   auto result4 = RegisterDictionary(isolation_key_, dict4);
1968   dict4.set_primary_key_in_database(result4.primary_key_in_database());
1969 
1970   // No matching dictionaries to be deleted.
1971   EXPECT_TRUE(ClearDictionaries(base::Time::Now() - base::Seconds(200),
1972                                 base::Time::Now() - base::Seconds(4),
1973                                 base::RepeatingCallback<bool(const GURL&)>())
1974                   .empty());
1975 
1976   std::set<base::UnguessableToken> tokens =
1977       ClearDictionaries(base::Time::Now() - base::Seconds(3),
1978                         base::Time::Now() - base::Seconds(1),
1979                         base::RepeatingCallback<bool(const GURL&)>());
1980   // The dict2 which res_time is "now - 3 sec" and the dict3
1981   // which res_time is "now - 2 sec" must be deleted.
1982   EXPECT_THAT(tokens, UnorderedElementsAreArray({token2, token3}));
1983 
1984   // Check the remaining dictionaries.
1985   EXPECT_THAT(GetAllDictionaries(),
1986               ElementsAre(Pair(isolation_key_,
1987                                UnorderedElementsAreArray({dict1, dict4}))));
1988   // Check the total size of remaining dictionaries.
1989   EXPECT_EQ(dict1.size() + dict4.size(), GetTotalDictionarySize());
1990 }
1991 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesWithUrlMatcher)1992 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
1993        ClearDictionariesWithUrlMatcher) {
1994   CreateStore();
1995 
1996   auto isolation_key1 =
1997       CreateIsolationKey("https://a1.example/", "https://a2.example/");
1998   auto token1 = base::UnguessableToken::Create();
1999   SharedDictionaryInfo dict1 = SharedDictionaryInfo(
2000       GURL("https://a3.example/dict"),
2001       /*response_time=*/base::Time::Now() - base::Seconds(4),
2002       /*expiration*/ base::Seconds(100), "/pattern*",
2003       /*last_used_time*/ base::Time::Now(),
2004       /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2005       /*disk_cache_key_token=*/token1,
2006       /*primary_key_in_database=*/absl::nullopt);
2007   auto result1 = RegisterDictionary(isolation_key1, dict1);
2008   dict1.set_primary_key_in_database(result1.primary_key_in_database());
2009 
2010   auto isolation_key2 =
2011       CreateIsolationKey("https://b1.example/", "https://b2.example/");
2012   auto token2 = base::UnguessableToken::Create();
2013   SharedDictionaryInfo dict2 = SharedDictionaryInfo(
2014       GURL("https://b3.example/dict"),
2015       /*response_time=*/base::Time::Now() - base::Seconds(3),
2016       /*expiration*/ base::Seconds(100), "/pattern*",
2017       /*last_used_time*/ base::Time::Now(),
2018       /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
2019       /*disk_cache_key_token=*/token2,
2020       /*primary_key_in_database=*/absl::nullopt);
2021   auto result2 = RegisterDictionary(isolation_key2, dict2);
2022   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2023 
2024   auto isolation_key3 =
2025       CreateIsolationKey("https://c1.example/", "https://c2.example/");
2026   auto token3 = base::UnguessableToken::Create();
2027   SharedDictionaryInfo dict3 = SharedDictionaryInfo(
2028       GURL("https://c3.example/dict"),
2029       /*response_time=*/base::Time::Now() - base::Seconds(2),
2030       /*expiration*/ base::Seconds(100), "/pattern*",
2031       /*last_used_time*/ base::Time::Now(),
2032       /*size=*/5000, SHA256HashValue({{0x00, 0x03}}),
2033       /*disk_cache_key_token=*/token3,
2034       /*primary_key_in_database=*/absl::nullopt);
2035   auto result3 = RegisterDictionary(isolation_key3, dict3);
2036   dict3.set_primary_key_in_database(result3.primary_key_in_database());
2037 
2038   auto isolation_key4 =
2039       CreateIsolationKey("https://d1.example/", "https://d2.example/");
2040   auto token4 = base::UnguessableToken::Create();
2041   SharedDictionaryInfo dict4 = SharedDictionaryInfo(
2042       GURL("https://d3.example/dict"),
2043       /*response_time=*/base::Time::Now() - base::Seconds(1),
2044       /*expiration*/ base::Seconds(100), "/pattern*",
2045       /*last_used_time*/ base::Time::Now(),
2046       /*size=*/7000, SHA256HashValue({{0x00, 0x04}}),
2047       /*disk_cache_key_token=*/token4,
2048       /*primary_key_in_database=*/absl::nullopt);
2049   auto result4 = RegisterDictionary(isolation_key4, dict4);
2050   dict4.set_primary_key_in_database(result4.primary_key_in_database());
2051 
2052   // No matching dictionaries to be deleted.
2053   EXPECT_TRUE(ClearDictionaries(base::Time::Now() - base::Seconds(200),
2054                                 base::Time::Now() - base::Seconds(4),
2055                                 base::BindRepeating([](const GURL&) {
2056                                   EXPECT_TRUE(false)
2057                                       << "Should not be reached.";
2058                                   return true;
2059                                 }))
2060                   .empty());
2061   std::set<GURL> checked_urls;
2062   EXPECT_TRUE(
2063       ClearDictionaries(base::Time::Now() - base::Seconds(3),
2064                         base::Time::Now() - base::Seconds(1),
2065                         base::BindLambdaForTesting([&](const GURL& url) {
2066                           checked_urls.insert(url);
2067                           return false;
2068                         }))
2069           .empty());
2070   // The dict2 which last_used_time is "now - 3 sec" and the dict3
2071   // which last_used_time is "now - 2 sec" must be selected and the macher is
2072   // called with those dictionaries frame_origin, top_frame_site and host.
2073   EXPECT_THAT(checked_urls,
2074               UnorderedElementsAreArray(
2075                   {GURL("https://b1.example/"), GURL("https://b2.example/"),
2076                    GURL("https://b3.example/"), GURL("https://c1.example/"),
2077                    GURL("https://c2.example/"), GURL("https://c3.example/")}));
2078 
2079   // Deletes dict3.
2080   std::set<base::UnguessableToken> tokens =
2081       ClearDictionaries(base::Time::Now() - base::Seconds(3),
2082                         base::Time::Now() - base::Seconds(1),
2083                         base::BindRepeating([](const GURL& url) {
2084                           return url == GURL("https://c3.example/");
2085                         }));
2086   EXPECT_THAT(tokens, ElementsAreArray({token3}));
2087 
2088   // Check the remaining dictionaries.
2089   EXPECT_THAT(GetAllDictionaries(),
2090               ElementsAre(Pair(isolation_key1, ElementsAreArray({dict1})),
2091                           Pair(isolation_key2, ElementsAreArray({dict2})),
2092                           Pair(isolation_key4, ElementsAreArray({dict4}))));
2093   // Check the total size of remaining dictionaries.
2094   EXPECT_EQ(dict1.size() + dict2.size() + dict4.size(),
2095             GetTotalDictionarySize());
2096 }
2097 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolationKeyEmptyStore)2098 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2099        ClearDictionariesForIsolationKeyEmptyStore) {
2100   CreateStore();
2101   EXPECT_TRUE(ClearDictionariesForIsolationKey(isolation_key_).empty());
2102 }
2103 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolation)2104 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2105        ClearDictionariesForIsolation) {
2106   CreateStore();
2107 
2108   auto isolation_key1 =
2109       CreateIsolationKey("https://a1.example/", "https://a2.example/");
2110   auto token1 = base::UnguessableToken::Create();
2111   SharedDictionaryInfo dict1 =
2112       SharedDictionaryInfo(GURL("https://a1.example/dict"),
2113                            /*response_time=*/base::Time::Now(),
2114                            /*expiration*/ base::Seconds(100), "/pattern*",
2115                            /*last_used_time*/ base::Time::Now(),
2116                            /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2117                            /*disk_cache_key_token=*/token1,
2118                            /*primary_key_in_database=*/absl::nullopt);
2119   auto result1 = RegisterDictionary(isolation_key1, dict1);
2120   dict1.set_primary_key_in_database(result1.primary_key_in_database());
2121 
2122   // Same frame origin, different top frame site.
2123   auto isolation_key2 =
2124       CreateIsolationKey("https://a1.example/", "https://a3.example/");
2125   auto token2 = base::UnguessableToken::Create();
2126   SharedDictionaryInfo dict2 =
2127       SharedDictionaryInfo(GURL("https://a2.example/dict"),
2128                            /*response_time=*/base::Time::Now(),
2129                            /*expiration*/ base::Seconds(100), "/pattern*",
2130                            /*last_used_time*/ base::Time::Now(),
2131                            /*size=*/2000, SHA256HashValue({{0x00, 0x02}}),
2132                            /*disk_cache_key_token=*/token2,
2133                            /*primary_key_in_database=*/absl::nullopt);
2134   auto result2 = RegisterDictionary(isolation_key2, dict2);
2135   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2136 
2137   // Different frame origin, same top frame site.
2138   auto isolation_key3 =
2139       CreateIsolationKey("https://a4.example/", "https://a2.example/");
2140   auto token3 = base::UnguessableToken::Create();
2141   SharedDictionaryInfo dict3 =
2142       SharedDictionaryInfo(GURL("https://a3.example/dict"),
2143                            /*response_time=*/base::Time::Now(),
2144                            /*expiration*/ base::Seconds(100), "/pattern*",
2145                            /*last_used_time*/ base::Time::Now(),
2146                            /*size=*/4000, SHA256HashValue({{0x00, 0x03}}),
2147                            /*disk_cache_key_token=*/token3,
2148                            /*primary_key_in_database=*/absl::nullopt);
2149   auto result3 = RegisterDictionary(isolation_key3, dict3);
2150   dict3.set_primary_key_in_database(result3.primary_key_in_database());
2151 
2152   // Different frame origin, different top frame site.
2153   auto isolation_key4 =
2154       CreateIsolationKey("https://a4.example/", "https://a5.example/");
2155   auto token4 = base::UnguessableToken::Create();
2156   SharedDictionaryInfo dict4 =
2157       SharedDictionaryInfo(GURL("https://a4.example/dict"),
2158                            /*response_time=*/base::Time::Now(),
2159                            /*expiration*/ base::Seconds(100), "/pattern*",
2160                            /*last_used_time*/ base::Time::Now(),
2161                            /*size=*/8000, SHA256HashValue({{0x00, 0x04}}),
2162                            /*disk_cache_key_token=*/token4,
2163                            /*primary_key_in_database=*/absl::nullopt);
2164   auto result4 = RegisterDictionary(isolation_key4, dict4);
2165   dict4.set_primary_key_in_database(result4.primary_key_in_database());
2166 
2167   // Deletes dictionaries for `isolation_key_`. The result should be empty.
2168   EXPECT_TRUE(ClearDictionariesForIsolationKey(isolation_key_).empty());
2169 
2170   // Deletes dictionaries for `isolation_key1`.
2171   EXPECT_THAT(ClearDictionariesForIsolationKey(isolation_key1),
2172               ElementsAreArray({token1}));
2173 
2174   // Check the remaining dictionaries.
2175   EXPECT_THAT(GetAllDictionaries(),
2176               ElementsAre(Pair(isolation_key2, ElementsAreArray({dict2})),
2177                           Pair(isolation_key3, ElementsAreArray({dict3})),
2178                           Pair(isolation_key4, ElementsAreArray({dict4}))));
2179   // Check the total size of remaining dictionaries.
2180   EXPECT_EQ(dict2.size() + dict3.size() + dict4.size(),
2181             GetTotalDictionarySize());
2182 }
2183 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ClearDictionariesForIsolationMultipleDictionaries)2184 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2185        ClearDictionariesForIsolationMultipleDictionaries) {
2186   CreateStore();
2187 
2188   auto isolation_key1 = CreateIsolationKey("https://a1.example/");
2189   auto token1_1 = base::UnguessableToken::Create();
2190   SharedDictionaryInfo dict1_1 =
2191       SharedDictionaryInfo(GURL("https://a1.example/dict1"),
2192                            /*response_time=*/base::Time::Now(),
2193                            /*expiration*/ base::Seconds(100), "/pattern1*",
2194                            /*last_used_time*/ base::Time::Now(),
2195                            /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2196                            /*disk_cache_key_token=*/token1_1,
2197                            /*primary_key_in_database=*/absl::nullopt);
2198   auto result1_1 = RegisterDictionary(isolation_key1, dict1_1);
2199   dict1_1.set_primary_key_in_database(result1_1.primary_key_in_database());
2200 
2201   auto token1_2 = base::UnguessableToken::Create();
2202   SharedDictionaryInfo dict1_2 =
2203       SharedDictionaryInfo(GURL("https://a1.example/dict1"),
2204                            /*response_time=*/base::Time::Now(),
2205                            /*expiration*/ base::Seconds(100), "/pattern2*",
2206                            /*last_used_time*/ base::Time::Now(),
2207                            /*size=*/2000, SHA256HashValue({{0x00, 0x02}}),
2208                            /*disk_cache_key_token=*/token1_2,
2209                            /*primary_key_in_database=*/absl::nullopt);
2210   auto result1_2 = RegisterDictionary(isolation_key1, dict1_2);
2211   dict1_2.set_primary_key_in_database(result1_2.primary_key_in_database());
2212 
2213   auto isolation_key2 = CreateIsolationKey("https://a2.example/");
2214   auto token2 = base::UnguessableToken::Create();
2215   SharedDictionaryInfo dict2 =
2216       SharedDictionaryInfo(GURL("https://a2.example/dict"),
2217                            /*response_time=*/base::Time::Now(),
2218                            /*expiration*/ base::Seconds(100), "/pattern*",
2219                            /*last_used_time*/ base::Time::Now(),
2220                            /*size=*/4000, SHA256HashValue({{0x00, 0x03}}),
2221                            /*disk_cache_key_token=*/token2,
2222                            /*primary_key_in_database=*/absl::nullopt);
2223   auto result2 = RegisterDictionary(isolation_key2, dict2);
2224   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2225 
2226   // Deletes dictionaries for `isolation_key1`.
2227   EXPECT_THAT(ClearDictionariesForIsolationKey(isolation_key1),
2228               UnorderedElementsAreArray({token1_1, token1_2}));
2229 
2230   // Check the remaining dictionaries.
2231   EXPECT_THAT(GetAllDictionaries(),
2232               ElementsAre(Pair(isolation_key2, ElementsAreArray({dict2}))));
2233   // Check the total size of remaining dictionaries.
2234   EXPECT_EQ(dict2.size(), GetTotalDictionarySize());
2235 }
2236 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteExpiredDictionaries)2237 TEST_F(SQLitePersistentSharedDictionaryStoreTest, DeleteExpiredDictionaries) {
2238   CreateStore();
2239 
2240   const base::Time now = base::Time::Now();
2241   auto token1 = base::UnguessableToken::Create();
2242   SharedDictionaryInfo dict1 =
2243       SharedDictionaryInfo(GURL("https://a.example/dict"),
2244                            /*response_time=*/now,
2245                            /*expiration*/ base::Seconds(100), "/pattern*",
2246                            /*last_used_time*/ now,
2247                            /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2248                            /*disk_cache_key_token=*/token1,
2249                            /*primary_key_in_database=*/absl::nullopt);
2250   auto result1 = RegisterDictionary(isolation_key_, dict1);
2251   dict1.set_primary_key_in_database(result1.primary_key_in_database());
2252 
2253   auto token2 = base::UnguessableToken::Create();
2254   SharedDictionaryInfo dict2 =
2255       SharedDictionaryInfo(GURL("https://b.example/dict"),
2256                            /*response_time=*/now + base::Seconds(1),
2257                            /*expiration*/ base::Seconds(99), "/pattern*",
2258                            /*last_used_time*/ now,
2259                            /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
2260                            /*disk_cache_key_token=*/token2,
2261                            /*primary_key_in_database=*/absl::nullopt);
2262   auto result2 = RegisterDictionary(isolation_key_, dict2);
2263   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2264 
2265   auto token3 = base::UnguessableToken::Create();
2266   SharedDictionaryInfo dict3 =
2267       SharedDictionaryInfo(GURL("https://c.example/dict"),
2268                            /*response_time=*/now + base::Seconds(1),
2269                            /*expiration*/ base::Seconds(100), "/pattern*",
2270                            /*last_used_time*/ now,
2271                            /*size=*/5000, SHA256HashValue({{0x00, 0x03}}),
2272                            /*disk_cache_key_token=*/token3,
2273                            /*primary_key_in_database=*/absl::nullopt);
2274   auto result3 = RegisterDictionary(isolation_key_, dict3);
2275   dict3.set_primary_key_in_database(result3.primary_key_in_database());
2276 
2277   auto token4 = base::UnguessableToken::Create();
2278   SharedDictionaryInfo dict4 =
2279       SharedDictionaryInfo(GURL("https://d.example/dict"),
2280                            /*response_time=*/now + base::Seconds(2),
2281                            /*expiration*/ base::Seconds(99), "/pattern*",
2282                            /*last_used_time*/ now,
2283                            /*size=*/7000, SHA256HashValue({{0x00, 0x04}}),
2284                            /*disk_cache_key_token=*/token4,
2285                            /*primary_key_in_database=*/absl::nullopt);
2286   auto result4 = RegisterDictionary(isolation_key_, dict4);
2287   dict4.set_primary_key_in_database(result4.primary_key_in_database());
2288 
2289   // No matching dictionaries to be deleted.
2290   EXPECT_TRUE(DeleteExpiredDictionaries(now + base::Seconds(99)).empty());
2291 
2292   std::set<base::UnguessableToken> tokens =
2293       DeleteExpiredDictionaries(now + base::Seconds(100));
2294   // The dict1 and dict2 must be deleted.
2295   EXPECT_THAT(tokens, UnorderedElementsAreArray({token1, token2}));
2296 
2297   // Check the remaining dictionaries.
2298   EXPECT_THAT(GetAllDictionaries(),
2299               ElementsAre(Pair(isolation_key_,
2300                                UnorderedElementsAreArray({dict3, dict4}))));
2301   // Check the total size of remaining dictionaries.
2302   EXPECT_EQ(dict3.size() + dict4.size(), GetTotalDictionarySize());
2303 }
2304 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionNotExceeded)2305 TEST_F(SQLitePersistentSharedDictionaryStoreTest, ProcessEvictionNotExceeded) {
2306   CreateStore();
2307   auto [dict1, dict2, dict3, dict4] =
2308       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2309                                                        isolation_key_);
2310   // The current status:
2311   //   dict1: size=1000 last_used_time=now
2312   //   dict3: size=5000 last_used_time=now+2
2313   //   dict4: size=7000 last_used_time=now+3
2314   //   dict2: size=3000 last_used_time=now+4
2315 
2316   // No matching dictionaries to be deleted.
2317   EXPECT_TRUE(ProcessEviction(16000, 15000, 10, 9).empty());
2318   // Check the remaining dictionaries.
2319   EXPECT_THAT(
2320       GetAllDictionaries(),
2321       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray(
2322                                            {dict1, dict2, dict3, dict4}))));
2323   // Check the total size of remaining dictionaries.
2324   EXPECT_EQ(dict1.size() + dict2.size() + dict3.size() + dict4.size(),
2325             GetTotalDictionarySize());
2326 }
2327 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionSizeExceeded)2328 TEST_F(SQLitePersistentSharedDictionaryStoreTest, ProcessEvictionSizeExceeded) {
2329   CreateStore();
2330   auto [dict1, dict2, dict3, dict4] =
2331       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2332                                                        isolation_key_);
2333   // The current status:
2334   //   dict1: size=1000 last_used_time=now
2335   //   dict3: size=5000 last_used_time=now+2
2336   //   dict4: size=7000 last_used_time=now+3
2337   //   dict2: size=3000 last_used_time=now+4
2338 
2339   std::set<base::UnguessableToken> tokens =
2340       ProcessEviction(15000, 10000, 10, 9);
2341   // The dict1 and dict3 must be deleted.
2342   EXPECT_THAT(tokens,
2343               UnorderedElementsAreArray({dict1.disk_cache_key_token(),
2344                                          dict3.disk_cache_key_token()}));
2345   // Check the remaining dictionaries.
2346   EXPECT_THAT(GetAllDictionaries(),
2347               ElementsAre(Pair(isolation_key_,
2348                                UnorderedElementsAreArray({dict4, dict2}))));
2349   // Check the total size of remaining dictionaries.
2350   EXPECT_EQ(dict4.size() + dict2.size(), GetTotalDictionarySize());
2351 }
2352 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionSizeExceededEvictiedUntilCountLowWatermark)2353 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2354        ProcessEvictionSizeExceededEvictiedUntilCountLowWatermark) {
2355   CreateStore();
2356   auto [dict1, dict2, dict3, dict4] =
2357       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2358                                                        isolation_key_);
2359   // The current status:
2360   //   dict1: size=1000 last_used_time=now
2361   //   dict3: size=5000 last_used_time=now+2
2362   //   dict4: size=7000 last_used_time=now+3
2363   //   dict2: size=3000 last_used_time=now+4
2364 
2365   std::set<base::UnguessableToken> tokens =
2366       ProcessEviction(15000, 10000, 10, 1);
2367   // The dict1 and dict3 and dict4 must be deleted.
2368   EXPECT_THAT(tokens,
2369               UnorderedElementsAreArray({dict1.disk_cache_key_token(),
2370                                          dict3.disk_cache_key_token(),
2371                                          dict4.disk_cache_key_token()}));
2372   // Check the remaining dictionaries.
2373   EXPECT_THAT(
2374       GetAllDictionaries(),
2375       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray({dict2}))));
2376   // Check the total size of remaining dictionaries.
2377   EXPECT_EQ(dict2.size(), GetTotalDictionarySize());
2378 }
2379 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionCountExceeded)2380 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2381        ProcessEvictionCountExceeded) {
2382   CreateStore();
2383 
2384   auto [dict1, dict2, dict3, dict4] =
2385       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2386                                                        isolation_key_);
2387   // The current status:
2388   //   dict1: size=1000 last_used_time=now
2389   //   dict3: size=5000 last_used_time=now+2
2390   //   dict4: size=7000 last_used_time=now+3
2391   //   dict2: size=3000 last_used_time=now+4
2392 
2393   std::set<base::UnguessableToken> tokens = ProcessEviction(20000, 20000, 3, 2);
2394   // The dict1 and dict3 must be deleted.
2395   EXPECT_THAT(tokens,
2396               UnorderedElementsAreArray({dict1.disk_cache_key_token(),
2397                                          dict3.disk_cache_key_token()}));
2398   // Check the remaining dictionaries.
2399   EXPECT_THAT(GetAllDictionaries(),
2400               ElementsAre(Pair(isolation_key_,
2401                                UnorderedElementsAreArray({dict4, dict2}))));
2402   // Check the total size of remaining dictionaries.
2403   EXPECT_EQ(dict4.size() + dict2.size(), GetTotalDictionarySize());
2404 }
2405 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionCountExceededEvictedUntilSizeLowWaterMark)2406 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2407        ProcessEvictionCountExceededEvictedUntilSizeLowWaterMark) {
2408   CreateStore();
2409 
2410   auto [dict1, dict2, dict3, dict4] =
2411       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2412                                                        isolation_key_);
2413   // The current status:
2414   //   dict1: size=1000 last_used_time=now
2415   //   dict3: size=5000 last_used_time=now+2
2416   //   dict4: size=7000 last_used_time=now+3
2417   //   dict2: size=3000 last_used_time=now+4
2418 
2419   std::set<base::UnguessableToken> tokens = ProcessEviction(20000, 3000, 3, 2);
2420   // The dict1 and dict3 and dict4 must be deleted.
2421   EXPECT_THAT(tokens,
2422               UnorderedElementsAreArray({dict1.disk_cache_key_token(),
2423                                          dict3.disk_cache_key_token(),
2424                                          dict4.disk_cache_key_token()}));
2425   // Check the remaining dictionaries.
2426   EXPECT_THAT(
2427       GetAllDictionaries(),
2428       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray({dict2}))));
2429   // Check the total size of remaining dictionaries.
2430   EXPECT_EQ(dict2.size(), GetTotalDictionarySize());
2431 }
2432 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionZeroMaxSize)2433 TEST_F(SQLitePersistentSharedDictionaryStoreTest, ProcessEvictionZeroMaxSize) {
2434   CreateStore();
2435 
2436   auto [dict1, dict2, dict3, dict4] =
2437       RegisterSharedDictionariesForProcessEvictionTest(store_.get(),
2438                                                        isolation_key_);
2439   // The current status:
2440   //   dict1: size=1000 last_used_time=now
2441   //   dict3: size=5000 last_used_time=now+2
2442   //   dict4: size=7000 last_used_time=now+3
2443   //   dict2: size=3000 last_used_time=now+4
2444 
2445   EXPECT_TRUE(ProcessEviction(0, 0, 4, 2).empty());
2446 
2447   std::set<base::UnguessableToken> tokens = ProcessEviction(0, 0, 3, 2);
2448   // The dict1 and dict3 and dict4 must be deleted.
2449   EXPECT_THAT(tokens,
2450               UnorderedElementsAreArray({dict1.disk_cache_key_token(),
2451                                          dict3.disk_cache_key_token()}));
2452   // Check the remaining dictionaries.
2453   EXPECT_THAT(GetAllDictionaries(),
2454               ElementsAre(Pair(isolation_key_,
2455                                UnorderedElementsAreArray({dict2, dict4}))));
2456   // Check the total size of remaining dictionaries.
2457   EXPECT_EQ(dict2.size() + dict4.size(), GetTotalDictionarySize());
2458 }
2459 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,ProcessEvictionDeletesAll)2460 TEST_F(SQLitePersistentSharedDictionaryStoreTest, ProcessEvictionDeletesAll) {
2461   CreateStore();
2462 
2463   const base::Time now = base::Time::Now();
2464   auto token1 = base::UnguessableToken::Create();
2465   SharedDictionaryInfo dict1 =
2466       SharedDictionaryInfo(GURL("https://a.example/dict"),
2467                            /*response_time=*/now,
2468                            /*expiration*/ base::Seconds(100), "/pattern*",
2469                            /*last_used_time*/ now,
2470                            /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2471                            /*disk_cache_key_token=*/token1,
2472                            /*primary_key_in_database=*/absl::nullopt);
2473   auto result1 = RegisterDictionary(isolation_key_, dict1);
2474   dict1.set_primary_key_in_database(result1.primary_key_in_database());
2475 
2476   auto token2 = base::UnguessableToken::Create();
2477   SharedDictionaryInfo dict2 =
2478       SharedDictionaryInfo(GURL("https://b.example/dict"),
2479                            /*response_time=*/now,
2480                            /*expiration*/ base::Seconds(100), "/pattern*",
2481                            /*last_used_time*/ now + base::Seconds(1),
2482                            /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
2483                            /*disk_cache_key_token=*/token2,
2484                            /*primary_key_in_database=*/absl::nullopt);
2485   auto result2 = RegisterDictionary(isolation_key_, dict2);
2486   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2487 
2488   // The current status:
2489   //   dict1: size=1000 last_used_time=now
2490   //   dict2: size=3000 last_used_time=now+1
2491 
2492   std::set<base::UnguessableToken> tokens = ProcessEviction(1000, 900, 10, 9);
2493   // The dict1 and dict2 must be deleted.
2494   EXPECT_THAT(tokens, UnorderedElementsAreArray({token1, token2}));
2495 
2496   EXPECT_TRUE(GetAllDictionaries().empty());
2497 
2498   // Check the total size of remaining dictionaries.
2499   EXPECT_EQ(0u, GetTotalDictionarySize());
2500 }
2501 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,GetAllDiskCacheKeyTokens)2502 TEST_F(SQLitePersistentSharedDictionaryStoreTest, GetAllDiskCacheKeyTokens) {
2503   CreateStore();
2504   EXPECT_TRUE(GetAllDiskCacheKeyTokens().empty());
2505 
2506   auto token1 = base::UnguessableToken::Create();
2507   SharedDictionaryInfo dict1 = SharedDictionaryInfo(
2508       GURL("https://a.example/dict"),
2509       /*response_time=*/base::Time::Now() - base::Seconds(4),
2510       /*expiration*/ base::Seconds(100), "/pattern*",
2511       /*last_used_time*/ base::Time::Now(),
2512       /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2513       /*disk_cache_key_token=*/token1,
2514       /*primary_key_in_database=*/absl::nullopt);
2515   RegisterDictionary(isolation_key_, dict1);
2516 
2517   EXPECT_THAT(GetAllDiskCacheKeyTokens(), ElementsAreArray({token1}));
2518 
2519   auto token2 = base::UnguessableToken::Create();
2520   SharedDictionaryInfo dict2 = SharedDictionaryInfo(
2521       GURL("https://b.example/dict"),
2522       /*response_time=*/base::Time::Now() - base::Seconds(3),
2523       /*expiration*/ base::Seconds(100), "/pattern*",
2524       /*last_used_time*/ base::Time::Now(),
2525       /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
2526       /*disk_cache_key_token=*/token2,
2527       /*primary_key_in_database=*/absl::nullopt);
2528   RegisterDictionary(isolation_key_, dict2);
2529 
2530   EXPECT_THAT(GetAllDiskCacheKeyTokens(),
2531               UnorderedElementsAreArray({token1, token2}));
2532 }
2533 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,DeleteDictionariesByDiskCacheKeyTokens)2534 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2535        DeleteDictionariesByDiskCacheKeyTokens) {
2536   CreateStore();
2537   EXPECT_TRUE(GetAllDiskCacheKeyTokens().empty());
2538 
2539   auto token1 = base::UnguessableToken::Create();
2540   SharedDictionaryInfo dict1 = SharedDictionaryInfo(
2541       GURL("https://a.example/dict"),
2542       /*response_time=*/base::Time::Now() - base::Seconds(4),
2543       /*expiration*/ base::Seconds(100), "/pattern*",
2544       /*last_used_time*/ base::Time::Now(),
2545       /*size=*/1000, SHA256HashValue({{0x00, 0x01}}),
2546       /*disk_cache_key_token=*/token1,
2547       /*primary_key_in_database=*/absl::nullopt);
2548   auto result1 = RegisterDictionary(isolation_key_, dict1);
2549   dict1.set_primary_key_in_database(result1.primary_key_in_database());
2550 
2551   EXPECT_THAT(GetAllDiskCacheKeyTokens(), ElementsAreArray({token1}));
2552 
2553   auto token2 = base::UnguessableToken::Create();
2554   SharedDictionaryInfo dict2 = SharedDictionaryInfo(
2555       GURL("https://b.example/dict"),
2556       /*response_time=*/base::Time::Now() - base::Seconds(3),
2557       /*expiration*/ base::Seconds(100), "/pattern*",
2558       /*last_used_time*/ base::Time::Now(),
2559       /*size=*/3000, SHA256HashValue({{0x00, 0x02}}),
2560       /*disk_cache_key_token=*/token2,
2561       /*primary_key_in_database=*/absl::nullopt);
2562   RegisterDictionary(isolation_key_, dict2);
2563   auto result2 = RegisterDictionary(isolation_key_, dict2);
2564   dict2.set_primary_key_in_database(result2.primary_key_in_database());
2565 
2566   auto token3 = base::UnguessableToken::Create();
2567   SharedDictionaryInfo dict3 = SharedDictionaryInfo(
2568       GURL("https://c.example/dict"),
2569       /*response_time=*/base::Time::Now() - base::Seconds(2),
2570       /*expiration*/ base::Seconds(100), "/pattern*",
2571       /*last_used_time*/ base::Time::Now(),
2572       /*size=*/5000, SHA256HashValue({{0x00, 0x03}}),
2573       /*disk_cache_key_token=*/token3,
2574       /*primary_key_in_database=*/absl::nullopt);
2575   auto result3 = RegisterDictionary(isolation_key_, dict3);
2576   dict3.set_primary_key_in_database(result3.primary_key_in_database());
2577 
2578   auto token4 = base::UnguessableToken::Create();
2579   SharedDictionaryInfo dict4 = SharedDictionaryInfo(
2580       GURL("https://d.example/dict"),
2581       /*response_time=*/base::Time::Now() - base::Seconds(1),
2582       /*expiration*/ base::Seconds(100), "/pattern*",
2583       /*last_used_time*/ base::Time::Now(),
2584       /*size=*/7000, SHA256HashValue({{0x00, 0x04}}),
2585       /*disk_cache_key_token=*/token4,
2586       /*primary_key_in_database=*/absl::nullopt);
2587   auto result4 = RegisterDictionary(isolation_key_, dict4);
2588   dict4.set_primary_key_in_database(result4.primary_key_in_database());
2589 
2590   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
2591             DeleteDictionariesByDiskCacheKeyTokens({}));
2592 
2593   EXPECT_THAT(
2594       GetAllDictionaries(),
2595       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray(
2596                                            {dict1, dict2, dict3, dict4}))));
2597   EXPECT_EQ(16000u, GetTotalDictionarySize());
2598 
2599   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
2600             DeleteDictionariesByDiskCacheKeyTokens({token1}));
2601 
2602   // dict1 must have been deleted.
2603   EXPECT_THAT(GetAllDictionaries(),
2604               ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray(
2605                                                    {dict2, dict3, dict4}))));
2606   EXPECT_EQ(15000u, GetTotalDictionarySize());
2607 
2608   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
2609             DeleteDictionariesByDiskCacheKeyTokens({token2, token3}));
2610 
2611   // dict2 and dict3 must have been deleted.
2612   EXPECT_THAT(
2613       GetAllDictionaries(),
2614       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray({dict4}))));
2615   EXPECT_EQ(7000u, GetTotalDictionarySize());
2616 
2617   // Call DeleteDictionariesByDiskCacheKeyTokens() with no-maching token.
2618   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
2619             DeleteDictionariesByDiskCacheKeyTokens(
2620                 {base::UnguessableToken::Create()}));
2621   EXPECT_THAT(
2622       GetAllDictionaries(),
2623       ElementsAre(Pair(isolation_key_, UnorderedElementsAreArray({dict4}))));
2624   EXPECT_EQ(7000u, GetTotalDictionarySize());
2625 
2626   EXPECT_EQ(SQLitePersistentSharedDictionaryStore::Error::kOk,
2627             DeleteDictionariesByDiskCacheKeyTokens({token4}));
2628   // dict4 must have been deleted.
2629   EXPECT_TRUE(GetAllDictionaries().empty());
2630   EXPECT_EQ(0u, GetTotalDictionarySize());
2631 }
2632 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,UpdateDictionaryLastUsedTime)2633 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2634        UpdateDictionaryLastUsedTime) {
2635   CreateStore();
2636   auto register_dictionary_result =
2637       RegisterDictionary(isolation_key_, dictionary_info_);
2638 
2639   std::vector<SharedDictionaryInfo> dicts1 = GetDictionaries(isolation_key_);
2640   ASSERT_EQ(1u, dicts1.size());
2641 
2642   // Move the clock forward by 1 second.
2643   FastForwardBy(base::Seconds(1));
2644 
2645   std::vector<SharedDictionaryInfo> dicts2 = GetDictionaries(isolation_key_);
2646   ASSERT_EQ(1u, dicts2.size());
2647 
2648   EXPECT_EQ(dicts1[0].last_used_time(), dicts2[0].last_used_time());
2649 
2650   // Move the clock forward by 1 second.
2651   FastForwardBy(base::Seconds(1));
2652   base::Time updated_last_used_time = base::Time::Now();
2653   store_->UpdateDictionaryLastUsedTime(
2654       register_dictionary_result.primary_key_in_database(),
2655       updated_last_used_time);
2656 
2657   std::vector<SharedDictionaryInfo> dicts3 = GetDictionaries(isolation_key_);
2658   ASSERT_EQ(1u, dicts3.size());
2659   EXPECT_EQ(updated_last_used_time, dicts3[0].last_used_time());
2660 }
2661 
TEST_F(SQLitePersistentSharedDictionaryStoreTest,MassiveUpdateDictionaryLastUsedTime)2662 TEST_F(SQLitePersistentSharedDictionaryStoreTest,
2663        MassiveUpdateDictionaryLastUsedTime) {
2664   CreateStore();
2665   auto register_dictionary_result =
2666       RegisterDictionary(isolation_key_, dictionary_info_);
2667   base::Time updated_last_used_time;
2668   for (size_t i = 0; i < 1000; ++i) {
2669     // Move the clock forward by 10 millisecond.
2670     FastForwardBy(base::Milliseconds(10));
2671     updated_last_used_time = base::Time::Now();
2672     store_->UpdateDictionaryLastUsedTime(
2673         register_dictionary_result.primary_key_in_database(),
2674         updated_last_used_time);
2675   }
2676 
2677   std::vector<SharedDictionaryInfo> dicts3 = GetDictionaries(isolation_key_);
2678   ASSERT_EQ(1u, dicts3.size());
2679   EXPECT_EQ(updated_last_used_time, dicts3[0].last_used_time());
2680 }
2681 
2682 }  // namespace net
2683