sync_file_system_service_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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"
122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/mock_sync_status_observer.h"
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h"
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_callbacks.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
26a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/browser/browser_thread.h"
27a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_browser_thread_bundle.h"
28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_utils.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32a3f7b4e666c476898878fa745f637129375cd889Ben Murdochusing content::BrowserThread;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURL;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using fileapi::FileSystemURLSet;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AnyNumber;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InSequence;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InvokeWithoutArgs;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::Return;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::StrictMock;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::_;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOrigin[] = "http://example.com";
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R> struct AssignTrait {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef const R& ArgumentType;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <> struct AssignTrait<SyncFileStatus> {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef SyncFileStatus ArgumentType;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R>
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AssignValueAndQuit(base::RunLoop* run_loop,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode* status_out, R* value_out,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode status,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        typename AssignTrait<R>::ArgumentType value) {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(status_out);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(value_out);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(run_loop);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *status_out = status;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *value_out = value;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop->Quit();
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called on IO thread.
71a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid VerifyFileError(base::RunLoop* run_loop,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::PlatformFileError error) {
73a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  DCHECK(run_loop);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(base::PLATFORM_FILE_OK, error);
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  run_loop->Quit();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncEventObserver : public SyncEventObserver {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockSyncEventObserver() {}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MockSyncEventObserver() {}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD3(OnSyncStateUpdated,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               void(const GURL& app_origin,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncServiceState state,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& description));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD4(OnFileSynced,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               void(const fileapi::FileSystemURL& url,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncFileStatus status,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncAction action,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncDirection direction));
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P3(NotifyStateAndCallback,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          mock_remote_service, service_state, operation_status) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service->NotifyRemoteServiceStateUpdated(
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_state, "Test event.");
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg1, operation_status));
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(RecordState, states) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  states->push_back(arg1);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(MockStatusCallback, status) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg4, status));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P2(MockSyncFileCallback, status, url) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoopProxy::current()->PostTask(
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg0, status, url));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncFileSystemServiceTest : public testing::Test {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
120a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  SyncFileSystemServiceTest()
121a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD |
122a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                       content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_.reset(new CannedSyncableFileSystem(
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
127a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
128a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_service_ = new LocalFileSyncService(&profile_);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_service_ = new StrictMock<MockRemoteFileSyncService>;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_.reset(new SyncFileSystemService(&profile_));
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                AddServiceObserver(_)).Times(1);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                AddFileStatusObserver(sync_service_.get())).Times(1);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                GetLocalChangeProcessor())
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        .WillRepeatedly(Return(&local_change_processor_));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                SetRemoteChangeProcessor(local_service_)).Times(1);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Initialize(
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        make_scoped_ptr(local_service_),
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<RemoteFileSyncService>(remote_service_));
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Disable auto sync by default.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(false)).Times(1);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(false);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_->SetUp();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Shutdown();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_->TearDown();
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RevokeSyncableFileSystem();
159a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    content::RunAllPendingInMessageLoop(BrowserThread::FILE);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeApp() {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                RegisterOrigin(GURL(kOrigin), _)).Times(1);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // GetCurrentState may be called when a remote or local sync is scheduled
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // by change notifications or by a timer.
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), GetCurrentState())
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .Times(AnyNumber())
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .WillRepeatedly(Return(REMOTE_SERVICE_OK));
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &status));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->OpenFileSystem());
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calls InitializeForApp after setting up the mock remote service to
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // perform following when RegisterOrigin is called:
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. Notify RemoteFileSyncService's observers of |state_to_notify|
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. Run the given callback with |status_to_return|.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ..and verifies if following conditions are met:
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. The SyncEventObserver of the service is called with
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |expected_states| service state values.
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. InitializeForApp's callback is called with |expected_status|
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeAppForObserverTest(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RemoteServiceState state_to_notify,
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncStatusCode status_to_return,
1973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const std::vector<SyncServiceState>& expected_states,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SyncStatusCode expected_status) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StrictMock<MockSyncEventObserver> event_observer;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->AddSyncEventObserver(&event_observer);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EnableSync();
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), GetCurrentState())
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .Times(AnyNumber())
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .WillRepeatedly(Return(state_to_notify));
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                RegisterOrigin(GURL(kOrigin), _))
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(NotifyStateAndCallback(mock_remote_service(),
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         state_to_notify,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         status_to_return));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<SyncServiceState> actual_states;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(event_observer, OnSyncStateUpdated(GURL(), _, _))
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillRepeatedly(RecordState(&actual_states));
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &actual_status));
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_status, actual_status);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(expected_states.size(), actual_states.size());
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < actual_states.size(); ++i)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(expected_states[i], actual_states[i]);
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    sync_service_->RemoveSyncEventObserver(&event_observer);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystemURL URL(const std::string& path) const {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return file_system_->URL(path);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* mock_remote_service() {
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return remote_service_;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor>* mock_local_change_processor() {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return &local_change_processor_;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void EnableSync() {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(true)).Times(1);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(true);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedEnableSyncFSDirectoryOperation enable_directory_operation_;
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
253a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  content::TestBrowserThreadBundle thread_bundle_;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile_;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<CannedSyncableFileSystem> file_system_;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Their ownerships are transferred to SyncFileSystemService.
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocalFileSyncService* local_service_;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* remote_service_;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor_;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SyncFileSystemService> sync_service_;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForApp) {
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppSuccess) {
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_RUNNING);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_OK,
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_OK,
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_OK);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithNetworkFailure) {
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_TEMPORARY_UNAVAILABLE and callback with
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_NETWORK_ERROR.  This should let the
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InitializeApp fail.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithError) {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_DISABLED);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_DISABLED and callback with
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_FAILED.  This should let the InitializeApp fail.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_DISABLED,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_FAILED,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_FAILED);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleLocalSyncFlow) {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_->backend()->sync_context()->
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We'll test one local sync for this file.
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // We should get called OnSyncEnabled and OnWriteEnabled on kFile as in:
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // 1. OnWriteEnabled when PrepareForSync(SYNC_SHARED) is finished and
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    the target file is unlocked for writing
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // 2. OnSyncEnabled x 3 times; 1) when CreateFile is finished, 2) when
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    file is unlocked after PrepareForSync, and 3) when the sync is
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    finished.
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kFile))
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      .Times(AtLeast(1));
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ::testing::InSequence sequence;
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(status_observer, OnSyncEnabled(kFile))
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        .Times(AtLeast(2));
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(status_observer, OnSyncEnabled(kFile))
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The local_change_processor's ApplyLocalChange should be called once
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with ADD_OR_UPDATE change for TYPE_FILE.
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          SYNC_FILE_TYPE_FILE);
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(change, _, _, kFile, _))
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallback(SYNC_STATUS_OK));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile));
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleRemoteSyncFlow) {
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect a set of method calls for starting a remote sync.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleSyncFlowWithFileBusy) {
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_->backend()->sync_context()->
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InSequence sequence;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Return with SYNC_STATUS_FILE_BUSY once.
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(MockSyncFileCallback(SYNC_STATUS_FILE_BUSY,
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       kFile));
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ProcessRemoteChange should be called again when the becomes
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not busy.
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We might also see an activity for local sync as we're going to make
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a local write operation on kFile.
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(_, _, _, kFile, _))
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AnyNumber());
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a local operation on the same file (to make it BUSY).
406a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  base::RunLoop verify_file_error_run_loop;
407a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTask(
408a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::IO,
409a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
410a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&CannedSyncableFileSystem::DoCreateFile,
411a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 base::Unretained(file_system_.get()),
412a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 kFile, base::Bind(&VerifyFileError,
413a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                   &verify_file_error_run_loop)));
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(0);
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
419a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  verify_file_error_run_loop.Run();
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(THREAD_SANITIZER)
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// SyncFileSystemServiceTest.GetFileSyncStatus fails under ThreadSanitizer,
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// see http://crbug.com/294904.
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define MAYBE_GetFileSyncStatus DISABLED_GetFileSyncStatus
42668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#else
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define MAYBE_GetFileSyncStatus GetFileSyncStatus
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(SyncFileSystemServiceTest, MAYBE_GetFileSyncStatus) {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode status;
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileStatus sync_file_status;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 1. The file is not in conflicting nor in pending change state.
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(false));
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_SYNCED, sync_file_status);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 2. Conflicting case.
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(true));
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status);
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 3. The file has pending local changes.
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->CreateFile(kFile));
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(false));
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_HAS_PENDING_CHANGES, sync_file_status);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 4. The file has a conflict and pending local changes. In this case
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we return SYNC_FILE_STATUS_CONFLICTING.
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(base::PLATFORM_FILE_OK, file_system_->TruncateFile(kFile, 1U));
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), IsConflicting(kFile))
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(Return(true));
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_CONFLICTING, sync_file_status);
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
516