Home | History | Annotate | Download | only in fileapi
      1 // Copyright 2014 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/chromeos/drive/fileapi/fileapi_worker.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/file_util.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "chrome/browser/chromeos/drive/dummy_file_system.h"
     12 #include "chrome/browser/chromeos/drive/test_util.h"
     13 #include "content/public/test/test_browser_thread_bundle.h"
     14 #include "google_apis/drive/test_util.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace drive {
     18 namespace fileapi_internal {
     19 namespace {
     20 
     21 // Increments |num_called| for checking how many times the closure is called.
     22 void Increment(int* num_called) {
     23   ++*num_called;
     24 }
     25 
     26 // Returns the |instance| as is.
     27 FileSystemInterface* GetFileSystem(FileSystemInterface* instance) {
     28   return instance;
     29 }
     30 
     31 // A test file system that always returns |local_file_path|. For testing
     32 // purpose, it checks if |open_mode| is the expected value, and record if the
     33 // close callback is called.
     34 class TestFileSystemForOpenFile : public DummyFileSystem {
     35  public:
     36   TestFileSystemForOpenFile(const base::FilePath& local_file_path,
     37                             OpenMode expected_open_mode)
     38       : local_file_path_(local_file_path),
     39         expected_open_mode_(expected_open_mode),
     40         closed_(false) {
     41   }
     42 
     43   virtual void OpenFile(const base::FilePath& file_path,
     44                         OpenMode open_mode,
     45                         const std::string& mime_type,
     46                         const drive::OpenFileCallback& callback) OVERRIDE {
     47     EXPECT_EQ(expected_open_mode_, open_mode);
     48 
     49     callback.Run(
     50         FILE_ERROR_OK,
     51         local_file_path_,
     52         base::Bind(&TestFileSystemForOpenFile::Close, base::Unretained(this)));
     53   }
     54 
     55   void Close() {
     56     closed_ = true;
     57   }
     58 
     59   bool closed() const { return closed_; }
     60 
     61  private:
     62   const base::FilePath local_file_path_;
     63   const OpenMode expected_open_mode_;
     64   bool closed_;
     65 };
     66 
     67 // Helper function of testing OpenFile() for write access. It checks that the
     68 // file handle correctly writes to the expected file.
     69 void VerifyWrite(
     70     int64 expected_size,
     71     const base::FilePath& expected_written_path,
     72     const std::string& write_data,
     73     base::File file,
     74     const base::Closure& close_callback) {
     75   // Check that the file was properly opened.
     76   EXPECT_TRUE(file.IsValid());
     77   EXPECT_FALSE(close_callback.is_null());
     78 
     79   // Check that the file has the expected length (i.e., truncated or not)
     80   base::File::Info info;
     81   EXPECT_TRUE(file.GetInfo(&info));
     82   EXPECT_EQ(expected_size, info.size);
     83 
     84   // Write some data.
     85   const int data_size = static_cast<int>(write_data.size());
     86   EXPECT_EQ(data_size, file.Write(0, write_data.c_str(), data_size));
     87   EXPECT_TRUE(file.SetLength(data_size));
     88 
     89   // Close.
     90   file.Close();
     91   close_callback.Run();
     92 
     93   // Checks that the written content goes to |expected_written_path|. I.e.,
     94   // the |file| handle is pointing to the file.
     95   std::string written;
     96   EXPECT_TRUE(base::ReadFileToString(expected_written_path, &written));
     97   EXPECT_EQ(write_data, written);
     98 }
     99 
    100 // Helper function of testing OpenFile() for read access. It checks that the
    101 // file is readable and contains |expected_data|.
    102 void VerifyRead(const std::string& expected_data,
    103                 base::File file,
    104                 const base::Closure& close_callback) {
    105   // Check that the file was properly opened.
    106   EXPECT_TRUE(file.IsValid());
    107   EXPECT_FALSE(close_callback.is_null());
    108 
    109   // Check that the file has the expected content.
    110   const int data_size = static_cast<int>(expected_data.size());
    111   base::File::Info info;
    112   EXPECT_TRUE(file.GetInfo(&info));
    113   EXPECT_EQ(data_size, info.size);
    114 
    115   std::vector<char> buffer(data_size);
    116   EXPECT_EQ(data_size, file.Read(0, buffer.data(), data_size));
    117   EXPECT_EQ(expected_data, std::string(buffer.begin(), buffer.end()));
    118 
    119   // Close.
    120   file.Close();
    121   close_callback.Run();
    122 }
    123 
    124 }  // namespace
    125 
    126 class FileApiWorkerTest : public testing::Test {
    127  private:
    128   content::TestBrowserThreadBundle thread_bundle_;
    129 };
    130 
    131 TEST_F(FileApiWorkerTest, RunFileSystemCallbackSuccess) {
    132   DummyFileSystem dummy_file_system;
    133 
    134   FileSystemInterface* file_system = NULL;
    135   RunFileSystemCallback(
    136       base::Bind(&GetFileSystem, &dummy_file_system),
    137       google_apis::test_util::CreateCopyResultCallback(&file_system),
    138       base::Closure());
    139 
    140   EXPECT_EQ(&dummy_file_system, file_system);
    141 }
    142 
    143 TEST_F(FileApiWorkerTest, RunFileSystemCallbackFail) {
    144   FileSystemInterface* file_system = NULL;
    145 
    146   // Make sure on_error_callback is called if file_system_getter returns NULL.
    147   int num_called = 0;
    148   RunFileSystemCallback(
    149       base::Bind(&GetFileSystem, static_cast<FileSystemInterface*>(NULL)),
    150       google_apis::test_util::CreateCopyResultCallback(&file_system),
    151       base::Bind(&Increment, &num_called));
    152   EXPECT_EQ(1, num_called);
    153 
    154   // Just make sure this null |on_error_callback| doesn't cause a crash.
    155   RunFileSystemCallback(
    156       base::Bind(&GetFileSystem, static_cast<FileSystemInterface*>(NULL)),
    157       google_apis::test_util::CreateCopyResultCallback(&file_system),
    158       base::Closure());
    159 }
    160 
    161 TEST_F(FileApiWorkerTest, OpenFileForCreateWrite) {
    162   const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
    163   const std::string kWriteData = "byebye";
    164 
    165   base::FilePath temp_path;
    166   base::CreateTemporaryFile(&temp_path);
    167 
    168   // CREATE => CREATE (fails if file exists.)
    169   TestFileSystemForOpenFile file_system(temp_path, CREATE_FILE);
    170   const int64 kExpectedSize = 0;
    171 
    172   OpenFile(kDummyPath,
    173            base::File::FLAG_CREATE | base::File::FLAG_WRITE,
    174            base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
    175            &file_system);
    176   test_util::RunBlockingPoolTask();
    177   EXPECT_TRUE(file_system.closed());
    178 }
    179 
    180 TEST_F(FileApiWorkerTest, OpenFileForOpenAlwaysWrite) {
    181   const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
    182   const std::string kWriteData = "byebye";
    183   const std::string kInitialData = "hello";
    184 
    185   base::FilePath temp_path;
    186   base::CreateTemporaryFile(&temp_path);
    187   google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
    188 
    189   // OPEN_ALWAYS => OPEN_OR_CREATE (success whether file exists or not.)
    190   // No truncation should take place.
    191   TestFileSystemForOpenFile file_system(temp_path, OPEN_OR_CREATE_FILE);
    192   const int64 kExpectedSize = static_cast<int64>(kInitialData.size());
    193 
    194   OpenFile(kDummyPath,
    195            base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE,
    196            base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
    197            &file_system);
    198   test_util::RunBlockingPoolTask();
    199   EXPECT_TRUE(file_system.closed());
    200 }
    201 
    202 TEST_F(FileApiWorkerTest, OpenFileForOpenTruncatedWrite) {
    203   const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
    204   const std::string kInitialData = "hello";
    205   const std::string kWriteData = "byebye";
    206 
    207   base::FilePath temp_path;
    208   base::CreateTemporaryFile(&temp_path);
    209   google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
    210 
    211   // OPEN_TRUNCATED => OPEN (failure when the file did not exist.)
    212   // It should truncate the file before passing to the callback.
    213   TestFileSystemForOpenFile file_system(temp_path, OPEN_FILE);
    214   const int64 kExpectedSize = 0;
    215 
    216   OpenFile(kDummyPath,
    217            base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE,
    218            base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
    219            &file_system);
    220   test_util::RunBlockingPoolTask();
    221   EXPECT_TRUE(file_system.closed());
    222 }
    223 
    224 TEST_F(FileApiWorkerTest, OpenFileForOpenCreateAlwaysWrite) {
    225   const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
    226   const std::string kInitialData = "hello";
    227   const std::string kWriteData = "byebye";
    228 
    229   base::FilePath temp_path;
    230   base::CreateTemporaryFile(&temp_path);
    231   google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
    232 
    233   // CREATE_ALWAYS => OPEN_OR_CREATE (success whether file exists or not.)
    234   // It should truncate the file before passing to the callback.
    235   TestFileSystemForOpenFile file_system(temp_path, OPEN_OR_CREATE_FILE);
    236   const int64 kExpectedSize = 0;
    237 
    238   OpenFile(kDummyPath,
    239            base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE,
    240            base::Bind(&VerifyWrite, kExpectedSize, temp_path, kWriteData),
    241            &file_system);
    242   test_util::RunBlockingPoolTask();
    243   EXPECT_TRUE(file_system.closed());
    244 }
    245 
    246 TEST_F(FileApiWorkerTest, OpenFileForOpenRead) {
    247   const base::FilePath kDummyPath = base::FilePath::FromUTF8Unsafe("whatever");
    248   const std::string kInitialData = "hello";
    249 
    250   base::FilePath temp_path;
    251   base::CreateTemporaryFile(&temp_path);
    252   google_apis::test_util::WriteStringToFile(temp_path, kInitialData);
    253 
    254   // OPEN => OPEN (failure when the file did not exist.)
    255   TestFileSystemForOpenFile file_system(temp_path, OPEN_FILE);
    256 
    257   OpenFile(kDummyPath,
    258            base::File::FLAG_OPEN | base::File::FLAG_READ,
    259            base::Bind(&VerifyRead, kInitialData),
    260            &file_system);
    261   test_util::RunBlockingPoolTask();
    262   EXPECT_TRUE(file_system.closed());
    263 }
    264 
    265 }  // namespace fileapi_internal
    266 }  // namespace drive
    267