sync_file_system_service_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/local_file_sync_service.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/canned_syncable_file_system.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/local_file_sync_context.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/mock_sync_status_observer.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/sync_callbacks.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/sync_file_metadata.h"
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/sync_status_code.h"
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/syncable/syncable_file_system_util.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURL;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURLSet;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AnyNumber;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InSequence;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InvokeWithoutArgs;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::Return;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::StrictMock;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::_;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOrigin[] = "http://example.com";
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R> struct AssignTrait {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef const R& ArgumentType;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <> struct AssignTrait<SyncFileStatus> {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef SyncFileStatus ArgumentType;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R>
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AssignValueAndQuit(base::RunLoop* run_loop,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode* status_out, R* value_out,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode status,
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        typename AssignTrait<R>::ArgumentType value) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(status_out);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(value_out);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(run_loop);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *status_out = status;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *value_out = value;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop->Quit();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called on IO thread.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VerifyFileError(base::WaitableEvent* event,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::PlatformFileError error) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(event);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(base::PLATFORM_FILE_OK, error);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event->Signal();
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncEventObserver : public SyncEventObserver {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockSyncEventObserver() {}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MockSyncEventObserver() {}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD3(OnSyncStateUpdated,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               void(const GURL& app_origin,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncServiceState state,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& description));
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD4(OnFileSynced,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               void(const fileapi::FileSystemURL& url,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncFileStatus status,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncAction action,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncDirection direction));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P3(NotifyStateAndCallback,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          mock_remote_service, service_state, operation_status) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service->NotifyRemoteServiceStateUpdated(
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_state, "Test event.");
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg1, operation_status));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(RecordState, states) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  states->push_back(arg1);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(MockStatusCallback, status) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg4, status));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P2(MockSyncFileCallback, status, url) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg0, status, url));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncFileSystemServiceTest : public testing::Test {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileSystemServiceTest() {}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyncFileSystemServiceTest() {}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thread_helper_.SetUp();
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_.reset(new CannedSyncableFileSystem(
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thread_helper_.io_task_runner(),
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thread_helper_.file_task_runner()));
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_service_ = new LocalFileSyncService(&profile_);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_service_ = new StrictMock<MockRemoteFileSyncService>;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_.reset(new SyncFileSystemService(&profile_));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                AddServiceObserver(sync_service_.get())).Times(1);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                AddFileStatusObserver(sync_service_.get())).Times(1);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                GetLocalChangeProcessor())
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(&local_change_processor_));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                SetRemoteChangeProcessor(local_service_)).Times(1);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Initialize(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        make_scoped_ptr(local_service_),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<RemoteFileSyncService>(remote_service_));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Disable auto sync by default.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(false)).Times(1);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(false);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_->SetUp();
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Shutdown();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_->TearDown();
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RevokeSyncableFileSystem();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thread_helper_.TearDown();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeApp() {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                RegisterOriginForTrackingChanges(GURL(kOrigin), _)).Times(1);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &status));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->OpenFileSystem());
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calls InitializeForApp after setting up the mock remote service to
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // perform following when RegisterOriginForTrackingChanges is called:
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. Notify RemoteFileSyncService's observers of |state_to_notify|
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. Run the given callback with |status_to_return|.
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ..and verifies if following conditions are met:
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. The SyncEventObserver of the service is called with
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |expected_states| service state values.
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. InitializeForApp's callback is called with |expected_status|
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  3. GetCurrentState() is called at least |expected_current_state_calls|
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     times (which means that the sync service tried to start sync).
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeAppForObserverTest(
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RemoteServiceState state_to_notify,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncStatusCode status_to_return,
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const std::vector<SyncServiceState> expected_states,
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SyncStatusCode expected_status) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StrictMock<MockSyncEventObserver> event_observer;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->AddSyncEventObserver(&event_observer);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EnableSync();
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                RegisterOriginForTrackingChanges(GURL(kOrigin), _))
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(NotifyStateAndCallback(mock_remote_service(),
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         state_to_notify,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         status_to_return));
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<SyncServiceState> actual_states;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(event_observer, OnSyncStateUpdated(GURL(), _, _))
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillRepeatedly(RecordState(&actual_states));
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &actual_status));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_status, actual_status);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(expected_states.size(), actual_states.size());
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < actual_states.size(); ++i)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(expected_states[i], actual_states[i]);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystemURL URL(const std::string& path) const {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return file_system_->URL(path);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* mock_remote_service() {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return remote_service_;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor>* mock_local_change_processor() {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return &local_change_processor_;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void EnableSync() {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(true)).Times(1);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(true);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MultiThreadTestHelper thread_helper_;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile_;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<CannedSyncableFileSystem> file_system_;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Their ownerships are transferred to SyncFileSystemService.
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocalFileSyncService* local_service_;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* remote_service_;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor_;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SyncFileSystemService> sync_service_;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForApp) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppSuccess) {
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_RUNNING);
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_OK,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_OK,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_OK);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithNetworkFailure) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_TEMPORARY_UNAVAILABLE and callback with
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_NETWORK_ERROR.  This should let the
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InitializeApp fail.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR,
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithError) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_DISABLED);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_DISABLED and callback with
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_FAILED.  This should let the InitializeApp fail.
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_DISABLED,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_FAILED,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_FAILED);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Flaky.  http://crbug.com/237710
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, DISABLED_SimpleLocalSyncFlow) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->file_system_context()->sync_context()->
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We'll test one local sync for this file.
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should get called OnSyncEnabled and OnWriteEnabled on kFile.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (We quit the run loop when OnWriteEnabled is called on kFile)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kFile))
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AtLeast(1));
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kFile))
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect a set of method calls for starting a local sync.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), GetCurrentState())
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AtLeast(2))
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillRepeatedly(Return(REMOTE_SERVICE_OK));
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The local_change_processor's ApplyLocalChange should be called once
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with ADD_OR_UPDATE change for TYPE_FILE.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          SYNC_FILE_TYPE_FILE);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(change, _, _, kFile, _))
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallback(SYNC_STATUS_OK));
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile));
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleRemoteSyncFlow) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect a set of method calls for starting a remote sync.
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), GetCurrentState())
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1))
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillRepeatedly(Return(REMOTE_SERVICE_OK));
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleSyncFlowWithFileBusy) {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->file_system_context()->sync_context()->
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect a set of method calls for starting a remote sync.
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), GetCurrentState())
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AtLeast(3))
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillRepeatedly(Return(REMOTE_SERVICE_OK));
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InSequence sequence;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Return with SYNC_STATUS_FILE_BUSY once.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(MockSyncFileCallback(SYNC_STATUS_FILE_BUSY,
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       kFile));
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ProcessRemoteChange should be called again when the becomes
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not busy.
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We might also see an activity for local sync as we're going to make
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a local write operation on kFile.
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(_, _, _, kFile, _))
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AnyNumber());
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a local operation on the same file (to make it BUSY).
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WaitableEvent event(false, false);
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_helper_.io_task_runner()->PostTask(
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&CannedSyncableFileSystem::DoCreateFile,
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            base::Unretained(file_system_.get()),
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            kFile, base::Bind(&VerifyFileError, &event)));
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(0);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event.Wait();
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, GetFileSyncStatus) {
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode status;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileStatus sync_file_status;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 1. The file is not in conflicting nor in pending change state.
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(false));
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_SYNCED, sync_file_status);
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 2. Conflicting case.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(true));
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 3. The file has pending local changes.
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile));
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(false));
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_HAS_PENDING_CHANGES, sync_file_status);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 4. The file has a conflict and pending local changes. In this case
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we return SYNC_FILE_STATUS_CONFLICTING.
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->TruncateFile(kFile, 1U));
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(true));
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
493