1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075 |
- // Copyright 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 "components/sync_sessions/synced_session_tracker.h"
- #include "base/rand_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/test/mock_callback.h"
- #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
- #include "components/sync/protocol/sync_enums.pb.h"
- #include "components/sync_sessions/mock_sync_sessions_client.h"
- #include "components/sync_sessions/test_matchers.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using testing::_;
- using testing::AssertionFailure;
- using testing::AssertionResult;
- using testing::AssertionSuccess;
- using testing::ElementsAre;
- using testing::IsEmpty;
- using testing::IsNull;
- using testing::Ne;
- using testing::NotNull;
- using testing::Pointee;
- using testing::Return;
- namespace sync_sessions {
- namespace {
- const char kValidUrl[] = "http://www.example.com";
- const char kSessionName[] = "sessionname";
- const sync_pb::SyncEnums::DeviceType kDeviceType =
- sync_pb::SyncEnums_DeviceType_TYPE_PHONE;
- const char kTag[] = "tag";
- const char kTag2[] = "tag2";
- const char kTag3[] = "tag3";
- const int kTabNode1 = 0;
- const int kTabNode2 = 1;
- const int kTabNode3 = 2;
- const int kTabNode4 = 3;
- const int kTabNode5 = 4;
- const SessionID kWindow1 = SessionID::FromSerializedValue(1);
- const SessionID kWindow2 = SessionID::FromSerializedValue(2);
- const SessionID kWindow3 = SessionID::FromSerializedValue(3);
- const SessionID kTab1 = SessionID::FromSerializedValue(15);
- const SessionID kTab2 = SessionID::FromSerializedValue(25);
- const SessionID kTab3 = SessionID::FromSerializedValue(35);
- const SessionID kTab4 = SessionID::FromSerializedValue(45);
- const SessionID kTab5 = SessionID::FromSerializedValue(55);
- const SessionID kTab6 = SessionID::FromSerializedValue(65);
- const SessionID kTab7 = SessionID::FromSerializedValue(75);
- MATCHER_P(HasSessionTag, expected_tag, "") {
- return arg->session_tag == expected_tag;
- }
- } // namespace
- class SyncedSessionTrackerTest : public testing::Test {
- public:
- SyncedSessionTrackerTest() : tracker_(&sessions_client_) {}
- ~SyncedSessionTrackerTest() override = default;
- TabNodePool* GetLocalTabNodePool() {
- return &tracker_.LookupTrackedSession(tracker_.local_session_tag_)
- ->tab_node_pool;
- }
- // Returns whether |tab_node_id| refers to a valid tab node that is associated
- // with a tab.
- bool IsLocalTabNodeAssociated(int tab_node_id) const {
- return tracker_
- .LookupTabIdFromTabNodeId(tracker_.local_session_tag_, tab_node_id)
- .is_valid();
- }
- // Verify that each tab within a session is allocated one SessionTab object,
- // and that that tab object is owned either by the Session itself or the
- // |unmapped_tabs_| tab holder.
- AssertionResult VerifyTabIntegrity(const std::string& session_tag) {
- const SyncedSessionTracker::TrackedSession* session =
- tracker_.LookupTrackedSession(session_tag);
- if (!session) {
- return AssertionFailure()
- << "Not tracked session with tag " << session_tag;
- }
- // First get all the tabs associated with this session.
- int total_tab_count = session->synced_tab_map.size();
- // Now traverse the SyncedSession tree to verify the mapped tabs all match
- // up.
- int mapped_tab_count = 0;
- for (auto& [window_id, window] : session->synced_session.windows) {
- mapped_tab_count += window->wrapped_window.tabs.size();
- for (auto& tab : window->wrapped_window.tabs) {
- const auto tab_map_it = session->synced_tab_map.find(tab->tab_id);
- if (tab_map_it == session->synced_tab_map.end()) {
- return AssertionFailure() << "Tab ID " << tab->tab_id.id()
- << " has no corresponding synced tab entry";
- }
- if (tab_map_it->second != tab.get()) {
- return AssertionFailure()
- << "Mapped tab " << tab->tab_id.id()
- << " does not match synced tab map " << tab->tab_id.id();
- }
- }
- }
- // Wrap up by verifying all unmapped tabs are tracked.
- int unmapped_tab_count = session->unmapped_tabs.size();
- for (const auto& [id, tab] : session->unmapped_tabs) {
- if (id != tab->tab_id) {
- return AssertionFailure() << "Unmapped tab " << tab->tab_id.id()
- << " associated with wrong tab " << id;
- }
- const auto tab_map_it = session->synced_tab_map.find(tab->tab_id);
- if (tab_map_it == session->synced_tab_map.end()) {
- return AssertionFailure() << "Unmapped tab " << tab->tab_id
- << " has no corresponding synced tab entry";
- }
- if (tab_map_it->second != tab.get()) {
- return AssertionFailure()
- << "Unmapped tab " << tab->tab_id.id()
- << " does not match synced tab map " << tab_map_it->second;
- }
- }
- return mapped_tab_count + unmapped_tab_count == total_tab_count
- ? AssertionSuccess()
- : AssertionFailure()
- << " Tab count mismatch. Total: " << total_tab_count
- << ". Mapped + Unmapped: " << mapped_tab_count << " + "
- << unmapped_tab_count;
- }
- protected:
- testing::NiceMock<MockSyncSessionsClient> sessions_client_;
- testing::NiceMock<
- base::MockCallback<base::RepeatingCallback<bool(int /*tab_node_id*/)>>>
- is_tab_node_unsynced_cb_;
- SyncedSessionTracker tracker_;
- };
- TEST_F(SyncedSessionTrackerTest, GetSession) {
- SyncedSession* session1 = tracker_.GetSession(kTag);
- SyncedSession* session2 = tracker_.GetSession(kTag2);
- ASSERT_EQ(session1, tracker_.LookupSession(kTag));
- ASSERT_EQ(session1, tracker_.GetSession(kTag));
- ASSERT_NE(session1, session2);
- // Should clean up memory on its own.
- }
- TEST_F(SyncedSessionTrackerTest, GetTabUnmapped) {
- sessions::SessionTab* tab = tracker_.GetTab(kTag, kTab1);
- ASSERT_EQ(tab, tracker_.GetTab(kTag, kTab1));
- // Should clean up memory on its own.
- }
- TEST_F(SyncedSessionTrackerTest, PutWindowInSession) {
- tracker_.PutWindowInSession(kTag, kWindow1);
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- // Doing it again should have no effect.
- tracker_.PutWindowInSession(kTag, kWindow1);
- ASSERT_EQ(1U, session->windows.size());
- // Should clean up memory on its own.
- }
- TEST_F(SyncedSessionTrackerTest, PutTabInWindow) {
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- ASSERT_EQ(1U, session->windows.at(kWindow1)->wrapped_window.tabs.size());
- ASSERT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- // Should clean up memory on its own.
- }
- TEST_F(SyncedSessionTrackerTest, LookupAllSessions) {
- EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
- IsEmpty());
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::RAW),
- ElementsAre(HasSessionTag(kTag)));
- EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
- IsEmpty());
- sessions::SessionTab* tab = tracker_.GetTab(kTag, kTab1);
- ASSERT_TRUE(tab);
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
- EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
- ElementsAre(HasSessionTag(kTag)));
- tracker_.GetSession(kTag2);
- tracker_.PutWindowInSession(kTag2, kWindow1);
- tracker_.PutTabInWindow(kTag2, kWindow1, kTab2);
- sessions::SessionTab* tab2 = tracker_.GetTab(kTag2, kTab2);
- ASSERT_TRUE(tab2);
- tab2->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
- EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
- ElementsAre(HasSessionTag(kTag), HasSessionTag(kTag2)));
- }
- TEST_F(SyncedSessionTrackerTest, LookupAllForeignSessions) {
- const char kInvalidUrl[] = "invalid.url";
- ON_CALL(sessions_client_, ShouldSyncURL(GURL(kInvalidUrl)))
- .WillByDefault(testing::Return(false));
- EXPECT_THAT(
- tracker_.LookupAllForeignSessions(SyncedSessionTracker::PRESENTABLE),
- IsEmpty());
- tracker_.GetSession(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- sessions::SessionTab* tab = tracker_.GetTab(kTag, kTab1);
- ASSERT_TRUE(tab);
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
- tab->navigations.back().set_virtual_url(GURL(kValidUrl));
- tracker_.GetSession(kTag2);
- tracker_.GetSession(kTag3);
- tracker_.PutWindowInSession(kTag3, kWindow1);
- tracker_.PutTabInWindow(kTag3, kWindow1, kTab1);
- tab = tracker_.GetTab(kTag3, kTab1);
- ASSERT_TRUE(tab);
- tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
- tab->navigations.back().set_virtual_url(GURL(kInvalidUrl));
- // Only the session with a valid window and tab gets returned.
- EXPECT_THAT(
- tracker_.LookupAllForeignSessions(SyncedSessionTracker::PRESENTABLE),
- ElementsAre(HasSessionTag(kTag)));
- EXPECT_THAT(tracker_.LookupAllForeignSessions(SyncedSessionTracker::RAW),
- ElementsAre(HasSessionTag(kTag), HasSessionTag(kTag2),
- HasSessionTag(kTag3)));
- // Annotate kTag as local session.
- ON_CALL(sessions_client_, IsRecentLocalCacheGuid(kTag))
- .WillByDefault(Return(true));
- EXPECT_THAT(
- tracker_.LookupAllForeignSessions(SyncedSessionTracker::PRESENTABLE),
- IsEmpty());
- EXPECT_THAT(tracker_.LookupAllForeignSessions(SyncedSessionTracker::RAW),
- ElementsAre(HasSessionTag(kTag2), HasSessionTag(kTag3)));
- }
- TEST_F(SyncedSessionTrackerTest, LookupSessionWindows) {
- std::vector<const sessions::SessionWindow*> windows;
- ASSERT_FALSE(tracker_.LookupSessionWindows(kTag, &windows));
- tracker_.GetSession(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutWindowInSession(kTag, kWindow2);
- tracker_.GetSession(kTag2);
- tracker_.PutWindowInSession(kTag2, kWindow1);
- tracker_.PutWindowInSession(kTag2, kWindow2);
- ASSERT_TRUE(tracker_.LookupSessionWindows(kTag, &windows));
- ASSERT_EQ(2U, windows.size()); // Only windows from kTag session.
- ASSERT_NE((sessions::SessionWindow*)nullptr, windows[0]);
- ASSERT_NE((sessions::SessionWindow*)nullptr, windows[1]);
- ASSERT_NE(windows[1], windows[0]);
- }
- TEST_F(SyncedSessionTrackerTest, LookupSessionTab) {
- ASSERT_THAT(tracker_.LookupSessionTab(kTag, SessionID::InvalidValue()),
- IsNull());
- ASSERT_THAT(tracker_.LookupSessionTab(kTag, kTab1), IsNull());
- tracker_.GetSession(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- ASSERT_THAT(tracker_.LookupSessionTab(kTag, kTab1), NotNull());
- }
- TEST_F(SyncedSessionTrackerTest, Complex) {
- std::vector<sessions::SessionTab*> tabs1, tabs2;
- sessions::SessionTab* temp_tab;
- ASSERT_TRUE(tracker_.Empty());
- ASSERT_EQ(0U, tracker_.num_synced_sessions());
- ASSERT_EQ(0U, tracker_.num_synced_tabs(kTag));
- tabs1.push_back(tracker_.GetTab(kTag, kTab1));
- tabs1.push_back(tracker_.GetTab(kTag, kTab2));
- tabs1.push_back(tracker_.GetTab(kTag, kTab3));
- ASSERT_EQ(3U, tracker_.num_synced_tabs(kTag));
- ASSERT_EQ(1U, tracker_.num_synced_sessions());
- temp_tab = tracker_.GetTab(kTag, kTab1); // Already created.
- ASSERT_EQ(3U, tracker_.num_synced_tabs(kTag));
- ASSERT_EQ(1U, tracker_.num_synced_sessions());
- ASSERT_EQ(tabs1[0], temp_tab);
- tabs2.push_back(tracker_.GetTab(kTag2, kTab1));
- ASSERT_EQ(1U, tracker_.num_synced_tabs(kTag2));
- ASSERT_EQ(2U, tracker_.num_synced_sessions());
- ASSERT_FALSE(tracker_.DeleteForeignSession(kTag3));
- SyncedSession* session = tracker_.GetSession(kTag);
- ASSERT_EQ(2U, tracker_.num_synced_sessions());
- SyncedSession* session2 = tracker_.GetSession(kTag2);
- ASSERT_EQ(2U, tracker_.num_synced_sessions());
- SyncedSession* session3 = tracker_.GetSession(kTag3);
- session3->device_type = sync_pb::SyncEnums_DeviceType_TYPE_LINUX;
- ASSERT_EQ(3U, tracker_.num_synced_sessions());
- ASSERT_TRUE(session);
- ASSERT_TRUE(session2);
- ASSERT_TRUE(session3);
- ASSERT_NE(session, session2);
- ASSERT_NE(session2, session3);
- ASSERT_TRUE(tracker_.DeleteForeignSession(kTag3));
- ASSERT_EQ(2U, tracker_.num_synced_sessions());
- tracker_.PutWindowInSession(kTag, kWindow1); // Create a window.
- tracker_.PutTabInWindow(kTag, kWindow1, kTab3); // No longer unmapped.
- ASSERT_EQ(3U, tracker_.num_synced_tabs(kTag)); // Has not changed.
- ASSERT_EQ(tabs1[0], tracker_.LookupSessionTab(kTag, kTab1));
- ASSERT_EQ(tabs1[2], tracker_.LookupSessionTab(kTag, kTab3));
- ASSERT_THAT(tracker_.LookupSessionTab(kTag, kTab4), IsNull());
- std::vector<const sessions::SessionWindow*> windows;
- ASSERT_TRUE(tracker_.LookupSessionWindows(kTag, &windows));
- ASSERT_EQ(1U, windows.size());
- ASSERT_TRUE(tracker_.LookupSessionWindows(kTag2, &windows));
- ASSERT_EQ(0U, windows.size());
- // The sessions don't have valid tabs, lookup should not succeed.
- std::vector<const SyncedSession*> sessions;
- EXPECT_THAT(
- tracker_.LookupAllForeignSessions(SyncedSessionTracker::PRESENTABLE),
- IsEmpty());
- EXPECT_THAT(tracker_.LookupAllForeignSessions(SyncedSessionTracker::RAW),
- ElementsAre(HasSessionTag(kTag), HasSessionTag(kTag2)));
- tracker_.Clear();
- ASSERT_EQ(0U, tracker_.num_synced_tabs(kTag));
- ASSERT_EQ(0U, tracker_.num_synced_tabs(kTag2));
- ASSERT_EQ(0U, tracker_.num_synced_sessions());
- }
- TEST_F(SyncedSessionTrackerTest, ManyGetTabs) {
- ASSERT_TRUE(tracker_.Empty());
- const int kMaxSessions = 10;
- const int kMaxTabs = 1000;
- const int kMaxAttempts = 10000;
- for (int j = 0; j < kMaxSessions; ++j) {
- std::string tag = base::StringPrintf("tag%d", j);
- for (int i = 0; i < kMaxAttempts; ++i) {
- // More attempts than tabs means we'll sometimes get the same tabs,
- // sometimes have to allocate new tabs.
- int rand_tab_num = base::RandInt(0, kMaxTabs);
- sessions::SessionTab* tab = tracker_.GetTab(
- tag, SessionID::FromSerializedValue(rand_tab_num + 1));
- ASSERT_TRUE(tab);
- }
- }
- }
- TEST_F(SyncedSessionTrackerTest, LookupTabNodeIds) {
- tracker_.OnTabNodeSeen(kTag, 1, kTab1);
- tracker_.OnTabNodeSeen(kTag, 2, kTab2);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), ElementsAre(1, 2));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag2), IsEmpty());
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), ElementsAre(1, 2));
- tracker_.OnTabNodeSeen(kTag, 3, kTab3);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), ElementsAre(1, 2, 3));
- tracker_.OnTabNodeSeen(kTag2, 21, kTab4);
- tracker_.OnTabNodeSeen(kTag2, 22, kTab5);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag2), ElementsAre(21, 22));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), ElementsAre(1, 2, 3));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag3), IsEmpty());
- tracker_.PutWindowInSession(kTag3, kWindow2);
- tracker_.PutTabInWindow(kTag3, kWindow2, kTab2);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag3), IsEmpty());
- EXPECT_FALSE(tracker_.DeleteForeignSession(kTag3));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag3), IsEmpty());
- EXPECT_FALSE(tracker_.DeleteForeignSession(kTag));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), IsEmpty());
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag2), ElementsAre(21, 22));
- tracker_.OnTabNodeSeen(kTag2, 21, kTab6);
- tracker_.OnTabNodeSeen(kTag2, 23, kTab7);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag2), ElementsAre(21, 22, 23));
- EXPECT_FALSE(tracker_.DeleteForeignSession(kTag2));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag2), IsEmpty());
- }
- TEST_F(SyncedSessionTrackerTest, SessionTracking) {
- ASSERT_TRUE(tracker_.Empty());
- // Create some session information that is stale.
- SyncedSession* session1 = tracker_.GetSession(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- tracker_.GetTab(kTag, kTab3)->window_id =
- SessionID::FromSerializedValue(1); // Unmapped.
- tracker_.GetTab(kTag, kTab4)->window_id =
- SessionID::FromSerializedValue(1); // Unmapped.
- tracker_.PutWindowInSession(kTag, kWindow2);
- tracker_.PutTabInWindow(kTag, kWindow2, kTab5);
- tracker_.PutTabInWindow(kTag, kWindow2, kTab6);
- ASSERT_EQ(2U, session1->windows.size());
- ASSERT_EQ(2U, session1->windows[kWindow1]->wrapped_window.tabs.size());
- ASSERT_EQ(2U, session1->windows[kWindow2]->wrapped_window.tabs.size());
- ASSERT_EQ(6U, tracker_.num_synced_tabs(kTag));
- // Create a session that should not be affected.
- SyncedSession* session2 = tracker_.GetSession(kTag2);
- tracker_.PutWindowInSession(kTag2, kWindow3);
- tracker_.PutTabInWindow(kTag2, kWindow3, kTab2);
- ASSERT_EQ(1U, session2->windows.size());
- ASSERT_EQ(1U, session2->windows[kWindow3]->wrapped_window.tabs.size());
- ASSERT_EQ(1U, tracker_.num_synced_tabs(kTag2));
- // Reset tracking and get the current windows/tabs.
- // We simulate moving a tab from one window to another, then closing the
- // first window (including its one remaining tab), and opening a new tab
- // on the remaining window.
- // New tab, arrived before meta node so unmapped.
- tracker_.GetTab(kTag, kTab7);
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- // Tab 1 is closed.
- tracker_.PutTabInWindow(kTag, kWindow1, kTab3); // No longer unmapped.
- // Tab 3 was unmapped and does not get used.
- tracker_.PutTabInWindow(kTag, kWindow1, kTab5); // Moved from window 1.
- // Window 1 was closed, along with tab 5.
- tracker_.PutTabInWindow(kTag, kWindow1, kTab7); // No longer unmapped.
- // Session 2 should not be affected.
- tracker_.CleanupSession(kTag);
- // Verify that only those parts of the session not owned have been removed.
- ASSERT_EQ(1U, session1->windows.size());
- ASSERT_EQ(4U, session1->windows[kWindow1]->wrapped_window.tabs.size());
- ASSERT_EQ(1U, session2->windows.size());
- ASSERT_EQ(1U, session2->windows[kWindow3]->wrapped_window.tabs.size());
- ASSERT_EQ(2U, tracker_.num_synced_sessions());
- ASSERT_EQ(4U, tracker_.num_synced_tabs(kTag));
- ASSERT_EQ(1U, tracker_.num_synced_tabs(kTag2));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- // All memory should be properly deallocated by destructor for the
- // SyncedSessionTracker.
- }
- TEST_F(SyncedSessionTrackerTest, DeleteForeignTab) {
- int tab_node_id_1 = 1;
- int tab_node_id_2 = 2;
- std::set<int> result;
- tracker_.OnTabNodeSeen(kTag, tab_node_id_1, kTab1);
- tracker_.OnTabNodeSeen(kTag, tab_node_id_2, kTab2);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag),
- ElementsAre(tab_node_id_1, tab_node_id_2));
- tracker_.DeleteForeignTab(kTag, tab_node_id_1);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), ElementsAre(tab_node_id_2));
- tracker_.DeleteForeignTab(kTag, tab_node_id_2);
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag), IsEmpty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, CleanupLocalTabs) {
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- // Start with four restored tab nodes, one of which is mapped (|kTab1|).
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- tracker_.ReassociateLocalTab(kTabNode2, kTab2);
- tracker_.ReassociateLocalTab(kTabNode3, kTab3);
- tracker_.ReassociateLocalTab(kTabNode4, kTab4);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- // Modification times are very recent except for one tab, |kTab3|, which is
- // old, and hence is expected to be recycled immediately, even if it's
- // unsynced.
- tracker_.GetTab(kTag, kTab1)->timestamp = base::Time::Now();
- tracker_.GetTab(kTag, kTab2)->timestamp = base::Time::Now();
- tracker_.GetTab(kTag, kTab3)->timestamp = base::Time::Now() - base::Days(100);
- tracker_.GetTab(kTag, kTab4)->timestamp = base::Time::Now();
- // Among the unmapped (closed) ones, |kTab2| and |kTab3| are unsynced.
- // However, |kTab3| is old so it's irrelevant whether it's unsynced and the
- // callback shouldn't even run.
- EXPECT_CALL(is_tab_node_unsynced_cb_, Run(kTabNode2)).WillOnce(Return(true));
- EXPECT_CALL(is_tab_node_unsynced_cb_, Run(kTabNode3)).Times(0);
- EXPECT_CALL(is_tab_node_unsynced_cb_, Run(kTabNode4)).WillOnce(Return(false));
- // During cleanup, only two tabs should be freed:
- // - |kTabNode3| because of its age, although it's unsynced.
- // - |kTabNode4| because it's synced.
- EXPECT_THAT(tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()),
- ElementsAre(kTabNode3, kTabNode4));
- ASSERT_EQ(kTabNode1, tracker_.LookupTabNodeFromTabId(kTag, kTab1));
- EXPECT_EQ(kTabNode2, tracker_.LookupTabNodeFromTabId(kTag, kTab2));
- EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
- tracker_.LookupTabNodeFromTabId(kTag, kTab3));
- EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
- tracker_.LookupTabNodeFromTabId(kTag, kTab4));
- // |kTabNode2| now becomes synced (commit succeeded), which means it should be
- // freed during cleanup.
- EXPECT_CALL(is_tab_node_unsynced_cb_, Run(kTabNode2)).WillOnce(Return(false));
- EXPECT_THAT(tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()),
- ElementsAre(kTabNode2));
- EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
- tracker_.LookupTabNodeFromTabId(kTag, kTab2));
- EXPECT_EQ(kTabNode2, tracker_.AssociateLocalTabWithFreeTabNode(kTab5));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabMapped) {
- // First create the tab normally.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Map it to a window with the same tab id as it was created with.
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- ASSERT_EQ(1U, session->windows.at(kWindow1)->wrapped_window.tabs.size());
- ASSERT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- // Then reassociate with a new tab id.
- tracker_.ReassociateLocalTab(kTabNode1, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Reset tracking, and put the new tab id into the window.
- tracker_.ResetSessionTracking(kTag);
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab2));
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as the GetTab.
- ASSERT_EQ(tracker_.GetTab(kTag, kTab2),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_EQ(tracker_.LookupTabNodeIds(kTag).size(),
- tracker_.LookupTabNodeIds(kTag).count(kTabNode1));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabMappedTwice) {
- // First create the tab normally.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Map it to a window with the same tab id as it was created with.
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- ASSERT_EQ(1U, session->windows.at(kWindow1)->wrapped_window.tabs.size());
- EXPECT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- // Then reassociate with a new tab id.
- tracker_.ReassociateLocalTab(kTabNode1, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Tab 1 should no longer be associated with any SessionTab object. At this
- // point there's no need to verify it's unmapped state.
- EXPECT_THAT(tracker_.LookupSessionTab(kTag, kTab1), IsNull());
- // Reset tracking and add back both the old tab and the new tab (both of which
- // refer to the same tab node id).
- tracker_.ResetSessionTracking(kTag);
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab2));
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as the GetTab.
- EXPECT_EQ(tracker_.GetTab(kTag, kTab2),
- session->windows.at(kWindow1)->wrapped_window.tabs[1].get());
- EXPECT_EQ(tracker_.LookupTabNodeIds(kTag).size(),
- tracker_.LookupTabNodeIds(kTag).count(kTabNode1));
- // Attempting to access the original tab will create a new SessionTab object.
- EXPECT_NE(tracker_.GetTab(kTag, kTab1), tracker_.GetTab(kTag, kTab2));
- EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
- tracker_.LookupTabNodeFromTabId(kTag, kTab1));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabUnmapped) {
- // First create the old tab in an unmapped state.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Map it to a window, but reassociated with a new tab id.
- tracker_.ResetSessionTracking(kTag);
- tracker_.ReassociateLocalTab(kTabNode1, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab2));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as GetTab.
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(tracker_.GetTab(kTag, kTab2),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_EQ(tracker_.LookupTabNodeIds(kTag).size(),
- tracker_.LookupTabNodeIds(kTag).count(kTabNode1));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabOldUnmappedNewMapped) {
- // First create the old tab in an unmapped state.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Map an unseen tab to a window, then reassociate the existing tab to the
- // mapped tab id.
- tracker_.ResetSessionTracking(kTag);
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- tracker_.ReassociateLocalTab(kTabNode1, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as GetTab.
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(tracker_.GetTab(kTag, kTab2),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_EQ(tracker_.LookupTabNodeIds(kTag).size(),
- tracker_.LookupTabNodeIds(kTag).count(kTabNode1));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabSameTabId) {
- // First create the tab normally.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Map it to a window.
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- ASSERT_EQ(1U, session->windows.at(kWindow1)->wrapped_window.tabs.size());
- ASSERT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- // Reassociate, using the same tab id.
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Reset tracking, and put the tab id back into the same window.
- tracker_.ResetSessionTracking(kTag);
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- EXPECT_TRUE(
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get()).empty());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as the GetTab.
- ASSERT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_EQ(tracker_.LookupTabNodeIds(kTag).size(),
- tracker_.LookupTabNodeIds(kTag).count(kTabNode1));
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, ReassociateTabOldMappedNewUnmapped) {
- // First create an unmapped tab.
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode1));
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab1));
- // Now, map the first one, deleting the second one.
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- const SyncedSession* session = tracker_.LookupSession(kTag);
- ASSERT_EQ(1U, session->windows.size());
- ASSERT_EQ(1U, session->windows.at(kWindow1)->wrapped_window.tabs.size());
- ASSERT_EQ(tracker_.GetTab(kTag, kTab1),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- // Create a second unmapped tab.
- tracker_.ReassociateLocalTab(kTabNode2, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode2));
- EXPECT_TRUE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Reassociate the second tab with node of the first tab.
- tracker_.ReassociateLocalTab(kTabNode1, kTab2);
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_TRUE(IsLocalTabNodeAssociated(kTabNode1));
- EXPECT_FALSE(IsLocalTabNodeAssociated(kTabNode2));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now map the new one.
- tracker_.ResetSessionTracking(kTag);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- tracker_.CleanupLocalTabs(is_tab_node_unsynced_cb_.Get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab1));
- EXPECT_FALSE(tracker_.IsTabUnmappedForTesting(kTab2));
- // Now that it's been mapped, it should be accessible both via the
- // GetSession as well as the GetTab.
- ASSERT_EQ(tracker_.GetTab(kTag, kTab2),
- session->windows.at(kWindow1)->wrapped_window.tabs[0].get());
- ASSERT_TRUE(VerifyTabIntegrity(kTag));
- }
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithHeader) {
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab2.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- EXPECT_THAT(
- tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, {{kWindow1.id(), {kTab1.id(), kTab2.id()}}}));
- EXPECT_THAT(tracker_.LookupSessionTab(kTag, kTab1), NotNull());
- EXPECT_THAT(tracker_.LookupSessionTab(kTag, kTab2), NotNull());
- }
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithIdenticalHeader) {
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab2.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- ASSERT_THAT(
- tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, {{kWindow1.id(), {kTab1.id(), kTab2.id()}}}));
- // Update with an exact header entity.
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- EXPECT_THAT(
- tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, {{kWindow1.id(), {kTab1.id(), kTab2.id()}}}));
- EXPECT_THAT(tracker_.LookupSessionTab(kTag, kTab1), NotNull());
- }
- // Verifies that an invalid header (with duplicated tab IDs) is discarded.
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithHeaderWithDuplicateTabIds) {
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs=*/{}));
- }
- // Verifies that an invalid tab (with invalid ID) is discarded.
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithInvalidTab) {
- const int kInvalidTabId = -1;
- sync_pb::SessionSpecifics tab;
- tab.set_session_tag(kTag);
- tab.mutable_tab()->set_tab_id(kInvalidTabId);
- UpdateTrackerWithSpecifics(tab, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSessionTab(
- kTag, SessionID::FromSerializedValue(kInvalidTabId)),
- IsNull());
- }
- // Verifies that an invalid header (with duplicated window IDs) is discarded.
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithHeaderWithDuplicateWindowId) {
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- header.mutable_header()->mutable_window(1)->add_tab(kTab2.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs=*/{}));
- }
- // Verifies that an invalid header with duplicated window IDs is ignored. It
- // specifically tests feeding the same input twice to
- // UpdateTrackerWithSpecifics(), as a regression test for crbug.com/803205 to
- // verify that it at least doesn't crash.
- TEST_F(SyncedSessionTrackerTest,
- UpdateTrackerWithHeaderWithDuplicateWindowIdTwice) {
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(1)->add_tab(kTab2.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs=*/{}));
- }
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithTab) {
- sync_pb::SessionSpecifics tab;
- tab.set_session_tag(kTag);
- tab.set_tab_node_id(kTabNode1);
- tab.mutable_tab()->set_window_id(kWindow1.id());
- tab.mutable_tab()->set_tab_id(kTab1.id());
- UpdateTrackerWithSpecifics(tab, base::Time::Now(), &tracker_);
- const sessions::SessionTab* tracked_tab =
- tracker_.LookupSessionTab(kTag, kTab1);
- ASSERT_THAT(tracked_tab, NotNull());
- EXPECT_EQ(kWindow1, tracked_tab->window_id);
- EXPECT_EQ(false, tracked_tab->pinned);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs*/ {}));
- // Overwrite some attribute.
- tab.mutable_tab()->set_pinned(true);
- UpdateTrackerWithSpecifics(tab, base::Time::Now(), &tracker_);
- tracked_tab = tracker_.LookupSessionTab(kTag, kTab1);
- ASSERT_THAT(tracked_tab, NotNull());
- EXPECT_EQ(kWindow1, tracked_tab->window_id);
- EXPECT_EQ(true, tracked_tab->pinned);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs*/ {}));
- }
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithTabThenHeader) {
- sync_pb::SessionSpecifics tab;
- tab.set_session_tag(kTag);
- tab.set_tab_node_id(kTabNode1);
- tab.mutable_tab()->set_window_id(kWindow1.id());
- tab.mutable_tab()->set_tab_id(kTab1.id());
- UpdateTrackerWithSpecifics(tab, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs*/ {}));
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->add_window()->set_window_id(kWindow1.id());
- header.mutable_header()->mutable_window(0)->add_tab(kTab1.id());
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- const sessions::SessionTab* tracked_tab =
- tracker_.LookupSessionTab(kTag, kTab1);
- ASSERT_THAT(tracked_tab, NotNull());
- EXPECT_EQ(kWindow1, tracked_tab->window_id);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(
- kTag, {{kWindow1.id(), std::vector<int>{kTab1.id()}}}));
- }
- TEST_F(SyncedSessionTrackerTest, UpdateTrackerWithTwoTabsSameId) {
- sync_pb::SessionSpecifics tab1;
- tab1.set_session_tag(kTag);
- tab1.set_tab_node_id(kTabNode1);
- tab1.mutable_tab()->set_window_id(kWindow1.id());
- tab1.mutable_tab()->set_tab_id(kTab1.id());
- tab1.mutable_tab()->set_pinned(false);
- UpdateTrackerWithSpecifics(tab1, base::Time::Now(), &tracker_);
- sync_pb::SessionSpecifics tab2;
- tab2.set_session_tag(kTag);
- tab2.set_tab_node_id(kTabNode2);
- tab2.mutable_tab()->set_window_id(kWindow1.id());
- tab2.mutable_tab()->set_tab_id(kTab1.id());
- tab2.mutable_tab()->set_pinned(true);
- UpdateTrackerWithSpecifics(tab2, base::Time::Now(), &tracker_);
- EXPECT_THAT(tracker_.LookupSession(kTag),
- MatchesSyncedSession(kTag, /*window_id_to_tabs*/ {}));
- EXPECT_THAT(tracker_.LookupTabNodeIds(kTag),
- ElementsAre(kTabNode1, kTabNode2));
- const sessions::SessionTab* tracked_tab =
- tracker_.LookupSessionTab(kTag, kTab1);
- ASSERT_THAT(tracked_tab, NotNull());
- EXPECT_EQ(kWindow1, tracked_tab->window_id);
- EXPECT_EQ(true, tracked_tab->pinned);
- }
- TEST_F(SyncedSessionTrackerTest, SerializeTrackerToSpecifics) {
- tracker_.InitLocalSession(kTag, kSessionName, kDeviceType);
- tracker_.PutWindowInSession(kTag, kWindow1);
- tracker_.GetSession(kTag)->windows[kWindow1]->window_type =
- sync_pb::SyncEnums_BrowserType_TYPE_TABBED;
- tracker_.PutTabInWindow(kTag, kWindow1, kTab1);
- tracker_.PutTabInWindow(kTag, kWindow1, kTab2);
- // Unmapped tab.
- tracker_.GetTab(kTag, kTab3);
- // |kTabNode4| will be unassociated, because |kTab1| is associated twice.
- tracker_.ReassociateLocalTab(kTabNode4, kTab1);
- tracker_.ReassociateLocalTab(kTabNode1, kTab1);
- // Regular associations.
- tracker_.ReassociateLocalTab(kTabNode2, kTab2);
- tracker_.ReassociateLocalTab(kTabNode3, kTab3);
- base::MockCallback<base::RepeatingCallback<void(
- const std::string& session_name, sync_pb::SessionSpecifics* specifics)>>
- callback;
- EXPECT_CALL(callback, Run(kSessionName,
- Pointee(MatchesHeader(kTag, {kWindow1.id()},
- {kTab1.id(), kTab2.id()}))));
- EXPECT_CALL(callback, Run(kSessionName,
- Pointee(MatchesTab(kTag, kWindow1.id(), kTab1.id(),
- kTabNode1, /*urls=*/_))));
- EXPECT_CALL(callback, Run(kSessionName,
- Pointee(MatchesTab(kTag, kWindow1.id(), kTab2.id(),
- kTabNode2, /*urls=*/_))));
- EXPECT_CALL(
- callback,
- Run(kSessionName, Pointee(MatchesTab(kTag, Ne(kWindow1.id()), kTab3.id(),
- kTabNode3, /*urls=*/_))));
- SerializeTrackerToSpecifics(tracker_, callback.Get());
- EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&callback));
- // Serialize the header only.
- EXPECT_CALL(callback, Run(kSessionName,
- Pointee(MatchesHeader(kTag, {kWindow1.id()},
- {kTab1.id(), kTab2.id()}))));
- SerializePartialTrackerToSpecifics(
- tracker_, {{kTag, {TabNodePool::kInvalidTabNodeID}}}, callback.Get());
- EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&callback));
- // Serialize a known and associated tab.
- EXPECT_CALL(callback, Run(kSessionName,
- Pointee(MatchesTab(kTag, kWindow1.id(), kTab1.id(),
- kTabNode1, /*urls=*/_))));
- SerializePartialTrackerToSpecifics(tracker_, {{kTag, {kTabNode1}}},
- callback.Get());
- EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&callback));
- // Attempt to serialize unknown entities.
- EXPECT_CALL(callback, Run).Times(0);
- SerializePartialTrackerToSpecifics(tracker_, {{kTag, {kTabNode5}}},
- callback.Get());
- SerializePartialTrackerToSpecifics(
- tracker_, {{kTag2, {TabNodePool::kInvalidTabNodeID, kTabNode1}}},
- callback.Get());
- }
- TEST_F(SyncedSessionTrackerTest, SerializeTrackerToSpecificsWithEmptyHeader) {
- sync_pb::SessionSpecifics tab;
- tab.set_session_tag(kTag);
- tab.set_tab_node_id(kTabNode1);
- tab.mutable_tab()->set_window_id(kWindow1.id());
- tab.mutable_tab()->set_tab_id(kTab1.id());
- UpdateTrackerWithSpecifics(tab, base::Time::Now(), &tracker_);
- sync_pb::SessionSpecifics header;
- header.set_session_tag(kTag);
- header.mutable_header()->set_client_name(kSessionName);
- UpdateTrackerWithSpecifics(header, base::Time::Now(), &tracker_);
- base::MockCallback<base::RepeatingCallback<void(
- const std::string& session_name, sync_pb::SessionSpecifics* specifics)>>
- callback;
- EXPECT_CALL(callback,
- Run(kSessionName, Pointee(MatchesHeader(kTag, /*window_ids=*/{},
- /*tab_ids=*/{}))));
- EXPECT_CALL(
- callback,
- Run(kSessionName, Pointee(MatchesTab(kTag, /*window_id=*/0, kTab1.id(),
- kTabNode1, /*urls=*/_))));
- SerializeTrackerToSpecifics(tracker_, callback.Get());
- }
- } // namespace sync_sessions
|