cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / components / visitedlink / test / visitedlink_unittest.cc
blob0943106338a54a7da4893ed7e2a56fb05edce0ac
1 // Copyright (c) 2012 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 <cstdio>
6 #include <string>
7 #include <vector>
9 #include "base/file_util.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/process/process_handle.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_util.h"
16 #include "base/time/time.h"
17 #include "components/visitedlink/browser/visitedlink_delegate.h"
18 #include "components/visitedlink/browser/visitedlink_event_listener.h"
19 #include "components/visitedlink/browser/visitedlink_master.h"
20 #include "components/visitedlink/common/visitedlink_messages.h"
21 #include "components/visitedlink/renderer/visitedlink_slave.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/test/mock_render_process_host.h"
26 #include "content/public/test/test_browser_context.h"
27 #include "content/public/test/test_browser_thread_bundle.h"
28 #include "content/public/test/test_renderer_host.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
32 using content::BrowserThread;
33 using content::MockRenderProcessHost;
34 using content::RenderViewHostTester;
36 namespace visitedlink {
38 namespace {
40 typedef std::vector<GURL> URLs;
42 // a nice long URL that we can append numbers to to get new URLs
43 const char g_test_prefix[] =
44 "http://www.google.com/products/foo/index.html?id=45028640526508376&seq=";
45 const int g_test_count = 1000;
47 // Returns a test URL for index |i|
48 GURL TestURL(int i) {
49 return GURL(base::StringPrintf("%s%d", g_test_prefix, i));
52 std::vector<VisitedLinkSlave*> g_slaves;
54 class TestVisitedLinkDelegate : public VisitedLinkDelegate {
55 public:
56 virtual void RebuildTable(
57 const scoped_refptr<URLEnumerator>& enumerator) OVERRIDE;
59 void AddURLForRebuild(const GURL& url);
61 private:
63 URLs rebuild_urls_;
66 void TestVisitedLinkDelegate::RebuildTable(
67 const scoped_refptr<URLEnumerator>& enumerator) {
68 for (URLs::const_iterator itr = rebuild_urls_.begin();
69 itr != rebuild_urls_.end();
70 ++itr)
71 enumerator->OnURL(*itr);
72 enumerator->OnComplete(true);
75 void TestVisitedLinkDelegate::AddURLForRebuild(const GURL& url) {
76 rebuild_urls_.push_back(url);
79 class TestURLIterator : public VisitedLinkMaster::URLIterator {
80 public:
81 explicit TestURLIterator(const URLs& urls);
83 virtual const GURL& NextURL() OVERRIDE;
84 virtual bool HasNextURL() const OVERRIDE;
86 private:
87 URLs::const_iterator iterator_;
88 URLs::const_iterator end_;
91 TestURLIterator::TestURLIterator(const URLs& urls)
92 : iterator_(urls.begin()),
93 end_(urls.end()) {
96 const GURL& TestURLIterator::NextURL() {
97 return *(iterator_++);
100 bool TestURLIterator::HasNextURL() const {
101 return iterator_ != end_;
104 } // namespace
106 class TrackingVisitedLinkEventListener : public VisitedLinkMaster::Listener {
107 public:
108 TrackingVisitedLinkEventListener()
109 : reset_count_(0),
110 add_count_(0) {}
112 virtual void NewTable(base::SharedMemory* table) OVERRIDE {
113 if (table) {
114 for (std::vector<VisitedLinkSlave>::size_type i = 0;
115 i < g_slaves.size(); i++) {
116 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
117 table->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle);
118 g_slaves[i]->OnUpdateVisitedLinks(new_handle);
122 virtual void Add(VisitedLinkCommon::Fingerprint) OVERRIDE { add_count_++; }
123 virtual void Reset() OVERRIDE { reset_count_++; }
125 void SetUp() {
126 reset_count_ = 0;
127 add_count_ = 0;
130 int reset_count() const { return reset_count_; }
131 int add_count() const { return add_count_; }
133 private:
134 int reset_count_;
135 int add_count_;
138 class VisitedLinkTest : public testing::Test {
139 protected:
140 // Initializes the visited link objects. Pass in the size that you want a
141 // freshly created table to be. 0 means use the default.
143 // |suppress_rebuild| is set when we're not testing rebuilding, see
144 // the VisitedLinkMaster constructor.
145 bool InitVisited(int initial_size, bool suppress_rebuild) {
146 // Initialize the visited link system.
147 master_.reset(new VisitedLinkMaster(new TrackingVisitedLinkEventListener(),
148 &delegate_,
149 true,
150 suppress_rebuild, visited_file_,
151 initial_size));
152 return master_->Init();
155 // May be called multiple times (some tests will do this to clear things,
156 // and TearDown will do this to make sure eveything is shiny before quitting.
157 void ClearDB() {
158 if (master_.get())
159 master_.reset(NULL);
161 // Wait for all pending file I/O to be completed.
162 BrowserThread::GetBlockingPool()->FlushForTesting();
165 // Loads the database from disk and makes sure that the same URLs are present
166 // as were generated by TestIO_Create(). This also checks the URLs with a
167 // slave to make sure it reads the data properly.
168 void Reload() {
169 // Clean up after our caller, who may have left the database open.
170 ClearDB();
172 ASSERT_TRUE(InitVisited(0, true));
173 master_->DebugValidate();
175 // check that the table has the proper number of entries
176 int used_count = master_->GetUsedCount();
177 ASSERT_EQ(used_count, g_test_count);
179 // Create a slave database.
180 VisitedLinkSlave slave;
181 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
182 master_->shared_memory()->ShareToProcess(
183 base::GetCurrentProcessHandle(), &new_handle);
184 slave.OnUpdateVisitedLinks(new_handle);
185 g_slaves.push_back(&slave);
187 bool found;
188 for (int i = 0; i < g_test_count; i++) {
189 GURL cur = TestURL(i);
190 found = master_->IsVisited(cur);
191 EXPECT_TRUE(found) << "URL " << i << "not found in master.";
193 found = slave.IsVisited(cur);
194 EXPECT_TRUE(found) << "URL " << i << "not found in slave.";
197 // test some random URL so we know that it returns false sometimes too
198 found = master_->IsVisited(GURL("http://unfound.site/"));
199 ASSERT_FALSE(found);
200 found = slave.IsVisited(GURL("http://unfound.site/"));
201 ASSERT_FALSE(found);
203 master_->DebugValidate();
205 g_slaves.clear();
208 // testing::Test
209 virtual void SetUp() {
210 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
212 history_dir_ = temp_dir_.path().AppendASCII("VisitedLinkTest");
213 ASSERT_TRUE(file_util::CreateDirectory(history_dir_));
215 visited_file_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinks"));
218 virtual void TearDown() {
219 ClearDB();
222 base::ScopedTempDir temp_dir_;
224 // Filenames for the services;
225 base::FilePath history_dir_;
226 base::FilePath visited_file_;
228 scoped_ptr<VisitedLinkMaster> master_;
229 TestVisitedLinkDelegate delegate_;
230 content::TestBrowserThreadBundle thread_bundle_;
233 // This test creates and reads some databases to make sure the data is
234 // preserved throughout those operations.
235 TEST_F(VisitedLinkTest, DatabaseIO) {
236 ASSERT_TRUE(InitVisited(0, true));
238 for (int i = 0; i < g_test_count; i++)
239 master_->AddURL(TestURL(i));
241 // Test that the database was written properly
242 Reload();
245 // Checks that we can delete things properly when there are collisions.
246 TEST_F(VisitedLinkTest, Delete) {
247 static const int32 kInitialSize = 17;
248 ASSERT_TRUE(InitVisited(kInitialSize, true));
250 // Add a cluster from 14-17 wrapping around to 0. These will all hash to the
251 // same value.
252 const VisitedLinkCommon::Fingerprint kFingerprint0 = kInitialSize * 0 + 14;
253 const VisitedLinkCommon::Fingerprint kFingerprint1 = kInitialSize * 1 + 14;
254 const VisitedLinkCommon::Fingerprint kFingerprint2 = kInitialSize * 2 + 14;
255 const VisitedLinkCommon::Fingerprint kFingerprint3 = kInitialSize * 3 + 14;
256 const VisitedLinkCommon::Fingerprint kFingerprint4 = kInitialSize * 4 + 14;
257 master_->AddFingerprint(kFingerprint0, false); // @14
258 master_->AddFingerprint(kFingerprint1, false); // @15
259 master_->AddFingerprint(kFingerprint2, false); // @16
260 master_->AddFingerprint(kFingerprint3, false); // @0
261 master_->AddFingerprint(kFingerprint4, false); // @1
263 // Deleting 14 should move the next value up one slot (we do not specify an
264 // order).
265 EXPECT_EQ(kFingerprint3, master_->hash_table_[0]);
266 master_->DeleteFingerprint(kFingerprint3, false);
267 VisitedLinkCommon::Fingerprint zero_fingerprint = 0;
268 EXPECT_EQ(zero_fingerprint, master_->hash_table_[1]);
269 EXPECT_NE(zero_fingerprint, master_->hash_table_[0]);
271 // Deleting the other four should leave the table empty.
272 master_->DeleteFingerprint(kFingerprint0, false);
273 master_->DeleteFingerprint(kFingerprint1, false);
274 master_->DeleteFingerprint(kFingerprint2, false);
275 master_->DeleteFingerprint(kFingerprint4, false);
277 EXPECT_EQ(0, master_->used_items_);
278 for (int i = 0; i < kInitialSize; i++)
279 EXPECT_EQ(zero_fingerprint, master_->hash_table_[i]) <<
280 "Hash table has values in it.";
283 // When we delete more than kBigDeleteThreshold we trigger different behavior
284 // where the entire file is rewritten.
285 TEST_F(VisitedLinkTest, BigDelete) {
286 ASSERT_TRUE(InitVisited(16381, true));
288 // Add the base set of URLs that won't be deleted.
289 // Reload() will test for these.
290 for (int32 i = 0; i < g_test_count; i++)
291 master_->AddURL(TestURL(i));
293 // Add more URLs than necessary to trigger this case.
294 const int kTestDeleteCount = VisitedLinkMaster::kBigDeleteThreshold + 2;
295 URLs urls_to_delete;
296 for (int32 i = g_test_count; i < g_test_count + kTestDeleteCount; i++) {
297 GURL url(TestURL(i));
298 master_->AddURL(url);
299 urls_to_delete.push_back(url);
302 TestURLIterator iterator(urls_to_delete);
303 master_->DeleteURLs(&iterator);
304 master_->DebugValidate();
306 Reload();
309 TEST_F(VisitedLinkTest, DeleteAll) {
310 ASSERT_TRUE(InitVisited(0, true));
313 VisitedLinkSlave slave;
314 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
315 master_->shared_memory()->ShareToProcess(
316 base::GetCurrentProcessHandle(), &new_handle);
317 slave.OnUpdateVisitedLinks(new_handle);
318 g_slaves.push_back(&slave);
320 // Add the test URLs.
321 for (int i = 0; i < g_test_count; i++) {
322 master_->AddURL(TestURL(i));
323 ASSERT_EQ(i + 1, master_->GetUsedCount());
325 master_->DebugValidate();
327 // Make sure the slave picked up the adds.
328 for (int i = 0; i < g_test_count; i++)
329 EXPECT_TRUE(slave.IsVisited(TestURL(i)));
331 // Clear the table and make sure the slave picked it up.
332 master_->DeleteAllURLs();
333 EXPECT_EQ(0, master_->GetUsedCount());
334 for (int i = 0; i < g_test_count; i++) {
335 EXPECT_FALSE(master_->IsVisited(TestURL(i)));
336 EXPECT_FALSE(slave.IsVisited(TestURL(i)));
339 // Close the database.
340 g_slaves.clear();
341 ClearDB();
344 // Reopen and validate.
345 ASSERT_TRUE(InitVisited(0, true));
346 master_->DebugValidate();
347 EXPECT_EQ(0, master_->GetUsedCount());
348 for (int i = 0; i < g_test_count; i++)
349 EXPECT_FALSE(master_->IsVisited(TestURL(i)));
352 // This tests that the master correctly resizes its tables when it gets too
353 // full, notifies its slaves of the change, and updates the disk.
354 TEST_F(VisitedLinkTest, Resizing) {
355 // Create a very small database.
356 const int32 initial_size = 17;
357 ASSERT_TRUE(InitVisited(initial_size, true));
359 // ...and a slave
360 VisitedLinkSlave slave;
361 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
362 master_->shared_memory()->ShareToProcess(
363 base::GetCurrentProcessHandle(), &new_handle);
364 slave.OnUpdateVisitedLinks(new_handle);
365 g_slaves.push_back(&slave);
367 int32 used_count = master_->GetUsedCount();
368 ASSERT_EQ(used_count, 0);
370 for (int i = 0; i < g_test_count; i++) {
371 master_->AddURL(TestURL(i));
372 used_count = master_->GetUsedCount();
373 ASSERT_EQ(i + 1, used_count);
376 // Verify that the table got resized sufficiently.
377 int32 table_size;
378 VisitedLinkCommon::Fingerprint* table;
379 master_->GetUsageStatistics(&table_size, &table);
380 used_count = master_->GetUsedCount();
381 ASSERT_GT(table_size, used_count);
382 ASSERT_EQ(used_count, g_test_count) <<
383 "table count doesn't match the # of things we added";
385 // Verify that the slave got the resize message and has the same
386 // table information.
387 int32 child_table_size;
388 VisitedLinkCommon::Fingerprint* child_table;
389 slave.GetUsageStatistics(&child_table_size, &child_table);
390 ASSERT_EQ(table_size, child_table_size);
391 for (int32 i = 0; i < table_size; i++) {
392 ASSERT_EQ(table[i], child_table[i]);
395 master_->DebugValidate();
396 g_slaves.clear();
398 // This tests that the file is written correctly by reading it in using
399 // a new database.
400 Reload();
403 // Tests that if the database doesn't exist, it will be rebuilt from history.
404 TEST_F(VisitedLinkTest, Rebuild) {
405 // Add half of our URLs to history. This needs to be done before we
406 // initialize the visited link DB.
407 int history_count = g_test_count / 2;
408 for (int i = 0; i < history_count; i++)
409 delegate_.AddURLForRebuild(TestURL(i));
411 // Initialize the visited link DB. Since the visited links file doesn't exist
412 // and we don't suppress history rebuilding, this will load from history.
413 ASSERT_TRUE(InitVisited(0, false));
415 // While the table is rebuilding, add the rest of the URLs to the visited
416 // link system. This isn't guaranteed to happen during the rebuild, so we
417 // can't be 100% sure we're testing the right thing, but in practice is.
418 // All the adds above will generally take some time queuing up on the
419 // history thread, and it will take a while to catch up to actually
420 // processing the rebuild that has queued behind it. We will generally
421 // finish adding all of the URLs before it has even found the first URL.
422 for (int i = history_count; i < g_test_count; i++)
423 master_->AddURL(TestURL(i));
425 // Add one more and then delete it.
426 master_->AddURL(TestURL(g_test_count));
427 URLs urls_to_delete;
428 urls_to_delete.push_back(TestURL(g_test_count));
429 TestURLIterator iterator(urls_to_delete);
430 master_->DeleteURLs(&iterator);
432 // Wait for the rebuild to complete. The task will terminate the message
433 // loop when the rebuild is done. There's no chance that the rebuild will
434 // complete before we set the task because the rebuild completion message
435 // is posted to the message loop; until we Run() it, rebuild can not
436 // complete.
437 base::RunLoop run_loop;
438 master_->set_rebuild_complete_task(run_loop.QuitClosure());
439 run_loop.Run();
441 // Test that all URLs were written to the database properly.
442 Reload();
444 // Make sure the extra one was *not* written (Reload won't test this).
445 EXPECT_FALSE(master_->IsVisited(TestURL(g_test_count)));
448 // Test that importing a large number of URLs will work
449 TEST_F(VisitedLinkTest, BigImport) {
450 ASSERT_TRUE(InitVisited(0, false));
452 // Before the table rebuilds, add a large number of URLs
453 int total_count = VisitedLinkMaster::kDefaultTableSize + 10;
454 for (int i = 0; i < total_count; i++)
455 master_->AddURL(TestURL(i));
457 // Wait for the rebuild to complete.
458 base::RunLoop run_loop;
459 master_->set_rebuild_complete_task(run_loop.QuitClosure());
460 run_loop.Run();
462 // Ensure that the right number of URLs are present
463 int used_count = master_->GetUsedCount();
464 ASSERT_EQ(used_count, total_count);
467 TEST_F(VisitedLinkTest, Listener) {
468 ASSERT_TRUE(InitVisited(0, true));
470 // Add test URLs.
471 for (int i = 0; i < g_test_count; i++) {
472 master_->AddURL(TestURL(i));
473 ASSERT_EQ(i + 1, master_->GetUsedCount());
476 // Delete an URL.
477 URLs urls_to_delete;
478 urls_to_delete.push_back(TestURL(0));
479 TestURLIterator iterator(urls_to_delete);
480 master_->DeleteURLs(&iterator);
482 // ... and all of the remaining ones.
483 master_->DeleteAllURLs();
485 TrackingVisitedLinkEventListener* listener =
486 static_cast<TrackingVisitedLinkEventListener*>(master_->GetListener());
488 // Verify that VisitedLinkMaster::Listener::Add was called for each added URL.
489 EXPECT_EQ(g_test_count, listener->add_count());
490 // Verify that VisitedLinkMaster::Listener::Reset was called both when one and
491 // all URLs are deleted.
492 EXPECT_EQ(2, listener->reset_count());
495 class VisitCountingContext : public content::TestBrowserContext {
496 public:
497 VisitCountingContext()
498 : add_count_(0),
499 add_event_count_(0),
500 reset_event_count_(0),
501 new_table_count_(0) {}
503 void CountAddEvent(int by) {
504 add_count_ += by;
505 add_event_count_++;
508 void CountResetEvent() {
509 reset_event_count_++;
512 void CountNewTable() {
513 new_table_count_++;
516 int add_count() const { return add_count_; }
517 int add_event_count() const { return add_event_count_; }
518 int reset_event_count() const { return reset_event_count_; }
519 int new_table_count() const { return new_table_count_; }
521 private:
522 int add_count_;
523 int add_event_count_;
524 int reset_event_count_;
525 int new_table_count_;
528 // Stub out as little as possible, borrowing from RenderProcessHost.
529 class VisitRelayingRenderProcessHost : public MockRenderProcessHost {
530 public:
531 explicit VisitRelayingRenderProcessHost(
532 content::BrowserContext* browser_context)
533 : MockRenderProcessHost(browser_context), widgets_(0) {
534 content::NotificationService::current()->Notify(
535 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
536 content::Source<RenderProcessHost>(this),
537 content::NotificationService::NoDetails());
539 virtual ~VisitRelayingRenderProcessHost() {
540 content::NotificationService::current()->Notify(
541 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
542 content::Source<content::RenderProcessHost>(this),
543 content::NotificationService::NoDetails());
546 virtual void WidgetRestored() OVERRIDE { widgets_++; }
547 virtual void WidgetHidden() OVERRIDE { widgets_--; }
548 virtual int VisibleWidgetCount() const OVERRIDE { return widgets_; }
550 virtual bool Send(IPC::Message* msg) OVERRIDE {
551 VisitCountingContext* counting_context =
552 static_cast<VisitCountingContext*>(
553 GetBrowserContext());
555 if (msg->type() == ChromeViewMsg_VisitedLink_Add::ID) {
556 PickleIterator iter(*msg);
557 std::vector<uint64> fingerprints;
558 CHECK(IPC::ReadParam(msg, &iter, &fingerprints));
559 counting_context->CountAddEvent(fingerprints.size());
560 } else if (msg->type() == ChromeViewMsg_VisitedLink_Reset::ID) {
561 counting_context->CountResetEvent();
562 } else if (msg->type() == ChromeViewMsg_VisitedLink_NewTable::ID) {
563 counting_context->CountNewTable();
566 delete msg;
567 return true;
570 private:
571 int widgets_;
573 DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost);
576 class VisitedLinkRenderProcessHostFactory
577 : public content::RenderProcessHostFactory {
578 public:
579 VisitedLinkRenderProcessHostFactory()
580 : content::RenderProcessHostFactory() {}
581 virtual content::RenderProcessHost* CreateRenderProcessHost(
582 content::BrowserContext* browser_context,
583 content::SiteInstance* site_instance) const OVERRIDE {
584 return new VisitRelayingRenderProcessHost(browser_context);
587 private:
589 DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory);
592 class VisitedLinkEventsTest : public content::RenderViewHostTestHarness {
593 public:
594 virtual void SetUp() {
595 SetRenderProcessHostFactory(&vc_rph_factory_);
596 content::RenderViewHostTestHarness::SetUp();
599 virtual content::BrowserContext* CreateBrowserContext() OVERRIDE {
600 VisitCountingContext* context = new VisitCountingContext();
601 master_.reset(new VisitedLinkMaster(context, &delegate_, true));
602 master_->Init();
603 return context;
606 VisitCountingContext* context() {
607 return static_cast<VisitCountingContext*>(browser_context());
610 VisitedLinkMaster* master() const {
611 return master_.get();
614 void WaitForCoalescense() {
615 // Let the timer fire.
617 // TODO(ajwong): This is horrid! What is the right synchronization method?
618 base::RunLoop run_loop;
619 base::MessageLoop::current()->PostDelayedTask(
620 FROM_HERE,
621 run_loop.QuitClosure(),
622 base::TimeDelta::FromMilliseconds(110));
623 run_loop.Run();
626 protected:
627 VisitedLinkRenderProcessHostFactory vc_rph_factory_;
629 private:
630 TestVisitedLinkDelegate delegate_;
631 scoped_ptr<VisitedLinkMaster> master_;
634 TEST_F(VisitedLinkEventsTest, Coalescense) {
635 // add some URLs to master.
636 // Add a few URLs.
637 master()->AddURL(GURL("http://acidtests.org/"));
638 master()->AddURL(GURL("http://google.com/"));
639 master()->AddURL(GURL("http://chromium.org/"));
640 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting
641 master()->AddURL(GURL("http://acidtests.org/"));
643 // Make sure that coalescing actually occurs. There should be no links or
644 // events received by the renderer.
645 EXPECT_EQ(0, context()->add_count());
646 EXPECT_EQ(0, context()->add_event_count());
648 WaitForCoalescense();
650 // We now should have 3 entries added in 1 event.
651 EXPECT_EQ(3, context()->add_count());
652 EXPECT_EQ(1, context()->add_event_count());
654 // Test whether the coalescing continues by adding a few more URLs.
655 master()->AddURL(GURL("http://google.com/chrome/"));
656 master()->AddURL(GURL("http://webkit.org/"));
657 master()->AddURL(GURL("http://acid3.acidtests.org/"));
659 WaitForCoalescense();
661 // We should have 6 entries added in 2 events.
662 EXPECT_EQ(6, context()->add_count());
663 EXPECT_EQ(2, context()->add_event_count());
665 // Test whether duplicate entries produce add events.
666 master()->AddURL(GURL("http://acidtests.org/"));
668 WaitForCoalescense();
670 // We should have no change in results.
671 EXPECT_EQ(6, context()->add_count());
672 EXPECT_EQ(2, context()->add_event_count());
674 // Ensure that the coalescing does not resume after resetting.
675 master()->AddURL(GURL("http://build.chromium.org/"));
676 master()->DeleteAllURLs();
678 WaitForCoalescense();
680 // We should have no change in results except for one new reset event.
681 EXPECT_EQ(6, context()->add_count());
682 EXPECT_EQ(2, context()->add_event_count());
683 EXPECT_EQ(1, context()->reset_event_count());
686 TEST_F(VisitedLinkEventsTest, Basics) {
687 RenderViewHostTester::For(rvh())->CreateRenderView(base::string16(),
688 MSG_ROUTING_NONE,
689 -1);
691 // Add a few URLs.
692 master()->AddURL(GURL("http://acidtests.org/"));
693 master()->AddURL(GURL("http://google.com/"));
694 master()->AddURL(GURL("http://chromium.org/"));
696 WaitForCoalescense();
698 // We now should have 1 add event.
699 EXPECT_EQ(1, context()->add_event_count());
700 EXPECT_EQ(0, context()->reset_event_count());
702 master()->DeleteAllURLs();
704 WaitForCoalescense();
706 // We should have no change in add results, plus one new reset event.
707 EXPECT_EQ(1, context()->add_event_count());
708 EXPECT_EQ(1, context()->reset_event_count());
711 TEST_F(VisitedLinkEventsTest, TabVisibility) {
712 RenderViewHostTester::For(rvh())->CreateRenderView(base::string16(),
713 MSG_ROUTING_NONE,
714 -1);
716 // Simulate tab becoming inactive.
717 RenderViewHostTester::For(rvh())->SimulateWasHidden();
719 // Add a few URLs.
720 master()->AddURL(GURL("http://acidtests.org/"));
721 master()->AddURL(GURL("http://google.com/"));
722 master()->AddURL(GURL("http://chromium.org/"));
724 WaitForCoalescense();
726 // We shouldn't have any events.
727 EXPECT_EQ(0, context()->add_event_count());
728 EXPECT_EQ(0, context()->reset_event_count());
730 // Simulate the tab becoming active.
731 RenderViewHostTester::For(rvh())->SimulateWasShown();
733 // We should now have 3 add events, still no reset events.
734 EXPECT_EQ(1, context()->add_event_count());
735 EXPECT_EQ(0, context()->reset_event_count());
737 // Deactivate the tab again.
738 RenderViewHostTester::For(rvh())->SimulateWasHidden();
740 // Add a bunch of URLs (over 50) to exhaust the link event buffer.
741 for (int i = 0; i < 100; i++)
742 master()->AddURL(TestURL(i));
744 WaitForCoalescense();
746 // Again, no change in events until tab is active.
747 EXPECT_EQ(1, context()->add_event_count());
748 EXPECT_EQ(0, context()->reset_event_count());
750 // Activate the tab.
751 RenderViewHostTester::For(rvh())->SimulateWasShown();
753 // We should have only one more reset event.
754 EXPECT_EQ(1, context()->add_event_count());
755 EXPECT_EQ(1, context()->reset_event_count());
758 // Tests that VisitedLink ignores renderer process creation notification for a
759 // different context.
760 TEST_F(VisitedLinkEventsTest, IgnoreRendererCreationFromDifferentContext) {
761 VisitCountingContext different_context;
762 VisitRelayingRenderProcessHost different_process_host(&different_context);
764 content::NotificationService::current()->Notify(
765 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
766 content::Source<content::RenderProcessHost>(&different_process_host),
767 content::NotificationService::NoDetails());
768 WaitForCoalescense();
770 EXPECT_EQ(0, different_context.new_table_count());
774 } // namespace visitedlink