Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 #include <vector>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/rand_util.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "chrome/browser/sessions/session_types.h"
     13 #include "chrome/browser/sync/glue/synced_session_tracker.h"
     14 #include "components/sessions/serialized_navigation_entry_test_helper.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace browser_sync {
     18 
     19 typedef testing::Test SyncedSessionTrackerTest;
     20 
     21 TEST_F(SyncedSessionTrackerTest, GetSession) {
     22   SyncedSessionTracker tracker;
     23   SyncedSession* session1 = tracker.GetSession("tag");
     24   SyncedSession* session2 = tracker.GetSession("tag2");
     25   ASSERT_EQ(session1, tracker.GetSession("tag"));
     26   ASSERT_NE(session1, session2);
     27   // Should clean up memory on its own.
     28 }
     29 
     30 TEST_F(SyncedSessionTrackerTest, GetTabUnmapped) {
     31   SyncedSessionTracker tracker;
     32   SessionTab* tab = tracker.GetTab("tag", 0, 0);
     33   ASSERT_EQ(tab, tracker.GetTab("tag", 0, 0));
     34   // Should clean up memory on its own.
     35 }
     36 
     37 TEST_F(SyncedSessionTrackerTest, PutWindowInSession) {
     38   SyncedSessionTracker tracker;
     39   tracker.PutWindowInSession("tag", 0);
     40   SyncedSession* session = tracker.GetSession("tag");
     41   ASSERT_EQ(1U, session->windows.size());
     42   // Should clean up memory on its own.
     43 }
     44 
     45 TEST_F(SyncedSessionTrackerTest, PutTabInWindow) {
     46   SyncedSessionTracker tracker;
     47   tracker.PutWindowInSession("tag", 10);
     48   tracker.PutTabInWindow("tag", 10, 15, 0);  // win id 10, tab id 15, tab ind 0.
     49   SyncedSession* session = tracker.GetSession("tag");
     50   ASSERT_EQ(1U, session->windows.size());
     51   ASSERT_EQ(1U, session->windows[10]->tabs.size());
     52   ASSERT_EQ(tracker.GetTab("tag", 15, 1), session->windows[10]->tabs[0]);
     53   // Should clean up memory on its own.
     54 }
     55 
     56 TEST_F(SyncedSessionTrackerTest, LookupAllForeignSessions) {
     57   SyncedSessionTracker tracker;
     58   std::vector<const SyncedSession*> sessions;
     59   ASSERT_FALSE(tracker.LookupAllForeignSessions(&sessions));
     60   tracker.GetSession("tag1");
     61   tracker.GetSession("tag2");
     62   tracker.PutWindowInSession("tag1", 0);
     63   tracker.PutTabInWindow("tag1", 0, 15, 0);
     64   SessionTab* tab = tracker.GetTab("tag1", 15, 1);
     65   ASSERT_TRUE(tab);
     66   tab->navigations.push_back(
     67       sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
     68       "bla://valid_url", "title"));
     69   ASSERT_TRUE(tracker.LookupAllForeignSessions(&sessions));
     70   // Only the session with a valid window and tab gets returned.
     71   ASSERT_EQ(1U, sessions.size());
     72   ASSERT_EQ("tag1", sessions[0]->session_tag);
     73 }
     74 
     75 TEST_F(SyncedSessionTrackerTest, LookupSessionWindows) {
     76   SyncedSessionTracker tracker;
     77   std::vector<const SessionWindow*> windows;
     78   ASSERT_FALSE(tracker.LookupSessionWindows("tag1", &windows));
     79   tracker.GetSession("tag1");
     80   tracker.PutWindowInSession("tag1", 0);
     81   tracker.PutWindowInSession("tag1", 2);
     82   tracker.GetSession("tag2");
     83   tracker.PutWindowInSession("tag2", 0);
     84   tracker.PutWindowInSession("tag2", 2);
     85   ASSERT_TRUE(tracker.LookupSessionWindows("tag1", &windows));
     86   ASSERT_EQ(2U, windows.size());  // Only windows from tag1 session.
     87   ASSERT_NE((SessionWindow*)NULL, windows[0]);
     88   ASSERT_NE((SessionWindow*)NULL, windows[1]);
     89   ASSERT_NE(windows[1], windows[0]);
     90 }
     91 
     92 TEST_F(SyncedSessionTrackerTest, LookupSessionTab) {
     93   SyncedSessionTracker tracker;
     94   const SessionTab* tab;
     95   ASSERT_FALSE(tracker.LookupSessionTab("tag1", 5, &tab));
     96   tracker.GetSession("tag1");
     97   tracker.PutWindowInSession("tag1", 0);
     98   tracker.PutTabInWindow("tag1", 0, 5, 0);
     99   ASSERT_TRUE(tracker.LookupSessionTab("tag1", 5, &tab));
    100   ASSERT_NE((SessionTab*)NULL, tab);
    101 }
    102 
    103 TEST_F(SyncedSessionTrackerTest, Complex) {
    104   const std::string tag1 = "tag";
    105   const std::string tag2 = "tag2";
    106   const std::string tag3 = "tag3";
    107   SyncedSessionTracker tracker;
    108   std::vector<SessionTab*> tabs1, tabs2;
    109   SessionTab* temp_tab;
    110   ASSERT_TRUE(tracker.Empty());
    111   ASSERT_EQ(0U, tracker.num_synced_sessions());
    112   ASSERT_EQ(0U, tracker.num_synced_tabs(tag1));
    113   tabs1.push_back(tracker.GetTab(tag1, 0, 0));
    114   tabs1.push_back(tracker.GetTab(tag1, 1, 1));
    115   tabs1.push_back(tracker.GetTab(tag1, 2, 2));
    116   ASSERT_EQ(3U, tracker.num_synced_tabs(tag1));
    117   ASSERT_EQ(0U, tracker.num_synced_sessions());
    118   temp_tab = tracker.GetTab(tag1, 0, 0);  // Already created.
    119   ASSERT_EQ(3U, tracker.num_synced_tabs(tag1));
    120   ASSERT_EQ(0U, tracker.num_synced_sessions());
    121   ASSERT_EQ(tabs1[0], temp_tab);
    122   tabs2.push_back(tracker.GetTab(tag2, 0, 0));
    123   ASSERT_EQ(1U, tracker.num_synced_tabs(tag2));
    124   ASSERT_EQ(0U, tracker.num_synced_sessions());
    125   ASSERT_FALSE(tracker.DeleteSession(tag3));
    126 
    127   SyncedSession* session = tracker.GetSession(tag1);
    128   SyncedSession* session2 = tracker.GetSession(tag2);
    129   SyncedSession* session3 = tracker.GetSession(tag3);
    130   ASSERT_EQ(3U, tracker.num_synced_sessions());
    131 
    132   ASSERT_TRUE(session);
    133   ASSERT_TRUE(session2);
    134   ASSERT_TRUE(session3);
    135   ASSERT_NE(session, session2);
    136   ASSERT_NE(session2, session3);
    137   ASSERT_TRUE(tracker.DeleteSession(tag3));
    138   ASSERT_EQ(2U, tracker.num_synced_sessions());
    139 
    140   tracker.PutWindowInSession(tag1, 0);      // Create a window.
    141   tracker.PutTabInWindow(tag1, 0, 2, 0);    // No longer unmapped.
    142   ASSERT_EQ(3U, tracker.num_synced_tabs(tag1));      // Has not changed.
    143 
    144   const SessionTab *tab_ptr;
    145   ASSERT_TRUE(tracker.LookupSessionTab(tag1, 0, &tab_ptr));
    146   ASSERT_EQ(tab_ptr, tabs1[0]);
    147   ASSERT_TRUE(tracker.LookupSessionTab(tag1, 2, &tab_ptr));
    148   ASSERT_EQ(tab_ptr, tabs1[2]);
    149   ASSERT_FALSE(tracker.LookupSessionTab(tag1, 3, &tab_ptr));
    150   ASSERT_EQ(static_cast<const SessionTab*>(NULL), tab_ptr);
    151 
    152   std::vector<const SessionWindow*> windows;
    153   ASSERT_TRUE(tracker.LookupSessionWindows(tag1, &windows));
    154   ASSERT_EQ(1U, windows.size());
    155   ASSERT_TRUE(tracker.LookupSessionWindows(tag2, &windows));
    156   ASSERT_EQ(0U, windows.size());
    157 
    158   // The sessions don't have valid tabs, lookup should not succeed.
    159   std::vector<const SyncedSession*> sessions;
    160   ASSERT_FALSE(tracker.LookupAllForeignSessions(&sessions));
    161 
    162   tracker.Clear();
    163   ASSERT_EQ(0U, tracker.num_synced_tabs(tag1));
    164   ASSERT_EQ(0U, tracker.num_synced_tabs(tag2));
    165   ASSERT_EQ(0U, tracker.num_synced_sessions());
    166 }
    167 
    168 TEST_F(SyncedSessionTrackerTest, ManyGetTabs) {
    169   SyncedSessionTracker tracker;
    170   ASSERT_TRUE(tracker.Empty());
    171   const int kMaxSessions = 10;
    172   const int kMaxTabs = 1000;
    173   const int kMaxAttempts = 10000;
    174   for (int j=0; j<kMaxSessions; ++j) {
    175     std::string tag = base::StringPrintf("tag%d", j);
    176     for (int i=0; i<kMaxAttempts; ++i) {
    177       // More attempts than tabs means we'll sometimes get the same tabs,
    178       // sometimes have to allocate new tabs.
    179       int rand_tab_num = base::RandInt(0, kMaxTabs);
    180       SessionTab* tab = tracker.GetTab(tag, rand_tab_num, rand_tab_num + 1);
    181       ASSERT_TRUE(tab);
    182     }
    183   }
    184 }
    185 
    186 TEST_F(SyncedSessionTrackerTest, LookupTabNodeIds) {
    187   SyncedSessionTracker tracker;
    188   std::set<int> result;
    189   std::string tag1 = "session1";
    190   std::string tag2 = "session2";
    191   std::string tag3 = "session3";
    192 
    193   tracker.GetTab(tag1, 1, 1);
    194   tracker.GetTab(tag1, 2, 2);
    195   EXPECT_TRUE(tracker.LookupTabNodeIds(tag1, &result));
    196   EXPECT_EQ(2U, result.size());
    197   EXPECT_FALSE(result.end() == result.find(1));
    198   EXPECT_FALSE(result.end() == result.find(2));
    199   EXPECT_FALSE(tracker.LookupTabNodeIds(tag2, &result));
    200 
    201   tracker.PutWindowInSession(tag1, 0);
    202   tracker.PutTabInWindow(tag1, 0, 3, 0);
    203   EXPECT_TRUE(tracker.LookupTabNodeIds(tag1, &result));
    204   EXPECT_EQ(2U, result.size());
    205 
    206   tracker.GetTab(tag1, 3, 3);
    207   EXPECT_TRUE(tracker.LookupTabNodeIds(tag1, &result));
    208   EXPECT_EQ(3U, result.size());
    209   EXPECT_FALSE(result.end() == result.find(3));
    210 
    211   tracker.GetTab(tag2, 1, 21);
    212   tracker.GetTab(tag2, 2, 22);
    213   EXPECT_TRUE(tracker.LookupTabNodeIds(tag2, &result));
    214   EXPECT_EQ(2U, result.size());
    215   EXPECT_FALSE(result.end() == result.find(21));
    216   EXPECT_FALSE(result.end() == result.find(22));
    217   EXPECT_TRUE(tracker.LookupTabNodeIds(tag1, &result));
    218   EXPECT_EQ(3U, result.size());
    219   EXPECT_FALSE(result.end() == result.find(1));
    220   EXPECT_FALSE(result.end() == result.find(2));
    221 
    222   EXPECT_FALSE(tracker.LookupTabNodeIds(tag3, &result));
    223   tracker.PutWindowInSession(tag3, 1);
    224   tracker.PutTabInWindow(tag3, 1, 5, 0);
    225   EXPECT_TRUE(tracker.LookupTabNodeIds(tag3, &result));
    226   EXPECT_TRUE(result.empty());
    227   EXPECT_TRUE(tracker.DeleteSession(tag3));
    228   EXPECT_FALSE(tracker.LookupTabNodeIds(tag3, &result));
    229 
    230   EXPECT_TRUE(tracker.DeleteSession(tag1));
    231   EXPECT_FALSE(tracker.LookupTabNodeIds(tag1, &result));
    232   EXPECT_TRUE(tracker.LookupTabNodeIds(tag2, &result));
    233   EXPECT_EQ(2U, result.size());
    234   EXPECT_FALSE(result.end() == result.find(21));
    235   EXPECT_FALSE(result.end() == result.find(22));
    236   EXPECT_TRUE(tracker.DeleteSession(tag2));
    237   EXPECT_FALSE(tracker.LookupTabNodeIds(tag2, &result));
    238 }
    239 
    240 TEST_F(SyncedSessionTrackerTest, SessionTracking) {
    241   SyncedSessionTracker tracker;
    242   ASSERT_TRUE(tracker.Empty());
    243   std::string tag1 = "tag1";
    244   std::string tag2 = "tag2";
    245 
    246   // Create some session information that is stale.
    247   SyncedSession* session1= tracker.GetSession(tag1);
    248   tracker.PutWindowInSession(tag1, 0);
    249   tracker.PutTabInWindow(tag1, 0, 0, 0);
    250   tracker.PutTabInWindow(tag1, 0, 1, 1);
    251   tracker.GetTab(tag1, 2, 3U)->window_id.set_id(0);  // Will be unmapped.
    252   tracker.GetTab(tag1, 3, 4U)->window_id.set_id(0);  // Will be unmapped.
    253   tracker.PutWindowInSession(tag1, 1);
    254   tracker.PutTabInWindow(tag1, 1, 4, 0);
    255   tracker.PutTabInWindow(tag1, 1, 5, 1);
    256   ASSERT_EQ(2U, session1->windows.size());
    257   ASSERT_EQ(2U, session1->windows[0]->tabs.size());
    258   ASSERT_EQ(2U, session1->windows[1]->tabs.size());
    259   ASSERT_EQ(6U, tracker.num_synced_tabs(tag1));
    260 
    261   // Create a session that should not be affected.
    262   SyncedSession* session2 = tracker.GetSession(tag2);
    263   tracker.PutWindowInSession(tag2, 2);
    264   tracker.PutTabInWindow(tag2, 2, 1, 0);
    265   ASSERT_EQ(1U, session2->windows.size());
    266   ASSERT_EQ(1U, session2->windows[2]->tabs.size());
    267   ASSERT_EQ(1U, tracker.num_synced_tabs(tag2));
    268 
    269   // Reset tracking and get the current windows/tabs.
    270   // We simulate moving a tab from one window to another, then closing the
    271   // first window (including its one remaining tab), and opening a new tab
    272   // on the remaining window.
    273 
    274   // New tab, arrived before meta node so unmapped.
    275   tracker.GetTab(tag1, 6, 7U);
    276   tracker.ResetSessionTracking(tag1);
    277   tracker.PutWindowInSession(tag1, 0);
    278   tracker.PutTabInWindow(tag1, 0, 0, 0);
    279   // Tab 1 is closed.
    280   tracker.PutTabInWindow(tag1, 0, 2, 1);  // No longer unmapped.
    281   // Tab 3 was unmapped and does not get used.
    282   tracker.PutTabInWindow(tag1, 0, 4, 2);  // Moved from window 1.
    283   // Window 1 was closed, along with tab 5.
    284   tracker.PutTabInWindow(tag1, 0, 6, 3);  // No longer unmapped.
    285   // Session 2 should not be affected.
    286   tracker.CleanupSession(tag1);
    287 
    288   // Verify that only those parts of the session not owned have been removed.
    289   ASSERT_EQ(1U, session1->windows.size());
    290   ASSERT_EQ(4U, session1->windows[0]->tabs.size());
    291   ASSERT_EQ(1U, session2->windows.size());
    292   ASSERT_EQ(1U, session2->windows[2]->tabs.size());
    293   ASSERT_EQ(2U, tracker.num_synced_sessions());
    294   ASSERT_EQ(4U, tracker.num_synced_tabs(tag1));
    295   ASSERT_EQ(1U, tracker.num_synced_tabs(tag2));
    296 
    297   // All memory should be properly deallocated by destructor for the
    298   // SyncedSessionTracker.
    299 }
    300 
    301 }  // namespace browser_sync
    302