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 11using storage::CrackIsolatedFileSystemName; 12using storage::GetExternalFileSystemRootURIString; 13using storage::GetIsolatedFileSystemName; 14using storage::GetIsolatedFileSystemRootURIString; 15using storage::ValidateIsolatedFileSystemId; 16using storage::VirtualPath; 17 18namespace content { 19namespace { 20 21class FileSystemUtilTest : public testing::Test {}; 22 23TEST_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 39TEST_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 46TEST_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 53TEST_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 79TEST_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 119TEST_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 140TEST_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 147TEST_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 161TEST_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 217TEST_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 223TEST_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 235TEST_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 248TEST_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 285TEST_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 296TEST_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