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.
9 #include "base/files/file_util.h"
10 #include "base/location.h"
11 #include "base/memory/shared_memory.h"
12 #include "base/process/process_handle.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_util.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/time/time.h"
18 #include "components/visitedlink/browser/visitedlink_delegate.h"
19 #include "components/visitedlink/browser/visitedlink_event_listener.h"
20 #include "components/visitedlink/browser/visitedlink_master.h"
21 #include "components/visitedlink/common/visitedlink_messages.h"
22 #include "components/visitedlink/renderer/visitedlink_slave.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/notification_types.h"
26 #include "content/public/test/mock_render_process_host.h"
27 #include "content/public/test/test_browser_context.h"
28 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "content/public/test/test_renderer_host.h"
30 #include "content/public/test/test_utils.h"
31 #include "testing/gtest/include/gtest/gtest.h"
34 using content::BrowserThread
;
35 using content::MockRenderProcessHost
;
36 using content::RenderViewHostTester
;
38 namespace visitedlink
{
42 typedef std::vector
<GURL
> URLs
;
44 // a nice long URL that we can append numbers to to get new URLs
45 const char g_test_prefix
[] =
46 "http://www.google.com/products/foo/index.html?id=45028640526508376&seq=";
47 const int g_test_count
= 1000;
49 // Returns a test URL for index |i|
51 return GURL(base::StringPrintf("%s%d", g_test_prefix
, i
));
54 std::vector
<VisitedLinkSlave
*> g_slaves
;
56 class TestVisitedLinkDelegate
: public VisitedLinkDelegate
{
58 void RebuildTable(const scoped_refptr
<URLEnumerator
>& enumerator
) override
;
60 void AddURLForRebuild(const GURL
& url
);
66 void TestVisitedLinkDelegate::RebuildTable(
67 const scoped_refptr
<URLEnumerator
>& enumerator
) {
68 for (URLs::const_iterator itr
= rebuild_urls_
.begin();
69 itr
!= rebuild_urls_
.end();
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
{
81 explicit TestURLIterator(const URLs
& urls
);
83 const GURL
& NextURL() override
;
84 bool HasNextURL() const override
;
87 URLs::const_iterator iterator_
;
88 URLs::const_iterator end_
;
91 TestURLIterator::TestURLIterator(const URLs
& urls
)
92 : iterator_(urls
.begin()),
96 const GURL
& TestURLIterator::NextURL() {
97 return *(iterator_
++);
100 bool TestURLIterator::HasNextURL() const {
101 return iterator_
!= end_
;
106 class TrackingVisitedLinkEventListener
: public VisitedLinkMaster::Listener
{
108 TrackingVisitedLinkEventListener()
112 void NewTable(base::SharedMemory
* table
) override
{
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 void Add(VisitedLinkCommon::Fingerprint
) override
{ add_count_
++; }
123 void Reset() override
{ reset_count_
++; }
130 int reset_count() const { return reset_count_
; }
131 int add_count() const { return add_count_
; }
138 class VisitedLinkTest
: public testing::Test
{
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(),
150 suppress_rebuild
, visited_file_
,
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.
161 // Wait for all pending file I/O to be completed.
162 content::RunAllBlockingPoolTasksUntilIdle();
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.
169 // Clean up after our caller, who may have left the database open.
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
);
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/"));
200 found
= slave
.IsVisited(GURL("http://unfound.site/"));
203 master_
->DebugValidate();
209 void SetUp() override
{
210 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
212 history_dir_
= temp_dir_
.path().AppendASCII("VisitedLinkTest");
213 ASSERT_TRUE(base::CreateDirectory(history_dir_
));
215 visited_file_
= history_dir_
.Append(FILE_PATH_LITERAL("VisitedLinks"));
218 void TearDown() override
{ ClearDB(); }
220 base::ScopedTempDir temp_dir_
;
222 // Filenames for the services;
223 base::FilePath history_dir_
;
224 base::FilePath visited_file_
;
226 scoped_ptr
<VisitedLinkMaster
> master_
;
227 TestVisitedLinkDelegate delegate_
;
228 content::TestBrowserThreadBundle thread_bundle_
;
231 // This test creates and reads some databases to make sure the data is
232 // preserved throughout those operations.
233 TEST_F(VisitedLinkTest
, DatabaseIO
) {
234 ASSERT_TRUE(InitVisited(0, true));
236 for (int i
= 0; i
< g_test_count
; i
++)
237 master_
->AddURL(TestURL(i
));
239 // Test that the database was written properly
243 // Checks that we can delete things properly when there are collisions.
244 TEST_F(VisitedLinkTest
, Delete
) {
245 static const int32 kInitialSize
= 17;
246 ASSERT_TRUE(InitVisited(kInitialSize
, true));
248 // Add a cluster from 14-17 wrapping around to 0. These will all hash to the
250 const VisitedLinkCommon::Fingerprint kFingerprint0
= kInitialSize
* 0 + 14;
251 const VisitedLinkCommon::Fingerprint kFingerprint1
= kInitialSize
* 1 + 14;
252 const VisitedLinkCommon::Fingerprint kFingerprint2
= kInitialSize
* 2 + 14;
253 const VisitedLinkCommon::Fingerprint kFingerprint3
= kInitialSize
* 3 + 14;
254 const VisitedLinkCommon::Fingerprint kFingerprint4
= kInitialSize
* 4 + 14;
255 master_
->AddFingerprint(kFingerprint0
, false); // @14
256 master_
->AddFingerprint(kFingerprint1
, false); // @15
257 master_
->AddFingerprint(kFingerprint2
, false); // @16
258 master_
->AddFingerprint(kFingerprint3
, false); // @0
259 master_
->AddFingerprint(kFingerprint4
, false); // @1
261 // Deleting 14 should move the next value up one slot (we do not specify an
263 EXPECT_EQ(kFingerprint3
, master_
->hash_table_
[0]);
264 master_
->DeleteFingerprint(kFingerprint3
, false);
265 VisitedLinkCommon::Fingerprint zero_fingerprint
= 0;
266 EXPECT_EQ(zero_fingerprint
, master_
->hash_table_
[1]);
267 EXPECT_NE(zero_fingerprint
, master_
->hash_table_
[0]);
269 // Deleting the other four should leave the table empty.
270 master_
->DeleteFingerprint(kFingerprint0
, false);
271 master_
->DeleteFingerprint(kFingerprint1
, false);
272 master_
->DeleteFingerprint(kFingerprint2
, false);
273 master_
->DeleteFingerprint(kFingerprint4
, false);
275 EXPECT_EQ(0, master_
->used_items_
);
276 for (int i
= 0; i
< kInitialSize
; i
++)
277 EXPECT_EQ(zero_fingerprint
, master_
->hash_table_
[i
]) <<
278 "Hash table has values in it.";
281 // When we delete more than kBigDeleteThreshold we trigger different behavior
282 // where the entire file is rewritten.
283 TEST_F(VisitedLinkTest
, BigDelete
) {
284 ASSERT_TRUE(InitVisited(16381, true));
286 // Add the base set of URLs that won't be deleted.
287 // Reload() will test for these.
288 for (int32 i
= 0; i
< g_test_count
; i
++)
289 master_
->AddURL(TestURL(i
));
291 // Add more URLs than necessary to trigger this case.
292 const int kTestDeleteCount
= VisitedLinkMaster::kBigDeleteThreshold
+ 2;
294 for (int32 i
= g_test_count
; i
< g_test_count
+ kTestDeleteCount
; i
++) {
295 GURL
url(TestURL(i
));
296 master_
->AddURL(url
);
297 urls_to_delete
.push_back(url
);
300 TestURLIterator
iterator(urls_to_delete
);
301 master_
->DeleteURLs(&iterator
);
302 master_
->DebugValidate();
307 TEST_F(VisitedLinkTest
, DeleteAll
) {
308 ASSERT_TRUE(InitVisited(0, true));
311 VisitedLinkSlave slave
;
312 base::SharedMemoryHandle new_handle
= base::SharedMemory::NULLHandle();
313 master_
->shared_memory()->ShareToProcess(
314 base::GetCurrentProcessHandle(), &new_handle
);
315 slave
.OnUpdateVisitedLinks(new_handle
);
316 g_slaves
.push_back(&slave
);
318 // Add the test URLs.
319 for (int i
= 0; i
< g_test_count
; i
++) {
320 master_
->AddURL(TestURL(i
));
321 ASSERT_EQ(i
+ 1, master_
->GetUsedCount());
323 master_
->DebugValidate();
325 // Make sure the slave picked up the adds.
326 for (int i
= 0; i
< g_test_count
; i
++)
327 EXPECT_TRUE(slave
.IsVisited(TestURL(i
)));
329 // Clear the table and make sure the slave picked it up.
330 master_
->DeleteAllURLs();
331 EXPECT_EQ(0, master_
->GetUsedCount());
332 for (int i
= 0; i
< g_test_count
; i
++) {
333 EXPECT_FALSE(master_
->IsVisited(TestURL(i
)));
334 EXPECT_FALSE(slave
.IsVisited(TestURL(i
)));
337 // Close the database.
342 // Reopen and validate.
343 ASSERT_TRUE(InitVisited(0, true));
344 master_
->DebugValidate();
345 EXPECT_EQ(0, master_
->GetUsedCount());
346 for (int i
= 0; i
< g_test_count
; i
++)
347 EXPECT_FALSE(master_
->IsVisited(TestURL(i
)));
350 // This tests that the master correctly resizes its tables when it gets too
351 // full, notifies its slaves of the change, and updates the disk.
352 TEST_F(VisitedLinkTest
, Resizing
) {
353 // Create a very small database.
354 const int32 initial_size
= 17;
355 ASSERT_TRUE(InitVisited(initial_size
, true));
358 VisitedLinkSlave slave
;
359 base::SharedMemoryHandle new_handle
= base::SharedMemory::NULLHandle();
360 master_
->shared_memory()->ShareToProcess(
361 base::GetCurrentProcessHandle(), &new_handle
);
362 slave
.OnUpdateVisitedLinks(new_handle
);
363 g_slaves
.push_back(&slave
);
365 int32 used_count
= master_
->GetUsedCount();
366 ASSERT_EQ(used_count
, 0);
368 for (int i
= 0; i
< g_test_count
; i
++) {
369 master_
->AddURL(TestURL(i
));
370 used_count
= master_
->GetUsedCount();
371 ASSERT_EQ(i
+ 1, used_count
);
374 // Verify that the table got resized sufficiently.
376 VisitedLinkCommon::Fingerprint
* table
;
377 master_
->GetUsageStatistics(&table_size
, &table
);
378 used_count
= master_
->GetUsedCount();
379 ASSERT_GT(table_size
, used_count
);
380 ASSERT_EQ(used_count
, g_test_count
) <<
381 "table count doesn't match the # of things we added";
383 // Verify that the slave got the resize message and has the same
384 // table information.
385 int32 child_table_size
;
386 VisitedLinkCommon::Fingerprint
* child_table
;
387 slave
.GetUsageStatistics(&child_table_size
, &child_table
);
388 ASSERT_EQ(table_size
, child_table_size
);
389 for (int32 i
= 0; i
< table_size
; i
++) {
390 ASSERT_EQ(table
[i
], child_table
[i
]);
393 master_
->DebugValidate();
396 // This tests that the file is written correctly by reading it in using
401 // Tests that if the database doesn't exist, it will be rebuilt from history.
402 TEST_F(VisitedLinkTest
, Rebuild
) {
403 // Add half of our URLs to history. This needs to be done before we
404 // initialize the visited link DB.
405 int history_count
= g_test_count
/ 2;
406 for (int i
= 0; i
< history_count
; i
++)
407 delegate_
.AddURLForRebuild(TestURL(i
));
409 // Initialize the visited link DB. Since the visited links file doesn't exist
410 // and we don't suppress history rebuilding, this will load from history.
411 ASSERT_TRUE(InitVisited(0, false));
413 // While the table is rebuilding, add the rest of the URLs to the visited
414 // link system. This isn't guaranteed to happen during the rebuild, so we
415 // can't be 100% sure we're testing the right thing, but in practice is.
416 // All the adds above will generally take some time queuing up on the
417 // history thread, and it will take a while to catch up to actually
418 // processing the rebuild that has queued behind it. We will generally
419 // finish adding all of the URLs before it has even found the first URL.
420 for (int i
= history_count
; i
< g_test_count
; i
++)
421 master_
->AddURL(TestURL(i
));
423 // Add one more and then delete it.
424 master_
->AddURL(TestURL(g_test_count
));
426 urls_to_delete
.push_back(TestURL(g_test_count
));
427 TestURLIterator
iterator(urls_to_delete
);
428 master_
->DeleteURLs(&iterator
);
430 // Wait for the rebuild to complete. The task will terminate the message
431 // loop when the rebuild is done. There's no chance that the rebuild will
432 // complete before we set the task because the rebuild completion message
433 // is posted to the message loop; until we Run() it, rebuild can not
435 base::RunLoop run_loop
;
436 master_
->set_rebuild_complete_task(run_loop
.QuitClosure());
439 // Test that all URLs were written to the database properly.
442 // Make sure the extra one was *not* written (Reload won't test this).
443 EXPECT_FALSE(master_
->IsVisited(TestURL(g_test_count
)));
446 // Test that importing a large number of URLs will work
447 TEST_F(VisitedLinkTest
, BigImport
) {
448 ASSERT_TRUE(InitVisited(0, false));
450 // Before the table rebuilds, add a large number of URLs
451 int total_count
= VisitedLinkMaster::kDefaultTableSize
+ 10;
452 for (int i
= 0; i
< total_count
; i
++)
453 master_
->AddURL(TestURL(i
));
455 // Wait for the rebuild to complete.
456 base::RunLoop run_loop
;
457 master_
->set_rebuild_complete_task(run_loop
.QuitClosure());
460 // Ensure that the right number of URLs are present
461 int used_count
= master_
->GetUsedCount();
462 ASSERT_EQ(used_count
, total_count
);
465 TEST_F(VisitedLinkTest
, Listener
) {
466 ASSERT_TRUE(InitVisited(0, true));
469 for (int i
= 0; i
< g_test_count
; i
++) {
470 master_
->AddURL(TestURL(i
));
471 ASSERT_EQ(i
+ 1, master_
->GetUsedCount());
476 urls_to_delete
.push_back(TestURL(0));
477 TestURLIterator
iterator(urls_to_delete
);
478 master_
->DeleteURLs(&iterator
);
480 // ... and all of the remaining ones.
481 master_
->DeleteAllURLs();
483 TrackingVisitedLinkEventListener
* listener
=
484 static_cast<TrackingVisitedLinkEventListener
*>(master_
->GetListener());
486 // Verify that VisitedLinkMaster::Listener::Add was called for each added URL.
487 EXPECT_EQ(g_test_count
, listener
->add_count());
488 // Verify that VisitedLinkMaster::Listener::Reset was called both when one and
489 // all URLs are deleted.
490 EXPECT_EQ(2, listener
->reset_count());
493 class VisitCountingContext
: public content::TestBrowserContext
{
495 VisitCountingContext()
498 reset_event_count_(0),
499 new_table_count_(0) {}
501 void CountAddEvent(int by
) {
506 void CountResetEvent() {
507 reset_event_count_
++;
510 void CountNewTable() {
514 int add_count() const { return add_count_
; }
515 int add_event_count() const { return add_event_count_
; }
516 int reset_event_count() const { return reset_event_count_
; }
517 int new_table_count() const { return new_table_count_
; }
521 int add_event_count_
;
522 int reset_event_count_
;
523 int new_table_count_
;
526 // Stub out as little as possible, borrowing from RenderProcessHost.
527 class VisitRelayingRenderProcessHost
: public MockRenderProcessHost
{
529 explicit VisitRelayingRenderProcessHost(
530 content::BrowserContext
* browser_context
)
531 : MockRenderProcessHost(browser_context
), widgets_(0) {
532 content::NotificationService::current()->Notify(
533 content::NOTIFICATION_RENDERER_PROCESS_CREATED
,
534 content::Source
<RenderProcessHost
>(this),
535 content::NotificationService::NoDetails());
537 ~VisitRelayingRenderProcessHost() override
{
538 content::NotificationService::current()->Notify(
539 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED
,
540 content::Source
<content::RenderProcessHost
>(this),
541 content::NotificationService::NoDetails());
544 void WidgetRestored() override
{ widgets_
++; }
545 void WidgetHidden() override
{ widgets_
--; }
546 int VisibleWidgetCount() const override
{ return widgets_
; }
548 bool Send(IPC::Message
* msg
) override
{
549 VisitCountingContext
* counting_context
=
550 static_cast<VisitCountingContext
*>(
551 GetBrowserContext());
553 if (msg
->type() == ChromeViewMsg_VisitedLink_Add::ID
) {
554 base::PickleIterator
iter(*msg
);
555 std::vector
<uint64
> fingerprints
;
556 CHECK(IPC::ReadParam(msg
, &iter
, &fingerprints
));
557 counting_context
->CountAddEvent(fingerprints
.size());
558 } else if (msg
->type() == ChromeViewMsg_VisitedLink_Reset::ID
) {
559 counting_context
->CountResetEvent();
560 } else if (msg
->type() == ChromeViewMsg_VisitedLink_NewTable::ID
) {
561 counting_context
->CountNewTable();
571 DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost
);
574 class VisitedLinkRenderProcessHostFactory
575 : public content::RenderProcessHostFactory
{
577 VisitedLinkRenderProcessHostFactory()
578 : content::RenderProcessHostFactory() {}
579 content::RenderProcessHost
* CreateRenderProcessHost(
580 content::BrowserContext
* browser_context
,
581 content::SiteInstance
* site_instance
) const override
{
582 return new VisitRelayingRenderProcessHost(browser_context
);
586 DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory
);
589 class VisitedLinkEventsTest
: public content::RenderViewHostTestHarness
{
591 void SetUp() override
{
592 SetRenderProcessHostFactory(&vc_rph_factory_
);
593 content::RenderViewHostTestHarness::SetUp();
596 content::BrowserContext
* CreateBrowserContext() override
{
597 VisitCountingContext
* context
= new VisitCountingContext();
598 master_
.reset(new VisitedLinkMaster(context
, &delegate_
, true));
603 VisitCountingContext
* context() {
604 return static_cast<VisitCountingContext
*>(browser_context());
607 VisitedLinkMaster
* master() const {
608 return master_
.get();
611 void WaitForCoalescense() {
612 // Let the timer fire.
614 // TODO(ajwong): This is horrid! What is the right synchronization method?
615 base::RunLoop run_loop
;
616 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
617 FROM_HERE
, run_loop
.QuitClosure(),
618 base::TimeDelta::FromMilliseconds(110));
623 VisitedLinkRenderProcessHostFactory vc_rph_factory_
;
626 TestVisitedLinkDelegate delegate_
;
627 scoped_ptr
<VisitedLinkMaster
> master_
;
630 TEST_F(VisitedLinkEventsTest
, Coalescense
) {
631 // add some URLs to master.
633 master()->AddURL(GURL("http://acidtests.org/"));
634 master()->AddURL(GURL("http://google.com/"));
635 master()->AddURL(GURL("http://chromium.org/"));
636 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting
637 master()->AddURL(GURL("http://acidtests.org/"));
639 // Make sure that coalescing actually occurs. There should be no links or
640 // events received by the renderer.
641 EXPECT_EQ(0, context()->add_count());
642 EXPECT_EQ(0, context()->add_event_count());
644 WaitForCoalescense();
646 // We now should have 3 entries added in 1 event.
647 EXPECT_EQ(3, context()->add_count());
648 EXPECT_EQ(1, context()->add_event_count());
650 // Test whether the coalescing continues by adding a few more URLs.
651 master()->AddURL(GURL("http://google.com/chrome/"));
652 master()->AddURL(GURL("http://webkit.org/"));
653 master()->AddURL(GURL("http://acid3.acidtests.org/"));
655 WaitForCoalescense();
657 // We should have 6 entries added in 2 events.
658 EXPECT_EQ(6, context()->add_count());
659 EXPECT_EQ(2, context()->add_event_count());
661 // Test whether duplicate entries produce add events.
662 master()->AddURL(GURL("http://acidtests.org/"));
664 WaitForCoalescense();
666 // We should have no change in results.
667 EXPECT_EQ(6, context()->add_count());
668 EXPECT_EQ(2, context()->add_event_count());
670 // Ensure that the coalescing does not resume after resetting.
671 master()->AddURL(GURL("http://build.chromium.org/"));
672 master()->DeleteAllURLs();
674 WaitForCoalescense();
676 // We should have no change in results except for one new reset event.
677 EXPECT_EQ(6, context()->add_count());
678 EXPECT_EQ(2, context()->add_event_count());
679 EXPECT_EQ(1, context()->reset_event_count());
682 TEST_F(VisitedLinkEventsTest
, Basics
) {
683 RenderViewHostTester::For(rvh())->CreateTestRenderView(
684 base::string16(), MSG_ROUTING_NONE
, MSG_ROUTING_NONE
, -1, false);
687 master()->AddURL(GURL("http://acidtests.org/"));
688 master()->AddURL(GURL("http://google.com/"));
689 master()->AddURL(GURL("http://chromium.org/"));
691 WaitForCoalescense();
693 // We now should have 1 add event.
694 EXPECT_EQ(1, context()->add_event_count());
695 EXPECT_EQ(0, context()->reset_event_count());
697 master()->DeleteAllURLs();
699 WaitForCoalescense();
701 // We should have no change in add results, plus one new reset event.
702 EXPECT_EQ(1, context()->add_event_count());
703 EXPECT_EQ(1, context()->reset_event_count());
706 TEST_F(VisitedLinkEventsTest
, TabVisibility
) {
707 RenderViewHostTester::For(rvh())->CreateTestRenderView(
708 base::string16(), MSG_ROUTING_NONE
, MSG_ROUTING_NONE
, -1, false);
710 // Simulate tab becoming inactive.
711 RenderViewHostTester::For(rvh())->SimulateWasHidden();
714 master()->AddURL(GURL("http://acidtests.org/"));
715 master()->AddURL(GURL("http://google.com/"));
716 master()->AddURL(GURL("http://chromium.org/"));
718 WaitForCoalescense();
720 // We shouldn't have any events.
721 EXPECT_EQ(0, context()->add_event_count());
722 EXPECT_EQ(0, context()->reset_event_count());
724 // Simulate the tab becoming active.
725 RenderViewHostTester::For(rvh())->SimulateWasShown();
727 // We should now have 3 add events, still no reset events.
728 EXPECT_EQ(1, context()->add_event_count());
729 EXPECT_EQ(0, context()->reset_event_count());
731 // Deactivate the tab again.
732 RenderViewHostTester::For(rvh())->SimulateWasHidden();
734 // Add a bunch of URLs (over 50) to exhaust the link event buffer.
735 for (int i
= 0; i
< 100; i
++)
736 master()->AddURL(TestURL(i
));
738 WaitForCoalescense();
740 // Again, no change in events until tab is active.
741 EXPECT_EQ(1, context()->add_event_count());
742 EXPECT_EQ(0, context()->reset_event_count());
745 RenderViewHostTester::For(rvh())->SimulateWasShown();
747 // We should have only one more reset event.
748 EXPECT_EQ(1, context()->add_event_count());
749 EXPECT_EQ(1, context()->reset_event_count());
752 // Tests that VisitedLink ignores renderer process creation notification for a
753 // different context.
754 TEST_F(VisitedLinkEventsTest
, IgnoreRendererCreationFromDifferentContext
) {
755 VisitCountingContext different_context
;
756 VisitRelayingRenderProcessHost
different_process_host(&different_context
);
758 content::NotificationService::current()->Notify(
759 content::NOTIFICATION_RENDERER_PROCESS_CREATED
,
760 content::Source
<content::RenderProcessHost
>(&different_process_host
),
761 content::NotificationService::NoDetails());
762 WaitForCoalescense();
764 EXPECT_EQ(0, different_context
.new_table_count());
767 } // namespace visitedlink