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#ifndef SYNC_TEST_ENGINE_SYNCER_COMMAND_TEST_H_ 6#define SYNC_TEST_ENGINE_SYNCER_COMMAND_TEST_H_ 7 8#include <algorithm> 9#include <string> 10#include <vector> 11 12#include "base/compiler_specific.h" 13#include "base/memory/ref_counted.h" 14#include "base/message_loop/message_loop.h" 15#include "sync/engine/model_changing_syncer_command.h" 16#include "sync/engine/traffic_recorder.h" 17#include "sync/internal_api/public/engine/model_safe_worker.h" 18#include "sync/sessions/debug_info_getter.h" 19#include "sync/sessions/sync_session.h" 20#include "sync/sessions/sync_session_context.h" 21#include "sync/syncable/directory.h" 22#include "sync/test/engine/fake_model_worker.h" 23#include "sync/test/engine/mock_connection_manager.h" 24#include "sync/test/engine/test_directory_setter_upper.h" 25#include "sync/util/extensions_activity.h" 26#include "testing/gmock/include/gmock/gmock.h" 27#include "testing/gtest/include/gtest/gtest.h" 28 29using ::testing::NiceMock; 30 31namespace syncer { 32 33class MockDebugInfoGetter : public sessions::DebugInfoGetter { 34 public: 35 MockDebugInfoGetter(); 36 virtual ~MockDebugInfoGetter(); 37 MOCK_METHOD1(GetAndClearDebugInfo, void(sync_pb::DebugInfo* debug_info)); 38}; 39 40// A test fixture that simplifies writing unit tests for individual 41// SyncerCommands, providing convenient access to a test directory 42// and a syncer session. 43class SyncerCommandTestBase : public testing::Test, 44 public sessions::SyncSession::Delegate { 45 public: 46 // SyncSession::Delegate implementation. 47 virtual void OnThrottled( 48 const base::TimeDelta& throttle_duration) OVERRIDE { 49 FAIL() << "Should not get silenced."; 50 } 51 virtual void OnTypesThrottled( 52 ModelTypeSet types, 53 const base::TimeDelta& throttle_duration) OVERRIDE { 54 FAIL() << "Should not get silenced."; 55 } 56 virtual bool IsCurrentlyThrottled() OVERRIDE { 57 return false; 58 } 59 virtual void OnReceivedLongPollIntervalUpdate( 60 const base::TimeDelta& new_interval) OVERRIDE { 61 FAIL() << "Should not get poll interval update."; 62 } 63 virtual void OnReceivedShortPollIntervalUpdate( 64 const base::TimeDelta& new_interval) OVERRIDE { 65 FAIL() << "Should not get poll interval update."; 66 } 67 virtual void OnReceivedSessionsCommitDelay( 68 const base::TimeDelta& new_delay) OVERRIDE { 69 FAIL() << "Should not get sessions commit delay."; 70 } 71 virtual void OnReceivedClientInvalidationHintBufferSize(int size) OVERRIDE { 72 FAIL() << "Should not get hint buffer size."; 73 } 74 virtual void OnShouldStopSyncingPermanently() OVERRIDE { 75 FAIL() << "Shouldn't be called."; 76 } 77 virtual void OnSyncProtocolError( 78 const sessions::SyncSessionSnapshot& session) OVERRIDE { 79 return; 80 } 81 82 std::vector<ModelSafeWorker*> GetWorkers() { 83 std::vector<ModelSafeWorker*> workers; 84 std::vector<scoped_refptr<ModelSafeWorker> >::iterator it; 85 for (it = workers_.begin(); it != workers_.end(); ++it) 86 workers.push_back(it->get()); 87 return workers; 88 } 89 void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { 90 ModelSafeRoutingInfo copy(routing_info_); 91 out->swap(copy); 92 } 93 94 protected: 95 SyncerCommandTestBase(); 96 97 virtual ~SyncerCommandTestBase(); 98 virtual void SetUp(); 99 virtual void TearDown(); 100 101 sessions::SyncSessionContext* context() const { return context_.get(); } 102 sessions::SyncSession::Delegate* delegate() { return this; } 103 104 // Lazily create a session requesting all datatypes with no state. 105 sessions::SyncSession* session() { 106 if (!session_.get()) 107 session_.reset(sessions::SyncSession::Build(context(), delegate())); 108 return session_.get(); 109 } 110 111 void ClearSession() { 112 session_.reset(); 113 } 114 115 void ResetContext() { 116 context_.reset(new sessions::SyncSessionContext( 117 mock_server_.get(), directory(), 118 GetWorkers(), extensions_activity_.get(), 119 std::vector<SyncEngineEventListener*>(), 120 &mock_debug_info_getter_, 121 &traffic_recorder_, 122 true, // enable keystore encryption 123 false, // force enable pre-commit GU avoidance experiment 124 "fake_invalidator_client_id")); 125 context_->set_routing_info(routing_info_); 126 context_->set_account_name(directory()->name()); 127 ClearSession(); 128 } 129 130 // Install a MockServerConnection. Resets the context. By default, 131 // the context does not have a MockServerConnection attached. 132 void ConfigureMockServerConnection() { 133 mock_server_.reset(new MockConnectionManager(directory())); 134 ResetContext(); 135 } 136 137 virtual syncable::Directory* directory() = 0; 138 139 std::vector<scoped_refptr<ModelSafeWorker> >* workers() { 140 return &workers_; 141 } 142 143 const ModelSafeRoutingInfo& routing_info() { return routing_info_; } 144 ModelSafeRoutingInfo* mutable_routing_info() { return &routing_info_; } 145 146 MockConnectionManager* mock_server() { 147 return mock_server_.get(); 148 } 149 150 MockDebugInfoGetter* mock_debug_info_getter() { 151 return &mock_debug_info_getter_; 152 } 153 154 // Helper functions to check command.GetGroupsToChange(). 155 156 void ExpectNoGroupsToChange(const ModelChangingSyncerCommand& command) { 157 EXPECT_TRUE(command.GetGroupsToChangeForTest(*session()).empty()); 158 } 159 160 void ExpectGroupToChange( 161 const ModelChangingSyncerCommand& command, ModelSafeGroup group) { 162 std::set<ModelSafeGroup> expected_groups_to_change; 163 expected_groups_to_change.insert(group); 164 EXPECT_EQ(expected_groups_to_change, 165 command.GetGroupsToChangeForTest(*session())); 166 } 167 168 void ExpectGroupsToChange( 169 const ModelChangingSyncerCommand& command, 170 ModelSafeGroup group1, ModelSafeGroup group2) { 171 std::set<ModelSafeGroup> expected_groups_to_change; 172 expected_groups_to_change.insert(group1); 173 expected_groups_to_change.insert(group2); 174 EXPECT_EQ(expected_groups_to_change, 175 command.GetGroupsToChangeForTest(*session())); 176 } 177 178 void ExpectGroupsToChange( 179 const ModelChangingSyncerCommand& command, 180 ModelSafeGroup group1, ModelSafeGroup group2, ModelSafeGroup group3) { 181 std::set<ModelSafeGroup> expected_groups_to_change; 182 expected_groups_to_change.insert(group1); 183 expected_groups_to_change.insert(group2); 184 expected_groups_to_change.insert(group3); 185 EXPECT_EQ(expected_groups_to_change, 186 command.GetGroupsToChangeForTest(*session())); 187 } 188 189 private: 190 base::MessageLoop message_loop_; 191 scoped_ptr<sessions::SyncSessionContext> context_; 192 scoped_ptr<MockConnectionManager> mock_server_; 193 scoped_ptr<sessions::SyncSession> session_; 194 std::vector<scoped_refptr<ModelSafeWorker> > workers_; 195 ModelSafeRoutingInfo routing_info_; 196 NiceMock<MockDebugInfoGetter> mock_debug_info_getter_; 197 scoped_refptr<ExtensionsActivity> extensions_activity_; 198 TrafficRecorder traffic_recorder_; 199 DISALLOW_COPY_AND_ASSIGN(SyncerCommandTestBase); 200}; 201 202class SyncerCommandTest : public SyncerCommandTestBase { 203 public: 204 virtual void SetUp() OVERRIDE; 205 virtual void TearDown() OVERRIDE; 206 virtual syncable::Directory* directory() OVERRIDE; 207 208 private: 209 TestDirectorySetterUpper dir_maker_; 210}; 211 212} // namespace syncer 213 214#endif // SYNC_TEST_ENGINE_SYNCER_COMMAND_TEST_H_ 215