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