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"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/single_thread_task_runner.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h"
142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/mock_sync_status_observer.h"
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h"
202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_callbacks.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_event_observer.h"
222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_service.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/browser/browser_thread.h"
29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_browser_thread_bundle.h"
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_utils.h"
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36a3f7b4e666c476898878fa745f637129375cd889Ben Murdochusing content::BrowserThread;
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURLSet;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AnyNumber;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InSequence;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InvokeWithoutArgs;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::Return;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::StrictMock;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::_;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOrigin[] = "http://example.com";
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R> struct AssignTrait {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef const R& ArgumentType;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <> struct AssignTrait<SyncFileStatus> {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef SyncFileStatus ArgumentType;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename R>
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AssignValueAndQuit(base::RunLoop* run_loop,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode* status_out, R* value_out,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        SyncStatusCode status,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        typename AssignTrait<R>::ArgumentType value) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(status_out);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(value_out);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(run_loop);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *status_out = status;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *value_out = value;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop->Quit();
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is called on IO thread.
75a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid VerifyFileError(base::RunLoop* run_loop,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::File::Error error) {
77a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  DCHECK(run_loop);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, error);
79a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  run_loop->Quit();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockSyncEventObserver : public SyncEventObserver {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockSyncEventObserver() {}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~MockSyncEventObserver() {}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD3(OnSyncStateUpdated,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               void(const GURL& app_origin,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncServiceState state,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& description));
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MOCK_METHOD4(OnFileSynced,
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)               void(const storage::FileSystemURL& url,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncFileStatus status,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncAction action,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SyncDirection direction));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P3(NotifyStateAndCallback,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          mock_remote_service, service_state, operation_status) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service->NotifyRemoteServiceStateUpdated(
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      service_state, "Test event.");
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg1, operation_status));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(RecordState, states) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  states->push_back(arg1);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P(MockStatusCallback, status) {
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg4, status));
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ACTION_P2(MockSyncFileCallback, status, url) {
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg0, status, url));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ACTION(InvokeCompletionClosure) {
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::ThreadTaskRunnerHandle::Get()->PostTask(
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE, base::Bind(arg0));
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncFileSystemServiceTest : public testing::Test {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
129a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  SyncFileSystemServiceTest()
130a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD |
131a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                       content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_.reset(new CannedSyncableFileSystem(
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        in_memory_env_.get(),
138a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
139a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<LocalFileSyncService> local_service =
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        LocalFileSyncService::CreateForTesting(&profile_, in_memory_env_.get());
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_service_ = new StrictMock<MockRemoteFileSyncService>;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_.reset(new SyncFileSystemService(&profile_));
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                AddServiceObserver(_)).Times(1);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                AddFileStatusObserver(sync_service_.get())).Times(1);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                GetLocalChangeProcessor())
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        .WillRepeatedly(Return(&local_change_processor_));
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                SetRemoteChangeProcessor(local_service.get())).Times(1);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Initialize(
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        local_service.Pass(),
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<RemoteFileSyncService>(remote_service_));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Disable auto sync by default.
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(false)).Times(1);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(false);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    file_system_->SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->Shutdown();
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_->TearDown();
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RevokeSyncableFileSystem();
171a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    content::RunAllPendingInMessageLoop(BrowserThread::FILE);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeApp() {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                RegisterOrigin(GURL(kOrigin), _)).Times(1);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // GetCurrentState may be called when a remote or local sync is scheduled
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // by change notifications or by a timer.
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), GetCurrentState())
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .Times(AnyNumber())
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .WillRepeatedly(Return(REMOTE_SERVICE_OK));
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &status));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(base::File::FILE_OK, file_system_->OpenFileSystem());
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calls InitializeForApp after setting up the mock remote service to
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // perform following when RegisterOrigin is called:
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. Notify RemoteFileSyncService's observers of |state_to_notify|
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. Run the given callback with |status_to_return|.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ..and verifies if following conditions are met:
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  1. The SyncEventObserver of the service is called with
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     |expected_states| service state values.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //  2. InitializeForApp's callback is called with |expected_status|
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeAppForObserverTest(
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RemoteServiceState state_to_notify,
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SyncStatusCode status_to_return,
2093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const std::vector<SyncServiceState>& expected_states,
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SyncStatusCode expected_status) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StrictMock<MockSyncEventObserver> event_observer;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->AddSyncEventObserver(&event_observer);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EnableSync();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), GetCurrentState())
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .Times(AnyNumber())
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        .WillRepeatedly(Return(state_to_notify));
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(),
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                RegisterOrigin(GURL(kOrigin), _))
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(NotifyStateAndCallback(mock_remote_service(),
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         state_to_notify,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         status_to_return));
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<SyncServiceState> actual_states;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(event_observer, OnSyncStateUpdated(GURL(), _, _))
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillRepeatedly(RecordState(&actual_states));
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->InitializeForApp(
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_system_->file_system_context(),
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AssignAndQuitCallback(&run_loop, &actual_status));
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_status, actual_status);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(expected_states.size(), actual_states.size());
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < actual_states.size(); ++i)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(expected_states[i], actual_states[i]);
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    sync_service_->RemoveSyncEventObserver(&event_observer);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystemURL URL(const std::string& path) const {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return file_system_->URL(path);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* mock_remote_service() {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return remote_service_;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor>* mock_local_change_processor() {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return &local_change_processor_;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void EnableSync() {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), SetSyncEnabled(true)).Times(1);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->SetSyncEnabledForTesting(true);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
263a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  content::TestBrowserThreadBundle thread_bundle_;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<leveldb::Env> in_memory_env_;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile_;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<CannedSyncableFileSystem> file_system_;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Their ownerships are transferred to SyncFileSystemService.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockRemoteFileSyncService>* remote_service_;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor_;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SyncFileSystemService> sync_service_;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForApp) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppSuccess) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_RUNNING);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_OK,
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_OK,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_OK);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithNetworkFailure) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_TEMPORARY_UNAVAILABLE);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_TEMPORARY_UNAVAILABLE and callback with
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_NETWORK_ERROR.  This should let the
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InitializeApp fail.
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_NETWORK_ERROR);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, InitializeForAppWithError) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<SyncServiceState> expected_states;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_states.push_back(SYNC_SERVICE_DISABLED);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Notify REMOTE_SERVICE_DISABLED and callback with
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SYNC_STATUS_FAILED.  This should let the InitializeApp fail.
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeAppForObserverTest(
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      REMOTE_SERVICE_DISABLED,
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SYNC_STATUS_FAILED,
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_states,
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SYNC_STATUS_FAILED);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleLocalSyncFlow) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_->backend()->sync_context()->
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We'll test one local sync for this file.
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // We should get called OnSyncEnabled and OnWriteEnabled on kFile as in:
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // 1. OnWriteEnabled when PrepareForSync(SYNC_SHARED) is finished and
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    the target file is unlocked for writing
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // 2. OnSyncEnabled x 3 times; 1) when CreateFile is finished, 2) when
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    file is unlocked after PrepareForSync, and 3) when the sync is
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  //    finished.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kFile))
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      .Times(AtLeast(1));
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ::testing::InSequence sequence;
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(status_observer, OnSyncEnabled(kFile))
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        .Times(AtLeast(2));
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(status_observer, OnSyncEnabled(kFile))
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The local_change_processor's ApplyLocalChange should be called once
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with ADD_OR_UPDATE change for TYPE_FILE.
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          SYNC_FILE_TYPE_FILE);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(change, _, _, kFile, _))
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallback(SYNC_STATUS_OK));
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      .WillRepeatedly(MockSyncFileCallback(SYNC_STATUS_NO_CHANGE_TO_SYNC,
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           FileSystemURL()));
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), PromoteDemotedChanges(_))
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      .WillRepeatedly(InvokeCompletionClosure());
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile));
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleRemoteSyncFlow) {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect a set of method calls for starting a remote sync.
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SyncFileSystemServiceTest, SimpleSyncFlowWithFileBusy) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnableSync();
391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system_->backend()->sync_context()->
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::RunLoop run_loop;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InSequence sequence;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Return with SYNC_STATUS_FILE_BUSY once.
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(MockSyncFileCallback(SYNC_STATUS_FILE_BUSY,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       kFile));
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ProcessRemoteChange should be called again when the becomes
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not busy.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_CALL(*mock_remote_service(), ProcessRemoteChange(_))
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  EXPECT_CALL(*mock_remote_service(), PromoteDemotedChanges(_))
4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      .WillRepeatedly(InvokeCompletionClosure());
4146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We might also see an activity for local sync as we're going to make
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a local write operation on kFile.
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(*mock_local_change_processor(),
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              ApplyLocalChange(_, _, _, kFile, _))
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Times(AnyNumber());
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should trigger a remote sync.
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(1);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a local operation on the same file (to make it BUSY).
425a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  base::RunLoop verify_file_error_run_loop;
426a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  BrowserThread::PostTask(
427a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::IO,
428a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FROM_HERE,
429a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      base::Bind(&CannedSyncableFileSystem::DoCreateFile,
430a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 base::Unretained(file_system_.get()),
431a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                 kFile, base::Bind(&VerifyFileError,
432a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                   &verify_file_error_run_loop)));
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_loop.Run();
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mock_remote_service()->NotifyRemoteChangeQueueUpdated(0);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
438a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  verify_file_error_run_loop.Run();
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
44168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if defined(THREAD_SANITIZER)
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// SyncFileSystemServiceTest.GetFileSyncStatus fails under ThreadSanitizer,
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// see http://crbug.com/294904.
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define MAYBE_GetFileSyncStatus DISABLED_GetFileSyncStatus
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#else
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define MAYBE_GetFileSyncStatus GetFileSyncStatus
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
44868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(SyncFileSystemServiceTest, MAYBE_GetFileSyncStatus) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InitializeApp();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode status;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileStatus sync_file_status;
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // 1. The file is synced state.
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_SYNCED, sync_file_status);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // 2. The file has pending local changes.
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile));
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = SYNC_STATUS_UNKNOWN;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_file_status = SYNC_FILE_STATUS_UNKNOWN;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_service_->GetFileSyncStatus(
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kFile,
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AssignValueAndQuit<SyncFileStatus>,
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   &run_loop, &status, &sync_file_status));
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_FILE_STATUS_HAS_PENDING_CHANGES, sync_file_status);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
490