Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: chrome/test/live_sync/live_sessions_sync_test.h

Issue 4158009: Session sync integration tests. Left out many client for now, since even... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/chrome_tests.gypi ('k') | chrome/test/live_sync/live_sync_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #ifndef CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
6 #define CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
7 #pragma once
8
9 #include <algorithm>
10 #include <vector>
11
12 #include "base/compiler_specific.h"
13 #include "base/scoped_vector.h"
14 #include "base/ref_counted.h"
15 #include "base/waitable_event.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/browser_window.h"
18 #include "chrome/browser/profile.h"
19 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
20 #include "chrome/browser/sessions/base_session_service.h"
21 #include "chrome/browser/sessions/session_service_test_helper.h"
22 #include "chrome/browser/tab_contents/tab_contents.h"
23 #include "chrome/test/live_sync/live_sync_test.h"
24 #include "chrome/test/ui_test_utils.h"
25 #include "googleurl/src/gurl.h"
26 #include "webkit/glue/window_open_disposition.h"
27
28 // Helper for accessing session service internals.
29 class TestSessionService
30 : public SessionServiceTestHelper,
31 public base::RefCountedThreadSafe<TestSessionService> {
32 public:
33 TestSessionService()
34 : SessionServiceTestHelper(),
35 done_saving_(false, false),
36 got_windows_(false, false),
37 profile_(NULL),
38 window_bounds_(0, 1, 2, 3) {}
39 TestSessionService(SessionService * service,
40 Profile* profile)
41 : SessionServiceTestHelper(service),
42 done_saving_(false, false),
43 got_windows_(false, false),
44 profile_(profile),
45 window_bounds_(0, 1, 2, 3) {}
46
47 void SetUp() {
48 ASSERT_TRUE(service()) << "SetUp() called without setting SessionService";
49 ASSERT_TRUE(profile_);
50 service()->SetWindowType(window_id_, Browser::TYPE_NORMAL);
51 service()->SetWindowBounds(window_id_, window_bounds_, false);
52 }
53
54 // Trigger saving the current session commands to file.
55 void Save() {
56 service()->Save();
57 }
58
59 // Synchronously reads the contents of the current session.
60 std::vector<SessionWindow*>* ReadWindows() {
61 // The session backend will post the callback as a task to whatever thread
62 // called it. In our case, we don't want the main test thread to have tasks
63 // posted to, so we perform the actual call to session service from the same
64 // thread the work will be done on (backend_thread aka file thread). As a
65 // result, it will directly call back, instead of posting a task, and we can
66 // block on that callback.
67 BrowserThread::PostTask(
68 BrowserThread::FILE,
69 FROM_HERE,
70 NewRunnableMethod(this, &TestSessionService::DoReadWindows));
71
72 // Wait for callback to happen.
73 got_windows_.Wait();
74
75 // By the time we reach here we've received the windows, so return them.
76 return windows_;
77 }
78
79 // Makes the actual call to session service.
80 // Lives on the file thread.
81 void DoReadWindows() {
82 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
83 LOG(ERROR) << "DoReadWindows called from wrong thread!";
84 windows_ = NULL;
85 got_windows_.Signal();
86 return;
87 }
88 SessionService::SessionCallback* callback =
89 NewCallback(this, &TestSessionService::OnGotSession);
90 service()->GetCurrentSession(&consumer_, callback);
91 }
92
93 // Internal method used in the callback to obtain the current session.
94 // Lives on and called from backend thread (file_thread).
95 // We don't own windows so need to make a deep copy.
96 void OnGotSession(int handle, std::vector<SessionWindow*>* windows) {
97 // Hacky. We need to make a deep copy of the session windows. One way to do
98 // this is to use the session model associators functionality to create
99 // foreign sessions, which themselves wrap a SessionWindow vector. We just
100 // need to make sure to destroy all the foreign sessions we created when
101 // we're done. That's what the foreign_sessions_ ScopedVector is for.
102 sync_pb::SessionSpecifics session;
103 profile_->GetProfileSyncService()->
104 GetSessionModelAssociator()->
105 FillSpecificsFromSessions(windows, &session);
106
107 std::vector<ForeignSession*> foreign_sessions;
108 profile_->GetProfileSyncService()->
109 GetSessionModelAssociator()->
110 AppendForeignSessionFromSpecifics(&session, &foreign_sessions);
111 ASSERT_EQ(foreign_sessions.size(), 1U);
112 foreign_sessions_.push_back(foreign_sessions[0]);
113 windows_ = &foreign_sessions[0]->windows;
114 got_windows_.Signal();
115 }
116
117 private:
118 ~TestSessionService() {
119 ReleaseService(); // We don't own this, so don't destroy it.
120 }
121
122 friend class base::RefCountedThreadSafe<TestSessionService>;
123
124 // Current session buffer.
125 std::vector<SessionWindow*>* windows_;
126
127 // List of all foreign sessions we created in ReadWindows. We delete them all
128 // at destruction time so that complex tests can keep comparing against old
129 // SessionWindow data. Note that since we're constantly creating new foreign
130 // sessions, we don't have to worry about duplicates.
131 ScopedVector<ForeignSession> foreign_sessions_;
132
133 // Barrier for saving session.
134 base::WaitableEvent done_saving_;
135
136 // Barrier for getting current windows in ReadWindows.
137 base::WaitableEvent got_windows_;
138
139 // Consumer used to obtain the current session.
140 CancelableRequestConsumer consumer_;
141
142 // Sync profile associated with this session service.
143 Profile* profile_;
144
145 SessionID window_id_;
146 const gfx::Rect window_bounds_;
147 };
148
149 class LiveSessionsSyncTest : public LiveSyncTest {
150 public:
151 explicit LiveSessionsSyncTest(TestType test_type)
152 : LiveSyncTest(test_type),
153 done_closing_(false, false) {}
154 virtual ~LiveSessionsSyncTest() {}
155
156 // Used to access the session service associated with a specific sync profile.
157 SessionService* GetSessionService(int index) {
158 return GetProfile(index)->GetSessionService();
159 }
160
161 // Used to access the session service test helper associated with a specific
162 // sync profile.
163 TestSessionService* GetHelper(int index) {
164 return test_session_services_[index]->get();
165 }
166
167 // Used to access the browser associated with a specific sync profile.
168 Browser* GetBrowser(int index) {
169 return browsers_[index];
170 }
171
172 // Sets up the TestSessionService helper and the new browser windows.
173 bool SetupClients() {
174 if (!LiveSyncTest::SetupClients()) {
175 return false;
176 }
177
178 // Go through and make the TestSessionServices and Browsers.
179 for (int i = 0; i < num_clients(); ++i) {
180 scoped_refptr<TestSessionService>* new_tester =
181 new scoped_refptr<TestSessionService>;
182 *new_tester = new TestSessionService(
183 GetSessionService(i), GetProfile(i));
184 test_session_services_.push_back(new_tester);
185 GetHelper(i)->SetUp();
186
187 browsers_.push_back(Browser::Create(GetProfile(i)));
188 }
189
190 return true;
191 }
192
193 // Open a single tab and return the TabContents. TabContents must be checked
194 // to ensure the tab opened successsfully.
195 TabContents* OpenTab(int index, GURL url) WARN_UNUSED_RESULT {
196 TabContents* tab = GetBrowser(index)->
197 AddSelectedTabWithURL(url, PageTransition::START_PAGE);
198
199 // Wait for the page to finish loading.
200 ui_test_utils::WaitForNavigation(
201 &GetBrowser(index)->GetSelectedTabContents()->controller());
202
203 return tab;
204 }
205
206 // Creates and verifies the creation of a new window with one tab displaying
207 // the specified GURL.
208 // Returns: the SessionWindow associated with the new window.
209 std::vector<SessionWindow*>* InitializeNewWindowWithTab(int index, GURL url)
210 WARN_UNUSED_RESULT {
211 if (!OpenTab(index, url)) {
212 return NULL;
213 }
214 GetHelper(index)->Save();
215 std::vector<SessionWindow*>* windows = GetHelper(index)->ReadWindows();
216 if (windows->size() != 1) {
217 LOG(ERROR) << "InitializeNewWindowWithTab called with open windows!";
218 return NULL;
219 }
220 if (1U != (*windows)[0]->tabs.size())
221 return NULL;
222 SortSessionWindows(windows);
223 return windows;
224 }
225
226 // Checks that window count and foreign session count are 0.
227 bool CheckInitialState(int index) WARN_UNUSED_RESULT {
228 if (0 != GetNumWindows(index))
229 return false;
230 if (0 != GetNumForeignSessions(index))
231 return false;
232 return true;
233 }
234
235 // Returns number of open windows for a profile.
236 int GetNumWindows(int index) {
237 // We don't own windows.
238 std::vector<SessionWindow*>* windows = GetHelper(index)->ReadWindows();
239 return windows->size();
240 }
241
242 // Returns number of foreign sessions for a profile.
243 int GetNumForeignSessions(int index) {
244 ScopedVector<ForeignSession> sessions;
245 if (!GetProfile(index)->GetProfileSyncService()->
246 GetSessionModelAssociator()->GetSessionData(&sessions.get()))
247 return 0;
248 return sessions.size();
249 }
250
251 // Fills the sessions vector with the model associator's foreign session data.
252 // Caller owns sessions.
253 bool GetSessionData(int index, std::vector<ForeignSession*>* sessions)
254 WARN_UNUSED_RESULT {
255 if (!GetProfile(index)->GetProfileSyncService()->
256 GetSessionModelAssociator()->GetSessionData(sessions))
257 return false;
258 SortForeignSessions(sessions);
259 return true;
260 }
261
262 // Compare session windows based on their first tab's url.
263 // Returns true if the virtual url of the lhs is < the rhs.
264 static bool CompareSessionWindows(SessionWindow* lhs, SessionWindow* rhs) {
265 if (!lhs ||
266 !rhs ||
267 lhs->tabs.size() < 1 ||
268 rhs->tabs.size() < 1 ||
269 lhs->tabs[0]->navigations.size() < 1 ||
270 rhs->tabs[0]->navigations.size() < 1) {
271 // Catchall for uncomparable data.
272 return false;
273 }
274
275 return lhs->tabs[0]->navigations[0].virtual_url() <
276 rhs->tabs[0]->navigations[0].virtual_url();
277 }
278
279 // Sort session windows using our custom comparator (first tab url
280 // comparison).
281 void SortSessionWindows(std::vector<SessionWindow*>* windows) {
282 std::sort(windows->begin(), windows->end(),
283 LiveSessionsSyncTest::CompareSessionWindows);
284 }
285
286 // Compares a foreign session based on the first session window.
287 // Returns true based on the comparison of the session windows.
288 static bool CompareForeignSessions(ForeignSession* lhs, ForeignSession* rhs) {
289 if (!lhs ||
290 !rhs ||
291 lhs->windows.size() < 1 ||
292 rhs->windows.size() < 1) {
293 // Catchall for uncomparable data.
294 return false;
295 }
296
297 return CompareSessionWindows(lhs->windows[0], rhs->windows[0]);
298 }
299
300 // Sort a foreign session vector using our custom foreign session comparator.
301 void SortForeignSessions(std::vector<ForeignSession*>* sessions) {
302 std::sort(sessions->begin(), sessions->end(),
303 LiveSessionsSyncTest::CompareForeignSessions);
304 }
305
306 // Verifies that two SessionWindows match.
307 // Returns:
308 // - true if all the following match:
309 // 1. number of SessionWindows per vector,
310 // 2. number of tabs per SessionWindow,
311 // 3. number of tab navigations per nab,
312 // 4. actual tab navigations
313 // - false otherwise.
314 bool WindowsMatch(const std::vector<SessionWindow*> &win1,
315 const std::vector<SessionWindow*> &win2) WARN_UNUSED_RESULT {
316 SessionTab* client0_tab;
317 SessionTab* client1_tab;
318 if (win1.size() != win2.size())
319 return false;
320 for (size_t i = 0; i < win1.size(); ++i) {
321 if (win1[i]->tabs.size() != win2[i]->tabs.size())
322 return false;
323 for (size_t j = 0; j < win1[i]->tabs.size(); ++j) {
324 client0_tab = win1[i]->tabs[j];
325 client1_tab = win2[i]->tabs[j];
326 for (size_t k = 0; k < client0_tab->navigations.size(); ++k) {
327 GetHelper(0)->AssertNavigationEquals(client0_tab->navigations[k],
328 client1_tab->navigations[k]);
329 }
330 }
331 }
332
333 return true;
334 }
335
336 // Retrieves the foreign sessions for a particular profile and compares them
337 // with a reference SessionWindow list.
338 // Returns true if the session windows of the foreign session matches the
339 // reference.
340 bool CheckForeignSessionsAgainst(int index,
341 const std::vector<std::vector<SessionWindow*>* >& windows)
342 WARN_UNUSED_RESULT {
343 ScopedVector<ForeignSession> sessions;
344 if (!GetSessionData(index, &sessions.get()))
345 return false;
346 if ((size_t)(num_clients()-1) != sessions.size())
347 return false;
348
349 int window_index = 0;
350 for (size_t j = 0; j < sessions->size(); ++j, ++window_index) {
351 if (window_index == index)
352 window_index++; // Skip self.
353 if (!WindowsMatch(sessions[j]->windows, *windows[window_index]))
354 return false;
355 }
356
357 return true;
358 }
359
360 protected:
361 // Clean up our mess.
362 virtual void CleanUpOnMainThread() {
363 // Close all browsers. We need to do this now, as opposed to letting the
364 // test framework handle it, because we created our own browser for each
365 // sync profile.
366 BrowserList::CloseAllBrowsers();
367 ui_test_utils::RunAllPendingInMessageLoop();
368
369 // All browsers should be closed at this point, else when the framework
370 // calls QuitBrowsers() we could see memory corruption.
371 ASSERT_EQ(0U, BrowserList::size());
372
373 LiveSyncTest::CleanUpOnMainThread();
374 }
375
376 // Vector of our TestSessionService helpers.
377 ScopedVector<scoped_refptr<TestSessionService> > test_session_services_;
378
379 // Vector of our browsers for each profile.
380 std::vector<Browser*> browsers_;
381
382 // Barrier for closing the browsers we create in UI thread.
383 base::WaitableEvent done_closing_;
384
385 DISALLOW_COPY_AND_ASSIGN(LiveSessionsSyncTest);
386 };
387
388 class SingleClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
389 public:
390 SingleClientLiveSessionsSyncTest()
391 : LiveSessionsSyncTest(SINGLE_CLIENT) {}
392 virtual ~SingleClientLiveSessionsSyncTest() {}
393
394 private:
395 DISALLOW_COPY_AND_ASSIGN(SingleClientLiveSessionsSyncTest);
396 };
397
398 class TwoClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
399 public:
400 TwoClientLiveSessionsSyncTest() : LiveSessionsSyncTest(TWO_CLIENT) {}
401 virtual ~TwoClientLiveSessionsSyncTest() {}
402
403 private:
404 DISALLOW_COPY_AND_ASSIGN(TwoClientLiveSessionsSyncTest);
405 };
406
407 class MultipleClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
408 public:
409 MultipleClientLiveSessionsSyncTest()
410 : LiveSessionsSyncTest(MULTIPLE_CLIENT) {}
411 virtual ~MultipleClientLiveSessionsSyncTest() {}
412
413 private:
414 DISALLOW_COPY_AND_ASSIGN(MultipleClientLiveSessionsSyncTest);
415 };
416
417 #endif // CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
418
OLDNEW
« no previous file with comments | « chrome/chrome_tests.gypi ('k') | chrome/test/live_sync/live_sync_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698