1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file.
4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/recursive_operation_delegate.h"
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <vector>
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/basictypes.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/bind.h"
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/callback.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop.h"
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/run_loop.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/test/sandbox_file_system_test_helper.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_file_util.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_runner.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemContext;
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemOperationContext;
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace {
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class LoggingRecursiveOperation : public storage::RecursiveOperationDelegate {
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct LogEntry {
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    enum Type {
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      PROCESS_FILE,
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      PROCESS_DIRECTORY,
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      POST_PROCESS_DIRECTORY
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    };
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Type type;
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FileSystemURL url;
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LoggingRecursiveOperation(FileSystemContext* file_system_context,
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                            const FileSystemURL& root,
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                            const StatusCallback& callback)
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      : storage::RecursiveOperationDelegate(file_system_context),
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        root_(root),
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        callback_(callback),
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        weak_factory_(this) {}
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual ~LoggingRecursiveOperation() {}
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const std::vector<LogEntry>& log_entries() const { return log_entries_; }
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // RecursiveOperationDelegate overrides.
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void Run() OVERRIDE {
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    NOTREACHED();
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void RunRecursively() OVERRIDE {
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    StartRecursiveOperation(root_, callback_);
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void ProcessFile(const FileSystemURL& url,
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                           const StatusCallback& callback) OVERRIDE {
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    RecordLogEntry(LogEntry::PROCESS_FILE, url);
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    operation_runner()->GetMetadata(
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        url,
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void ProcessDirectory(const FileSystemURL& url,
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                const StatusCallback& callback) OVERRIDE {
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_OK);
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void PostProcessDirectory(const FileSystemURL& url,
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                    const StatusCallback& callback) OVERRIDE {
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_OK);
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LogEntry entry;
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    entry.type = type;
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    entry.url = url;
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    log_entries_.push_back(entry);
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void DidGetMetadata(const StatusCallback& callback,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      base::File::Error result,
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      const base::File::Info& file_info) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result != base::File::FILE_OK) {
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback.Run(result);
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    callback.Run(file_info.is_directory ?
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::File::FILE_ERROR_NOT_A_FILE :
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::File::FILE_OK);
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL root_;
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  StatusCallback callback_;
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<LogEntry> log_entries_;
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ReportStatus(base::File::Error* out_error,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  base::File::Error error) {
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(out_error);
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  *out_error = error;
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// To test the Cancel() during operation, calls Cancel() of |operation|
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// after |counter| times message posting.
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void CallCancelLater(storage::RecursiveOperationDelegate* operation,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     int counter) {
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (counter > 0) {
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        FROM_HERE,
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation->Cancel();
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class RecursiveOperationDelegateTest : public testing::Test {
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) protected:
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_TRUE(base_.CreateUniqueTempDir());
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    sandbox_file_system_.TearDown();
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<FileSystemOperationContext> NewContext() {
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FileSystemOperationContext* context =
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        sandbox_file_system_.NewOperationContext();
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Grant enough quota for all test cases.
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    context->set_allowed_bytes_growth(1000000);
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return make_scoped_ptr(context);
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::FileSystemFileUtil* file_util() {
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return sandbox_file_system_.file_util();
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL URLForPath(const std::string& path) const {
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return sandbox_file_system_.CreateURLFromUTF8(path);
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL CreateFile(const std::string& path) {
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FileSystemURL url = URLForPath(path);
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    bool created = false;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(base::File::FILE_OK,
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              file_util()->EnsureFileExists(NewContext().get(),
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                            url, &created));
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_TRUE(created);
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return url;
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL CreateDirectory(const std::string& path) {
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    FileSystemURL url = URLForPath(path);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(base::File::FILE_OK,
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              file_util()->CreateDirectory(NewContext().get(), url,
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                           false /* exclusive */, true));
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return url;
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::MessageLoop message_loop_;
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Common temp base for nondestructive uses.
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::ScopedTempDir base_;
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SandboxFileSystemTestHelper sandbox_file_system_;
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file(CreateFile("src"));
188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error error = base::File::FILE_ERROR_FAILED;
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<FileSystemOperationContext> context = NewContext();
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<LoggingRecursiveOperation> operation(
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      new LoggingRecursiveOperation(
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          context->file_system_context(), src_file,
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          base::Bind(&ReportStatus, &error)));
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation->RunRecursively();
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_OK, error);
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      operation->log_entries();
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(1U, log_entries.size());
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_file, entry.url);
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_root(CreateDirectory("src"));
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file1(CreateFile("src/file1"));
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file2(CreateFile("src/dir1/file2"));
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file3(CreateFile("src/dir1/file3"));
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error error = base::File::FILE_ERROR_FAILED;
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<FileSystemOperationContext> context = NewContext();
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<LoggingRecursiveOperation> operation(
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      new LoggingRecursiveOperation(
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          context->file_system_context(), src_root,
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          base::Bind(&ReportStatus, &error)));
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation->RunRecursively();
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_OK, error);
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      operation->log_entries();
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(8U, log_entries.size());
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[0].type);
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_root, log_entries[0].url);
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[1].type);
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_root, log_entries[1].url);
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[2].type);
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_file1, log_entries[2].url);
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[3].type);
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_dir1, log_entries[3].url);
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // implementation (can be swapped).
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[4].type);
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[5].type);
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE((src_file2 == log_entries[4].url &&
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               src_file3 == log_entries[5].url) ||
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              (src_file3 == log_entries[4].url &&
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               src_file2 == log_entries[5].url));
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[6].type);
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_dir1, log_entries[6].url);
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            log_entries[7].type);
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(src_root, log_entries[7].url);
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RecursiveOperationDelegateTest, Cancel) {
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_root(CreateDirectory("src"));
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_dir1(CreateDirectory("src/dir1"));
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file1(CreateFile("src/file1"));
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemURL src_file2(CreateFile("src/dir1/file2"));
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error error = base::File::FILE_ERROR_FAILED;
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<FileSystemOperationContext> context = NewContext();
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<LoggingRecursiveOperation> operation(
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      new LoggingRecursiveOperation(
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          context->file_system_context(), src_root,
275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          base::Bind(&ReportStatus, &error)));
276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation->RunRecursively();
277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Invoke Cancel(), after 5 times message posting.
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CallCancelLater(operation.get(), 5);
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_ABORT, error);
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
285