Add ICU message format support
[chromium-blink-merge.git] / content / browser / dom_storage / dom_storage_area_unittest.cc
blobba91f2697dd43aee6fcab753793d4cbbf79eeafe
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.
5 #include "base/bind.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "base/time/time.h"
15 #include "content/browser/dom_storage/dom_storage_area.h"
16 #include "content/browser/dom_storage/dom_storage_database.h"
17 #include "content/browser/dom_storage/dom_storage_database_adapter.h"
18 #include "content/browser/dom_storage/dom_storage_task_runner.h"
19 #include "content/browser/dom_storage/local_storage_database_adapter.h"
20 #include "content/common/dom_storage/dom_storage_types.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using base::ASCIIToUTF16;
26 namespace content {
28 class DOMStorageAreaTest : public testing::Test {
29 public:
30 DOMStorageAreaTest()
31 : kOrigin(GURL("http://dom_storage/")),
32 kKey(ASCIIToUTF16("key")),
33 kValue(ASCIIToUTF16("value")),
34 kKey2(ASCIIToUTF16("key2")),
35 kValue2(ASCIIToUTF16("value2")) {
38 const GURL kOrigin;
39 const base::string16 kKey;
40 const base::string16 kValue;
41 const base::string16 kKey2;
42 const base::string16 kValue2;
44 // Method used in the CommitTasks test case.
45 void InjectedCommitSequencingTask1(
46 const scoped_refptr<DOMStorageArea>& area) {
47 // At this point the StartCommitTimer task has run and
48 // the OnCommitTimer task is queued. We want to inject after
49 // that.
50 base::ThreadTaskRunnerHandle::Get()->PostTask(
51 FROM_HERE,
52 base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask2,
53 base::Unretained(this), area));
56 void InjectedCommitSequencingTask2(
57 const scoped_refptr<DOMStorageArea>& area) {
58 // At this point the OnCommitTimer has run.
59 // Verify that it put a commit in flight.
60 EXPECT_EQ(1, area->commit_batches_in_flight_);
61 EXPECT_FALSE(area->commit_batch_.get());
62 EXPECT_TRUE(area->HasUncommittedChanges());
63 // Make additional change and verify that a new commit batch
64 // is created for that change.
65 base::NullableString16 old_value;
66 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
67 EXPECT_TRUE(area->commit_batch_.get());
68 EXPECT_EQ(1, area->commit_batches_in_flight_);
69 EXPECT_TRUE(area->HasUncommittedChanges());
72 // Class used in the CommitChangesAtShutdown test case.
73 class VerifyChangesCommittedDatabase : public DOMStorageDatabase {
74 public:
75 VerifyChangesCommittedDatabase() {}
76 ~VerifyChangesCommittedDatabase() override {
77 const base::string16 kKey(ASCIIToUTF16("key"));
78 const base::string16 kValue(ASCIIToUTF16("value"));
79 DOMStorageValuesMap values;
80 ReadAllValues(&values);
81 EXPECT_EQ(1u, values.size());
82 EXPECT_EQ(kValue, values[kKey].string());
86 private:
87 base::MessageLoop message_loop_;
90 TEST_F(DOMStorageAreaTest, DOMStorageAreaBasics) {
91 scoped_refptr<DOMStorageArea> area(
92 new DOMStorageArea(1, std::string(), kOrigin, NULL, NULL));
93 base::string16 old_value;
94 base::NullableString16 old_nullable_value;
95 scoped_refptr<DOMStorageArea> copy;
97 // We don't focus on the underlying DOMStorageMap functionality
98 // since that's covered by seperate unit tests.
99 EXPECT_EQ(kOrigin, area->origin());
100 EXPECT_EQ(1, area->namespace_id());
101 EXPECT_EQ(0u, area->Length());
102 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
103 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_nullable_value));
104 EXPECT_FALSE(area->HasUncommittedChanges());
106 // Verify that a copy shares the same map.
107 copy = area->ShallowCopy(2, std::string());
108 EXPECT_EQ(kOrigin, copy->origin());
109 EXPECT_EQ(2, copy->namespace_id());
110 EXPECT_EQ(area->Length(), copy->Length());
111 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string());
112 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string());
113 EXPECT_EQ(copy->map_.get(), area->map_.get());
115 // But will deep copy-on-write as needed.
116 EXPECT_TRUE(area->RemoveItem(kKey, &old_value));
117 EXPECT_NE(copy->map_.get(), area->map_.get());
118 copy = area->ShallowCopy(2, std::string());
119 EXPECT_EQ(copy->map_.get(), area->map_.get());
120 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
121 EXPECT_NE(copy->map_.get(), area->map_.get());
122 copy = area->ShallowCopy(2, std::string());
123 EXPECT_EQ(copy->map_.get(), area->map_.get());
124 EXPECT_NE(0u, area->Length());
125 EXPECT_TRUE(area->Clear());
126 EXPECT_EQ(0u, area->Length());
127 EXPECT_NE(copy->map_.get(), area->map_.get());
129 // Verify that once Shutdown(), behaves that way.
130 area->Shutdown();
131 EXPECT_TRUE(area->is_shutdown_);
132 EXPECT_FALSE(area->map_.get());
133 EXPECT_EQ(0u, area->Length());
134 EXPECT_TRUE(area->Key(0).is_null());
135 EXPECT_TRUE(area->GetItem(kKey).is_null());
136 EXPECT_FALSE(area->SetItem(kKey, kValue, &old_nullable_value));
137 EXPECT_FALSE(area->RemoveItem(kKey, &old_value));
138 EXPECT_FALSE(area->Clear());
141 TEST_F(DOMStorageAreaTest, BackingDatabaseOpened) {
142 const int64 kSessionStorageNamespaceId = kLocalStorageNamespaceId + 1;
143 base::ScopedTempDir temp_dir;
144 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
145 const base::FilePath kExpectedOriginFilePath = temp_dir.path().Append(
146 DOMStorageArea::DatabaseFileNameFromOrigin(kOrigin));
148 // No directory, backing should be null.
150 scoped_refptr<DOMStorageArea> area(
151 new DOMStorageArea(kOrigin, base::FilePath(), NULL));
152 EXPECT_EQ(NULL, area->backing_.get());
153 EXPECT_TRUE(area->is_initial_import_done_);
154 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath));
157 // Valid directory and origin but no session storage backing. Backing should
158 // be null.
160 scoped_refptr<DOMStorageArea> area(
161 new DOMStorageArea(kSessionStorageNamespaceId, std::string(), kOrigin,
162 NULL, NULL));
163 EXPECT_EQ(NULL, area->backing_.get());
164 EXPECT_TRUE(area->is_initial_import_done_);
166 base::NullableString16 old_value;
167 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
168 ASSERT_TRUE(old_value.is_null());
170 // Check that saving a value has still left us without a backing database.
171 EXPECT_EQ(NULL, area->backing_.get());
172 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath));
175 // This should set up a DOMStorageArea that is correctly backed to disk.
177 scoped_refptr<DOMStorageArea> area(
178 new DOMStorageArea(kOrigin, temp_dir.path(),
179 new MockDOMStorageTaskRunner(
180 base::ThreadTaskRunnerHandle::Get().get())));
182 EXPECT_TRUE(area->backing_.get());
183 DOMStorageDatabase* database = static_cast<LocalStorageDatabaseAdapter*>(
184 area->backing_.get())->db_.get();
185 EXPECT_FALSE(database->IsOpen());
186 EXPECT_FALSE(area->is_initial_import_done_);
188 // Inject an in-memory db to speed up the test.
189 // We will verify that something is written into the database but not
190 // that a file is written to disk - DOMStorageDatabase unit tests cover
191 // that.
192 area->backing_.reset(new LocalStorageDatabaseAdapter());
194 // Need to write something to ensure that the database is created.
195 base::NullableString16 old_value;
196 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
197 ASSERT_TRUE(old_value.is_null());
198 EXPECT_TRUE(area->is_initial_import_done_);
199 EXPECT_TRUE(area->commit_batch_.get());
200 EXPECT_EQ(0, area->commit_batches_in_flight_);
202 base::MessageLoop::current()->RunUntilIdle();
204 EXPECT_FALSE(area->commit_batch_.get());
205 EXPECT_EQ(0, area->commit_batches_in_flight_);
206 database = static_cast<LocalStorageDatabaseAdapter*>(
207 area->backing_.get())->db_.get();
208 EXPECT_TRUE(database->IsOpen());
209 EXPECT_EQ(1u, area->Length());
210 EXPECT_EQ(kValue, area->GetItem(kKey).string());
212 // Verify the content made it to the in memory database.
213 DOMStorageValuesMap values;
214 area->backing_->ReadAllValues(&values);
215 EXPECT_EQ(1u, values.size());
216 EXPECT_EQ(kValue, values[kKey].string());
220 TEST_F(DOMStorageAreaTest, CommitTasks) {
221 base::ScopedTempDir temp_dir;
222 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
224 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
225 kOrigin, temp_dir.path(),
226 new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
227 // Inject an in-memory db to speed up the test.
228 area->backing_.reset(new LocalStorageDatabaseAdapter());
230 // Unrelated to commits, but while we're here, see that querying Length()
231 // causes the backing database to be opened and presumably read from.
232 EXPECT_FALSE(area->is_initial_import_done_);
233 EXPECT_EQ(0u, area->Length());
234 EXPECT_TRUE(area->is_initial_import_done_);
236 DOMStorageValuesMap values;
237 base::NullableString16 old_value;
239 // See that changes are batched up.
240 EXPECT_FALSE(area->commit_batch_.get());
241 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
242 EXPECT_TRUE(area->HasUncommittedChanges());
243 EXPECT_TRUE(area->commit_batch_.get());
244 EXPECT_FALSE(area->commit_batch_->clear_all_first);
245 EXPECT_EQ(1u, area->commit_batch_->changed_values.size());
246 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
247 EXPECT_TRUE(area->commit_batch_.get());
248 EXPECT_FALSE(area->commit_batch_->clear_all_first);
249 EXPECT_EQ(2u, area->commit_batch_->changed_values.size());
250 base::MessageLoop::current()->RunUntilIdle();
251 EXPECT_FALSE(area->HasUncommittedChanges());
252 EXPECT_FALSE(area->commit_batch_.get());
253 EXPECT_EQ(0, area->commit_batches_in_flight_);
254 // Verify the changes made it to the database.
255 values.clear();
256 area->backing_->ReadAllValues(&values);
257 EXPECT_EQ(2u, values.size());
258 EXPECT_EQ(kValue, values[kKey].string());
259 EXPECT_EQ(kValue2, values[kKey2].string());
261 // See that clear is handled properly.
262 EXPECT_TRUE(area->Clear());
263 EXPECT_TRUE(area->commit_batch_.get());
264 EXPECT_TRUE(area->commit_batch_->clear_all_first);
265 EXPECT_TRUE(area->commit_batch_->changed_values.empty());
266 base::MessageLoop::current()->RunUntilIdle();
267 EXPECT_FALSE(area->commit_batch_.get());
268 EXPECT_EQ(0, area->commit_batches_in_flight_);
269 // Verify the changes made it to the database.
270 values.clear();
271 area->backing_->ReadAllValues(&values);
272 EXPECT_TRUE(values.empty());
274 // See that if changes accrue while a commit is "in flight"
275 // those will also get committed.
276 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
277 EXPECT_TRUE(area->HasUncommittedChanges());
278 // At this point the StartCommitTimer task has been posted to the after
279 // startup task queue. We inject another task in the queue that will
280 // execute when the CommitChanges task is inflight. From within our
281 // injected task, we'll make an additional SetItem() call and verify
282 // that a new commit batch is created for that additional change.
283 BrowserThread::PostAfterStartupTask(
284 FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
285 base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask1,
286 base::Unretained(this),
287 area));
288 base::MessageLoop::current()->RunUntilIdle();
289 EXPECT_TRUE(area->HasOneRef());
290 EXPECT_FALSE(area->HasUncommittedChanges());
291 // Verify the changes made it to the database.
292 values.clear();
293 area->backing_->ReadAllValues(&values);
294 EXPECT_EQ(2u, values.size());
295 EXPECT_EQ(kValue, values[kKey].string());
296 EXPECT_EQ(kValue2, values[kKey2].string());
299 TEST_F(DOMStorageAreaTest, CommitChangesAtShutdown) {
300 base::ScopedTempDir temp_dir;
301 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
302 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
303 kOrigin, temp_dir.path(),
304 new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
306 // Inject an in-memory db to speed up the test and also to verify
307 // the final changes are commited in it's dtor.
308 static_cast<LocalStorageDatabaseAdapter*>(area->backing_.get())->db_.reset(
309 new VerifyChangesCommittedDatabase());
311 DOMStorageValuesMap values;
312 base::NullableString16 old_value;
313 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
314 EXPECT_TRUE(area->HasUncommittedChanges());
315 area->backing_->ReadAllValues(&values);
316 EXPECT_TRUE(values.empty()); // not committed yet
317 area->Shutdown();
318 base::MessageLoop::current()->RunUntilIdle();
319 EXPECT_TRUE(area->HasOneRef());
320 EXPECT_FALSE(area->backing_.get());
321 // The VerifyChangesCommittedDatabase destructor verifies values
322 // were committed.
325 TEST_F(DOMStorageAreaTest, DeleteOrigin) {
326 base::ScopedTempDir temp_dir;
327 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
328 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
329 kOrigin, temp_dir.path(),
330 new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
332 // This test puts files on disk.
333 base::FilePath db_file_path = static_cast<LocalStorageDatabaseAdapter*>(
334 area->backing_.get())->db_->file_path();
335 base::FilePath db_journal_file_path =
336 DOMStorageDatabase::GetJournalFilePath(db_file_path);
338 // Nothing bad should happen when invoked w/o any files on disk.
339 area->DeleteOrigin();
340 EXPECT_FALSE(base::PathExists(db_file_path));
342 // Commit something in the database and then delete.
343 base::NullableString16 old_value;
344 area->SetItem(kKey, kValue, &old_value);
345 base::MessageLoop::current()->RunUntilIdle();
346 EXPECT_TRUE(base::PathExists(db_file_path));
347 area->DeleteOrigin();
348 EXPECT_EQ(0u, area->Length());
349 EXPECT_FALSE(base::PathExists(db_file_path));
350 EXPECT_FALSE(base::PathExists(db_journal_file_path));
352 // Put some uncommitted changes to a non-existing database in
353 // and then delete. No file ever gets created in this case.
354 area->SetItem(kKey, kValue, &old_value);
355 EXPECT_TRUE(area->HasUncommittedChanges());
356 EXPECT_EQ(1u, area->Length());
357 area->DeleteOrigin();
358 EXPECT_TRUE(area->HasUncommittedChanges());
359 EXPECT_EQ(0u, area->Length());
360 base::MessageLoop::current()->RunUntilIdle();
361 EXPECT_FALSE(area->HasUncommittedChanges());
362 EXPECT_FALSE(base::PathExists(db_file_path));
364 // Put some uncommitted changes to a an existing database in
365 // and then delete.
366 area->SetItem(kKey, kValue, &old_value);
367 base::MessageLoop::current()->RunUntilIdle();
368 EXPECT_TRUE(base::PathExists(db_file_path));
369 area->SetItem(kKey2, kValue2, &old_value);
370 EXPECT_TRUE(area->HasUncommittedChanges());
371 EXPECT_EQ(2u, area->Length());
372 area->DeleteOrigin();
373 EXPECT_TRUE(area->HasUncommittedChanges());
374 EXPECT_EQ(0u, area->Length());
375 base::MessageLoop::current()->RunUntilIdle();
376 EXPECT_FALSE(area->HasUncommittedChanges());
377 // Since the area had uncommitted changes at the time delete
378 // was called, the file will linger until the shutdown time.
379 EXPECT_TRUE(base::PathExists(db_file_path));
380 area->Shutdown();
381 base::MessageLoop::current()->RunUntilIdle();
382 EXPECT_FALSE(base::PathExists(db_file_path));
385 TEST_F(DOMStorageAreaTest, PurgeMemory) {
386 base::ScopedTempDir temp_dir;
387 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
388 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
389 kOrigin, temp_dir.path(),
390 new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
392 // Inject an in-memory db to speed up the test.
393 area->backing_.reset(new LocalStorageDatabaseAdapter());
395 // Unowned ptrs we use to verify that 'purge' has happened.
396 DOMStorageDatabase* original_backing =
397 static_cast<LocalStorageDatabaseAdapter*>(
398 area->backing_.get())->db_.get();
399 DOMStorageMap* original_map = area->map_.get();
401 // Should do no harm when called on a newly constructed object.
402 EXPECT_FALSE(area->is_initial_import_done_);
403 area->PurgeMemory();
404 EXPECT_FALSE(area->is_initial_import_done_);
405 DOMStorageDatabase* new_backing = static_cast<LocalStorageDatabaseAdapter*>(
406 area->backing_.get())->db_.get();
407 EXPECT_EQ(original_backing, new_backing);
408 EXPECT_EQ(original_map, area->map_.get());
410 // Should not do anything when commits are pending.
411 base::NullableString16 old_value;
412 area->SetItem(kKey, kValue, &old_value);
413 EXPECT_TRUE(area->is_initial_import_done_);
414 EXPECT_TRUE(area->HasUncommittedChanges());
415 area->PurgeMemory();
416 EXPECT_TRUE(area->is_initial_import_done_);
417 EXPECT_TRUE(area->HasUncommittedChanges());
418 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
419 area->backing_.get())->db_.get();
420 EXPECT_EQ(original_backing, new_backing);
421 EXPECT_EQ(original_map, area->map_.get());
423 // Commit the changes from above,
424 base::MessageLoop::current()->RunUntilIdle();
425 EXPECT_FALSE(area->HasUncommittedChanges());
426 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
427 area->backing_.get())->db_.get();
428 EXPECT_EQ(original_backing, new_backing);
429 EXPECT_EQ(original_map, area->map_.get());
431 // Should drop caches and reset database connections
432 // when invoked on an area that's loaded up primed.
433 area->PurgeMemory();
434 EXPECT_FALSE(area->is_initial_import_done_);
435 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
436 area->backing_.get())->db_.get();
437 EXPECT_NE(original_backing, new_backing);
438 EXPECT_NE(original_map, area->map_.get());
441 TEST_F(DOMStorageAreaTest, DatabaseFileNames) {
442 struct {
443 const char* origin;
444 const char* file_name;
445 const char* journal_file_name;
446 } kCases[] = {
447 { "https://www.google.com/",
448 "https_www.google.com_0.localstorage",
449 "https_www.google.com_0.localstorage-journal" },
450 { "http://www.google.com:8080/",
451 "http_www.google.com_8080.localstorage",
452 "http_www.google.com_8080.localstorage-journal" },
453 { "file:///",
454 "file__0.localstorage",
455 "file__0.localstorage-journal" },
458 for (size_t i = 0; i < arraysize(kCases); ++i) {
459 GURL origin = GURL(kCases[i].origin).GetOrigin();
460 base::FilePath file_name =
461 base::FilePath().AppendASCII(kCases[i].file_name);
462 base::FilePath journal_file_name =
463 base::FilePath().AppendASCII(kCases[i].journal_file_name);
465 EXPECT_EQ(file_name,
466 DOMStorageArea::DatabaseFileNameFromOrigin(origin));
467 EXPECT_EQ(origin,
468 DOMStorageArea::OriginFromDatabaseFileName(file_name));
469 EXPECT_EQ(journal_file_name,
470 DOMStorageDatabase::GetJournalFilePath(file_name));
473 // Also test some DOMStorageDatabase::GetJournalFilePath cases here.
474 base::FilePath parent = base::FilePath().AppendASCII("a").AppendASCII("b");
475 EXPECT_EQ(
476 parent.AppendASCII("file-journal"),
477 DOMStorageDatabase::GetJournalFilePath(parent.AppendASCII("file")));
478 EXPECT_EQ(
479 base::FilePath().AppendASCII("-journal"),
480 DOMStorageDatabase::GetJournalFilePath(base::FilePath()));
481 EXPECT_EQ(
482 base::FilePath().AppendASCII(".extensiononly-journal"),
483 DOMStorageDatabase::GetJournalFilePath(
484 base::FilePath().AppendASCII(".extensiononly")));
487 TEST_F(DOMStorageAreaTest, RateLimiter) {
488 // Limit to 1000 samples per second
489 DOMStorageArea::RateLimiter rate_limiter(
490 1000, base::TimeDelta::FromSeconds(1));
492 // No samples have been added so no time/delay should be needed.
493 EXPECT_EQ(base::TimeDelta(),
494 rate_limiter.ComputeTimeNeeded());
495 EXPECT_EQ(base::TimeDelta(),
496 rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
497 EXPECT_EQ(base::TimeDelta(),
498 rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromDays(1)));
500 // Add a seconds worth of samples.
501 rate_limiter.add_samples(1000);
502 EXPECT_EQ(base::TimeDelta::FromSeconds(1),
503 rate_limiter.ComputeTimeNeeded());
504 EXPECT_EQ(base::TimeDelta::FromSeconds(1),
505 rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
506 EXPECT_EQ(base::TimeDelta(),
507 rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
508 EXPECT_EQ(base::TimeDelta::FromMilliseconds(250),
509 rate_limiter.ComputeDelayNeeded(
510 base::TimeDelta::FromMilliseconds(750)));
511 EXPECT_EQ(base::TimeDelta(),
512 rate_limiter.ComputeDelayNeeded(
513 base::TimeDelta::FromDays(1)));
515 // And another half seconds worth.
516 rate_limiter.add_samples(500);
517 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
518 rate_limiter.ComputeTimeNeeded());
519 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
520 rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
521 EXPECT_EQ(base::TimeDelta::FromMilliseconds(500),
522 rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
523 EXPECT_EQ(base::TimeDelta::FromMilliseconds(750),
524 rate_limiter.ComputeDelayNeeded(
525 base::TimeDelta::FromMilliseconds(750)));
526 EXPECT_EQ(base::TimeDelta(),
527 rate_limiter.ComputeDelayNeeded(
528 base::TimeDelta::FromMilliseconds(1500)));
529 EXPECT_EQ(base::TimeDelta(),
530 rate_limiter.ComputeDelayNeeded(
531 base::TimeDelta::FromDays(1)));
534 } // namespace content