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 "storage/common/fileapi/file_system_util.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 #include "url/gurl.h"
     10 
     11 using storage::CrackIsolatedFileSystemName;
     12 using storage::GetExternalFileSystemRootURIString;
     13 using storage::GetIsolatedFileSystemName;
     14 using storage::GetIsolatedFileSystemRootURIString;
     15 using storage::ValidateIsolatedFileSystemId;
     16 using storage::VirtualPath;
     17 
     18 namespace content {
     19 namespace {
     20 
     21 class FileSystemUtilTest : public testing::Test {};
     22 
     23 TEST_F(FileSystemUtilTest, ParseFileSystemSchemeURL) {
     24   GURL uri("filesystem:http://chromium.org/temporary/foo/bar");
     25   GURL origin_url;
     26   storage::FileSystemType type;
     27   base::FilePath virtual_path;
     28   ParseFileSystemSchemeURL(uri, &origin_url, &type, &virtual_path);
     29   EXPECT_EQ(GURL("http://chromium.org"), origin_url);
     30   EXPECT_EQ(storage::kFileSystemTypeTemporary, type);
     31 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
     32   base::FilePath expected_path(FILE_PATH_LITERAL("foo\\bar"));
     33 #else
     34   base::FilePath expected_path(FILE_PATH_LITERAL("foo/bar"));
     35 #endif
     36   EXPECT_EQ(expected_path, virtual_path);
     37 }
     38 
     39 TEST_F(FileSystemUtilTest, GetTempFileSystemRootURI) {
     40   GURL origin_url("http://chromium.org");
     41   storage::FileSystemType type = storage::kFileSystemTypeTemporary;
     42   GURL uri = GURL("filesystem:http://chromium.org/temporary/");
     43   EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
     44 }
     45 
     46 TEST_F(FileSystemUtilTest, GetPersistentFileSystemRootURI) {
     47   GURL origin_url("http://chromium.org");
     48   storage::FileSystemType type = storage::kFileSystemTypePersistent;
     49   GURL uri = GURL("filesystem:http://chromium.org/persistent/");
     50   EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
     51 }
     52 
     53 TEST_F(FileSystemUtilTest, VirtualPathBaseName) {
     54   struct test_data {
     55     const base::FilePath::StringType path;
     56     const base::FilePath::StringType base_name;
     57   } test_cases[] = {
     58     { FILE_PATH_LITERAL("foo/bar"), FILE_PATH_LITERAL("bar") },
     59     { FILE_PATH_LITERAL("foo/b:bar"), FILE_PATH_LITERAL("b:bar") },
     60     { FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("") },
     61     { FILE_PATH_LITERAL("/"), FILE_PATH_LITERAL("/") },
     62     { FILE_PATH_LITERAL("foo//////bar"), FILE_PATH_LITERAL("bar") },
     63     { FILE_PATH_LITERAL("foo/bar/"), FILE_PATH_LITERAL("bar") },
     64     { FILE_PATH_LITERAL("foo/bar/////"), FILE_PATH_LITERAL("bar") },
     65     { FILE_PATH_LITERAL("/bar/////"), FILE_PATH_LITERAL("bar") },
     66     { FILE_PATH_LITERAL("bar/////"), FILE_PATH_LITERAL("bar") },
     67     { FILE_PATH_LITERAL("bar/"), FILE_PATH_LITERAL("bar") },
     68     { FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("bar") },
     69     { FILE_PATH_LITERAL("////bar"), FILE_PATH_LITERAL("bar") },
     70     { FILE_PATH_LITERAL("bar"), FILE_PATH_LITERAL("bar") }
     71   };
     72   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
     73     base::FilePath input = base::FilePath(test_cases[i].path);
     74     base::FilePath base_name = VirtualPath::BaseName(input);
     75     EXPECT_EQ(test_cases[i].base_name, base_name.value());
     76   }
     77 }
     78 
     79 TEST_F(FileSystemUtilTest, VirtualPathDirName) {
     80   struct test_data {
     81     const base::FilePath::StringType path;
     82     const base::FilePath::StringType dir_name;
     83   } test_cases[] = {
     84     { FILE_PATH_LITERAL("foo/bar"), FILE_PATH_LITERAL("foo") },
     85     { FILE_PATH_LITERAL("foo/b:bar"), FILE_PATH_LITERAL("foo") },
     86     { FILE_PATH_LITERAL(""), FILE_PATH_LITERAL(".") },
     87     { FILE_PATH_LITERAL("/"), FILE_PATH_LITERAL("/") },
     88     { FILE_PATH_LITERAL("foo//////bar"), FILE_PATH_LITERAL("foo") },
     89     { FILE_PATH_LITERAL("foo/bar/"), FILE_PATH_LITERAL("foo") },
     90     { FILE_PATH_LITERAL("foo/bar/////"), FILE_PATH_LITERAL("foo") },
     91     { FILE_PATH_LITERAL("/bar/////"), FILE_PATH_LITERAL("/") },
     92     { FILE_PATH_LITERAL("bar/////"), FILE_PATH_LITERAL(".") },
     93     { FILE_PATH_LITERAL("bar/"), FILE_PATH_LITERAL(".") },
     94     { FILE_PATH_LITERAL("/bar"), FILE_PATH_LITERAL("/") },
     95     { FILE_PATH_LITERAL("////bar"), FILE_PATH_LITERAL("/") },
     96     { FILE_PATH_LITERAL("bar"), FILE_PATH_LITERAL(".") },
     97     { FILE_PATH_LITERAL("c:bar"), FILE_PATH_LITERAL(".") },
     98 #ifdef FILE_PATH_USES_WIN_SEPARATORS
     99     { FILE_PATH_LITERAL("foo\\bar"), FILE_PATH_LITERAL("foo") },
    100     { FILE_PATH_LITERAL("foo\\b:bar"), FILE_PATH_LITERAL("foo") },
    101     { FILE_PATH_LITERAL("\\"), FILE_PATH_LITERAL("\\") },
    102     { FILE_PATH_LITERAL("foo\\\\\\\\\\\\bar"), FILE_PATH_LITERAL("foo") },
    103     { FILE_PATH_LITERAL("foo\\bar\\"), FILE_PATH_LITERAL("foo") },
    104     { FILE_PATH_LITERAL("foo\\bar\\\\\\\\\\"), FILE_PATH_LITERAL("foo") },
    105     { FILE_PATH_LITERAL("\\bar\\\\\\\\\\"), FILE_PATH_LITERAL("\\") },
    106     { FILE_PATH_LITERAL("bar\\\\\\\\\\"), FILE_PATH_LITERAL(".") },
    107     { FILE_PATH_LITERAL("bar\\"), FILE_PATH_LITERAL(".") },
    108     { FILE_PATH_LITERAL("\\bar"), FILE_PATH_LITERAL("\\") },
    109     { FILE_PATH_LITERAL("\\\\\\\\bar"), FILE_PATH_LITERAL("\\") },
    110 #endif
    111   };
    112   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    113     base::FilePath input = base::FilePath(test_cases[i].path);
    114     base::FilePath dir_name = VirtualPath::DirName(input);
    115     EXPECT_EQ(test_cases[i].dir_name, dir_name.value());
    116   }
    117 }
    118 
    119 TEST_F(FileSystemUtilTest, GetNormalizedFilePath) {
    120   struct test_data {
    121     const base::FilePath::StringType path;
    122     const base::FilePath::StringType normalized_path;
    123   } test_cases[] = {
    124     { FILE_PATH_LITERAL(""), FILE_PATH_LITERAL("/") },
    125     { FILE_PATH_LITERAL("/"), FILE_PATH_LITERAL("/") },
    126     { FILE_PATH_LITERAL("foo/bar"), FILE_PATH_LITERAL("/foo/bar") },
    127     { FILE_PATH_LITERAL("/foo/bar"), FILE_PATH_LITERAL("/foo/bar") },
    128 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
    129     { FILE_PATH_LITERAL("\\foo"), FILE_PATH_LITERAL("/foo") },
    130 #endif
    131   };
    132   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    133     base::FilePath input = base::FilePath(test_cases[i].path);
    134     base::FilePath::StringType normalized_path_string =
    135         VirtualPath::GetNormalizedFilePath(input);
    136     EXPECT_EQ(test_cases[i].normalized_path, normalized_path_string);
    137   }
    138 }
    139 
    140 TEST_F(FileSystemUtilTest, IsAbsolutePath) {
    141   EXPECT_TRUE(VirtualPath::IsAbsolute(FILE_PATH_LITERAL("/")));
    142   EXPECT_TRUE(VirtualPath::IsAbsolute(FILE_PATH_LITERAL("/foo/bar")));
    143   EXPECT_FALSE(VirtualPath::IsAbsolute(base::FilePath::StringType()));
    144   EXPECT_FALSE(VirtualPath::IsAbsolute(FILE_PATH_LITERAL("foo/bar")));
    145 }
    146 
    147 TEST_F(FileSystemUtilTest, IsRootPath) {
    148   EXPECT_TRUE(VirtualPath::IsRootPath(base::FilePath(FILE_PATH_LITERAL(""))));
    149   EXPECT_TRUE(VirtualPath::IsRootPath(base::FilePath()));
    150   EXPECT_TRUE(VirtualPath::IsRootPath(base::FilePath(FILE_PATH_LITERAL("/"))));
    151   EXPECT_TRUE(VirtualPath::IsRootPath(base::FilePath(FILE_PATH_LITERAL("//"))));
    152   EXPECT_FALSE(VirtualPath::IsRootPath(
    153       base::FilePath(FILE_PATH_LITERAL("c:/"))));
    154 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
    155   EXPECT_TRUE(VirtualPath::IsRootPath(base::FilePath(FILE_PATH_LITERAL("\\"))));
    156   EXPECT_FALSE(VirtualPath::IsRootPath(
    157       base::FilePath(FILE_PATH_LITERAL("c:\\"))));
    158 #endif
    159 }
    160 
    161 TEST_F(FileSystemUtilTest, VirtualPathGetComponents) {
    162   struct test_data {
    163     const base::FilePath::StringType path;
    164     size_t count;
    165     const base::FilePath::StringType components[2];
    166   } test_cases[] = {
    167     { FILE_PATH_LITERAL("foo/bar"),
    168       2,
    169       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("bar") } },
    170     { FILE_PATH_LITERAL("foo"),
    171       1,
    172       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("") } },
    173     { FILE_PATH_LITERAL("foo////bar"),
    174       2,
    175       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("bar") } },
    176     { FILE_PATH_LITERAL("foo/c:bar"),
    177       2,
    178       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("c:bar") } },
    179     { FILE_PATH_LITERAL("c:foo/bar"),
    180       2,
    181       { FILE_PATH_LITERAL("c:foo"), FILE_PATH_LITERAL("bar") } },
    182     { FILE_PATH_LITERAL("foo/bar"),
    183       2,
    184       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("bar") } },
    185     { FILE_PATH_LITERAL("/foo/bar"),
    186       2,
    187       { FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("bar") } },
    188     { FILE_PATH_LITERAL("c:/bar"),
    189       2,
    190       { FILE_PATH_LITERAL("c:"), FILE_PATH_LITERAL("bar") } },
    191 #ifdef FILE_PATH_USES_WIN_SEPARATORS
    192     { FILE_PATH_LITERAL("c:\\bar"),
    193       2,
    194       { FILE_PATH_LITERAL("c:"), FILE_PATH_LITERAL("bar") } },
    195 #endif
    196   };
    197   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    198     base::FilePath input = base::FilePath(test_cases[i].path);
    199     std::vector<base::FilePath::StringType> components;
    200     VirtualPath::GetComponents(input, &components);
    201     EXPECT_EQ(test_cases[i].count, components.size());
    202     for (size_t j = 0; j < components.size(); ++j)
    203       EXPECT_EQ(test_cases[i].components[j], components[j]);
    204   }
    205   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    206     base::FilePath input = base::FilePath(test_cases[i].path);
    207     std::vector<std::string> components;
    208     VirtualPath::GetComponentsUTF8Unsafe(input, &components);
    209     EXPECT_EQ(test_cases[i].count, components.size());
    210     for (size_t j = 0; j < components.size(); ++j) {
    211       EXPECT_EQ(base::FilePath(test_cases[i].components[j]).AsUTF8Unsafe(),
    212                 components[j]);
    213     }
    214   }
    215 }
    216 
    217 TEST_F(FileSystemUtilTest, GetIsolatedFileSystemName) {
    218   GURL origin_url("http://foo");
    219   std::string fsname1 = GetIsolatedFileSystemName(origin_url, "bar");
    220   EXPECT_EQ("http_foo_0:Isolated_bar", fsname1);
    221 }
    222 
    223 TEST_F(FileSystemUtilTest, CrackIsolatedFileSystemName) {
    224   std::string fsid;
    225   EXPECT_TRUE(CrackIsolatedFileSystemName("foo:Isolated_bar", &fsid));
    226   EXPECT_EQ("bar", fsid);
    227   EXPECT_TRUE(CrackIsolatedFileSystemName("foo:isolated_bar", &fsid));
    228   EXPECT_EQ("bar", fsid);
    229   EXPECT_TRUE(CrackIsolatedFileSystemName("foo:Isolated__bar", &fsid));
    230   EXPECT_EQ("_bar", fsid);
    231   EXPECT_TRUE(CrackIsolatedFileSystemName("foo::Isolated_bar", &fsid));
    232   EXPECT_EQ("bar", fsid);
    233 }
    234 
    235 TEST_F(FileSystemUtilTest, RejectBadIsolatedFileSystemName) {
    236   std::string fsid;
    237   EXPECT_FALSE(CrackIsolatedFileSystemName("foobar", &fsid));
    238   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:_bar", &fsid));
    239   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Isolatedbar", &fsid));
    240   EXPECT_FALSE(CrackIsolatedFileSystemName("fooIsolatedbar", &fsid));
    241   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Persistent", &fsid));
    242   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Temporary", &fsid));
    243   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:External", &fsid));
    244   EXPECT_FALSE(CrackIsolatedFileSystemName(":Isolated_bar", &fsid));
    245   EXPECT_FALSE(CrackIsolatedFileSystemName("foo:Isolated_", &fsid));
    246 }
    247 
    248 TEST_F(FileSystemUtilTest, ValidateIsolatedFileSystemId) {
    249   EXPECT_TRUE(ValidateIsolatedFileSystemId("ABCDEF0123456789ABCDEF0123456789"));
    250   EXPECT_TRUE(ValidateIsolatedFileSystemId("ABCDEFABCDEFABCDEFABCDEFABCDEFAB"));
    251   EXPECT_TRUE(ValidateIsolatedFileSystemId("01234567890123456789012345678901"));
    252 
    253   const size_t kExpectedFileSystemIdSize = 32;
    254 
    255   // Should not contain lowercase characters.
    256   const std::string kLowercaseId = "abcdef0123456789abcdef0123456789";
    257   EXPECT_EQ(kExpectedFileSystemIdSize, kLowercaseId.size());
    258   EXPECT_FALSE(ValidateIsolatedFileSystemId(kLowercaseId));
    259 
    260   // Should not be shorter/longer than expected.
    261   EXPECT_FALSE(ValidateIsolatedFileSystemId(std::string()));
    262 
    263   const std::string kShorterId = "ABCDEF0123456789ABCDEF";
    264   EXPECT_GT(kExpectedFileSystemIdSize, kShorterId.size());
    265   EXPECT_FALSE(ValidateIsolatedFileSystemId(kShorterId));
    266 
    267   const std::string kLongerId = "ABCDEF0123456789ABCDEF0123456789ABCDEF";
    268   EXPECT_LT(kExpectedFileSystemIdSize, kLongerId.size());
    269   EXPECT_FALSE(ValidateIsolatedFileSystemId(kLongerId));
    270 
    271   // Should not contain not alphabetical nor numerical characters.
    272   const std::string kSlashId = "ABCD/EFGH/IJKL/MNOP/QRST/UVWX/YZ";
    273   EXPECT_EQ(kExpectedFileSystemIdSize, kSlashId.size());
    274   EXPECT_FALSE(ValidateIsolatedFileSystemId(kSlashId));
    275 
    276   const std::string kBackslashId = "ABCD\\EFGH\\IJKL\\MNOP\\QRST\\UVWX\\YZ";
    277   EXPECT_EQ(kExpectedFileSystemIdSize, kBackslashId.size());
    278   EXPECT_FALSE(ValidateIsolatedFileSystemId(kBackslashId));
    279 
    280   const std::string kSpaceId = "ABCD EFGH IJKL MNOP QRST UVWX YZ";
    281   EXPECT_EQ(kExpectedFileSystemIdSize, kSpaceId.size());
    282   EXPECT_FALSE(ValidateIsolatedFileSystemId(kSpaceId));
    283 }
    284 
    285 TEST_F(FileSystemUtilTest, GetIsolatedFileSystemRootURIString) {
    286   const GURL kOriginURL("http://foo");
    287   // Percents must be escaped, otherwise they will be unintentionally unescaped.
    288   const std::string kFileSystemId = "A%20B";
    289   const std::string kRootName = "C%20D";
    290 
    291   const std::string url_string =
    292       GetIsolatedFileSystemRootURIString(kOriginURL, kFileSystemId, kRootName);
    293   EXPECT_EQ("filesystem:http://foo/isolated/A%2520B/C%2520D/", url_string);
    294 }
    295 
    296 TEST_F(FileSystemUtilTest, GetExternalFileSystemRootURIString) {
    297   const GURL kOriginURL("http://foo");
    298   // Percents must be escaped, otherwise they will be unintentionally unescaped.
    299   const std::string kMountName = "X%20Y";
    300 
    301   const std::string url_string =
    302       GetExternalFileSystemRootURIString(kOriginURL, kMountName);
    303   EXPECT_EQ("filesystem:http://foo/external/X%2520Y/", url_string);
    304 }
    305 
    306 }  // namespace
    307 }  // namespace content
    308