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