profile_sync_test_util.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block// Use of this source code is governed by a BSD-style license that can be 3e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block// found in the LICENSE file. 4e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 5e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_ 6e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#define CHROME_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_ 7e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#pragma once 8e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 9e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include <string> 10e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 11e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/logging.h" 12e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/message_loop.h" 13e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/ref_counted.h" 14e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/scoped_ptr.h" 15e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/task.h" 16e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/thread.h" 17e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/waitable_event.h" 18e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "base/utf_string_conversions.h" 19e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/chrome_thread.h" 20e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/profile.h" 21e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/webdata/web_database.h" 22e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/glue/bookmark_change_processor.h" 23e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" 24e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/glue/bookmark_model_associator.h" 25e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/glue/change_processor.h" 26e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/glue/data_type_manager_impl.h" 27e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "chrome/browser/sync/profile_sync_factory.h" 28e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/browser/sync/profile_sync_service.h" 29967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "chrome/browser/sync/unrecoverable_error_handler.h" 30e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/common/notification_details.h" 31e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/common/notification_service.h" 32e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/common/notification_source.h" 33e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/common/notification_type.h" 34e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "chrome/test/sync/test_http_bridge_factory.h" 35e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "testing/gmock/include/gmock/gmock.h" 36e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 37e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockACTION_P(Notify, type) { 380617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen NotificationService::current()->Notify(type, 39e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block NotificationService::AllSources(), 40db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block NotificationService::NoDetails()); 41db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block} 42e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block 43e78cbe89e6f337f2f1fe40315be88f742b547151Steve BlockACTION(QuitUIMessageLoop) { 44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen MessageLoop::current()->Quit(); 46bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} 47bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen 48bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenACTION_P(InvokeTask, task) { 490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (task) 500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen task->Run(); 510617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen} 52e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenclass TestModelAssociatorHelper { 54e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block public: 550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen template <class ModelAssociatorImpl> 560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen bool GetSyncIdForTaggedNode(ModelAssociatorImpl* associator, 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block const std::string& tag, int64* sync_id) { 580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen std::wstring tag_wide; 590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if (!UTF8ToWide(tag.c_str(), tag.length(), &tag_wide)) { 600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen NOTREACHED() << "Unable to convert UTF8 to wide for string: " << tag; 610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return false; 620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen } 630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 64967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch sync_api::WriteTransaction trans( 65e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block associator->sync_service()->backend()->GetUserShareHandle()); 66e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block sync_api::ReadNode root(&trans); 67e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block root.InitByRootLookup(); 680617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 69e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // First, try to find a node with the title among the root's children. 700617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // This will be the case if we are testing model persistence, and 710617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen // are reloading a sync repository created earlier in the test. 720617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen int64 last_child_id = sync_api::kInvalidId; 730617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen for (int64 id = root.GetFirstChildId(); id != sync_api::kInvalidId; /***/) { 740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen sync_api::ReadNode child(&trans); 750617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen child.InitByIdLookup(id); 76967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch last_child_id = id; 77967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (tag_wide == child.GetTitle()) { 78e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *sync_id = id; 79967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch return true; 80967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 81967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch id = child.GetSuccessorId(); 82967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 83967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 84967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch sync_api::ReadNode predecessor_node(&trans); 850617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen sync_api::ReadNode* predecessor = NULL; 86e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (last_child_id != sync_api::kInvalidId) { 87967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch predecessor_node.InitByIdLookup(last_child_id); 88967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch predecessor = &predecessor_node; 89967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch } 90967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch sync_api::WriteNode node(&trans); 91967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch // Create new fake tagged nodes at the end of the ordering. 92967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch node.InitByCreation(ModelAssociatorImpl::model_type(), root, predecessor); 93967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch node.SetIsFolder(true); 94967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch node.SetTitle(tag_wide); 95967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch node.SetExternalId(0); 96967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch *sync_id = node.GetId(); 970617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return true; 98e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 99967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 100967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch ~TestModelAssociatorHelper() {} 101967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}; 102967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 103967717af5423377c967781471ee106e2bb4e11c8Ben Murdochclass ProfileSyncServiceObserverMock : public ProfileSyncServiceObserver { 104967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch public: 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block MOCK_METHOD0(OnStateChanged, void()); 106967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch}; 107967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch 108967717af5423377c967781471ee106e2bb4e11c8Ben Murdochclass ThreadNotificationService 109e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block : public base::RefCountedThreadSafe<ThreadNotificationService> { 110e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block public: 111e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block explicit ThreadNotificationService(base::Thread* notification_thread) 112 : done_event_(false, false), 113 notification_thread_(notification_thread) {} 114 115 void Init() { 116 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 117 notification_thread_->message_loop()->PostTask( 118 FROM_HERE, 119 NewRunnableMethod(this, &ThreadNotificationService::InitTask)); 120 done_event_.Wait(); 121 } 122 123 void TearDown() { 124 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 125 notification_thread_->message_loop()->PostTask( 126 FROM_HERE, 127 NewRunnableMethod(this, 128 &ThreadNotificationService::TearDownTask)); 129 done_event_.Wait(); 130 } 131 132 private: 133 friend class base::RefCountedThreadSafe<ThreadNotificationService>; 134 135 void InitTask() { 136 service_.reset(new NotificationService()); 137 done_event_.Signal(); 138 } 139 140 void TearDownTask() { 141 service_.reset(NULL); 142 done_event_.Signal(); 143 } 144 145 base::WaitableEvent done_event_; 146 base::Thread* notification_thread_; 147 scoped_ptr<NotificationService> service_; 148}; 149 150class ThreadNotifier : // NOLINT 151 public base::RefCountedThreadSafe<ThreadNotifier> { 152 public: 153 explicit ThreadNotifier(base::Thread* notify_thread) 154 : done_event_(false, false), 155 notify_thread_(notify_thread) {} 156 157 void Notify(NotificationType type, const NotificationDetails& details) { 158 Notify(type, NotificationService::AllSources(), details); 159 } 160 161 void Notify(NotificationType type, 162 const NotificationSource& source, 163 const NotificationDetails& details) { 164 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 165 notify_thread_->message_loop()->PostTask( 166 FROM_HERE, 167 NewRunnableMethod(this, 168 &ThreadNotifier::NotifyTask, 169 type, 170 source, 171 details)); 172 done_event_.Wait(); 173 } 174 175 private: 176 friend class base::RefCountedThreadSafe<ThreadNotifier>; 177 178 void NotifyTask(NotificationType type, 179 const NotificationSource& source, 180 const NotificationDetails& details) { 181 NotificationService::current()->Notify(type, source, details); 182 done_event_.Signal(); 183 } 184 185 base::WaitableEvent done_event_; 186 base::Thread* notify_thread_; 187}; 188 189#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_ 190