sync_file_system_service_unittest.cc revision a3f7b4e666c476898878fa745f637129375cd889
16762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver// Copyright (c) 2012 The Chromium Authors. All rights reserved. 26762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver// Use of this source code is governed by a BSD-style license that can be 36762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver// found in the LICENSE file. 46762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 56762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include <vector> 66762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 76762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "base/basictypes.h" 86762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "base/bind.h" 96762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "base/run_loop.h" 106762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "base/stl_util.h" 116762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "base/synchronization/waitable_event.h" 126762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/browser/sync_file_system/local_file_sync_service.h" 136762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h" 146762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/browser/sync_file_system/sync_event_observer.h" 156762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/browser/sync_file_system/sync_file_system_service.h" 166762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 176762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "chrome/test/base/testing_profile.h" 186762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "content/public/browser/browser_thread.h" 196762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "content/public/test/test_browser_thread_bundle.h" 206762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "content/public/test/test_utils.h" 216762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "testing/gtest/include/gtest/gtest.h" 226762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/file_system_context.h" 236762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/canned_syncable_file_system.h" 246762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/local_file_sync_context.h" 256762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/mock_sync_status_observer.h" 266762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/sync_callbacks.h" 276762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/sync_file_metadata.h" 286762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/sync_status_code.h" 296762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h" 306762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 316762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing content::BrowserThread; 326762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing fileapi::FileSystemURL; 336762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing fileapi::FileSystemURLSet; 346762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::AnyNumber; 356762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::AtLeast; 366762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::InSequence; 376762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::InvokeWithoutArgs; 386762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::Return; 396762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::StrictMock; 406762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverusing ::testing::_; 416762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 426762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvernamespace sync_file_system { 436762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 446762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvernamespace { 456762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 466762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverconst char kOrigin[] = "http://example.com"; 476762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 486762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvertemplate <typename R> struct AssignTrait { 496762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver typedef const R& ArgumentType; 506762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver}; 516762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 526762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvertemplate <> struct AssignTrait<SyncFileStatus> { 536762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver typedef SyncFileStatus ArgumentType; 546762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver}; 556762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 566762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvertemplate <typename R> 576762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvervoid AssignValueAndQuit(base::RunLoop* run_loop, 586762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncStatusCode* status_out, R* value_out, 596762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncStatusCode status, 606762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver typename AssignTrait<R>::ArgumentType value) { 616762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver DCHECK(status_out); 626762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver DCHECK(value_out); 636762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver DCHECK(run_loop); 646762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver *status_out = status; 656762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver *value_out = value; 666762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver run_loop->Quit(); 676762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver} 686762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 696762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver// This is called on IO thread. 706762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruvervoid VerifyFileError(base::RunLoop* run_loop, 716762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver base::PlatformFileError error) { 726762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver DCHECK(run_loop); 736762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver EXPECT_EQ(base::PLATFORM_FILE_OK, error); 746762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver run_loop->Quit(); 756762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver} 766762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 776762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver} // namespace 786762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 796762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruverclass MockSyncEventObserver : public SyncEventObserver { 806762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver public: 816762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver MockSyncEventObserver() {} 826762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver virtual ~MockSyncEventObserver() {} 836762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 846762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver MOCK_METHOD3(OnSyncStateUpdated, 856762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver void(const GURL& app_origin, 866762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncServiceState state, 876762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver const std::string& description)); 886762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver MOCK_METHOD4(OnFileSynced, 896762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver void(const fileapi::FileSystemURL& url, 906762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncFileStatus status, 916762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncAction action, 926762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver SyncDirection direction)); 936762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver}; 946762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 956762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben GruverACTION_P3(NotifyStateAndCallback, 966762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver mock_remote_service, service_state, operation_status) { 976762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver mock_remote_service->NotifyRemoteServiceStateUpdated( 986762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver service_state, "Test event."); 996762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver base::MessageLoopProxy::current()->PostTask( 1006762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver FROM_HERE, base::Bind(arg1, operation_status)); 1016762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver} 1026762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver 1036762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben GruverACTION_P(RecordState, states) { 1046762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver states->push_back(arg1); 1056762350ca0e11ca69ecb2c7bcf78cbafa2103ad6Ben Gruver} 106 107ACTION_P(MockStatusCallback, status) { 108 base::MessageLoopProxy::current()->PostTask( 109 FROM_HERE, base::Bind(arg4, status)); 110} 111 112ACTION_P2(MockSyncFileCallback, status, url) { 113 base::MessageLoopProxy::current()->PostTask( 114 FROM_HERE, base::Bind(arg0, status, url)); 115} 116 117class SyncFileSystemServiceTest : public testing::Test { 118 protected: 119 SyncFileSystemServiceTest() 120 : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD | 121 content::TestBrowserThreadBundle::REAL_IO_THREAD) {} 122 123 virtual void SetUp() OVERRIDE { 124 file_system_.reset(new CannedSyncableFileSystem( 125 GURL(kOrigin), 126 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), 127 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE))); 128 129 local_service_ = new LocalFileSyncService(&profile_); 130 remote_service_ = new StrictMock<MockRemoteFileSyncService>; 131 sync_service_.reset(new SyncFileSystemService(&profile_)); 132 133 EXPECT_CALL(*mock_remote_service(), 134 AddServiceObserver(sync_service_.get())).Times(1); 135 EXPECT_CALL(*mock_remote_service(), 136 AddFileStatusObserver(sync_service_.get())).Times(1); 137 EXPECT_CALL(*mock_remote_service(), 138 GetLocalChangeProcessor()) 139 .WillOnce(Return(&local_change_processor_)); 140 EXPECT_CALL(*mock_remote_service(), 141 SetRemoteChangeProcessor(local_service_)).Times(1); 142 143 sync_service_->Initialize( 144 make_scoped_ptr(local_service_), 145 scoped_ptr<RemoteFileSyncService>(remote_service_)); 146 147 // Disable auto sync by default. 148 EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(false)).Times(1); 149 sync_service_->SetSyncEnabledForTesting(false); 150 151 file_system_->SetUp(); 152 } 153 154 virtual void TearDown() OVERRIDE { 155 sync_service_->Shutdown(); 156 file_system_->TearDown(); 157 RevokeSyncableFileSystem(); 158 content::RunAllPendingInMessageLoop(BrowserThread::FILE); 159 } 160 161 void InitializeApp() { 162 base::RunLoop run_loop; 163 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 164 165 EXPECT_CALL(*mock_remote_service(), 166 RegisterOriginForTrackingChanges(GURL(kOrigin), _)).Times(1); 167 168 sync_service_->InitializeForApp( 169 file_system_->file_system_context(), 170 GURL(kOrigin), 171 AssignAndQuitCallback(&run_loop, &status)); 172 run_loop.Run(); 173 174 EXPECT_EQ(SYNC_STATUS_OK, status); 175 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->OpenFileSystem()); 176 } 177 178 // Calls InitializeForApp after setting up the mock remote service to 179 // perform following when RegisterOriginForTrackingChanges is called: 180 // 1. Notify RemoteFileSyncService's observers of |state_to_notify| 181 // 2. Run the given callback with |status_to_return|. 182 // 183 // ..and verifies if following conditions are met: 184 // 1. The SyncEventObserver of the service is called with 185 // |expected_states| service state values. 186 // 2. InitializeForApp's callback is called with |expected_status| 187 // 3. GetCurrentState() is called at least |expected_current_state_calls| 188 // times (which means that the sync service tried to start sync). 189 void InitializeAppForObserverTest( 190 RemoteServiceState state_to_notify, 191 SyncStatusCode status_to_return, 192 const std::vector<SyncServiceState> expected_states, 193 SyncStatusCode expected_status) { 194 StrictMock<MockSyncEventObserver> event_observer; 195 sync_service_->AddSyncEventObserver(&event_observer); 196 197 EnableSync(); 198 199 EXPECT_CALL(*mock_remote_service(), 200 RegisterOriginForTrackingChanges(GURL(kOrigin), _)) 201 .WillOnce(NotifyStateAndCallback(mock_remote_service(), 202 state_to_notify, 203 status_to_return)); 204 205 std::vector<SyncServiceState> actual_states; 206 EXPECT_CALL(event_observer, OnSyncStateUpdated(GURL(), _, _)) 207 .WillRepeatedly(RecordState(&actual_states)); 208 209 SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN; 210 base::RunLoop run_loop; 211 sync_service_->InitializeForApp( 212 file_system_->file_system_context(), 213 GURL(kOrigin), 214 AssignAndQuitCallback(&run_loop, &actual_status)); 215 run_loop.Run(); 216 217 EXPECT_EQ(expected_status, actual_status); 218 ASSERT_EQ(expected_states.size(), actual_states.size()); 219 for (size_t i = 0; i < actual_states.size(); ++i) 220 EXPECT_EQ(expected_states[i], actual_states[i]); 221 } 222 223 FileSystemURL URL(const std::string& path) const { 224 return file_system_->URL(path); 225 } 226 227 StrictMock<MockRemoteFileSyncService>* mock_remote_service() { 228 return remote_service_; 229 } 230 231 StrictMock<MockLocalChangeProcessor>* mock_local_change_processor() { 232 return &local_change_processor_; 233 } 234 235 void EnableSync() { 236 EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(true)).Times(1); 237 sync_service_->SetSyncEnabledForTesting(true); 238 } 239 240 ScopedEnableSyncFSDirectoryOperation enable_directory_operation_; 241 242 content::TestBrowserThreadBundle thread_bundle_; 243 TestingProfile profile_; 244 scoped_ptr<CannedSyncableFileSystem> file_system_; 245 246 // Their ownerships are transferred to SyncFileSystemService. 247 LocalFileSyncService* local_service_; 248 StrictMock<MockRemoteFileSyncService>* remote_service_; 249 StrictMock<MockLocalChangeProcessor> local_change_processor_; 250 251 scoped_ptr<SyncFileSystemService> sync_service_; 252}; 253 254TEST_F(SyncFileSystemServiceTest, InitializeForApp) { 255 InitializeApp(); 256} 257 258TEST_F(SyncFileSystemServiceTest, InitializeForAppSuccess) { 259 std::vector<SyncServiceState> expected_states; 260 expected_states.push_back(SYNC_SERVICE_RUNNING); 261 262 InitializeAppForObserverTest( 263 REMOTE_SERVICE_OK, 264 SYNC_STATUS_OK, 265 expected_states, 266 SYNC_STATUS_OK); 267} 268 269TEST_F(SyncFileSystemServiceTest, InitializeForAppWithNetworkFailure) { 270 std::vector<SyncServiceState> expected_states; 271 expected_states.push_back(SYNC_SERVICE_TEMPORARY_UNAVAILABLE); 272 273 // Notify REMOTE_SERVICE_TEMPORARY_UNAVAILABLE and callback with 274 // SYNC_STATUS_NETWORK_ERROR. This should let the 275 // InitializeApp fail. 276 InitializeAppForObserverTest( 277 REMOTE_SERVICE_TEMPORARY_UNAVAILABLE, 278 SYNC_STATUS_NETWORK_ERROR, 279 expected_states, 280 SYNC_STATUS_NETWORK_ERROR); 281} 282 283TEST_F(SyncFileSystemServiceTest, InitializeForAppWithError) { 284 std::vector<SyncServiceState> expected_states; 285 expected_states.push_back(SYNC_SERVICE_DISABLED); 286 287 // Notify REMOTE_SERVICE_DISABLED and callback with 288 // SYNC_STATUS_FAILED. This should let the InitializeApp fail. 289 InitializeAppForObserverTest( 290 REMOTE_SERVICE_DISABLED, 291 SYNC_STATUS_FAILED, 292 expected_states, 293 SYNC_STATUS_FAILED); 294} 295 296// Flaky. http://crbug.com/237710 297TEST_F(SyncFileSystemServiceTest, DISABLED_SimpleLocalSyncFlow) { 298 InitializeApp(); 299 300 StrictMock<MockSyncStatusObserver> status_observer; 301 302 EnableSync(); 303 file_system_->file_system_context()->sync_context()-> 304 set_mock_notify_changes_duration_in_sec(0); 305 file_system_->AddSyncStatusObserver(&status_observer); 306 307 // We'll test one local sync for this file. 308 const FileSystemURL kFile(file_system_->URL("foo")); 309 310 base::RunLoop run_loop; 311 312 // We should get called OnSyncEnabled and OnWriteEnabled on kFile. 313 // (We quit the run loop when OnWriteEnabled is called on kFile) 314 EXPECT_CALL(status_observer, OnSyncEnabled(kFile)) 315 .Times(AtLeast(1)); 316 EXPECT_CALL(status_observer, OnWriteEnabled(kFile)) 317 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 318 319 // We expect a set of method calls for starting a local sync. 320 EXPECT_CALL(*mock_remote_service(), GetCurrentState()) 321 .Times(AtLeast(2)) 322 .WillRepeatedly(Return(REMOTE_SERVICE_OK)); 323 324 // The local_change_processor's ApplyLocalChange should be called once 325 // with ADD_OR_UPDATE change for TYPE_FILE. 326 const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 327 SYNC_FILE_TYPE_FILE); 328 EXPECT_CALL(*mock_local_change_processor(), 329 ApplyLocalChange(change, _, _, kFile, _)) 330 .WillOnce(MockStatusCallback(SYNC_STATUS_OK)); 331 332 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile)); 333 334 run_loop.Run(); 335} 336 337TEST_F(SyncFileSystemServiceTest, SimpleRemoteSyncFlow) { 338 InitializeApp(); 339 340 EnableSync(); 341 342 base::RunLoop run_loop; 343 344 // We expect a set of method calls for starting a remote sync. 345 EXPECT_CALL(*mock_remote_service(), GetCurrentState()) 346 .Times(AtLeast(1)) 347 .WillRepeatedly(Return(REMOTE_SERVICE_OK)); 348 EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_)) 349 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 350 351 // This should trigger a remote sync. 352 mock_remote_service()->NotifyRemoteChangeQueueUpdated(1); 353 354 run_loop.Run(); 355} 356 357TEST_F(SyncFileSystemServiceTest, SimpleSyncFlowWithFileBusy) { 358 InitializeApp(); 359 360 EnableSync(); 361 file_system_->file_system_context()->sync_context()-> 362 set_mock_notify_changes_duration_in_sec(0); 363 364 const FileSystemURL kFile(file_system_->URL("foo")); 365 366 base::RunLoop run_loop; 367 368 // We expect a set of method calls for starting a remote sync. 369 EXPECT_CALL(*mock_remote_service(), GetCurrentState()) 370 .Times(AtLeast(3)) 371 .WillRepeatedly(Return(REMOTE_SERVICE_OK)); 372 373 { 374 InSequence sequence; 375 376 // Return with SYNC_STATUS_FILE_BUSY once. 377 EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_)) 378 .WillOnce(MockSyncFileCallback(SYNC_STATUS_FILE_BUSY, 379 kFile)); 380 381 // ProcessRemoteChange should be called again when the becomes 382 // not busy. 383 EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_)) 384 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 385 } 386 387 // We might also see an activity for local sync as we're going to make 388 // a local write operation on kFile. 389 EXPECT_CALL(*mock_local_change_processor(), 390 ApplyLocalChange(_, _, _, kFile, _)) 391 .Times(AnyNumber()); 392 393 // This should trigger a remote sync. 394 mock_remote_service()->NotifyRemoteChangeQueueUpdated(1); 395 396 // Start a local operation on the same file (to make it BUSY). 397 base::RunLoop verify_file_error_run_loop; 398 BrowserThread::PostTask( 399 BrowserThread::IO, 400 FROM_HERE, 401 base::Bind(&CannedSyncableFileSystem::DoCreateFile, 402 base::Unretained(file_system_.get()), 403 kFile, base::Bind(&VerifyFileError, 404 &verify_file_error_run_loop))); 405 406 run_loop.Run(); 407 408 mock_remote_service()->NotifyRemoteChangeQueueUpdated(0); 409 410 verify_file_error_run_loop.Run(); 411} 412 413TEST_F(SyncFileSystemServiceTest, GetFileSyncStatus) { 414 InitializeApp(); 415 416 const FileSystemURL kFile(file_system_->URL("foo")); 417 418 SyncStatusCode status; 419 SyncFileStatus sync_file_status; 420 421 // 1. The file is not in conflicting nor in pending change state. 422 { 423 base::RunLoop run_loop; 424 EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile)) 425 .WillOnce(Return(false)); 426 427 status = SYNC_STATUS_UNKNOWN; 428 sync_file_status = SYNC_FILE_STATUS_UNKNOWN; 429 sync_service_->GetFileSyncStatus( 430 kFile, 431 base::Bind(&AssignValueAndQuit<SyncFileStatus>, 432 &run_loop, &status, &sync_file_status)); 433 run_loop.Run(); 434 435 EXPECT_EQ(SYNC_STATUS_OK, status); 436 EXPECT_EQ(SYNC_FILE_STATUS_SYNCED, sync_file_status); 437 } 438 439 // 2. Conflicting case. 440 { 441 base::RunLoop run_loop; 442 EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile)) 443 .WillOnce(Return(true)); 444 445 status = SYNC_STATUS_UNKNOWN; 446 sync_file_status = SYNC_FILE_STATUS_UNKNOWN; 447 sync_service_->GetFileSyncStatus( 448 kFile, 449 base::Bind(&AssignValueAndQuit<SyncFileStatus>, 450 &run_loop, &status, &sync_file_status)); 451 run_loop.Run(); 452 453 EXPECT_EQ(SYNC_STATUS_OK, status); 454 EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status); 455 } 456 457 // 3. The file has pending local changes. 458 { 459 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile)); 460 461 base::RunLoop run_loop; 462 EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile)) 463 .WillOnce(Return(false)); 464 465 status = SYNC_STATUS_UNKNOWN; 466 sync_file_status = SYNC_FILE_STATUS_UNKNOWN; 467 sync_service_->GetFileSyncStatus( 468 kFile, 469 base::Bind(&AssignValueAndQuit<SyncFileStatus>, 470 &run_loop, &status, &sync_file_status)); 471 run_loop.Run(); 472 473 EXPECT_EQ(SYNC_STATUS_OK, status); 474 EXPECT_EQ(SYNC_FILE_STATUS_HAS_PENDING_CHANGES, sync_file_status); 475 } 476 477 // 4. The file has a conflict and pending local changes. In this case 478 // we return SYNC_FILE_STATUS_CONFLICTING. 479 { 480 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->TruncateFile(kFile, 1U)); 481 482 base::RunLoop run_loop; 483 EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile)) 484 .WillOnce(Return(true)); 485 486 status = SYNC_STATUS_UNKNOWN; 487 sync_file_status = SYNC_FILE_STATUS_UNKNOWN; 488 sync_service_->GetFileSyncStatus( 489 kFile, 490 base::Bind(&AssignValueAndQuit<SyncFileStatus>, 491 &run_loop, &status, &sync_file_status)); 492 run_loop.Run(); 493 494 EXPECT_EQ(SYNC_STATUS_OK, status); 495 EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status); 496 } 497} 498 499} // namespace sync_file_system 500