1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "base/time/time.h"
13 #include "content/browser/dom_storage/dom_storage_area.h"
14 #include "content/browser/dom_storage/dom_storage_database.h"
15 #include "content/browser/dom_storage/dom_storage_database_adapter.h"
16 #include "content/browser/dom_storage/dom_storage_task_runner.h"
17 #include "content/browser/dom_storage/local_storage_database_adapter.h"
18 #include "content/common/dom_storage/dom_storage_types.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using base::ASCIIToUTF16
;
25 class DOMStorageAreaTest
: public testing::Test
{
28 : kOrigin(GURL("http://dom_storage/")),
29 kKey(ASCIIToUTF16("key")),
30 kValue(ASCIIToUTF16("value")),
31 kKey2(ASCIIToUTF16("key2")),
32 kValue2(ASCIIToUTF16("value2")) {
36 const base::string16 kKey
;
37 const base::string16 kValue
;
38 const base::string16 kKey2
;
39 const base::string16 kValue2
;
41 // Method used in the CommitTasks test case.
42 void InjectedCommitSequencingTask(DOMStorageArea
* area
) {
43 // At this point the OnCommitTimer has run.
44 // Verify that it put a commit in flight.
45 EXPECT_EQ(1, area
->commit_batches_in_flight_
);
46 EXPECT_FALSE(area
->commit_batch_
.get());
47 EXPECT_TRUE(area
->HasUncommittedChanges());
48 // Make additional change and verify that a new commit batch
49 // is created for that change.
50 base::NullableString16 old_value
;
51 EXPECT_TRUE(area
->SetItem(kKey2
, kValue2
, &old_value
));
52 EXPECT_TRUE(area
->commit_batch_
.get());
53 EXPECT_EQ(1, area
->commit_batches_in_flight_
);
54 EXPECT_TRUE(area
->HasUncommittedChanges());
57 // Class used in the CommitChangesAtShutdown test case.
58 class VerifyChangesCommittedDatabase
: public DOMStorageDatabase
{
60 VerifyChangesCommittedDatabase() {}
61 ~VerifyChangesCommittedDatabase() override
{
62 const base::string16
kKey(ASCIIToUTF16("key"));
63 const base::string16
kValue(ASCIIToUTF16("value"));
64 DOMStorageValuesMap values
;
65 ReadAllValues(&values
);
66 EXPECT_EQ(1u, values
.size());
67 EXPECT_EQ(kValue
, values
[kKey
].string());
72 base::MessageLoop message_loop_
;
75 TEST_F(DOMStorageAreaTest
, DOMStorageAreaBasics
) {
76 scoped_refptr
<DOMStorageArea
> area(
77 new DOMStorageArea(1, std::string(), kOrigin
, NULL
, NULL
));
78 base::string16 old_value
;
79 base::NullableString16 old_nullable_value
;
80 scoped_refptr
<DOMStorageArea
> copy
;
82 // We don't focus on the underlying DOMStorageMap functionality
83 // since that's covered by seperate unit tests.
84 EXPECT_EQ(kOrigin
, area
->origin());
85 EXPECT_EQ(1, area
->namespace_id());
86 EXPECT_EQ(0u, area
->Length());
87 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_nullable_value
));
88 EXPECT_TRUE(area
->SetItem(kKey2
, kValue2
, &old_nullable_value
));
89 EXPECT_FALSE(area
->HasUncommittedChanges());
91 // Verify that a copy shares the same map.
92 copy
= area
->ShallowCopy(2, std::string());
93 EXPECT_EQ(kOrigin
, copy
->origin());
94 EXPECT_EQ(2, copy
->namespace_id());
95 EXPECT_EQ(area
->Length(), copy
->Length());
96 EXPECT_EQ(area
->GetItem(kKey
).string(), copy
->GetItem(kKey
).string());
97 EXPECT_EQ(area
->Key(0).string(), copy
->Key(0).string());
98 EXPECT_EQ(copy
->map_
.get(), area
->map_
.get());
100 // But will deep copy-on-write as needed.
101 EXPECT_TRUE(area
->RemoveItem(kKey
, &old_value
));
102 EXPECT_NE(copy
->map_
.get(), area
->map_
.get());
103 copy
= area
->ShallowCopy(2, std::string());
104 EXPECT_EQ(copy
->map_
.get(), area
->map_
.get());
105 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_nullable_value
));
106 EXPECT_NE(copy
->map_
.get(), area
->map_
.get());
107 copy
= area
->ShallowCopy(2, std::string());
108 EXPECT_EQ(copy
->map_
.get(), area
->map_
.get());
109 EXPECT_NE(0u, area
->Length());
110 EXPECT_TRUE(area
->Clear());
111 EXPECT_EQ(0u, area
->Length());
112 EXPECT_NE(copy
->map_
.get(), area
->map_
.get());
114 // Verify that once Shutdown(), behaves that way.
116 EXPECT_TRUE(area
->is_shutdown_
);
117 EXPECT_FALSE(area
->map_
.get());
118 EXPECT_EQ(0u, area
->Length());
119 EXPECT_TRUE(area
->Key(0).is_null());
120 EXPECT_TRUE(area
->GetItem(kKey
).is_null());
121 EXPECT_FALSE(area
->SetItem(kKey
, kValue
, &old_nullable_value
));
122 EXPECT_FALSE(area
->RemoveItem(kKey
, &old_value
));
123 EXPECT_FALSE(area
->Clear());
126 TEST_F(DOMStorageAreaTest
, BackingDatabaseOpened
) {
127 const int64 kSessionStorageNamespaceId
= kLocalStorageNamespaceId
+ 1;
128 base::ScopedTempDir temp_dir
;
129 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
130 const base::FilePath kExpectedOriginFilePath
= temp_dir
.path().Append(
131 DOMStorageArea::DatabaseFileNameFromOrigin(kOrigin
));
133 // No directory, backing should be null.
135 scoped_refptr
<DOMStorageArea
> area(
136 new DOMStorageArea(kOrigin
, base::FilePath(), NULL
));
137 EXPECT_EQ(NULL
, area
->backing_
.get());
138 EXPECT_TRUE(area
->is_initial_import_done_
);
139 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath
));
142 // Valid directory and origin but no session storage backing. Backing should
145 scoped_refptr
<DOMStorageArea
> area(
146 new DOMStorageArea(kSessionStorageNamespaceId
, std::string(), kOrigin
,
148 EXPECT_EQ(NULL
, area
->backing_
.get());
149 EXPECT_TRUE(area
->is_initial_import_done_
);
151 base::NullableString16 old_value
;
152 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_value
));
153 ASSERT_TRUE(old_value
.is_null());
155 // Check that saving a value has still left us without a backing database.
156 EXPECT_EQ(NULL
, area
->backing_
.get());
157 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath
));
160 // This should set up a DOMStorageArea that is correctly backed to disk.
162 scoped_refptr
<DOMStorageArea
> area(new DOMStorageArea(
165 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
167 EXPECT_TRUE(area
->backing_
.get());
168 DOMStorageDatabase
* database
= static_cast<LocalStorageDatabaseAdapter
*>(
169 area
->backing_
.get())->db_
.get();
170 EXPECT_FALSE(database
->IsOpen());
171 EXPECT_FALSE(area
->is_initial_import_done_
);
173 // Inject an in-memory db to speed up the test.
174 // We will verify that something is written into the database but not
175 // that a file is written to disk - DOMStorageDatabase unit tests cover
177 area
->backing_
.reset(new LocalStorageDatabaseAdapter());
179 // Need to write something to ensure that the database is created.
180 base::NullableString16 old_value
;
181 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_value
));
182 ASSERT_TRUE(old_value
.is_null());
183 EXPECT_TRUE(area
->is_initial_import_done_
);
184 EXPECT_TRUE(area
->commit_batch_
.get());
185 EXPECT_EQ(0, area
->commit_batches_in_flight_
);
187 base::MessageLoop::current()->RunUntilIdle();
189 EXPECT_FALSE(area
->commit_batch_
.get());
190 EXPECT_EQ(0, area
->commit_batches_in_flight_
);
191 database
= static_cast<LocalStorageDatabaseAdapter
*>(
192 area
->backing_
.get())->db_
.get();
193 EXPECT_TRUE(database
->IsOpen());
194 EXPECT_EQ(1u, area
->Length());
195 EXPECT_EQ(kValue
, area
->GetItem(kKey
).string());
197 // Verify the content made it to the in memory database.
198 DOMStorageValuesMap values
;
199 area
->backing_
->ReadAllValues(&values
);
200 EXPECT_EQ(1u, values
.size());
201 EXPECT_EQ(kValue
, values
[kKey
].string());
205 TEST_F(DOMStorageAreaTest
, CommitTasks
) {
206 base::ScopedTempDir temp_dir
;
207 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
209 scoped_refptr
<DOMStorageArea
> area(new DOMStorageArea(
212 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
213 // Inject an in-memory db to speed up the test.
214 area
->backing_
.reset(new LocalStorageDatabaseAdapter());
216 // Unrelated to commits, but while we're here, see that querying Length()
217 // causes the backing database to be opened and presumably read from.
218 EXPECT_FALSE(area
->is_initial_import_done_
);
219 EXPECT_EQ(0u, area
->Length());
220 EXPECT_TRUE(area
->is_initial_import_done_
);
222 DOMStorageValuesMap values
;
223 base::NullableString16 old_value
;
225 // See that changes are batched up.
226 EXPECT_FALSE(area
->commit_batch_
.get());
227 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_value
));
228 EXPECT_TRUE(area
->HasUncommittedChanges());
229 EXPECT_TRUE(area
->commit_batch_
.get());
230 EXPECT_FALSE(area
->commit_batch_
->clear_all_first
);
231 EXPECT_EQ(1u, area
->commit_batch_
->changed_values
.size());
232 EXPECT_TRUE(area
->SetItem(kKey2
, kValue2
, &old_value
));
233 EXPECT_TRUE(area
->commit_batch_
.get());
234 EXPECT_FALSE(area
->commit_batch_
->clear_all_first
);
235 EXPECT_EQ(2u, area
->commit_batch_
->changed_values
.size());
236 base::MessageLoop::current()->RunUntilIdle();
237 EXPECT_FALSE(area
->HasUncommittedChanges());
238 EXPECT_FALSE(area
->commit_batch_
.get());
239 EXPECT_EQ(0, area
->commit_batches_in_flight_
);
240 // Verify the changes made it to the database.
242 area
->backing_
->ReadAllValues(&values
);
243 EXPECT_EQ(2u, values
.size());
244 EXPECT_EQ(kValue
, values
[kKey
].string());
245 EXPECT_EQ(kValue2
, values
[kKey2
].string());
247 // See that clear is handled properly.
248 EXPECT_TRUE(area
->Clear());
249 EXPECT_TRUE(area
->commit_batch_
.get());
250 EXPECT_TRUE(area
->commit_batch_
->clear_all_first
);
251 EXPECT_TRUE(area
->commit_batch_
->changed_values
.empty());
252 base::MessageLoop::current()->RunUntilIdle();
253 EXPECT_FALSE(area
->commit_batch_
.get());
254 EXPECT_EQ(0, area
->commit_batches_in_flight_
);
255 // Verify the changes made it to the database.
257 area
->backing_
->ReadAllValues(&values
);
258 EXPECT_TRUE(values
.empty());
260 // See that if changes accrue while a commit is "in flight"
261 // those will also get committed.
262 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_value
));
263 EXPECT_TRUE(area
->HasUncommittedChanges());
264 // At this point the OnCommitTimer task has been posted. We inject
265 // another task in the queue that will execute after the timer task,
266 // but before the CommitChanges task. From within our injected task,
267 // we'll make an additional SetItem() call.
268 base::MessageLoop::current()->PostTask(
270 base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask
,
271 base::Unretained(this),
273 base::MessageLoop::current()->RunUntilIdle();
274 EXPECT_TRUE(area
->HasOneRef());
275 EXPECT_FALSE(area
->HasUncommittedChanges());
276 // Verify the changes made it to the database.
278 area
->backing_
->ReadAllValues(&values
);
279 EXPECT_EQ(2u, values
.size());
280 EXPECT_EQ(kValue
, values
[kKey
].string());
281 EXPECT_EQ(kValue2
, values
[kKey2
].string());
284 TEST_F(DOMStorageAreaTest
, CommitChangesAtShutdown
) {
285 base::ScopedTempDir temp_dir
;
286 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
287 scoped_refptr
<DOMStorageArea
> area(new DOMStorageArea(
290 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
292 // Inject an in-memory db to speed up the test and also to verify
293 // the final changes are commited in it's dtor.
294 static_cast<LocalStorageDatabaseAdapter
*>(area
->backing_
.get())->db_
.reset(
295 new VerifyChangesCommittedDatabase());
297 DOMStorageValuesMap values
;
298 base::NullableString16 old_value
;
299 EXPECT_TRUE(area
->SetItem(kKey
, kValue
, &old_value
));
300 EXPECT_TRUE(area
->HasUncommittedChanges());
301 area
->backing_
->ReadAllValues(&values
);
302 EXPECT_TRUE(values
.empty()); // not committed yet
304 base::MessageLoop::current()->RunUntilIdle();
305 EXPECT_TRUE(area
->HasOneRef());
306 EXPECT_FALSE(area
->backing_
.get());
307 // The VerifyChangesCommittedDatabase destructor verifies values
311 TEST_F(DOMStorageAreaTest
, DeleteOrigin
) {
312 base::ScopedTempDir temp_dir
;
313 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
314 scoped_refptr
<DOMStorageArea
> area(new DOMStorageArea(
317 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
319 // This test puts files on disk.
320 base::FilePath db_file_path
= static_cast<LocalStorageDatabaseAdapter
*>(
321 area
->backing_
.get())->db_
->file_path();
322 base::FilePath db_journal_file_path
=
323 DOMStorageDatabase::GetJournalFilePath(db_file_path
);
325 // Nothing bad should happen when invoked w/o any files on disk.
326 area
->DeleteOrigin();
327 EXPECT_FALSE(base::PathExists(db_file_path
));
329 // Commit something in the database and then delete.
330 base::NullableString16 old_value
;
331 area
->SetItem(kKey
, kValue
, &old_value
);
332 base::MessageLoop::current()->RunUntilIdle();
333 EXPECT_TRUE(base::PathExists(db_file_path
));
334 area
->DeleteOrigin();
335 EXPECT_EQ(0u, area
->Length());
336 EXPECT_FALSE(base::PathExists(db_file_path
));
337 EXPECT_FALSE(base::PathExists(db_journal_file_path
));
339 // Put some uncommitted changes to a non-existing database in
340 // and then delete. No file ever gets created in this case.
341 area
->SetItem(kKey
, kValue
, &old_value
);
342 EXPECT_TRUE(area
->HasUncommittedChanges());
343 EXPECT_EQ(1u, area
->Length());
344 area
->DeleteOrigin();
345 EXPECT_TRUE(area
->HasUncommittedChanges());
346 EXPECT_EQ(0u, area
->Length());
347 base::MessageLoop::current()->RunUntilIdle();
348 EXPECT_FALSE(area
->HasUncommittedChanges());
349 EXPECT_FALSE(base::PathExists(db_file_path
));
351 // Put some uncommitted changes to a an existing database in
353 area
->SetItem(kKey
, kValue
, &old_value
);
354 base::MessageLoop::current()->RunUntilIdle();
355 EXPECT_TRUE(base::PathExists(db_file_path
));
356 area
->SetItem(kKey2
, kValue2
, &old_value
);
357 EXPECT_TRUE(area
->HasUncommittedChanges());
358 EXPECT_EQ(2u, area
->Length());
359 area
->DeleteOrigin();
360 EXPECT_TRUE(area
->HasUncommittedChanges());
361 EXPECT_EQ(0u, area
->Length());
362 base::MessageLoop::current()->RunUntilIdle();
363 EXPECT_FALSE(area
->HasUncommittedChanges());
364 // Since the area had uncommitted changes at the time delete
365 // was called, the file will linger until the shutdown time.
366 EXPECT_TRUE(base::PathExists(db_file_path
));
368 base::MessageLoop::current()->RunUntilIdle();
369 EXPECT_FALSE(base::PathExists(db_file_path
));
372 TEST_F(DOMStorageAreaTest
, PurgeMemory
) {
373 base::ScopedTempDir temp_dir
;
374 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
375 scoped_refptr
<DOMStorageArea
> area(new DOMStorageArea(
378 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
380 // Inject an in-memory db to speed up the test.
381 area
->backing_
.reset(new LocalStorageDatabaseAdapter());
383 // Unowned ptrs we use to verify that 'purge' has happened.
384 DOMStorageDatabase
* original_backing
=
385 static_cast<LocalStorageDatabaseAdapter
*>(
386 area
->backing_
.get())->db_
.get();
387 DOMStorageMap
* original_map
= area
->map_
.get();
389 // Should do no harm when called on a newly constructed object.
390 EXPECT_FALSE(area
->is_initial_import_done_
);
392 EXPECT_FALSE(area
->is_initial_import_done_
);
393 DOMStorageDatabase
* new_backing
= static_cast<LocalStorageDatabaseAdapter
*>(
394 area
->backing_
.get())->db_
.get();
395 EXPECT_EQ(original_backing
, new_backing
);
396 EXPECT_EQ(original_map
, area
->map_
.get());
398 // Should not do anything when commits are pending.
399 base::NullableString16 old_value
;
400 area
->SetItem(kKey
, kValue
, &old_value
);
401 EXPECT_TRUE(area
->is_initial_import_done_
);
402 EXPECT_TRUE(area
->HasUncommittedChanges());
404 EXPECT_TRUE(area
->is_initial_import_done_
);
405 EXPECT_TRUE(area
->HasUncommittedChanges());
406 new_backing
= static_cast<LocalStorageDatabaseAdapter
*>(
407 area
->backing_
.get())->db_
.get();
408 EXPECT_EQ(original_backing
, new_backing
);
409 EXPECT_EQ(original_map
, area
->map_
.get());
411 // Commit the changes from above,
412 base::MessageLoop::current()->RunUntilIdle();
413 EXPECT_FALSE(area
->HasUncommittedChanges());
414 new_backing
= static_cast<LocalStorageDatabaseAdapter
*>(
415 area
->backing_
.get())->db_
.get();
416 EXPECT_EQ(original_backing
, new_backing
);
417 EXPECT_EQ(original_map
, area
->map_
.get());
419 // Should drop caches and reset database connections
420 // when invoked on an area that's loaded up primed.
422 EXPECT_FALSE(area
->is_initial_import_done_
);
423 new_backing
= static_cast<LocalStorageDatabaseAdapter
*>(
424 area
->backing_
.get())->db_
.get();
425 EXPECT_NE(original_backing
, new_backing
);
426 EXPECT_NE(original_map
, area
->map_
.get());
429 TEST_F(DOMStorageAreaTest
, DatabaseFileNames
) {
432 const char* file_name
;
433 const char* journal_file_name
;
435 { "https://www.google.com/",
436 "https_www.google.com_0.localstorage",
437 "https_www.google.com_0.localstorage-journal" },
438 { "http://www.google.com:8080/",
439 "http_www.google.com_8080.localstorage",
440 "http_www.google.com_8080.localstorage-journal" },
442 "file__0.localstorage",
443 "file__0.localstorage-journal" },
446 for (size_t i
= 0; i
< arraysize(kCases
); ++i
) {
447 GURL origin
= GURL(kCases
[i
].origin
).GetOrigin();
448 base::FilePath file_name
=
449 base::FilePath().AppendASCII(kCases
[i
].file_name
);
450 base::FilePath journal_file_name
=
451 base::FilePath().AppendASCII(kCases
[i
].journal_file_name
);
454 DOMStorageArea::DatabaseFileNameFromOrigin(origin
));
456 DOMStorageArea::OriginFromDatabaseFileName(file_name
));
457 EXPECT_EQ(journal_file_name
,
458 DOMStorageDatabase::GetJournalFilePath(file_name
));
461 // Also test some DOMStorageDatabase::GetJournalFilePath cases here.
462 base::FilePath parent
= base::FilePath().AppendASCII("a").AppendASCII("b");
464 parent
.AppendASCII("file-journal"),
465 DOMStorageDatabase::GetJournalFilePath(parent
.AppendASCII("file")));
467 base::FilePath().AppendASCII("-journal"),
468 DOMStorageDatabase::GetJournalFilePath(base::FilePath()));
470 base::FilePath().AppendASCII(".extensiononly-journal"),
471 DOMStorageDatabase::GetJournalFilePath(
472 base::FilePath().AppendASCII(".extensiononly")));
475 TEST_F(DOMStorageAreaTest
, RateLimiter
) {
476 // Limit to 1000 samples per second
477 DOMStorageArea::RateLimiter
rate_limiter(
478 1000, base::TimeDelta::FromSeconds(1));
480 // No samples have been added so no time/delay should be needed.
481 EXPECT_EQ(base::TimeDelta(),
482 rate_limiter
.ComputeTimeNeeded());
483 EXPECT_EQ(base::TimeDelta(),
484 rate_limiter
.ComputeDelayNeeded(base::TimeDelta()));
485 EXPECT_EQ(base::TimeDelta(),
486 rate_limiter
.ComputeDelayNeeded(base::TimeDelta::FromDays(1)));
488 // Add a seconds worth of samples.
489 rate_limiter
.add_samples(1000);
490 EXPECT_EQ(base::TimeDelta::FromSeconds(1),
491 rate_limiter
.ComputeTimeNeeded());
492 EXPECT_EQ(base::TimeDelta::FromSeconds(1),
493 rate_limiter
.ComputeDelayNeeded(base::TimeDelta()));
494 EXPECT_EQ(base::TimeDelta(),
495 rate_limiter
.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
496 EXPECT_EQ(base::TimeDelta::FromMilliseconds(250),
497 rate_limiter
.ComputeDelayNeeded(
498 base::TimeDelta::FromMilliseconds(750)));
499 EXPECT_EQ(base::TimeDelta(),
500 rate_limiter
.ComputeDelayNeeded(
501 base::TimeDelta::FromDays(1)));
503 // And another half seconds worth.
504 rate_limiter
.add_samples(500);
505 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
506 rate_limiter
.ComputeTimeNeeded());
507 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
508 rate_limiter
.ComputeDelayNeeded(base::TimeDelta()));
509 EXPECT_EQ(base::TimeDelta::FromMilliseconds(500),
510 rate_limiter
.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
511 EXPECT_EQ(base::TimeDelta::FromMilliseconds(750),
512 rate_limiter
.ComputeDelayNeeded(
513 base::TimeDelta::FromMilliseconds(750)));
514 EXPECT_EQ(base::TimeDelta(),
515 rate_limiter
.ComputeDelayNeeded(
516 base::TimeDelta::FromMilliseconds(1500)));
517 EXPECT_EQ(base::TimeDelta(),
518 rate_limiter
.ComputeDelayNeeded(
519 base::TimeDelta::FromDays(1)));
522 } // namespace content