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