158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file.
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/basictypes.h"
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/files/file_path.h"
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/run_loop.h"
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/test/test_file_system_context.h"
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h"
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_operation_runner.h"
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using fileapi::FileSystemContext;
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using fileapi::FileSystemOperationRunner;
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using fileapi::FileSystemType;
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using fileapi::FileSystemURL;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void GetStatus(bool* done,
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               base::File::Error *status_out,
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               base::File::Error status) {
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(*done);
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  *done = true;
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  *status_out = status;
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void GetCancelStatus(bool* operation_done,
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     bool* cancel_done,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::File::Error *status_out,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     base::File::Error status) {
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Cancel callback must be always called after the operation's callback.
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(*operation_done);
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(*cancel_done);
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  *cancel_done = true;
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  *status_out = status;
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class FileSystemOperationRunnerTest : public testing::Test {
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protected:
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunnerTest() {}
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~FileSystemOperationRunnerTest() {}
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_TRUE(base_.CreateUniqueTempDir());
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    base::FilePath base_dir = base_.path();
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    file_system_context_ =
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        CreateFileSystemContextForTesting(NULL, base_dir);
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    file_system_context_ = NULL;
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemURL URL(const std::string& path) {
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return file_system_context_->CreateCrackedFileSystemURL(
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GURL("http://example.com"), fileapi::kFileSystemTypeTemporary,
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::FilePath::FromUTF8Unsafe(path));
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunner* operation_runner() {
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return file_system_context_->operation_runner();
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::ScopedTempDir base_;
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::MessageLoop message_loop_;
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<FileSystemContext> file_system_context_;
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunnerTest);
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(FileSystemOperationRunnerTest, NotFoundError) {
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool done = false;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status = base::File::FILE_ERROR_FAILED;
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Regular NOT_FOUND error, which is called asynchronously.
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  operation_runner()->Truncate(URL("foo"), 0,
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               base::Bind(&GetStatus, &done, &status));
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(done);
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(done);
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, status);
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(FileSystemOperationRunnerTest, InvalidURLError) {
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool done = false;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status = base::File::FILE_ERROR_FAILED;
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Invalid URL error, which calls DidFinish synchronously.
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  operation_runner()->Truncate(FileSystemURL(), 0,
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               base::Bind(&GetStatus, &done, &status));
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The error call back shouldn't be fired synchronously.
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(done);
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(done);
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_INVALID_URL, status);
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(FileSystemOperationRunnerTest, NotFoundErrorAndCancel) {
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool done = false;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool cancel_done = false;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status = base::File::FILE_ERROR_FAILED;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error cancel_status = base::File::FILE_ERROR_FAILED;
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Call Truncate with non-existent URL, and try to cancel it immediately
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // after that (before its callback is fired).
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunner::OperationID id =
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      operation_runner()->Truncate(URL("foo"), 0,
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   base::Bind(&GetStatus, &done, &status));
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            &done, &cancel_done,
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            &cancel_status));
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(done);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(cancel_done);
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(done);
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(cancel_done);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, status);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status);
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(FileSystemOperationRunnerTest, InvalidURLErrorAndCancel) {
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool done = false;
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool cancel_done = false;
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status = base::File::FILE_ERROR_FAILED;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error cancel_status = base::File::FILE_ERROR_FAILED;
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Call Truncate with invalid URL, and try to cancel it immediately
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // after that (before its callback is fired).
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunner::OperationID id =
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      operation_runner()->Truncate(FileSystemURL(), 0,
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  base::Bind(&GetStatus, &done, &status));
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            &done, &cancel_done,
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                            &cancel_status));
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(done);
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_FALSE(cancel_done);
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(done);
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(cancel_done);
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_INVALID_URL, status);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status);
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(FileSystemOperationRunnerTest, CancelWithInvalidId) {
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const FileSystemOperationRunner::OperationID kInvalidId = -1;
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool done = true;  // The operation is not running.
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool cancel_done = false;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error cancel_status = base::File::FILE_ERROR_FAILED;
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation_runner()->Cancel(kInvalidId, base::Bind(&GetCancelStatus,
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                    &done, &cancel_done,
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                    &cancel_status));
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(cancel_done);
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, cancel_status);
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
167