Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2012 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 "ppapi/tests/test_flash_file.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "ppapi/c/pp_file_info.h"
     11 #include "ppapi/c/ppb_file_io.h"
     12 #include "ppapi/cpp/module.h"
     13 #include "ppapi/cpp/private/flash_file.h"
     14 #include "ppapi/tests/testing_instance.h"
     15 #include "ppapi/tests/test_utils.h"
     16 
     17 #if defined(PPAPI_OS_WIN)
     18 #include <windows.h>
     19 #else
     20 #include <errno.h>
     21 #include <unistd.h>
     22 #endif
     23 
     24 using pp::flash::FileModuleLocal;
     25 
     26 namespace {
     27 
     28 void CloseFileHandle(PP_FileHandle file_handle) {
     29 #if defined(PPAPI_OS_WIN)
     30   CloseHandle(file_handle);
     31 #else
     32   close(file_handle);
     33 #endif
     34 }
     35 
     36 bool WriteFile(PP_FileHandle file_handle, const std::string& contents) {
     37 #if defined(PPAPI_OS_WIN)
     38   DWORD bytes_written = 0;
     39   BOOL result = ::WriteFile(file_handle, contents.c_str(), contents.size(),
     40                             &bytes_written, NULL);
     41   return result && bytes_written == static_cast<DWORD>(contents.size());
     42 #else
     43   ssize_t bytes_written = 0;
     44   do {
     45     bytes_written = write(file_handle, contents.c_str(), contents.size());
     46   } while (bytes_written == -1 && errno == EINTR);
     47   return bytes_written == static_cast<ssize_t>(contents.size());
     48 #endif
     49 }
     50 
     51 bool ReadFile(PP_FileHandle file_handle, std::string* contents) {
     52   static const size_t kBufferSize = 1024;
     53   char* buffer = new char[kBufferSize];
     54   bool result = false;
     55   contents->clear();
     56 
     57 #if defined(PPAPI_OS_WIN)
     58   SetFilePointer(file_handle, 0, NULL, FILE_BEGIN);
     59   DWORD bytes_read = 0;
     60   do {
     61     result = !!::ReadFile(file_handle, buffer, kBufferSize, &bytes_read, NULL);
     62     if (result && bytes_read > 0)
     63       contents->append(buffer, bytes_read);
     64   } while (result && bytes_read > 0);
     65 #else
     66   lseek(file_handle, 0, SEEK_SET);
     67   ssize_t bytes_read = 0;
     68   do {
     69     do {
     70       bytes_read = read(file_handle, buffer, kBufferSize);
     71     } while (bytes_read == -1 && errno == EINTR);
     72     result = bytes_read != -1;
     73     if (bytes_read > 0)
     74       contents->append(buffer, bytes_read);
     75   } while (bytes_read > 0);
     76 #endif
     77 
     78   delete[] buffer;
     79   return result;
     80 }
     81 
     82 bool DirEntryEqual(FileModuleLocal::DirEntry i,
     83                    FileModuleLocal::DirEntry j) {
     84   return i.name == j.name && i.is_dir == j.is_dir;
     85 }
     86 
     87 bool DirEntryLessThan(FileModuleLocal::DirEntry i,
     88                       FileModuleLocal::DirEntry j) {
     89   if (i.name == j.name)
     90     return i.is_dir < j.is_dir;
     91   return i.name < j.name;
     92 }
     93 
     94 }  // namespace
     95 
     96 REGISTER_TEST_CASE(FlashFile);
     97 
     98 TestFlashFile::TestFlashFile(TestingInstance* instance)
     99     : TestCase(instance) {
    100 }
    101 
    102 TestFlashFile::~TestFlashFile() {
    103 }
    104 
    105 bool TestFlashFile::Init() {
    106   return FileModuleLocal::IsAvailable();
    107 }
    108 
    109 void TestFlashFile::RunTests(const std::string& filter) {
    110   RUN_TEST(OpenFile, filter);
    111   RUN_TEST(RenameFile, filter);
    112   RUN_TEST(DeleteFileOrDir, filter);
    113   RUN_TEST(CreateDir, filter);
    114   RUN_TEST(QueryFile, filter);
    115   RUN_TEST(GetDirContents, filter);
    116   RUN_TEST(CreateTemporaryFile, filter);
    117 }
    118 
    119 void TestFlashFile::SetUp() {
    120   // Clear out existing test data.
    121   FileModuleLocal::DeleteFileOrDir(instance_, std::string(), true);
    122   // Make sure that the root directory exists.
    123   FileModuleLocal::CreateDir(instance_, std::string());
    124 }
    125 
    126 std::string TestFlashFile::TestOpenFile() {
    127   SetUp();
    128   std::string filename = "abc.txt";
    129   PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
    130                                                         filename,
    131                                                         PP_FILEOPENFLAG_WRITE |
    132                                                         PP_FILEOPENFLAG_CREATE);
    133   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    134 
    135   std::string contents = "This is file.";
    136   std::string read_contents;
    137   ASSERT_TRUE(WriteFile(file_handle, contents));
    138   ASSERT_FALSE(ReadFile(file_handle, &read_contents));
    139   CloseFileHandle(file_handle);
    140 
    141   file_handle = FileModuleLocal::OpenFile(instance_,
    142                                           filename,
    143                                           PP_FILEOPENFLAG_READ);
    144   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    145 
    146   ASSERT_FALSE(WriteFile(file_handle, contents));
    147   ASSERT_TRUE(ReadFile(file_handle, &read_contents));
    148   ASSERT_EQ(contents, read_contents);
    149   CloseFileHandle(file_handle);
    150 
    151   PASS();
    152 }
    153 
    154 std::string TestFlashFile::TestRenameFile() {
    155   SetUp();
    156   std::string filename = "abc.txt";
    157   std::string new_filename = "abc_new.txt";
    158   std::string contents = "This is file.";
    159   std::string read_contents;
    160 
    161   PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
    162                                                         filename,
    163                                                         PP_FILEOPENFLAG_WRITE |
    164                                                         PP_FILEOPENFLAG_CREATE);
    165   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    166   ASSERT_TRUE(WriteFile(file_handle, contents));
    167   CloseFileHandle(file_handle);
    168 
    169   ASSERT_TRUE(FileModuleLocal::RenameFile(instance_, filename, new_filename));
    170 
    171   file_handle = FileModuleLocal::OpenFile(instance_,
    172                                           new_filename,
    173                                           PP_FILEOPENFLAG_READ);
    174   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    175   ASSERT_TRUE(ReadFile(file_handle, &read_contents));
    176   ASSERT_EQ(contents, read_contents);
    177   CloseFileHandle(file_handle);
    178 
    179   // Check that the old file no longer exists.
    180   PP_FileInfo unused;
    181   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
    182 
    183   PASS();
    184 }
    185 
    186 std::string TestFlashFile::TestDeleteFileOrDir() {
    187   SetUp();
    188   std::string filename = "abc.txt";
    189   std::string dirname = "def";
    190   std::string contents = "This is file.";
    191 
    192   // Test file deletion.
    193   PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
    194                                                         filename,
    195                                                         PP_FILEOPENFLAG_WRITE |
    196                                                         PP_FILEOPENFLAG_CREATE);
    197   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    198   ASSERT_TRUE(WriteFile(file_handle, contents));
    199   CloseFileHandle(file_handle);
    200   ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, filename, false));
    201   PP_FileInfo unused;
    202   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
    203 
    204   // Test directory deletion.
    205   ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
    206   ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, false));
    207   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, dirname, &unused));
    208 
    209   // Test recursive directory deletion.
    210   ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
    211   file_handle = FileModuleLocal::OpenFile(
    212       instance_, dirname + "/" + filename,
    213       PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE);
    214   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    215   ASSERT_TRUE(WriteFile(file_handle, contents));
    216   CloseFileHandle(file_handle);
    217   ASSERT_FALSE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, false));
    218   ASSERT_TRUE(FileModuleLocal::DeleteFileOrDir(instance_, dirname, true));
    219   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, filename, &unused));
    220 
    221   PASS();
    222 }
    223 
    224 std::string TestFlashFile::TestCreateDir() {
    225   SetUp();
    226   std::string dirname = "abc";
    227   PP_FileInfo info;
    228   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, dirname, &info));
    229   ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
    230   ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, dirname, &info));
    231   ASSERT_EQ(info.type, PP_FILETYPE_DIRECTORY);
    232 
    233   PASS();
    234 }
    235 
    236 std::string TestFlashFile::TestQueryFile() {
    237   std::string filename = "abc.txt";
    238   std::string dirname = "def";
    239   std::string contents = "This is file.";
    240   PP_FileInfo info;
    241 
    242   // Test querying a file.
    243   PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
    244                                                         filename,
    245                                                         PP_FILEOPENFLAG_WRITE |
    246                                                         PP_FILEOPENFLAG_CREATE);
    247   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    248   ASSERT_TRUE(WriteFile(file_handle, contents));
    249   CloseFileHandle(file_handle);
    250   ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, filename, &info));
    251   ASSERT_EQ(static_cast<size_t>(info.size), contents.size());
    252   ASSERT_EQ(info.type, PP_FILETYPE_REGULAR);
    253   // TODO(raymes): Test the other fields.
    254 
    255   // Test querying a directory.
    256   ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
    257   ASSERT_TRUE(FileModuleLocal::QueryFile(instance_, dirname, &info));
    258   ASSERT_EQ(info.type, PP_FILETYPE_DIRECTORY);
    259   // TODO(raymes): Test the other fields.
    260 
    261   // Test querying a non-existent file.
    262   ASSERT_FALSE(FileModuleLocal::QueryFile(instance_, "xx", &info));
    263 
    264   PASS();
    265 }
    266 
    267 std::string TestFlashFile::TestGetDirContents() {
    268   SetUp();
    269   std::vector<FileModuleLocal::DirEntry> result;
    270   ASSERT_TRUE(FileModuleLocal::GetDirContents(instance_, std::string(),
    271                                               &result));
    272   ASSERT_EQ(result.size(), 1);
    273   ASSERT_EQ(result[0].name, "..");
    274   ASSERT_EQ(result[0].is_dir, true);
    275 
    276   std::string filename = "abc.txt";
    277   std::string dirname = "def";
    278   std::string contents = "This is file.";
    279   PP_FileHandle file_handle = FileModuleLocal::OpenFile(instance_,
    280                                                         filename,
    281                                                         PP_FILEOPENFLAG_WRITE |
    282                                                         PP_FILEOPENFLAG_CREATE);
    283   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    284   ASSERT_TRUE(WriteFile(file_handle, contents));
    285   CloseFileHandle(file_handle);
    286   ASSERT_TRUE(FileModuleLocal::CreateDir(instance_, dirname));
    287 
    288   ASSERT_TRUE(
    289       FileModuleLocal::GetDirContents(instance_, std::string(), &result));
    290   FileModuleLocal::DirEntry expected[] = { { "..", true }, { filename, false },
    291                                            { dirname, true } };
    292   size_t expected_size = sizeof(expected) / sizeof(expected[0]);
    293 
    294   std::sort(expected, expected + expected_size, DirEntryLessThan);
    295   std::sort(result.begin(), result.end(), DirEntryLessThan);
    296 
    297   ASSERT_EQ(expected_size, result.size());
    298   ASSERT_TRUE(std::equal(expected, expected + expected_size, result.begin(),
    299                          DirEntryEqual));
    300 
    301   PASS();
    302 }
    303 
    304 std::string TestFlashFile::TestCreateTemporaryFile() {
    305   SetUp();
    306   size_t before_create = 0;
    307   ASSERT_SUBTEST_SUCCESS(GetItemCountUnderModuleLocalRoot(&before_create));
    308 
    309   PP_FileHandle file_handle = FileModuleLocal::CreateTemporaryFile(instance_);
    310   ASSERT_NE(PP_kInvalidFileHandle, file_handle);
    311 
    312   std::string contents = "This is a temp file.";
    313   ASSERT_TRUE(WriteFile(file_handle, contents));
    314   std::string read_contents;
    315   ASSERT_TRUE(ReadFile(file_handle, &read_contents));
    316   ASSERT_EQ(contents, read_contents);
    317 
    318   CloseFileHandle(file_handle);
    319 
    320   size_t after_close = 0;
    321   ASSERT_SUBTEST_SUCCESS(GetItemCountUnderModuleLocalRoot(&after_close));
    322   ASSERT_EQ(before_create, after_close);
    323 
    324   PASS();
    325 }
    326 
    327 std::string TestFlashFile::GetItemCountUnderModuleLocalRoot(
    328     size_t* item_count) {
    329   std::vector<FileModuleLocal::DirEntry> contents;
    330   ASSERT_TRUE(
    331       FileModuleLocal::GetDirContents(instance_, std::string(), &contents));
    332   *item_count = contents.size();
    333   PASS();
    334 }
    335