diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/navigation_controller_unittest.cc | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/navigation_controller_unittest.cc')
-rw-r--r-- | chrome/browser/navigation_controller_unittest.cc | 818 |
1 files changed, 818 insertions, 0 deletions
diff --git a/chrome/browser/navigation_controller_unittest.cc b/chrome/browser/navigation_controller_unittest.cc new file mode 100644 index 0000000..6b8de0d --- /dev/null +++ b/chrome/browser/navigation_controller_unittest.cc @@ -0,0 +1,818 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/browser/browser_type.h" +#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/profile_manager.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/session_service_test_helper.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/browser/tab_contents_delegate.h" +#include "chrome/browser/tab_contents_factory.h" +#include "chrome/common/stl_util-inl.h" +#include "chrome/test/testing_profile.h" +#include "net/base/net_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// TODO(darin): come up with a better way to define these integers +// TODO(acw): we should have a real dynamic factory for content types. +// That way we could have several implementation of +// TabContents::CreateWithType(). Once this is done we'll be able to +// have a unit test for NavigationController::Clone() +const TabContentsType kTestContentsType1 = + static_cast<TabContentsType>(TAB_CONTENTS_NUM_TYPES + 1); +const TabContentsType kTestContentsType2 = + static_cast<TabContentsType>(TAB_CONTENTS_NUM_TYPES + 2); + +class TestContents : public TabContents { + public: + BEGIN_MSG_MAP(TestContents) + END_MSG_MAP() + + TestContents(TabContentsType type) : TabContents(type) { + } + + // Just record the navigation so it can be checked by the test case + bool Navigate(const NavigationEntry& entry, bool reload) { + pending_entry_.reset(new NavigationEntry(entry)); + return true; + } + + void CompleteNavigation(int page_id) { + DCHECK(pending_entry_.get()); + pending_entry_->SetPageID(page_id); + DidNavigateToEntry(pending_entry_.get()); + controller()->SyncSessionWithEntryByPageID(type(), NULL, page_id); + pending_entry_.release(); + } + + NavigationEntry* pending_entry() const { return pending_entry_.get(); } + void set_pending_entry(NavigationEntry* e) { pending_entry_.reset(e); } + + private: + scoped_ptr<NavigationEntry> pending_entry_; +}; + +class TestContentsFactory : public TabContentsFactory { + public: + TestContentsFactory(TabContentsType type, const char* scheme) + : type_(type), + scheme_(scheme) { + } + + virtual TabContents* CreateInstance() { + return new TestContents(type_); + } + + virtual bool CanHandleURL(const GURL& url) { + return url.SchemeIs(scheme_); + } + + private: + TabContentsType type_; + const char* scheme_; +}; + +TestContentsFactory factory1(kTestContentsType1, "test1"); +TestContentsFactory factory2(kTestContentsType2, "test2"); + +class NavigationControllerTest : public testing::Test, + public TabContentsDelegate { + public: + NavigationControllerTest() : contents(NULL), profile(NULL) { + } + + ~NavigationControllerTest() { + delete profile; + } + + // testing::Test methods: + + virtual void SetUp() { + TabContents::RegisterFactory(kTestContentsType1, &factory1); + TabContents::RegisterFactory(kTestContentsType2, &factory2); + + if (!profile) + profile = new TestingProfile(); + + contents = new TestContents(kTestContentsType1); + contents->set_delegate(this); + contents->CreateView(::GetDesktopWindow(), gfx::Rect()); + contents->SetupController(profile); + } + + virtual void TearDown() { + // Make sure contents is valid. NavigationControllerHistoryTest ends up + // resetting this before TearDown is invoked. + if (contents) + ClearContents(); + } + + + void ClearContents() { + contents->set_delegate(NULL); + contents->CloseContents(); + contents = NULL; + + TabContents::RegisterFactory(kTestContentsType1, NULL); + TabContents::RegisterFactory(kTestContentsType2, NULL); + } + + // TabContentsDelegate methods (only care about ReplaceContents): + virtual void OpenURLFromTab(TabContents*, + const GURL&, + WindowOpenDisposition, + PageTransition::Type) {} + virtual void NavigationStateChanged(const TabContents*, + unsigned flags) {} + virtual void ReplaceContents(TabContents* source, + TabContents* new_contents) { + contents->set_delegate(NULL); + contents = static_cast<TestContents*>(new_contents); + contents->set_delegate(this); + } + virtual void AddNewContents(TabContents*, + TabContents*, + WindowOpenDisposition, + const gfx::Rect&, + bool user_gesture) {} + virtual void ActivateContents(TabContents*) {} + virtual void LoadingStateChanged(TabContents*) {} + virtual void NavigateToPage(TabContents*, const GURL&, + PageTransition::Type) {} + virtual void CloseContents(TabContents*) {} + virtual void MoveContents(TabContents*, const gfx::Rect&) {} + virtual bool IsPopup(TabContents*) { return false; } + virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {} + virtual void URLStarredChanged(TabContents* source, bool starred) {} + virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}; + + TestContents* contents; + + Profile* profile; +}; + +class NavigationControllerHistoryTest : public NavigationControllerTest { + public: + NavigationControllerHistoryTest() + : profile_manager_(NULL), + url0("test1:foo1"), + url1("test1:foo1"), + url2("test1:foo1") { + } + + virtual ~NavigationControllerHistoryTest() { + // Prevent our base class from deleting the profile since profile's + // lifetime is managed by profile_manager_. + profile = NULL; + STLDeleteElements(&windows_); + } + + virtual void SetUp() { + // Calculate the path for a scratch profile, and make sure it's empty. + ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_)); + file_util::AppendToPath(&test_dir_, L"NavigationControllerTest"); + profile_path_ = test_dir_; + file_util::AppendToPath(&profile_path_, L"New Profile"); + file_util::Delete(test_dir_, true); + CreateDirectory(test_dir_.c_str(), NULL); + + // Create a profile. + profile_manager_ = new ProfileManager(); + profile = ProfileManager::CreateProfile(profile_path_, + L"New Profile", L"new-profile", L""); + ASSERT_TRUE(profile); + profile_manager_->AddProfile(profile); + + // Do the super thing. Notice that the above code sets profile, profile is + // used in NavigationControllerTest::SetUp(), hence it now. + NavigationControllerTest::SetUp(); + + // Force the session service to be created. + SessionService* service = profile->GetSessionService(); + service->SetWindowType(window_id, BrowserType::TABBED_BROWSER); + service->SetWindowBounds(window_id, gfx::Rect(0, 1, 2, 3), false); + service->SetTabIndexInWindow(window_id, + contents->controller()->session_id(), 0); + contents->controller()->SetWindowID(window_id); + } + + virtual void TearDown() { + NavigationControllerTest::TearDown(); + + helper_.set_service(NULL); + + // Make sure we wait for history to shut down before continuing. The task + // we add will cause our message loop to quit once it is destroyed. + HistoryService* history = + profile->GetHistoryService(Profile::IMPLICIT_ACCESS); + history->SetOnBackendDestroyTask(new MessageLoop::QuitTask); + delete profile_manager_; + MessageLoop::current()->Run(); + + ASSERT_TRUE(file_util::Delete(test_dir_, true)); + ASSERT_FALSE(file_util::PathExists(test_dir_)); + } + + // Deletes the current profile manager and creates a new one. Indirectly this + // shuts down the history database and reopens it. + void ReopenDatabase() { + ClearContents(); + helper_.set_service(NULL); + delete profile_manager_; + profile_manager_ = new ProfileManager(); + profile_manager_->AddProfileByPath(profile_path_); + profile = profile_manager_->GetProfileByPath(profile_path_); + helper_.set_service(profile->GetSessionService()); + } + + void GetLastSession() { + Profile* profile = contents->profile(); + profile->GetSessionService()->TabClosed( + contents->controller()->window_id(), + contents->controller()->session_id()); + + ReopenDatabase(); + Time close_time; + + helper_.ReadWindows(&windows_); + } + + CancelableRequestConsumer consumer; + + // URLs for testing. + const GURL url0; + const GURL url1; + const GURL url2; + + std::vector<SessionWindow*> windows_; + + SessionID window_id; + + SessionServiceTestHelper helper_; + + private: + ProfileManager* profile_manager_; + std::wstring test_dir_; + std::wstring profile_path_; +}; + +} // namespace + +TEST_F(NavigationControllerTest, Defaults) { + EXPECT_TRUE(contents->is_active()); + EXPECT_TRUE(contents->controller()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->GetLastCommittedEntry()); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), -1); + EXPECT_EQ(contents->controller()->GetEntryCount(), 0); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + EXPECT_FALSE(contents->controller()->CanStop()); +} + +TEST_F(NavigationControllerTest, LoadURL) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + + // the load should now be pending + EXPECT_TRUE(contents->pending_entry()); + EXPECT_EQ(contents->controller()->GetEntryCount(), 0); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), -1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_FALSE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + EXPECT_EQ(contents->GetMaxPageID(), -1); + + contents->CompleteNavigation(0); + + // the load should now be committed + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + EXPECT_EQ(contents->GetMaxPageID(), 0); + + // load another... + contents->controller()->LoadURL(url2, PageTransition::TYPED); + + // the load should now be pending + EXPECT_TRUE(contents->pending_entry()); + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + // TODO(darin): maybe this should really be true? + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + EXPECT_EQ(contents->GetMaxPageID(), 0); + + contents->CompleteNavigation(1); + + // the load should now be committed + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + EXPECT_EQ(contents->GetMaxPageID(), 1); +} + +// Tests what happens when the same page is loaded again. Should not create a +// new session history entry. +TEST_F(NavigationControllerTest, LoadURL_SamePage) { + const GURL url1("test1:foo1"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + // should not have produced a new session history entry + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +TEST_F(NavigationControllerTest, LoadURL_Discarded) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->controller()->DiscardPendingEntry(); + + // should not have produced a new session history entry + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +TEST_F(NavigationControllerTest, Reload) { + const GURL url1("test1:foo1"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->Reload(); + + // the reload is pending... + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + + contents->CompleteNavigation(0); + + // now the reload is committed... + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +// Tests what happens when a reload navigation produces a new page. +TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->Reload(); + + contents->pending_entry()->SetURL(url2); + contents->pending_entry()->SetTransitionType(PageTransition::LINK); + contents->CompleteNavigation(1); + + // now the reload is committed... + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +// Tests what happens when we navigate back successfully +TEST_F(NavigationControllerTest, Back) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->GoBack(); + + // should now have a pending navigation to go back... + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_TRUE(contents->controller()->CanGoForward()); + + contents->CompleteNavigation(0); + + // the back navigation completed successfully + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_TRUE(contents->controller()->CanGoForward()); +} + +// Tests what happens when a back navigation produces a new page. +TEST_F(NavigationControllerTest, Back_GeneratesNewPage) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + const GURL url3("test1:foo3"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->GoBack(); + + // should now have a pending navigation to go back... + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 0); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_TRUE(contents->controller()->CanGoForward()); + + contents->pending_entry()->SetURL(url3); + contents->pending_entry()->SetTransitionType(PageTransition::LINK); + contents->CompleteNavigation(2); + + // the back navigation resulted in a completely new navigation. + // TODO(darin): perhaps this behavior will be confusing to users? + EXPECT_EQ(contents->controller()->GetEntryCount(), 3); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 2); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +// Tests what happens when we navigate forward successfully +TEST_F(NavigationControllerTest, Forward) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->GoBack(); + contents->CompleteNavigation(0); + + contents->controller()->GoForward(); + + // should now have a pending navigation to go forward... + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + + contents->CompleteNavigation(1); + + // the forward navigation completed successfully + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +// Tests what happens when a forward navigation produces a new page. +TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + const GURL url3("test1:foo3"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->GoBack(); + contents->CompleteNavigation(0); + + contents->controller()->GoForward(); + + // should now have a pending navigation to go forward... + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), 1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_TRUE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + + contents->pending_entry()->SetURL(url3); + contents->pending_entry()->SetTransitionType(PageTransition::LINK); + contents->CompleteNavigation(2); + + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +TEST_F(NavigationControllerTest, LinkClick) { + const GURL url1("test1:foo1"); + const GURL url2("test1:foo2"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->set_pending_entry(new NavigationEntry(kTestContentsType1, NULL, 0, + url2, + std::wstring(), + PageTransition::LINK)); + contents->CompleteNavigation(1); + + // should not have produced a new session history entry + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +TEST_F(NavigationControllerTest, DISABLED_SwitchTypes) { + const GURL url1("test1:foo"); + const GURL url2("test2:foo"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + TestContents* initial_contents = contents; + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + + // The tab contents should have been replaced + ASSERT_TRUE(initial_contents != contents); + + contents->CompleteNavigation(0); + + // A second navigation entry should have been committed even though the + // PageIDs are the same. PageIDs are scoped to the tab contents type. + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_TRUE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); + + // Navigate back... + contents->controller()->GoBack(); + ASSERT_TRUE(initial_contents == contents); // switched again! + contents->CompleteNavigation(0); + + EXPECT_EQ(contents->controller()->GetEntryCount(), 2); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_TRUE(contents->controller()->CanGoForward()); +} + +// Tests what happens when we begin to navigate to a new contents type, but +// then that navigation gets discarded instead. +TEST_F(NavigationControllerTest, DISABLED_SwitchTypes_Discard) { + const GURL url1("test1:foo"); + const GURL url2("test2:foo"); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(0); + + TestContents* initial_contents = contents; + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + + // The tab contents should have been replaced + ASSERT_TRUE(initial_contents != contents); + + contents->controller()->DiscardPendingEntry(); + + // The tab contents should have been replaced back + ASSERT_TRUE(initial_contents == contents); + + EXPECT_EQ(contents->controller()->GetEntryCount(), 1); + EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); + EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); + EXPECT_TRUE(contents->controller()->GetLastCommittedEntry()); + EXPECT_FALSE(contents->controller()->GetPendingEntry()); + EXPECT_FALSE(contents->controller()->CanGoBack()); + EXPECT_FALSE(contents->controller()->CanGoForward()); +} + +// Tests that we limit the number of navigation entries created correctly. +TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) { + const size_t kMaxEntryCount = 5; + + contents->controller()->max_entry_count_ = kMaxEntryCount; + + int url_index; + char buffer[128]; + // Load up to the max count, all entries should be there. + for (url_index = 0; url_index < kMaxEntryCount; url_index++) { + SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index); + contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED); + contents->CompleteNavigation(url_index); + } + + EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount); + + // Navigate some more. + SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index); + contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED); + contents->CompleteNavigation(url_index); + url_index++; + + // We expect http://www.a.com/0 to be gone. + EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount); + EXPECT_EQ(contents->controller()->GetEntryAtIndex(0)->GetURL(), + GURL("test1://www.a.com/1")); + + // More navigations. + for (int i = 0; i < 3; i++) { + SNPrintF(buffer, 128, "test1://www.a.com/%d", url_index); + contents->controller()->LoadURL(GURL(buffer), PageTransition::TYPED); + contents->CompleteNavigation(url_index); + url_index++; + } + EXPECT_EQ(contents->controller()->GetEntryCount(), kMaxEntryCount); + EXPECT_EQ(contents->controller()->GetEntryAtIndex(0)->GetURL(), + GURL("test1://www.a.com/4")); +} + +// A basic test case. Navigates to a single url, and make sure the history +// db matches. +TEST_F(NavigationControllerHistoryTest, Basic) { + contents->controller()->LoadURL(url0, PageTransition::TYPED); + contents->CompleteNavigation(0); + + GetLastSession(); + + helper_.AssertSingleWindowWithSingleTab(windows_, 1); + helper_.AssertTabEquals(0, 0, 1, *(windows_[0]->tabs[0])); + TabNavigation nav1(0, url0, std::wstring(), std::string(), + PageTransition::TYPED); + helper_.AssertNavigationEquals(nav1, windows_[0]->tabs[0]->navigations[0]); +} + +// Navigates to three urls, then goes back and make sure the history database +// is in sync. +TEST_F(NavigationControllerHistoryTest, NavigationThenBack) { + contents->controller()->LoadURL(url0, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(2); + + contents->controller()->GoBack(); + contents->CompleteNavigation(1); + + GetLastSession(); + + helper_.AssertSingleWindowWithSingleTab(windows_, 3); + helper_.AssertTabEquals(0, 1, 3, *(windows_[0]->tabs[0])); + + TabNavigation nav(0, url0, std::wstring(), std::string(), + PageTransition::TYPED); + helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[0]); + nav.index = 1; + nav.url = url1; + helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[1]); + nav.index = 2; + nav.url = url2; + helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[2]); +} + +// Navigates to three urls, then goes back twice, then loads a new url. +TEST_F(NavigationControllerHistoryTest, NavigationPruning) { + contents->controller()->LoadURL(url0, PageTransition::TYPED); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url1, PageTransition::TYPED); + contents->CompleteNavigation(1); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(2); + + contents->controller()->GoBack(); + contents->CompleteNavigation(1); + + contents->controller()->GoBack(); + contents->CompleteNavigation(0); + + contents->controller()->LoadURL(url2, PageTransition::TYPED); + contents->CompleteNavigation(3); + + // Now have url0, and url2. + + GetLastSession(); + + helper_.AssertSingleWindowWithSingleTab(windows_, 2); + helper_.AssertTabEquals(0, 1, 2, *(windows_[0]->tabs[0])); + + TabNavigation nav(0, url0, std::wstring(), std::string(), + PageTransition::TYPED); + helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[0]); + nav.index = 1; + nav.url = url2; + helper_.AssertNavigationEquals(nav, windows_[0]->tabs[0]->navigations[1]); +} |