Index: ios/shared/chrome/browser/tabs/web_state_list_unittest.mm |
diff --git a/ios/shared/chrome/browser/tabs/web_state_list_unittest.mm b/ios/shared/chrome/browser/tabs/web_state_list_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1c0ed211d1910e4f790bee4090331cde12c92b90 |
--- /dev/null |
+++ b/ios/shared/chrome/browser/tabs/web_state_list_unittest.mm |
@@ -0,0 +1,373 @@ |
+// Copyright 2017 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. |
+ |
+#import "ios/shared/chrome/browser/tabs/web_state_list.h" |
+ |
+#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/supports_user_data.h" |
+#import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
+#import "ios/web/public/test/fakes/test_web_state.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/platform_test.h" |
+ |
+namespace { |
+const char kURL0[] = "https://chromium.org/0"; |
+const char kURL1[] = "https://chromium.org/1"; |
+const char kURL2[] = "https://chromium.org/2"; |
+const char kSupportsUserDataDeathGuardKey = '\0'; |
+ |
+// A base::SupportsUserData::Data that tracks whether a base::SupportsUserData |
+// has been deleted (the fact is recorded in a provided pointer as part of the |
+// object destruction). |
+class SupportsUserDataDeathGuard : public base::SupportsUserData::Data { |
+ public: |
+ explicit SupportsUserDataDeathGuard(bool* object_was_destroyed) |
+ : object_was_destroyed_(object_was_destroyed) { |
+ *object_was_destroyed_ = false; |
+ } |
+ |
+ ~SupportsUserDataDeathGuard() override { *object_was_destroyed_ = true; } |
+ |
+ private: |
+ bool* object_was_destroyed_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SupportsUserDataDeathGuard); |
+}; |
+ |
+// WebStateList observer that records which events have been called by the |
+// WebStateList. |
+class WebStateListTestObserver : public WebStateListObserver { |
+ public: |
+ WebStateListTestObserver() = default; |
+ |
+ // Reset statistics whether events have been called. |
+ void ResetStatistics() { |
+ web_state_inserted_called_ = false; |
+ web_state_moved_called_ = false; |
+ web_state_replaced_called_ = false; |
+ web_state_detached_called_ = false; |
+ } |
+ |
+ // Returns whether WebStateInsertedAt was invoked. |
+ bool web_state_inserted_called() const { return web_state_inserted_called_; } |
+ |
+ // Returns whether WebStateMoved was invoked. |
+ bool web_state_moved_called() const { return web_state_moved_called_; } |
+ |
+ // Returns whether WebStateReplacedAt was invoked. |
+ bool web_state_replaced_called() const { return web_state_replaced_called_; } |
+ |
+ // Returns whether WebStateDetachedAt was invoked. |
+ bool web_state_detached_called() const { return web_state_detached_called_; } |
+ |
+ // WebStateListObserver implementation. |
+ void WebStateInsertedAt(WebStateList* web_state_list, |
+ web::WebState* web_state, |
+ int index) override { |
+ web_state_inserted_called_ = true; |
+ } |
+ |
+ void WebStateMoved(WebStateList* web_state_list, |
+ web::WebState* web_state, |
+ int from_index, |
+ int to_index) override { |
+ web_state_moved_called_ = true; |
+ } |
+ |
+ void WebStateReplacedAt(WebStateList* web_state_list, |
+ web::WebState* old_web_state, |
+ web::WebState* new_web_state, |
+ int index) override { |
+ web_state_replaced_called_ = true; |
+ } |
+ |
+ void WebStateDetachedAt(WebStateList* web_state_list, |
+ web::WebState* web_state, |
+ int index) override { |
+ web_state_detached_called_ = true; |
+ } |
+ |
+ private: |
+ bool web_state_inserted_called_ = false; |
+ bool web_state_moved_called_ = false; |
+ bool web_state_replaced_called_ = false; |
+ bool web_state_detached_called_ = false; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WebStateListTestObserver); |
+}; |
+} // namespace |
+ |
+class WebStateListTest : public PlatformTest { |
+ public: |
+ WebStateListTest() : web_state_list_(WebStateList::WebStateOwned) { |
+ web_state_list_.AddObserver(&observer_); |
+ } |
+ |
+ ~WebStateListTest() override { web_state_list_.RemoveObserver(&observer_); } |
+ |
+ protected: |
+ WebStateList web_state_list_; |
+ WebStateListTestObserver observer_; |
+ |
+ // This method should return std::unique_ptr<> however, due to the complex |
+ // ownership of Tab, WebStateList currently uses raw pointers. Change this |
+ // once Tab ownership is sane, see http://crbug.com/546222 for progress. |
+ web::WebState* CreateWebState(const char* url) { |
+ auto test_web_state = base::MakeUnique<web::TestWebState>(); |
+ test_web_state->SetCurrentURL(GURL(url)); |
+ return test_web_state.release(); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(WebStateListTest); |
+}; |
+ |
+TEST_F(WebStateListTest, IsEmpty) { |
+ EXPECT_EQ(0, web_state_list_.count()); |
+ EXPECT_TRUE(web_state_list_.empty()); |
+ |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ |
+ EXPECT_TRUE(observer_.web_state_inserted_called()); |
+ EXPECT_EQ(1, web_state_list_.count()); |
+ EXPECT_FALSE(web_state_list_.empty()); |
+} |
+ |
+TEST_F(WebStateListTest, InsertUrlSingle) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ |
+ EXPECT_TRUE(observer_.web_state_inserted_called()); |
+ EXPECT_EQ(1, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, InsertUrlMultiple) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL2)); |
+ |
+ EXPECT_TRUE(observer_.web_state_inserted_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, MoveWebStateAtRightByOne) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.MoveWebStateAt(0, 1); |
+ |
+ EXPECT_TRUE(observer_.web_state_moved_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, MoveWebStateAtRightByMoreThanOne) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.MoveWebStateAt(0, 2); |
+ |
+ EXPECT_TRUE(observer_.web_state_moved_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, MoveWebStateAtLeftByOne) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.MoveWebStateAt(2, 1); |
+ |
+ EXPECT_TRUE(observer_.web_state_moved_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, MoveWebStateAtLeftByMoreThanOne) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.MoveWebStateAt(2, 0); |
+ |
+ EXPECT_TRUE(observer_.web_state_moved_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, MoveWebStateAtSameIndex) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.MoveWebStateAt(2, 2); |
+ |
+ EXPECT_FALSE(observer_.web_state_moved_called()); |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, ReplaceWebStateAt) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ |
+ // Sanity check before replacing WebState. |
+ EXPECT_EQ(2, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ std::unique_ptr<web::WebState> old_web_state( |
+ web_state_list_.ReplaceWebStateAt(1, CreateWebState(kURL2))); |
+ |
+ EXPECT_TRUE(observer_.web_state_replaced_called()); |
+ EXPECT_EQ(2, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, old_web_state->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, DetachWebStateAtIndexBegining) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.DetachWebStateAt(0); |
+ |
+ EXPECT_TRUE(observer_.web_state_detached_called()); |
+ EXPECT_EQ(2, web_state_list_.count()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, DetachWebStateAtIndexMiddle) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.DetachWebStateAt(1); |
+ |
+ EXPECT_TRUE(observer_.web_state_detached_called()); |
+ EXPECT_EQ(2, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, DetachWebStateAtIndexLast) { |
+ web_state_list_.InsertWebState(0, CreateWebState(kURL0)); |
+ web_state_list_.InsertWebState(1, CreateWebState(kURL1)); |
+ web_state_list_.InsertWebState(2, CreateWebState(kURL2)); |
+ |
+ // Sanity check before closing WebState. |
+ EXPECT_EQ(3, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL2, web_state_list_.GetWebStateAt(2)->GetVisibleURL().spec()); |
+ |
+ observer_.ResetStatistics(); |
+ web_state_list_.DetachWebStateAt(2); |
+ |
+ EXPECT_TRUE(observer_.web_state_detached_called()); |
+ EXPECT_EQ(2, web_state_list_.count()); |
+ EXPECT_EQ(kURL0, web_state_list_.GetWebStateAt(0)->GetVisibleURL().spec()); |
+ EXPECT_EQ(kURL1, web_state_list_.GetWebStateAt(1)->GetVisibleURL().spec()); |
+} |
+ |
+TEST_F(WebStateListTest, OwnershipBorrowed) { |
+ bool web_state_was_killed = false; |
+ auto test_web_state = base::MakeUnique<web::TestWebState>(); |
+ test_web_state->SetUserData( |
+ &kSupportsUserDataDeathGuardKey, |
+ base::MakeUnique<SupportsUserDataDeathGuard>(&web_state_was_killed)); |
+ |
+ auto web_state_list = |
+ base::MakeUnique<WebStateList>(WebStateList::WebStateBorrowed); |
+ web_state_list->InsertWebState(0, test_web_state.get()); |
+ EXPECT_FALSE(web_state_was_killed); |
+ |
+ web_state_list.reset(); |
+ EXPECT_FALSE(web_state_was_killed); |
+} |
+ |
+TEST_F(WebStateListTest, OwnershipOwned) { |
+ bool web_state_was_killed = false; |
+ auto test_web_state = base::MakeUnique<web::TestWebState>(); |
+ test_web_state->SetUserData( |
+ &kSupportsUserDataDeathGuardKey, |
+ base::MakeUnique<SupportsUserDataDeathGuard>(&web_state_was_killed)); |
+ |
+ auto web_state_list = |
+ base::MakeUnique<WebStateList>(WebStateList::WebStateOwned); |
+ web_state_list->InsertWebState(0, test_web_state.release()); |
+ EXPECT_FALSE(web_state_was_killed); |
+ |
+ web_state_list.reset(); |
+ EXPECT_TRUE(web_state_was_killed); |
+} |