12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/single_thread_task_runner.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h"
122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/file_change.h"
132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "chrome/browser/sync_file_system/sync_file_metadata.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace sync_file_system {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FakeRemoteChangeProcessor::FakeRemoteChangeProcessor() {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FakeRemoteChangeProcessor::~FakeRemoteChangeProcessor() {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FakeRemoteChangeProcessor::PrepareForProcessRemoteChange(
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PrepareChangeCallback& callback) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SyncFileMetadata local_metadata;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (storage::VirtualPath::IsRootPath(url.path())) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Origin root directory case.
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    local_metadata = SyncFileMetadata(
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        SYNC_FILE_TYPE_DIRECTORY, 0, base::Time::Now());
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  URLToFileMetadata::iterator found_metadata = local_file_metadata_.find(url);
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (found_metadata != local_file_metadata_.end())
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    local_metadata = found_metadata->second;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Override |local_metadata| by applied changes.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLToFileChangesMap::iterator found = applied_changes_.find(url);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (found != applied_changes_.end()) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!found->second.empty());
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileChange& applied_change = found->second.back();
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (applied_change.IsAddOrUpdate()) {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      local_metadata = SyncFileMetadata(
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          applied_change.file_type(),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          100 /* size */,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Time::Now());
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FileChangeList change_list;
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  URLToFileChangeList::iterator found_list = local_changes_.find(url);
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (found_list != local_changes_.end())
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    change_list = found_list->second;
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(callback, SYNC_STATUS_OK,
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 local_metadata, change_list));
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FakeRemoteChangeProcessor::ApplyRemoteChange(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileChange& change,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& local_path,
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback) {
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::FilePath ancestor = storage::VirtualPath::DirName(url.path());
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (true) {
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::FileSystemURL ancestor_url =
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        CreateSyncableFileSystemURL(url.origin(), ancestor);
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!ancestor_url.is_valid())
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      break;
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    URLToFileChangeList::iterator found_list =
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        local_changes_.find(ancestor_url);
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (found_list != local_changes_.end()) {
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const FileChange& local_change = found_list->second.back();
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (local_change.IsAddOrUpdate() &&
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          local_change.file_type() != SYNC_FILE_TYPE_DIRECTORY) {
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        status = SYNC_FILE_ERROR_NOT_A_DIRECTORY;
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::FilePath ancestor_parent = storage::VirtualPath::DirName(ancestor);
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (ancestor == ancestor_parent)
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      break;
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ancestor = ancestor_parent;
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (status == SYNC_STATUS_UNKNOWN) {
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    applied_changes_[url].push_back(change);
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    status = SYNC_STATUS_OK;
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FROM_HERE, base::Bind(callback, status));
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void FakeRemoteChangeProcessor::FinalizeRemoteSync(
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url,
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    bool clear_local_changes,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& completion_callback) {
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, completion_callback);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FakeRemoteChangeProcessor::RecordFakeLocalChange(
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileChange& change,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SyncStatusCallback& callback) {
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  local_changes_[url].Update(change);
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ThreadTaskRunnerHandle::Get()->PostTask(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void FakeRemoteChangeProcessor::UpdateLocalFileMetadata(
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url,
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const FileChange& change) {
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (change.IsAddOrUpdate()) {
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    local_file_metadata_[url] = SyncFileMetadata(
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        change.file_type(), 100 /* size */, base::Time::Now());
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    local_file_metadata_.erase(url);
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  local_changes_[url].Update(change);
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FakeRemoteChangeProcessor::ClearLocalChanges(
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  local_changes_.erase(url);
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const FakeRemoteChangeProcessor::URLToFileChangesMap&
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FakeRemoteChangeProcessor::GetAppliedRemoteChanges() const {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return applied_changes_;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FakeRemoteChangeProcessor::VerifyConsistency(
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const URLToFileChangesMap& expected_changes) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(expected_changes.size(), applied_changes_.size());
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (URLToFileChangesMap::const_iterator itr = applied_changes_.begin();
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       itr != applied_changes_.end(); ++itr) {
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const storage::FileSystemURL& url = itr->first;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLToFileChangesMap::const_iterator found = expected_changes.find(url);
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (found == expected_changes.end()) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_TRUE(found != expected_changes.end())
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          << "Change not expected for " << url.DebugString();
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<FileChange>& applied = itr->second;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<FileChange>& expected = found->second;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (applied.empty() || expected.empty()) {
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_TRUE(!applied.empty());
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_TRUE(!expected.empty());
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(expected.size(), applied.size());
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (size_t i = 0; i < applied.size() && i < expected.size(); ++i) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(expected[i], applied[i])
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          << url.DebugString()
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          << " expected:" << expected[i].DebugString()
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          << " applied:" << applied[i].DebugString();
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace sync_file_system
175