190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.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_change_tracker.h"
162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h"
202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/mock_blob_url_request_context.h"
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_runner.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemOperation;
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::MockBlobURLRequestContext;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::ScopedTextBlob;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::File;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string kParent = "foo";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string kFile   = "foo/file";
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string kDir    = "foo/dir";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string kChild  = "foo/dir/bar";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string kOther  = "bar";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncableFileOperationRunnerTest : public testing::Test {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef FileSystemOperation::StatusCallback StatusCallback;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the current thread as IO thread so that we can directly call
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // operations in the tests.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncableFileOperationRunnerTest()
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        in_memory_env_(leveldb::NewMemEnv(leveldb::Env::Default())),
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        file_system_(GURL("http://example.com"),
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     in_memory_env_.get(),
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     base::ThreadTaskRunnerHandle::Get().get(),
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     base::ThreadTaskRunnerHandle::Get().get()),
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        callback_count_(0),
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write_status_(File::FILE_ERROR_FAILED),
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        write_bytes_(0),
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        write_complete_(false),
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        url_request_context_(file_system_.file_system_context()),
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        weak_factory_(this) {}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(dir_.CreateUniqueTempDir());
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    file_system_.SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    sync_context_ = new LocalFileSyncContext(
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        dir_.path(),
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        in_memory_env_.get(),
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::ThreadTaskRunnerHandle::Get().get(),
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        base::ThreadTaskRunnerHandle::Get().get());
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_EQ(
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        SYNC_STATUS_OK,
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        file_system_.MaybeInitializeFileSystemContext(sync_context_.get()));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_EQ(File::FILE_OK, file_system_.OpenFileSystem());
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_EQ(File::FILE_OK,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              file_system_.CreateDirectory(URL(kParent)));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (sync_context_.get())
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_context_->ShutdownOnUIThread();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_context_ = NULL;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_system_.TearDown();
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RevokeSyncableFileSystem();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileSystemURL URL(const std::string& path) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return file_system_.URL(path);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocalFileSyncStatus* sync_status() {
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return file_system_.backend()->sync_context()->sync_status();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetCallbackStatus() {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    write_status_ = File::FILE_ERROR_FAILED;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_bytes_ = 0;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_complete_ = false;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_count_ = 0;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StatusCallback ExpectStatus(const tracked_objects::Location& location,
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              File::Error expect) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Bind(&SyncableFileOperationRunnerTest::DidFinish,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      weak_factory_.GetWeakPtr(), location, expect);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileSystemOperation::WriteCallback GetWriteCallback(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const tracked_objects::Location& location) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::Bind(&SyncableFileOperationRunnerTest::DidWrite,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      weak_factory_.GetWeakPtr(), location);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidWrite(const tracked_objects::Location& location,
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                File::Error status, int64 bytes, bool complete) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(testing::Message() << location.ToString());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_status_ = status;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_bytes_ += bytes;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_complete_ = complete;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++callback_count_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidFinish(const tracked_objects::Location& location,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 File::Error expect, File::Error status) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(testing::Message() << location.ToString());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expect, status);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++callback_count_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool CreateTempFile(base::FilePath* path) {
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::CreateTemporaryFileInDir(dir_.path(), path);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::TestBrowserThreadBundle thread_bundle_;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ScopedTempDir dir_;
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<leveldb::Env> in_memory_env_;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CannedSyncableFileSystem file_system_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<LocalFileSyncContext> sync_context_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int callback_count_;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  File::Error write_status_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t write_bytes_;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool write_complete_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockBlobURLRequestContext url_request_context_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) private:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<SyncableFileOperationRunnerTest> weak_factory_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncableFileOperationRunnerTest);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, SimpleQueue) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL(kFile));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The URL is in syncing so the write operations won't run.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->CreateFile(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kFile), false /* exclusive */,
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Truncate(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kFile), 1,
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback_count_);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read operations are not blocked (and are executed before queued ones).
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->FileExists(
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      URL(kFile), ExpectStatus(FROM_HERE, File::FILE_ERROR_NOT_FOUND));
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // End syncing (to enable write).
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->EndSyncing(URL(kFile));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, callback_count_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now the file must have been created and updated.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->FileExists(
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      URL(kFile), ExpectStatus(FROM_HERE, File::FILE_OK));
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, WriteToParentAndChild) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First create the kDir directory and kChild in the dir.
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, file_system_.CreateDirectory(URL(kDir)));
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, file_system_.CreateFile(URL(kChild)));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start syncing the kDir directory.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL(kDir));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(sync_status()->IsWritable(URL(kDir)));
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes to kParent and kChild should be all queued up.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Truncate(
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      URL(kChild), 1, ExpectStatus(FROM_HERE, File::FILE_OK));
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Remove(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kParent), true /* recursive */,
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback_count_);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read operations are not blocked (and are executed before queued ones).
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->DirectoryExists(
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      URL(kDir), ExpectStatus(FROM_HERE, File::FILE_OK));
220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes to unrelated files must succeed as well.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->CreateDirectory(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kOther), false /* exclusive */, false /* recursive */,
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // End syncing (to enable write).
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->EndSyncing(URL(kDir));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(sync_status()->IsWritable(URL(kDir)));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, callback_count_);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, CopyAndMove) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First create the kDir directory and kChild in the dir.
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, file_system_.CreateDirectory(URL(kDir)));
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, file_system_.CreateFile(URL(kChild)));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start syncing the kParent directory.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL(kParent));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copying kDir to other directory should succeed, while moving would fail
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (since the source directory is in syncing).
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Copy(
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL(kDir),
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL("dest-copy"),
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::FileSystemOperation::OPTION_NONE,
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::FileSystemOperationRunner::CopyProgressCallback(),
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Move(
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL(kDir),
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL("dest-move"),
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::FileSystemOperation::OPTION_NONE,
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only "dest-copy1" should exist.
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_.DirectoryExists(URL("dest-copy")));
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_ERROR_NOT_FOUND,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_.DirectoryExists(URL("dest-move")));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start syncing the "dest-copy2" directory.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL("dest-copy2"));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now the destination is also locked copying kDir should be queued.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Copy(
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL(kDir),
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      URL("dest-copy2"),
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::FileSystemOperation::OPTION_NONE,
28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::FileSystemOperationRunner::CopyProgressCallback(),
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback_count_);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish syncing the "dest-copy2" directory to unlock Copy.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->EndSyncing(URL("dest-copy2"));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we should have "dest-copy2".
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_.DirectoryExists(URL("dest-copy2")));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish syncing the kParent to unlock Move.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->EndSyncing(URL(kParent));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now we should have "dest-move".
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_system_.DirectoryExists(URL("dest-move")));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, Write) {
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, file_system_.CreateFile(URL(kFile)));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kData("Lorem ipsum.");
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context_, "blob:foo", kData);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL(kFile));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Write(
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &url_request_context_,
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      URL(kFile), blob.GetBlobDataHandle(), 0, GetWriteCallback(FROM_HERE));
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback_count_);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->EndSyncing(URL(kFile));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!write_complete_)
324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(File::FILE_OK, write_status_);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kData.size(), write_bytes_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(write_complete_);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, QueueAndCancel) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_status()->StartSyncing(URL(kFile));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->CreateFile(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kFile), false /* exclusive */,
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_ERROR_ABORT));
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Truncate(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URL(kFile), 1,
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_ERROR_ABORT));
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, callback_count_);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetCallbackStatus();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This shouldn't crash nor leak memory.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_context_->ShutdownOnUIThread();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_context_ = NULL;
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, callback_count_);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Test if CopyInForeignFile runs cooperatively with other Sync operations.
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, CopyInForeignFile) {
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestData("test data");
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath temp_path;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(CreateTempFile(&temp_path));
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(static_cast<int>(kTestData.size()),
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::WriteFile(
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                temp_path, kTestData.data(), kTestData.size()));
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sync_status()->StartSyncing(URL(kFile));
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_FALSE(sync_status()->IsWritable(URL(kFile)));
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The URL is in syncing so CopyIn (which is a write operation) won't run.
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResetCallbackStatus();
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->CopyInForeignFile(
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      temp_path, URL(kFile),
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0, callback_count_);
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // End syncing (to enable write).
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sync_status()->EndSyncing(URL(kFile));
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResetCallbackStatus();
380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1, callback_count_);
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Now the file must have been created and have the same content as temp_path.
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResetCallbackStatus();
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_system_.DoVerifyFile(
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      URL(kFile), kTestData,
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1, callback_count_);
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(SyncableFileOperationRunnerTest, Cancel) {
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Prepare a file.
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->CreateFile(
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      URL(kFile), false /* exclusive */,
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExpectStatus(FROM_HERE, File::FILE_OK));
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(1, callback_count_);
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Run Truncate and immediately cancel. This shouldn't crash.
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ResetCallbackStatus();
40203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::FileSystemOperationRunner::OperationID id =
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_system_.operation_runner()->Truncate(
40403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          URL(kFile), 10, ExpectStatus(FROM_HERE, File::FILE_OK));
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_.operation_runner()->Cancel(
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      id, ExpectStatus(FROM_HERE, File::FILE_ERROR_INVALID_OPERATION));
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(2, callback_count_);
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
412