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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/chrome_tests.gypi ('k') | chrome/test/live_sync/live_sync_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/live_sync/live_sessions_sync_test.h
===================================================================
--- chrome/test/live_sync/live_sessions_sync_test.h (revision 0)
+++ chrome/test/live_sync/live_sessions_sync_test.h (revision 0)
@@ -0,0 +1,418 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
+#define CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
+#pragma once
+
+#include <algorithm>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/scoped_vector.h"
+#include "base/ref_counted.h"
+#include "base/waitable_event.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/sessions/base_session_service.h"
+#include "chrome/browser/sessions/session_service_test_helper.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/test/live_sync/live_sync_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "googleurl/src/gurl.h"
+#include "webkit/glue/window_open_disposition.h"
+
+// Helper for accessing session service internals.
+class TestSessionService
+ : public SessionServiceTestHelper,
+ public base::RefCountedThreadSafe<TestSessionService> {
+ public:
+ TestSessionService()
+ : SessionServiceTestHelper(),
+ done_saving_(false, false),
+ got_windows_(false, false),
+ profile_(NULL),
+ window_bounds_(0, 1, 2, 3) {}
+ TestSessionService(SessionService * service,
+ Profile* profile)
+ : SessionServiceTestHelper(service),
+ done_saving_(false, false),
+ got_windows_(false, false),
+ profile_(profile),
+ window_bounds_(0, 1, 2, 3) {}
+
+ void SetUp() {
+ ASSERT_TRUE(service()) << "SetUp() called without setting SessionService";
+ ASSERT_TRUE(profile_);
+ service()->SetWindowType(window_id_, Browser::TYPE_NORMAL);
+ service()->SetWindowBounds(window_id_, window_bounds_, false);
+ }
+
+ // Trigger saving the current session commands to file.
+ void Save() {
+ service()->Save();
+ }
+
+ // Synchronously reads the contents of the current session.
+ std::vector<SessionWindow*>* ReadWindows() {
+ // The session backend will post the callback as a task to whatever thread
+ // called it. In our case, we don't want the main test thread to have tasks
+ // posted to, so we perform the actual call to session service from the same
+ // thread the work will be done on (backend_thread aka file thread). As a
+ // result, it will directly call back, instead of posting a task, and we can
+ // block on that callback.
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableMethod(this, &TestSessionService::DoReadWindows));
+
+ // Wait for callback to happen.
+ got_windows_.Wait();
+
+ // By the time we reach here we've received the windows, so return them.
+ return windows_;
+ }
+
+ // Makes the actual call to session service.
+ // Lives on the file thread.
+ void DoReadWindows() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ LOG(ERROR) << "DoReadWindows called from wrong thread!";
+ windows_ = NULL;
+ got_windows_.Signal();
+ return;
+ }
+ SessionService::SessionCallback* callback =
+ NewCallback(this, &TestSessionService::OnGotSession);
+ service()->GetCurrentSession(&consumer_, callback);
+ }
+
+ // Internal method used in the callback to obtain the current session.
+ // Lives on and called from backend thread (file_thread).
+ // We don't own windows so need to make a deep copy.
+ void OnGotSession(int handle, std::vector<SessionWindow*>* windows) {
+ // Hacky. We need to make a deep copy of the session windows. One way to do
+ // this is to use the session model associators functionality to create
+ // foreign sessions, which themselves wrap a SessionWindow vector. We just
+ // need to make sure to destroy all the foreign sessions we created when
+ // we're done. That's what the foreign_sessions_ ScopedVector is for.
+ sync_pb::SessionSpecifics session;
+ profile_->GetProfileSyncService()->
+ GetSessionModelAssociator()->
+ FillSpecificsFromSessions(windows, &session);
+
+ std::vector<ForeignSession*> foreign_sessions;
+ profile_->GetProfileSyncService()->
+ GetSessionModelAssociator()->
+ AppendForeignSessionFromSpecifics(&session, &foreign_sessions);
+ ASSERT_EQ(foreign_sessions.size(), 1U);
+ foreign_sessions_.push_back(foreign_sessions[0]);
+ windows_ = &foreign_sessions[0]->windows;
+ got_windows_.Signal();
+ }
+
+ private:
+ ~TestSessionService() {
+ ReleaseService(); // We don't own this, so don't destroy it.
+ }
+
+ friend class base::RefCountedThreadSafe<TestSessionService>;
+
+ // Current session buffer.
+ std::vector<SessionWindow*>* windows_;
+
+ // List of all foreign sessions we created in ReadWindows. We delete them all
+ // at destruction time so that complex tests can keep comparing against old
+ // SessionWindow data. Note that since we're constantly creating new foreign
+ // sessions, we don't have to worry about duplicates.
+ ScopedVector<ForeignSession> foreign_sessions_;
+
+ // Barrier for saving session.
+ base::WaitableEvent done_saving_;
+
+ // Barrier for getting current windows in ReadWindows.
+ base::WaitableEvent got_windows_;
+
+ // Consumer used to obtain the current session.
+ CancelableRequestConsumer consumer_;
+
+ // Sync profile associated with this session service.
+ Profile* profile_;
+
+ SessionID window_id_;
+ const gfx::Rect window_bounds_;
+};
+
+class LiveSessionsSyncTest : public LiveSyncTest {
+ public:
+ explicit LiveSessionsSyncTest(TestType test_type)
+ : LiveSyncTest(test_type),
+ done_closing_(false, false) {}
+ virtual ~LiveSessionsSyncTest() {}
+
+ // Used to access the session service associated with a specific sync profile.
+ SessionService* GetSessionService(int index) {
+ return GetProfile(index)->GetSessionService();
+ }
+
+ // Used to access the session service test helper associated with a specific
+ // sync profile.
+ TestSessionService* GetHelper(int index) {
+ return test_session_services_[index]->get();
+ }
+
+ // Used to access the browser associated with a specific sync profile.
+ Browser* GetBrowser(int index) {
+ return browsers_[index];
+ }
+
+ // Sets up the TestSessionService helper and the new browser windows.
+ bool SetupClients() {
+ if (!LiveSyncTest::SetupClients()) {
+ return false;
+ }
+
+ // Go through and make the TestSessionServices and Browsers.
+ for (int i = 0; i < num_clients(); ++i) {
+ scoped_refptr<TestSessionService>* new_tester =
+ new scoped_refptr<TestSessionService>;
+ *new_tester = new TestSessionService(
+ GetSessionService(i), GetProfile(i));
+ test_session_services_.push_back(new_tester);
+ GetHelper(i)->SetUp();
+
+ browsers_.push_back(Browser::Create(GetProfile(i)));
+ }
+
+ return true;
+ }
+
+ // Open a single tab and return the TabContents. TabContents must be checked
+ // to ensure the tab opened successsfully.
+ TabContents* OpenTab(int index, GURL url) WARN_UNUSED_RESULT {
+ TabContents* tab = GetBrowser(index)->
+ AddSelectedTabWithURL(url, PageTransition::START_PAGE);
+
+ // Wait for the page to finish loading.
+ ui_test_utils::WaitForNavigation(
+ &GetBrowser(index)->GetSelectedTabContents()->controller());
+
+ return tab;
+ }
+
+ // Creates and verifies the creation of a new window with one tab displaying
+ // the specified GURL.
+ // Returns: the SessionWindow associated with the new window.
+ std::vector<SessionWindow*>* InitializeNewWindowWithTab(int index, GURL url)
+ WARN_UNUSED_RESULT {
+ if (!OpenTab(index, url)) {
+ return NULL;
+ }
+ GetHelper(index)->Save();
+ std::vector<SessionWindow*>* windows = GetHelper(index)->ReadWindows();
+ if (windows->size() != 1) {
+ LOG(ERROR) << "InitializeNewWindowWithTab called with open windows!";
+ return NULL;
+ }
+ if (1U != (*windows)[0]->tabs.size())
+ return NULL;
+ SortSessionWindows(windows);
+ return windows;
+ }
+
+ // Checks that window count and foreign session count are 0.
+ bool CheckInitialState(int index) WARN_UNUSED_RESULT {
+ if (0 != GetNumWindows(index))
+ return false;
+ if (0 != GetNumForeignSessions(index))
+ return false;
+ return true;
+ }
+
+ // Returns number of open windows for a profile.
+ int GetNumWindows(int index) {
+ // We don't own windows.
+ std::vector<SessionWindow*>* windows = GetHelper(index)->ReadWindows();
+ return windows->size();
+ }
+
+ // Returns number of foreign sessions for a profile.
+ int GetNumForeignSessions(int index) {
+ ScopedVector<ForeignSession> sessions;
+ if (!GetProfile(index)->GetProfileSyncService()->
+ GetSessionModelAssociator()->GetSessionData(&sessions.get()))
+ return 0;
+ return sessions.size();
+ }
+
+ // Fills the sessions vector with the model associator's foreign session data.
+ // Caller owns sessions.
+ bool GetSessionData(int index, std::vector<ForeignSession*>* sessions)
+ WARN_UNUSED_RESULT {
+ if (!GetProfile(index)->GetProfileSyncService()->
+ GetSessionModelAssociator()->GetSessionData(sessions))
+ return false;
+ SortForeignSessions(sessions);
+ return true;
+ }
+
+ // Compare session windows based on their first tab's url.
+ // Returns true if the virtual url of the lhs is < the rhs.
+ static bool CompareSessionWindows(SessionWindow* lhs, SessionWindow* rhs) {
+ if (!lhs ||
+ !rhs ||
+ lhs->tabs.size() < 1 ||
+ rhs->tabs.size() < 1 ||
+ lhs->tabs[0]->navigations.size() < 1 ||
+ rhs->tabs[0]->navigations.size() < 1) {
+ // Catchall for uncomparable data.
+ return false;
+ }
+
+ return lhs->tabs[0]->navigations[0].virtual_url() <
+ rhs->tabs[0]->navigations[0].virtual_url();
+ }
+
+ // Sort session windows using our custom comparator (first tab url
+ // comparison).
+ void SortSessionWindows(std::vector<SessionWindow*>* windows) {
+ std::sort(windows->begin(), windows->end(),
+ LiveSessionsSyncTest::CompareSessionWindows);
+ }
+
+ // Compares a foreign session based on the first session window.
+ // Returns true based on the comparison of the session windows.
+ static bool CompareForeignSessions(ForeignSession* lhs, ForeignSession* rhs) {
+ if (!lhs ||
+ !rhs ||
+ lhs->windows.size() < 1 ||
+ rhs->windows.size() < 1) {
+ // Catchall for uncomparable data.
+ return false;
+ }
+
+ return CompareSessionWindows(lhs->windows[0], rhs->windows[0]);
+ }
+
+ // Sort a foreign session vector using our custom foreign session comparator.
+ void SortForeignSessions(std::vector<ForeignSession*>* sessions) {
+ std::sort(sessions->begin(), sessions->end(),
+ LiveSessionsSyncTest::CompareForeignSessions);
+ }
+
+ // Verifies that two SessionWindows match.
+ // Returns:
+ // - true if all the following match:
+ // 1. number of SessionWindows per vector,
+ // 2. number of tabs per SessionWindow,
+ // 3. number of tab navigations per nab,
+ // 4. actual tab navigations
+ // - false otherwise.
+ bool WindowsMatch(const std::vector<SessionWindow*> &win1,
+ const std::vector<SessionWindow*> &win2) WARN_UNUSED_RESULT {
+ SessionTab* client0_tab;
+ SessionTab* client1_tab;
+ if (win1.size() != win2.size())
+ return false;
+ for (size_t i = 0; i < win1.size(); ++i) {
+ if (win1[i]->tabs.size() != win2[i]->tabs.size())
+ return false;
+ for (size_t j = 0; j < win1[i]->tabs.size(); ++j) {
+ client0_tab = win1[i]->tabs[j];
+ client1_tab = win2[i]->tabs[j];
+ for (size_t k = 0; k < client0_tab->navigations.size(); ++k) {
+ GetHelper(0)->AssertNavigationEquals(client0_tab->navigations[k],
+ client1_tab->navigations[k]);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // Retrieves the foreign sessions for a particular profile and compares them
+ // with a reference SessionWindow list.
+ // Returns true if the session windows of the foreign session matches the
+ // reference.
+ bool CheckForeignSessionsAgainst(int index,
+ const std::vector<std::vector<SessionWindow*>* >& windows)
+ WARN_UNUSED_RESULT {
+ ScopedVector<ForeignSession> sessions;
+ if (!GetSessionData(index, &sessions.get()))
+ return false;
+ if ((size_t)(num_clients()-1) != sessions.size())
+ return false;
+
+ int window_index = 0;
+ for (size_t j = 0; j < sessions->size(); ++j, ++window_index) {
+ if (window_index == index)
+ window_index++; // Skip self.
+ if (!WindowsMatch(sessions[j]->windows, *windows[window_index]))
+ return false;
+ }
+
+ return true;
+ }
+
+ protected:
+ // Clean up our mess.
+ virtual void CleanUpOnMainThread() {
+ // Close all browsers. We need to do this now, as opposed to letting the
+ // test framework handle it, because we created our own browser for each
+ // sync profile.
+ BrowserList::CloseAllBrowsers();
+ ui_test_utils::RunAllPendingInMessageLoop();
+
+ // All browsers should be closed at this point, else when the framework
+ // calls QuitBrowsers() we could see memory corruption.
+ ASSERT_EQ(0U, BrowserList::size());
+
+ LiveSyncTest::CleanUpOnMainThread();
+ }
+
+ // Vector of our TestSessionService helpers.
+ ScopedVector<scoped_refptr<TestSessionService> > test_session_services_;
+
+ // Vector of our browsers for each profile.
+ std::vector<Browser*> browsers_;
+
+ // Barrier for closing the browsers we create in UI thread.
+ base::WaitableEvent done_closing_;
+
+ DISALLOW_COPY_AND_ASSIGN(LiveSessionsSyncTest);
+};
+
+class SingleClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
+ public:
+ SingleClientLiveSessionsSyncTest()
+ : LiveSessionsSyncTest(SINGLE_CLIENT) {}
+ virtual ~SingleClientLiveSessionsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SingleClientLiveSessionsSyncTest);
+};
+
+class TwoClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
+ public:
+ TwoClientLiveSessionsSyncTest() : LiveSessionsSyncTest(TWO_CLIENT) {}
+ virtual ~TwoClientLiveSessionsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TwoClientLiveSessionsSyncTest);
+};
+
+class MultipleClientLiveSessionsSyncTest : public LiveSessionsSyncTest {
+ public:
+ MultipleClientLiveSessionsSyncTest()
+ : LiveSessionsSyncTest(MULTIPLE_CLIENT) {}
+ virtual ~MultipleClientLiveSessionsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MultipleClientLiveSessionsSyncTest);
+};
+
+#endif // CHROME_TEST_LIVE_SYNC_LIVE_SESSIONS_SYNC_TEST_H_
+
Property changes on: chrome/test/live_sync/live_sessions_sync_test.h
___________________________________________________________________
Added: svn:eol-style
+ LF
« 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