12385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <vector>
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/file_change.h"
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/mock_sync_status_observer.h"
222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/mock_local_change_processor.h"
242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_status_code.h"
272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/browser/browser_thread.h"
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_browser_thread_bundle.h"
31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_utils.h"
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38a3f7b4e666c476898878fa745f637129375cd889Ben Murdochusing content::BrowserThread;
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InvokeWithoutArgs;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrictMock;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sync_file_system {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kOrigin[] = "http://example.com";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DidPrepareForProcessRemoteChange(const tracked_objects::Location& where,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const base::Closure& oncompleted,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      SyncStatusCode expected_status,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const SyncFileMetadata& expected_metadata,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      SyncStatusCode status,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const SyncFileMetadata& metadata,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const FileChangeList& changes) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCOPED_TRACE(testing::Message() << where.ToString());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_status, status);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_metadata.file_type, metadata.file_type);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_metadata.size, metadata.size);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(changes.empty());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oncompleted.Run();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OnSyncCompleted(const tracked_objects::Location& where,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::Closure& oncompleted,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SyncStatusCode expected_status,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const FileSystemURL& expected_url,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SyncStatusCode status,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const FileSystemURL& url) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCOPED_TRACE(testing::Message() << where.ToString());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_status, status);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected_url, url);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oncompleted.Run();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OnGetFileMetadata(const tracked_objects::Location& where,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const base::Closure& oncompleted,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SyncStatusCode* status_out,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SyncFileMetadata* metadata_out,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SyncStatusCode status,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const SyncFileMetadata& metadata) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCOPED_TRACE(testing::Message() << where.ToString());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *status_out = status;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *metadata_out = metadata;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oncompleted.Run();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(MockStatusCallback, status) {
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg4, status));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P2(MockStatusCallbackAndRecordChange, status, changes) {
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(arg4, status));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  changes->push_back(arg0);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LocalFileSyncServiceTest
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public testing::Test,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public LocalFileSyncService::Observer {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
107a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  LocalFileSyncServiceTest()
108a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD |
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                       content::TestBrowserThreadBundle::REAL_IO_THREAD),
110a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        num_changes_(0) {}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_system_.reset(new CannedSyncableFileSystem(
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin),
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        in_memory_env_.get(),
119a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
120a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    local_service_ = LocalFileSyncService::CreateForTesting(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &profile_, in_memory_env_.get());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    file_system_->SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_service_->MaybeInitializeFileSystemContext(
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GURL(kOrigin), file_system_->file_system_context(),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AssignAndQuitCallback(&run_loop, &status));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop.Run();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_service_->AddChangeObserver(this);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(base::File::FILE_OK, file_system_->OpenFileSystem());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    file_system_->backend()->sync_context()->
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_mock_notify_changes_duration_in_sec(0);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_service_->Shutdown();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_system_->TearDown();
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RevokeSyncableFileSystem();
146a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    content::RunAllPendingInMessageLoop(BrowserThread::FILE);
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    content::RunAllPendingInMessageLoop(BrowserThread::IO);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LocalChangeObserver overrides.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnLocalChangeAvailable(int64 num_changes) OVERRIDE {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_changes_ = num_changes;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PrepareForProcessRemoteChange(
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const FileSystemURL& url,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& where,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SyncStatusCode expected_status,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const SyncFileMetadata& expected_metadata) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_service_->PrepareForProcessRemoteChange(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&DidPrepareForProcessRemoteChange,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   where,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   run_loop.QuitClosure(),
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expected_status,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expected_metadata));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop.Run();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncStatusCode ApplyRemoteChange(const FileChange& change,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const base::FilePath& local_path,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const FileSystemURL& url) {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode sync_status = SYNC_STATUS_UNKNOWN;
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::RunLoop run_loop;
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      local_service_->ApplyRemoteChange(
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          change, local_path, url,
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          AssignAndQuitCallback(&run_loop, &sync_status));
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      run_loop.Run();
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::RunLoop run_loop;
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      local_service_->FinalizeRemoteSync(
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          url,
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          sync_status == SYNC_STATUS_OK,
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          run_loop.QuitClosure());
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      run_loop.Run();
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sync_status;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 GetNumChangesInTracker() const {
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return file_system_->backend()->change_tracker()->num_changes();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
197a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  content::TestBrowserThreadBundle thread_bundle_;
198a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<leveldb::Env> in_memory_env_;
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestingProfile profile_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<CannedSyncableFileSystem> file_system_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileSyncService> local_service_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 num_changes_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// More complete tests for PrepareForProcessRemoteChange and ApplyRemoteChange
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are also in content_unittest:LocalFileSyncContextTest.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, RemoteSyncStepsSimple) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("file"));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kDir(file_system_->URL("dir"));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kTestFileData[] = "0123456789";
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTestFileDataSize = static_cast<int>(arraysize(kTestFileData) - 1);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath local_path;
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &local_path));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestFileDataSize,
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::WriteFile(local_path, kTestFileData, kTestFileDataSize));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run PrepareForProcessRemoteChange for kFile.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncFileMetadata expected_metadata;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_metadata.file_type = SYNC_FILE_TYPE_UNKNOWN;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_metadata.size = 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrepareForProcessRemoteChange(kFile, FROM_HERE,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                SYNC_STATUS_OK,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                expected_metadata);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run ApplyRemoteChange for kFile.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SYNC_FILE_TYPE_FILE);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SYNC_STATUS_OK,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ApplyRemoteChange(change, local_path, kFile));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the file is synced.
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->VerifyFile(kFile, kTestFileData));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run PrepareForProcessRemoteChange for kDir.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrepareForProcessRemoteChange(kDir, FROM_HERE,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                SYNC_STATUS_OK,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                expected_metadata);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run ApplyRemoteChange for kDir.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      SYNC_FILE_TYPE_DIRECTORY);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SYNC_STATUS_OK,
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ApplyRemoteChange(change, base::FilePath(), kDir));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the directory.
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->DirectoryExists(kDir));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Run PrepareForProcessRemoteChange and ApplyRemoteChange for
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kDir once again for deletion.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_metadata.file_type = SYNC_FILE_TYPE_DIRECTORY;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_metadata.size = 0;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrepareForProcessRemoteChange(kDir, FROM_HERE,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                SYNC_STATUS_OK,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                expected_metadata);
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change = FileChange(FileChange::FILE_CHANGE_DELETE, SYNC_FILE_TYPE_UNKNOWN);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SYNC_STATUS_OK, ApplyRemoteChange(change, base::FilePath(), kDir));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now the directory must have deleted.
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->DirectoryExists(kDir));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, LocalChangeObserver) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("file"));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kDir(file_system_->URL("dir"));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kTestFileData[] = "0123456789";
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTestFileDataSize = static_cast<int>(arraysize(kTestFileData) - 1);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, num_changes_);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateDirectory(kDir));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kTestFileDataSize,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->WriteString(kFile, kTestFileData));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, num_changes_);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Flaky: http://crbug.com/171487
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAYBE_LocalChangeObserverMultipleContexts\
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DISABLED_LocalChangeObserverMultipleContexts
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAYBE_LocalChangeObserverMultipleContexts\
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LocalChangeObserverMultipleContexts
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(LocalFileSyncServiceTest, MAYBE_LocalChangeObserverMultipleContexts) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kOrigin2[] = "http://foo";
299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  CannedSyncableFileSystem file_system2(
300a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      GURL(kOrigin2),
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      in_memory_env_.get(),
302a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
303a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_system2.SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->MaybeInitializeFileSystemContext(
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GURL(kOrigin2), file_system2.file_system_context(),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AssignAndQuitCallback(&run_loop, &status));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system2.OpenFileSystem());
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  file_system2.backend()->sync_context()->
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_mock_notify_changes_duration_in_sec(0);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile1(file_system_->URL("file1"));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile2(file_system_->URL("file2"));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile3(file_system2.URL("file3"));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile4(file_system2.URL("file4"));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile1));
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile2));
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system2.CreateFile(kFile3));
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system2.CreateFile(kFile4));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4, num_changes_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system2.TearDown();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, ProcessLocalChange_CreateFile) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kTestFileData[] = "0123456789";
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTestFileDataSize = static_cast<int>(arraysize(kTestFileData) - 1);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We should get called OnSyncEnabled and OnWriteEnabled on kFile.
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // (OnWriteEnabled is called because we release lock before returning
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // from ApplyLocalChange)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kFile)).Times(AtLeast(1));
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kFile)).Times(AtLeast(0));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates and writes into a file.
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile));
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kTestFileDataSize,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->WriteString(kFile, std::string(kTestFileData)));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Retrieve the expected file info.
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Info info;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath platform_path;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK,
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            file_system_->GetMetadataAndPlatformPath(
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                kFile, &info, &platform_path));
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(info.is_directory);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(kTestFileDataSize, info.size);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileMetadata metadata;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  metadata.file_type = SYNC_FILE_TYPE_FILE;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  metadata.size = info.size;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  metadata.last_modified = info.last_modified;
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The local_change_processor's ApplyLocalChange should be called once
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with ADD_OR_UPDATE change for TYPE_FILE.
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          SYNC_FILE_TYPE_FILE);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(local_change_processor,
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              ApplyLocalChange(change, _, metadata, kFile, _))
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallback(SYNC_STATUS_OK));
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_service_->SetLocalChangeProcessor(&local_change_processor);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->ProcessLocalChange(
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&OnSyncCompleted, FROM_HERE, run_loop.QuitClosure(),
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 SYNC_STATUS_OK, kFile));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, GetNumChangesInTracker());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, ProcessLocalChange_CreateAndRemoveFile) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kFile(file_system_->URL("foo"));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We should get called OnSyncEnabled and possibly OnWriteEnabled (depends
394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // on timing) on kFile.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kFile)).Times(AtLeast(1));
397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kFile)).Times(AtLeast(0));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates and then deletes a file.
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kFile));
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->Remove(kFile, false));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The local_change_processor's ApplyLocalChange should be called once
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with DELETE change for TYPE_FILE.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The file will NOT exist in the remote side and the processor might
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return SYNC_FILE_ERROR_NOT_FOUND (as mocked).
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_DELETE, SYNC_FILE_TYPE_FILE);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(local_change_processor, ApplyLocalChange(change, _, _, kFile, _))
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallback(SYNC_FILE_ERROR_NOT_FOUND));
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The sync should succeed anyway.
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_service_->SetLocalChangeProcessor(&local_change_processor);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->ProcessLocalChange(
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&OnSyncCompleted, FROM_HERE, run_loop.QuitClosure(),
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 SYNC_STATUS_OK, kFile));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, GetNumChangesInTracker());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, ProcessLocalChange_CreateAndRemoveDirectory) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kDir(file_system_->URL("foo"));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnSyncEnabled is expected to be called at least or more than once.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kDir)).Times(AtLeast(1));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates and then deletes a directory.
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateDirectory(kDir));
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->Remove(kDir, false));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The local_change_processor's ApplyLocalChange should never be called.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_service_->SetLocalChangeProcessor(&local_change_processor);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->ProcessLocalChange(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&OnSyncCompleted, FROM_HERE, run_loop.QuitClosure(),
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 SYNC_STATUS_NO_CHANGE_TO_SYNC, FileSystemURL()));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, GetNumChangesInTracker());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, ProcessLocalChange_MultipleChanges) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kPath(file_system_->URL("foo"));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kOther(file_system_->URL("bar"));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should get called OnSyncEnabled and OnWriteEnabled on kPath and
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSyncEnabled on kOther.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockSyncStatusObserver> status_observer;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kPath)).Times(AtLeast(1));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(status_observer, OnSyncEnabled(kOther)).Times(AtLeast(1));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->AddSyncStatusObserver(&status_observer);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a file, delete the file and creates a directory with the same
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name.
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kPath));
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->Remove(kPath, false));
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateDirectory(kPath));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates one more file.
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kOther));
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The local_change_processor's ApplyLocalChange will be called
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // twice for FILE_TYPE and FILE_DIRECTORY.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<FileChange> changes;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(local_change_processor, ApplyLocalChange(_, _, _, kPath, _))
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(2)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallbackAndRecordChange(SYNC_STATUS_OK, &changes))
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallbackAndRecordChange(SYNC_STATUS_OK, &changes));
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  local_service_->SetLocalChangeProcessor(&local_change_processor);
486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // OnWriteEnabled will be notified on kPath (in multi-threaded this
488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // could be delayed, so AtLeast(0)).
489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_CALL(status_observer, OnWriteEnabled(kPath)).Times(AtLeast(0));
490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->ProcessLocalChange(
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&OnSyncCompleted, FROM_HERE, run_loop.QuitClosure(),
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 SYNC_STATUS_OK, kPath));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, changes.size());
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(FileChange(FileChange::FILE_CHANGE_DELETE, SYNC_FILE_TYPE_FILE),
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            changes[0]);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       SYNC_FILE_TYPE_DIRECTORY),
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            changes[1]);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_system_->RemoveSyncStatusObserver(&status_observer);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have one more change for kOther.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, GetNumChangesInTracker());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileSyncServiceTest, ProcessLocalChange_GetLocalMetadata) {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FileSystemURL kURL(file_system_->URL("foo"));
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Time kTime = base::Time::FromDoubleT(333);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSize = 555;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop run_loop;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a file.
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kURL));
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->TruncateFile(kURL, kSize));
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_->TouchFile(kURL, base::Time(), kTime));
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncFileMetadata metadata;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_service_->GetLocalFileMetadata(
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kURL,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&OnGetFileMetadata, FROM_HERE, run_loop.QuitClosure(),
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &status, &metadata));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_loop.Run();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SYNC_STATUS_OK, status);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kTime, metadata.last_modified);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kSize, metadata.size);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(LocalFileSyncServiceTest, RecordFakeChange) {
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileSystemURL kURL(file_system_->URL("foo"));
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a file and reset the changes (as preparation).
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, file_system_->CreateFile(kURL));
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->ClearChangeForURLInTracker(kURL);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, GetNumChangesInTracker());
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
54603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::FileSystemURLSet urlset;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->GetChangedURLsInTracker(&urlset);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(urlset.empty());
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          SYNC_FILE_TYPE_FILE);
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Call RecordFakeLocalChange to add an ADD_OR_UPDATE change.
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_service_->RecordFakeLocalChange(
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kURL, change, AssignAndQuitCallback(&run_loop, &status));
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(SYNC_STATUS_OK, status);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, GetNumChangesInTracker());
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_system_->GetChangedURLsInTracker(&urlset);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1U, urlset.size());
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(urlset.find(kURL) != urlset.end());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Next local sync should pick up the recorded change.
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StrictMock<MockLocalChangeProcessor> local_change_processor;
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<FileChange> changes;
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(local_change_processor, ApplyLocalChange(_, _, _, kURL, _))
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillOnce(MockStatusCallbackAndRecordChange(SYNC_STATUS_OK, &changes));
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::RunLoop run_loop;
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_service_->SetLocalChangeProcessor(&local_change_processor);
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    local_service_->ProcessLocalChange(
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&OnSyncCompleted, FROM_HERE, run_loop.QuitClosure(),
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SYNC_STATUS_OK, kURL));
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_loop.Run();
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1U, changes.size());
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(change, changes[0]);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kinuko): Add tests for multiple file changes and multiple
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FileSystemContexts.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Unit test for OriginChangeMap ---------------------------------------------
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OriginChangeMapTest : public testing::Test {
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OriginChangeMapTest() {}
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~OriginChangeMapTest() {}
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool NextOriginToProcess(GURL* origin) {
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return map_.NextOriginToProcess(origin);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 GetTotalChangeCount() const {
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return map_.GetTotalChangeCount();
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetOriginChangeCount(const GURL& origin, int64 changes) {
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    map_.SetOriginChangeCount(origin, changes);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetOriginEnabled(const GURL& origin, bool enabled) {
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    map_.SetOriginEnabled(origin, enabled);
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LocalFileSyncService::OriginChangeMap map_;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(OriginChangeMapTest, Basic) {
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin1("chrome-extension://foo");
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin2("chrome-extension://bar");
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin3("chrome-extension://baz");
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(0, GetTotalChangeCount());
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin1, 1);
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin2, 2);
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 2, GetTotalChangeCount());
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin3, 4);
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 2 + 4, GetTotalChangeCount());
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigins[] = { kOrigin1, kOrigin2, kOrigin3 };
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<GURL> all_origins;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins));
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL origin;
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set kOrigin2's change count 0.
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin2, 0);
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 4, GetTotalChangeCount());
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kOrigin2 won't return this time.
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin1);
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin3);
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calling NextOriginToProcess() again will just return
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the same set of origins (as far as we don't change the
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // change count).
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin1);
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin3);
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set kOrigin2's change count 8.
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin2, 8);
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 4 + 8, GetTotalChangeCount());
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins));
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(OriginChangeMapTest, WithDisabled) {
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin1("chrome-extension://foo");
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin2("chrome-extension://bar");
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigin3("chrome-extension://baz");
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL kOrigins[] = { kOrigin1, kOrigin2, kOrigin3 };
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(0, GetTotalChangeCount());
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin1, 1);
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin2, 2);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginChangeCount(kOrigin3, 4);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 2 + 4, GetTotalChangeCount());
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<GURL> all_origins;
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins));
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL origin;
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginEnabled(kOrigin2, false);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1 + 4, GetTotalChangeCount());
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kOrigin2 won't return this time.
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin1);
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin3);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kOrigin1 and kOrigin2 are now disabled.
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginEnabled(kOrigin1, false);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(4, GetTotalChangeCount());
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(NextOriginToProcess(&origin));
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(kOrigin3, origin);
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Re-enable kOrigin2.
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetOriginEnabled(kOrigin2, true);
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2 + 4, GetTotalChangeCount());
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // kOrigin1 won't return this time.
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin2);
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  all_origins.insert(kOrigin3);
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!all_origins.empty()) {
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(NextOriginToProcess(&origin));
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(ContainsKey(all_origins, origin));
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    all_origins.erase(origin);
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sync_file_system
736