Index: chrome/browser/prerender/prerender_render_view_tracker_unittest.cc |
diff --git a/chrome/browser/prerender/prerender_render_view_tracker_unittest.cc b/chrome/browser/prerender/prerender_render_view_tracker_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c5017cd026a07da271fcc18ff5e9bd25e8093a9e |
--- /dev/null |
+++ b/chrome/browser/prerender/prerender_render_view_tracker_unittest.cc |
@@ -0,0 +1,330 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <set> |
+ |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "chrome/browser/prerender/prerender_manager.h" |
+#include "chrome/browser/prerender/prerender_render_view_tracker.h" |
+#include "chrome/test/base/testing_browser_process.h" |
+#include "content/test/test_browser_thread.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using content::BrowserThread; |
+ |
+namespace prerender { |
+ |
+namespace { |
+ |
+class TestPrerenderManager : public PrerenderManager { |
+ public: |
+ explicit TestPrerenderManager( |
+ PrerenderRenderViewTracker* prerender_render_view_tracker) |
+ : PrerenderManager(NULL, prerender_render_view_tracker) { |
+ mutable_config().rate_limit_enabled = false; |
+ } |
+ |
+ virtual void DestroyPrerenderForRenderView( |
+ int process_id, int view_id, FinalStatus final_status) OVERRIDE { |
+ cancelled_id_pairs_.insert(std::make_pair(process_id, view_id)); |
+ } |
+ |
+ bool WasPrerenderCancelled(int child_id, int route_id) { |
+ std::pair<int, int> child_route_id_pair(child_id, route_id); |
+ return cancelled_id_pairs_.count(child_route_id_pair) != 0; |
+ } |
+ |
+ // Set of all the RenderViews that have been cancelled. |
+ std::set<std::pair<int, int> > cancelled_id_pairs_; |
+}; |
+ |
+} // namespace |
+ |
+class PrerenderRenderViewTrackerTest : public testing::Test { |
+ public: |
+ PrerenderRenderViewTrackerTest() : |
+ ui_thread_(BrowserThread::UI, &message_loop_), |
+ io_thread_(BrowserThread::IO, &message_loop_), |
+ prerender_manager_( |
+ new TestPrerenderManager(prerender_render_view_tracker())) { |
+ } |
+ |
+ TestPrerenderManager* prerender_manager() { |
+ return prerender_manager_.get(); |
+ } |
+ |
+ PrerenderRenderViewTracker* prerender_render_view_tracker() { |
+ return g_browser_process->prerender_render_view_tracker(); |
+ } |
+ |
+ int GetCurrentStatus(int child_id, int route_id) { |
+ FinalStatus final_status; |
+ if (!prerender_render_view_tracker()->GetFinalStatus(child_id, route_id, |
+ &final_status)) { |
+ return -1; |
+ } |
+ return final_status; |
+ } |
+ |
+ // Runs any tasks queued on either thread. |
+ void RunEvents() { |
+ message_loop_.RunAllPending(); |
+ } |
+ |
+ private: |
+ MessageLoop message_loop_; |
+ content::TestBrowserThread ui_thread_; |
+ content::TestBrowserThread io_thread_; |
+ |
+ scoped_ptr<TestPrerenderManager> prerender_manager_; |
+}; |
+ |
+// Check that a non-existant RenderView is handled correctly. |
+TEST_F(PrerenderRenderViewTrackerTest, PrerenderRenderViewTrackerNull) { |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+} |
+ |
+// Check that a page that is used is handled correctly. |
+TEST_F(PrerenderRenderViewTrackerTest, PrerenderRenderViewTrackerUsed) { |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 0, 0, prerender_manager()); |
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0)); |
+ |
+ // This calls AddPrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ EXPECT_TRUE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0)); |
+ |
+ // Display the prerendered RenderView. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ |
+ // Make sure the page can't be destroyed or claim it was destroyed after |
+ // it's been used. |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0)); |
+ |
+ // This would call DestroyPrerenderForChildRouteIdPair(), if the prerender |
+ // were cancelled. |
+ RunEvents(); |
+ |
+ // These functions should all behave as before. |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0)); |
+ |
+ // This calls DestroyPrerenderForChildRouteIdPair(). |
+ prerender_render_view_tracker()->OnPrerenderingFinished(0, 0); |
+ EXPECT_TRUE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ |
+ // This calls RemovePrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+} |
+ |
+// Check that a prerendered page cancelled by TryCancel() is handled correctly. |
+TEST_F(PrerenderRenderViewTrackerTest, PrerenderRenderViewTrackerCancelled) { |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 0, 0, prerender_manager()); |
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0)); |
+ |
+ // This calls AddPrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ // Cancel the prerender. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0)); |
+ |
+ // This calls DestroyPrerenderForChildRouteIdPair(). |
+ RunEvents(); |
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+ |
+ // These should all work until the prerendering RenderViewHost is destroyed. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0)); |
+ |
+ prerender_render_view_tracker()->OnPrerenderingFinished(0, 0); |
+ EXPECT_TRUE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ |
+ // This calls RemovePrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+} |
+ |
+// Check that a prerendered page cancelled on the IO thread by |
+// TryCancelOnIOThread() is handled correctly. |
+TEST_F(PrerenderRenderViewTrackerTest, |
+ PrerenderRenderViewTrackerCancelledOnIO) { |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 0, 0, prerender_manager()); |
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0)); |
+ |
+ // This calls AddPrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ // Cancel the prerender. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_EQ(FINAL_STATUS_TIMED_OUT, GetCurrentStatus(0, 0)); |
+ |
+ // This calls DestroyPrerenderForChildRouteIdPair(). |
+ RunEvents(); |
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+ |
+ // These should all work until the prerendering RenderViewHost is destroyed. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_EQ(FINAL_STATUS_TIMED_OUT, GetCurrentStatus(0, 0)); |
+ |
+ prerender_render_view_tracker()->OnPrerenderingFinished(0, 0); |
+ EXPECT_TRUE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ |
+ // This calls RemovePrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+} |
+ |
+// Check that a prerendered page cancelled before it reaches the IO thread is |
+// handled correctly. |
+TEST_F(PrerenderRenderViewTrackerTest, |
+ PrerenderRenderViewTrackerCancelledFast) { |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 0, 0, prerender_manager()); |
+ // Cancel the prerender. |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ |
+ // This calls AddPrerenderOnIOThreadTask() and |
+ // DestroyPrerenderForChildRouteIdPair(). |
+ RunEvents(); |
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+ |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_TIMED_OUT)); |
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0)); |
+ |
+ prerender_render_view_tracker()->OnPrerenderingFinished(0, 0); |
+ |
+ // This calls RemovePrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+} |
+ |
+// Check that handling two pages at once works. |
+TEST_F(PrerenderRenderViewTrackerTest, PrerenderRenderViewTrackerMultiple) { |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 0, 0, prerender_manager()); |
+ |
+ // This calls AddPrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ EXPECT_TRUE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(1, 2)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(1, 2)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 1, 2, FINAL_STATUS_HTTPS)); |
+ |
+ // Start second prerender. |
+ prerender_render_view_tracker()->OnPrerenderingStarted( |
+ 1, 2, prerender_manager()); |
+ // This calls AddPrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ // Use (0, 0). |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryUse(0, 0)); |
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0)); |
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(1, 2)); |
+ |
+ // Cancel (1, 2). |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancelOnIOThread( |
+ 1, 2, FINAL_STATUS_HTTPS)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryCancel( |
+ 0, 0, FINAL_STATUS_HTTPS)); |
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->TryUse(1, 2)); |
+ EXPECT_TRUE(prerender_render_view_tracker()->TryCancel( |
+ 1, 2, FINAL_STATUS_HTTPS)); |
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(1, 2)); |
+ |
+ // This calls DestroyPrerenderForChildRouteIdPair(). |
+ RunEvents(); |
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0)); |
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(1, 2)); |
+ |
+ prerender_render_view_tracker()->OnPrerenderingFinished(0, 0); |
+ prerender_render_view_tracker()->OnPrerenderingFinished(1, 2); |
+ |
+ // This calls RemovePrerenderOnIOThreadTask(). |
+ RunEvents(); |
+ |
+ FinalStatus final_status; |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 0, 0, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(0, 0)); |
+ |
+ EXPECT_FALSE(prerender_render_view_tracker()->GetFinalStatus( |
+ 1, 2, &final_status)); |
+ EXPECT_FALSE(prerender_render_view_tracker()->IsPrerenderingOnIOThread(1, 2)); |
+} |
+ |
+} // namespace prerender |