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