- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / synced_session_tracker_unittest.cc
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