fake_remote_change_processor.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
6
7#include "base/bind.h"
8#include "base/files/file_path.h"
9#include "base/location.h"
10#include "base/single_thread_task_runner.h"
11#include "base/thread_task_runner_handle.h"
12#include "chrome/browser/sync_file_system/file_change.h"
13#include "chrome/browser/sync_file_system/sync_file_metadata.h"
14#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "webkit/browser/fileapi/file_system_url.h"
17#include "webkit/common/fileapi/file_system_util.h"
18
19namespace sync_file_system {
20
21FakeRemoteChangeProcessor::FakeRemoteChangeProcessor() {
22}
23
24FakeRemoteChangeProcessor::~FakeRemoteChangeProcessor() {
25}
26
27void FakeRemoteChangeProcessor::PrepareForProcessRemoteChange(
28    const fileapi::FileSystemURL& url,
29    const PrepareChangeCallback& callback) {
30  SyncFileMetadata local_metadata;
31
32  if (fileapi::VirtualPath::IsRootPath(url.path())) {
33    // Origin root directory case.
34    local_metadata = SyncFileMetadata(
35        SYNC_FILE_TYPE_DIRECTORY, 0, base::Time::Now());
36  }
37
38  URLToFileMetadata::iterator found_metadata = local_file_metadata_.find(url);
39  if (found_metadata != local_file_metadata_.end())
40    local_metadata = found_metadata->second;
41
42  // Override |local_metadata| by applied changes.
43  URLToFileChangesMap::iterator found = applied_changes_.find(url);
44  if (found != applied_changes_.end()) {
45    DCHECK(!found->second.empty());
46    const FileChange& applied_change = found->second.back();
47    if (applied_change.IsAddOrUpdate()) {
48      local_metadata = SyncFileMetadata(
49          applied_change.file_type(),
50          100 /* size */,
51          base::Time::Now());
52    }
53  }
54
55  FileChangeList change_list;
56  URLToFileChangeList::iterator found_list = local_changes_.find(url);
57  if (found_list != local_changes_.end())
58    change_list = found_list->second;
59
60  base::ThreadTaskRunnerHandle::Get()->PostTask(
61      FROM_HERE,
62      base::Bind(callback, SYNC_STATUS_OK,
63                 local_metadata, change_list));
64}
65
66void FakeRemoteChangeProcessor::ApplyRemoteChange(
67    const FileChange& change,
68    const base::FilePath& local_path,
69    const fileapi::FileSystemURL& url,
70    const SyncStatusCallback& callback) {
71  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
72  base::FilePath ancestor = fileapi::VirtualPath::DirName(url.path());
73  while (true) {
74    fileapi::FileSystemURL ancestor_url =
75        CreateSyncableFileSystemURL(url.origin(), ancestor);
76    if (!ancestor_url.is_valid())
77      break;
78
79    URLToFileChangeList::iterator found_list =
80        local_changes_.find(ancestor_url);
81    if (found_list != local_changes_.end()) {
82      const FileChange& local_change = found_list->second.back();
83      if (local_change.IsAddOrUpdate() &&
84          local_change.file_type() != SYNC_FILE_TYPE_DIRECTORY) {
85        status = SYNC_FILE_ERROR_NOT_A_DIRECTORY;
86        break;
87      }
88    }
89
90    base::FilePath ancestor_parent = fileapi::VirtualPath::DirName(ancestor);
91    if (ancestor == ancestor_parent)
92      break;
93    ancestor = ancestor_parent;
94  }
95  if (status == SYNC_STATUS_UNKNOWN) {
96    applied_changes_[url].push_back(change);
97    status = SYNC_STATUS_OK;
98  }
99  base::ThreadTaskRunnerHandle::Get()->PostTask(
100      FROM_HERE, base::Bind(callback, status));
101}
102
103void FakeRemoteChangeProcessor::FinalizeRemoteSync(
104    const fileapi::FileSystemURL& url,
105    bool clear_local_changes,
106    const base::Closure& completion_callback) {
107  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, completion_callback);
108}
109
110void FakeRemoteChangeProcessor::RecordFakeLocalChange(
111    const fileapi::FileSystemURL& url,
112    const FileChange& change,
113    const SyncStatusCallback& callback) {
114  local_changes_[url].Update(change);
115  base::ThreadTaskRunnerHandle::Get()->PostTask(
116      FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
117}
118
119void FakeRemoteChangeProcessor::UpdateLocalFileMetadata(
120    const fileapi::FileSystemURL& url,
121    const FileChange& change) {
122  if (change.IsAddOrUpdate()) {
123    local_file_metadata_[url] = SyncFileMetadata(
124        change.file_type(), 100 /* size */, base::Time::Now());
125  } else {
126    local_file_metadata_.erase(url);
127  }
128  local_changes_[url].Update(change);
129}
130
131void FakeRemoteChangeProcessor::ClearLocalChanges(
132    const fileapi::FileSystemURL& url) {
133  local_changes_.erase(url);
134}
135
136const FakeRemoteChangeProcessor::URLToFileChangesMap&
137FakeRemoteChangeProcessor::GetAppliedRemoteChanges() const {
138  return applied_changes_;
139}
140
141void FakeRemoteChangeProcessor::VerifyConsistency(
142    const URLToFileChangesMap& expected_changes) {
143  EXPECT_EQ(expected_changes.size(), applied_changes_.size());
144  for (URLToFileChangesMap::const_iterator itr = applied_changes_.begin();
145       itr != applied_changes_.end(); ++itr) {
146    const fileapi::FileSystemURL& url = itr->first;
147    URLToFileChangesMap::const_iterator found = expected_changes.find(url);
148    if (found == expected_changes.end()) {
149      EXPECT_TRUE(found != expected_changes.end())
150          << "Change not expected for " << url.DebugString();
151      continue;
152    }
153
154    const std::vector<FileChange>& applied = itr->second;
155    const std::vector<FileChange>& expected = found->second;
156
157    if (applied.empty() || expected.empty()) {
158      EXPECT_TRUE(!applied.empty());
159      EXPECT_TRUE(!expected.empty());
160      continue;
161    }
162
163    EXPECT_EQ(expected.size(), applied.size());
164
165    for (size_t i = 0; i < applied.size() && i < expected.size(); ++i) {
166      EXPECT_EQ(expected[i], applied[i])
167          << url.DebugString()
168          << " expected:" << expected[i].DebugString()
169          << " applied:" << applied[i].DebugString();
170    }
171  }
172}
173
174}  // namespace sync_file_system
175