blob: 3a4962d62b960fd644ef6c87fc13df7c44f19472 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 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.
initial.commit3f4a7322008-07-27 06:49:38 +09004
erikkay@google.comc8ec9e92008-08-16 02:50:10 +09005#include "build/build_config.h"
6
erikkay@google.com014161d2008-08-16 02:45:13 +09007#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +09008#include <windows.h>
initial.commit3f4a7322008-07-27 06:49:38 +09009#include <shellapi.h>
10#include <shlobj.h>
erikkay@google.comdfb51b22008-08-16 02:32:10 +090011#endif
initial.commit3f4a7322008-07-27 06:49:38 +090012
13#include <fstream>
14#include <iostream>
erikkay@google.comdfb51b22008-08-16 02:32:10 +090015#include <set>
initial.commit3f4a7322008-07-27 06:49:38 +090016
17#include "base/base_paths.h"
evanm@google.com874d1672008-10-31 08:54:04 +090018#include "base/file_path.h"
initial.commit3f4a7322008-07-27 06:49:38 +090019#include "base/file_util.h"
20#include "base/logging.h"
21#include "base/path_service.h"
22#include "base/string_util.h"
23#include "testing/gtest/include/gtest/gtest.h"
jeremy@chromium.org0d8eba72008-12-03 04:20:15 +090024#include "testing/platform_test.h"
initial.commit3f4a7322008-07-27 06:49:38 +090025
26namespace {
27
erikkay@google.comf2406842008-08-21 00:59:49 +090028// file_util winds up using autoreleased objects on the Mac, so this needs
29// to be a PlatformTest
30class FileUtilTest : public PlatformTest {
initial.commit3f4a7322008-07-27 06:49:38 +090031 protected:
32 virtual void SetUp() {
erikkay@google.comf2406842008-08-21 00:59:49 +090033 PlatformTest::SetUp();
initial.commit3f4a7322008-07-27 06:49:38 +090034 // Name a subdirectory of the temp directory.
35 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
evanm@google.com874d1672008-10-31 08:54:04 +090036 test_dir_ = test_dir_.Append(FILE_PATH_LITERAL("FileUtilTest"));
initial.commit3f4a7322008-07-27 06:49:38 +090037
38 // Create a fresh, empty copy of this directory.
39 file_util::Delete(test_dir_, true);
evanm@google.com874d1672008-10-31 08:54:04 +090040 file_util::CreateDirectory(test_dir_);
initial.commit3f4a7322008-07-27 06:49:38 +090041 }
42 virtual void TearDown() {
erikkay@google.comf2406842008-08-21 00:59:49 +090043 PlatformTest::TearDown();
initial.commit3f4a7322008-07-27 06:49:38 +090044 // Clean up test directory
erikkay@google.comdfb51b22008-08-16 02:32:10 +090045 ASSERT_TRUE(file_util::Delete(test_dir_, true));
initial.commit3f4a7322008-07-27 06:49:38 +090046 ASSERT_FALSE(file_util::PathExists(test_dir_));
47 }
48
49 // the path to temporary directory used to contain the test operations
evanm@google.com874d1672008-10-31 08:54:04 +090050 FilePath test_dir_;
initial.commit3f4a7322008-07-27 06:49:38 +090051};
52
53// Collects all the results from the given file enumerator, and provides an
54// interface to query whether a given file is present.
55class FindResultCollector {
56 public:
57 FindResultCollector(file_util::FileEnumerator& enumerator) {
58 std::wstring cur_file;
59 while (!(cur_file = enumerator.Next()).empty()) {
evanm@google.com874d1672008-10-31 08:54:04 +090060 FilePath::StringType path = FilePath::FromWStringHack(cur_file).value();
initial.commit3f4a7322008-07-27 06:49:38 +090061 // The file should not be returned twice.
evanm@google.com874d1672008-10-31 08:54:04 +090062 EXPECT_TRUE(files_.end() == files_.find(path))
initial.commit3f4a7322008-07-27 06:49:38 +090063 << "Same file returned twice";
64
65 // Save for later.
evanm@google.com874d1672008-10-31 08:54:04 +090066 files_.insert(path);
initial.commit3f4a7322008-07-27 06:49:38 +090067 }
68 }
69
70 // Returns true if the enumerator found the file.
evanm@google.com874d1672008-10-31 08:54:04 +090071 bool HasFile(const FilePath& file) const {
72 return files_.find(file.value()) != files_.end();
initial.commit3f4a7322008-07-27 06:49:38 +090073 }
evanm@google.com874d1672008-10-31 08:54:04 +090074
erikkay@google.comdfb51b22008-08-16 02:32:10 +090075 int size() {
erikkay@google.comc8ec9e92008-08-16 02:50:10 +090076 return static_cast<int>(files_.size());
erikkay@google.comdfb51b22008-08-16 02:32:10 +090077 }
initial.commit3f4a7322008-07-27 06:49:38 +090078
79 private:
evanm@google.com874d1672008-10-31 08:54:04 +090080 std::set<FilePath::StringType> files_;
initial.commit3f4a7322008-07-27 06:49:38 +090081};
82
83// Simple function to dump some text into a new file.
evanm@google.com874d1672008-10-31 08:54:04 +090084void CreateTextFile(const FilePath& filename,
initial.commit3f4a7322008-07-27 06:49:38 +090085 const std::wstring& contents) {
86 std::ofstream file;
evanm@google.com874d1672008-10-31 08:54:04 +090087 file.open(WideToUTF8(filename.ToWStringHack()).c_str());
initial.commit3f4a7322008-07-27 06:49:38 +090088 ASSERT_TRUE(file.is_open());
89 file << contents;
90 file.close();
91}
92
93// Simple function to take out some text from a file.
evanm@google.com874d1672008-10-31 08:54:04 +090094std::wstring ReadTextFile(const FilePath& filename) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +090095 wchar_t contents[64];
initial.commit3f4a7322008-07-27 06:49:38 +090096 std::wifstream file;
evanm@google.com874d1672008-10-31 08:54:04 +090097 file.open(WideToUTF8(filename.ToWStringHack()).c_str());
initial.commit3f4a7322008-07-27 06:49:38 +090098 EXPECT_TRUE(file.is_open());
99 file.getline(contents, 64);
100 file.close();
101 return std::wstring(contents);
102}
103
erikkay@google.com014161d2008-08-16 02:45:13 +0900104#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900105uint64 FileTimeAsUint64(const FILETIME& ft) {
106 ULARGE_INTEGER u;
107 u.LowPart = ft.dwLowDateTime;
108 u.HighPart = ft.dwHighDateTime;
109 return u.QuadPart;
110}
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900111#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900112
113const struct append_case {
114 const wchar_t* path;
115 const wchar_t* ending;
116 const wchar_t* result;
117} append_cases[] = {
erikkay@google.com014161d2008-08-16 02:45:13 +0900118#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900119 {L"c:\\colon\\backslash", L"path", L"c:\\colon\\backslash\\path"},
120 {L"c:\\colon\\backslash\\", L"path", L"c:\\colon\\backslash\\path"},
121 {L"c:\\colon\\backslash\\\\", L"path", L"c:\\colon\\backslash\\\\path"},
122 {L"c:\\colon\\backslash\\", L"", L"c:\\colon\\backslash\\"},
123 {L"c:\\colon\\backslash", L"", L"c:\\colon\\backslash\\"},
124 {L"", L"path", L"\\path"},
125 {L"", L"", L"\\"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900126#elif defined(OS_POSIX)
127 {L"/foo/bar", L"path", L"/foo/bar/path"},
128 {L"/foo/bar/", L"path", L"/foo/bar/path"},
129 {L"/foo/bar//", L"path", L"/foo/bar//path"},
130 {L"/foo/bar/", L"", L"/foo/bar/"},
131 {L"/foo/bar", L"", L"/foo/bar/"},
132 {L"", L"path", L"/path"},
133 {L"", L"", L"/"},
134#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900135};
136
initial.commit3f4a7322008-07-27 06:49:38 +0900137TEST_F(FileUtilTest, AppendToPath) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900138 for (unsigned int i = 0; i < arraysize(append_cases); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900139 const append_case& value = append_cases[i];
140 std::wstring result = value.path;
141 file_util::AppendToPath(&result, value.ending);
142 EXPECT_EQ(value.result, result);
143 }
144
145#ifdef NDEBUG
146 file_util::AppendToPath(NULL, L"path"); // asserts in debug mode
147#endif
148}
149
estade@chromium.org97e37822008-11-27 13:03:57 +0900150// TODO(port): enable this test for non-Windows.
151#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900152static const struct InsertBeforeExtensionCase {
153 std::wstring path;
154 std::wstring suffix;
155 std::wstring result;
156} kInsertBeforeExtension[] = {
157 {L"", L"", L""},
158 {L"", L"txt", L"txt"},
159 {L".", L"txt", L"txt."},
160 {L".", L"", L"."},
161 {L"foo.dll", L"txt", L"footxt.dll"},
162 {L"foo.dll", L".txt", L"foo.txt.dll"},
163 {L"foo", L"txt", L"footxt"},
164 {L"foo", L".txt", L"foo.txt"},
165 {L"foo.baz.dll", L"txt", L"foo.baztxt.dll"},
166 {L"foo.baz.dll", L".txt", L"foo.baz.txt.dll"},
167 {L"foo.dll", L"", L"foo.dll"},
168 {L"foo.dll", L".", L"foo..dll"},
169 {L"foo", L"", L"foo"},
170 {L"foo", L".", L"foo."},
171 {L"foo.baz.dll", L"", L"foo.baz.dll"},
172 {L"foo.baz.dll", L".", L"foo.baz..dll"},
erikkay@google.com014161d2008-08-16 02:45:13 +0900173#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900174 {L"\\", L"", L"\\"},
175 {L"\\", L"txt", L"\\txt"},
176 {L"\\.", L"txt", L"\\txt."},
177 {L"\\.", L"", L"\\."},
178 {L"C:\\bar\\foo.dll", L"txt", L"C:\\bar\\footxt.dll"},
179 {L"C:\\bar.baz\\foodll", L"txt", L"C:\\bar.baz\\foodlltxt"},
180 {L"C:\\bar.baz\\foo.dll", L"txt", L"C:\\bar.baz\\footxt.dll"},
181 {L"C:\\bar.baz\\foo.dll.exe", L"txt", L"C:\\bar.baz\\foo.dlltxt.exe"},
182 {L"C:\\bar.baz\\foo", L"", L"C:\\bar.baz\\foo"},
183 {L"C:\\bar.baz\\foo.exe", L"", L"C:\\bar.baz\\foo.exe"},
184 {L"C:\\bar.baz\\foo.dll.exe", L"", L"C:\\bar.baz\\foo.dll.exe"},
185 {L"C:\\bar\\baz\\foo.exe", L" (1)", L"C:\\bar\\baz\\foo (1).exe"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900186#elif defined(OS_POSIX)
187 {L"/", L"", L"/"},
188 {L"/", L"txt", L"/txt"},
189 {L"/.", L"txt", L"/txt."},
190 {L"/.", L"", L"/."},
191 {L"/bar/foo.dll", L"txt", L"/bar/footxt.dll"},
192 {L"/bar.baz/foodll", L"txt", L"/bar.baz/foodlltxt"},
193 {L"/bar.baz/foo.dll", L"txt", L"/bar.baz/footxt.dll"},
194 {L"/bar.baz/foo.dll.exe", L"txt", L"/bar.baz/foo.dlltxt.exe"},
195 {L"/bar.baz/foo", L"", L"/bar.baz/foo"},
196 {L"/bar.baz/foo.exe", L"", L"/bar.baz/foo.exe"},
197 {L"/bar.baz/foo.dll.exe", L"", L"/bar.baz/foo.dll.exe"},
198 {L"/bar/baz/foo.exe", L" (1)", L"/bar/baz/foo (1).exe"},
199#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900200};
201
202TEST_F(FileUtilTest, InsertBeforeExtensionTest) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900203 for (unsigned int i = 0; i < arraysize(kInsertBeforeExtension); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900204 std::wstring path(kInsertBeforeExtension[i].path);
205 file_util::InsertBeforeExtension(&path, kInsertBeforeExtension[i].suffix);
206 EXPECT_EQ(path, kInsertBeforeExtension[i].result);
207 }
208}
estade@chromium.org97e37822008-11-27 13:03:57 +0900209#endif // defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900210
211static const struct filename_case {
212 const wchar_t* path;
213 const wchar_t* filename;
214} filename_cases[] = {
erikkay@google.com014161d2008-08-16 02:45:13 +0900215#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900216 {L"c:\\colon\\backslash", L"backslash"},
217 {L"c:\\colon\\backslash\\", L""},
218 {L"\\\\filename.exe", L"filename.exe"},
219 {L"filename.exe", L"filename.exe"},
220 {L"", L""},
221 {L"\\\\\\", L""},
222 {L"c:/colon/backslash", L"backslash"},
223 {L"c:/colon/backslash/", L""},
224 {L"//////", L""},
225 {L"///filename.exe", L"filename.exe"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900226#elif defined(OS_POSIX)
227 {L"/foo/bar", L"bar"},
228 {L"/foo/bar/", L""},
229 {L"/filename.exe", L"filename.exe"},
230 {L"filename.exe", L"filename.exe"},
231 {L"", L""},
232 {L"/", L""},
233#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900234};
235
236TEST_F(FileUtilTest, GetFilenameFromPath) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900237 for (unsigned int i = 0; i < arraysize(filename_cases); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900238 const filename_case& value = filename_cases[i];
239 std::wstring result = file_util::GetFilenameFromPath(value.path);
240 EXPECT_EQ(value.filename, result);
241 }
242}
243
244// Test finding the file type from a path name
245static const struct extension_case {
246 const wchar_t* path;
247 const wchar_t* extension;
248} extension_cases[] = {
erikkay@google.com014161d2008-08-16 02:45:13 +0900249#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900250 {L"C:\\colon\\backslash\\filename.extension", L"extension"},
251 {L"C:\\colon\\backslash\\filename.", L""},
252 {L"C:\\colon\\backslash\\filename", L""},
253 {L"C:\\colon\\backslash\\", L""},
254 {L"C:\\colon\\backslash.\\", L""},
255 {L"C:\\colon\\backslash\filename.extension.extension2", L"extension2"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900256#elif defined(OS_POSIX)
257 {L"/foo/bar/filename.extension", L"extension"},
258 {L"/foo/bar/filename.", L""},
259 {L"/foo/bar/filename", L""},
260 {L"/foo/bar/", L""},
261 {L"/foo/bar./", L""},
262 {L"/foo/bar/filename.extension.extension2", L"extension2"},
263 {L".", L""},
264 {L"..", L""},
265 {L"./foo", L""},
266 {L"./foo.extension", L"extension"},
267 {L"/foo.extension1/bar.extension2", L"extension2"},
268#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900269};
270
271TEST_F(FileUtilTest, GetFileExtensionFromPath) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900272 for (unsigned int i = 0; i < arraysize(extension_cases); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900273 const extension_case& ext = extension_cases[i];
274 const std::wstring fext = file_util::GetFileExtensionFromPath(ext.path);
275 EXPECT_EQ(ext.extension, fext);
276 }
277}
278
279// Test finding the directory component of a path
280static const struct dir_case {
281 const wchar_t* full_path;
282 const wchar_t* directory;
283} dir_cases[] = {
erikkay@google.com014161d2008-08-16 02:45:13 +0900284#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900285 {L"C:\\WINDOWS\\system32\\gdi32.dll", L"C:\\WINDOWS\\system32"},
286 {L"C:\\WINDOWS\\system32\\not_exist_thx_1138", L"C:\\WINDOWS\\system32"},
287 {L"C:\\WINDOWS\\system32\\", L"C:\\WINDOWS\\system32"},
288 {L"C:\\WINDOWS\\system32\\\\", L"C:\\WINDOWS\\system32"},
289 {L"C:\\WINDOWS\\system32", L"C:\\WINDOWS"},
290 {L"C:\\WINDOWS\\system32.\\", L"C:\\WINDOWS\\system32."},
291 {L"C:\\", L"C:"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900292#elif defined(OS_POSIX)
293 {L"/foo/bar/gdi32.dll", L"/foo/bar"},
294 {L"/foo/bar/not_exist_thx_1138", L"/foo/bar"},
295 {L"/foo/bar/", L"/foo/bar"},
296 {L"/foo/bar//", L"/foo/bar"},
297 {L"/foo/bar", L"/foo"},
298 {L"/foo/bar./", L"/foo/bar."},
299 {L"/", L"/"},
300 {L".", L"."},
301 {L"..", L"."}, // yes, ".." technically lives in "."
302#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900303};
304
305TEST_F(FileUtilTest, GetDirectoryFromPath) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900306 for (unsigned int i = 0; i < arraysize(dir_cases); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900307 const dir_case& dir = dir_cases[i];
308 const std::wstring parent =
309 file_util::GetDirectoryFromPath(dir.full_path);
310 EXPECT_EQ(dir.directory, parent);
311 }
312}
313
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900314// TODO(erikkay): implement
erikkay@google.com014161d2008-08-16 02:45:13 +0900315#if defined OS_WIN
initial.commit3f4a7322008-07-27 06:49:38 +0900316TEST_F(FileUtilTest, CountFilesCreatedAfter) {
317 // Create old file (that we don't want to count)
evanm@google.com874d1672008-10-31 08:54:04 +0900318 FilePath old_file_name = test_dir_.Append(L"Old File.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900319 CreateTextFile(old_file_name, L"Just call me Mr. Creakybits");
320
321 // Age to perfection
322 Sleep(100);
323
324 // Establish our cutoff time
325 FILETIME test_start_time;
326 GetSystemTimeAsFileTime(&test_start_time);
evanm@google.com874d1672008-10-31 08:54:04 +0900327 EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_.value(),
328 test_start_time));
initial.commit3f4a7322008-07-27 06:49:38 +0900329
330 // Create a new file (that we do want to count)
evanm@google.com874d1672008-10-31 08:54:04 +0900331 FilePath new_file_name = test_dir_.Append(L"New File.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900332 CreateTextFile(new_file_name, L"Waaaaaaaaaaaaaah.");
333
334 // We should see only the new file.
evanm@google.com874d1672008-10-31 08:54:04 +0900335 EXPECT_EQ(1, file_util::CountFilesCreatedAfter(test_dir_.value(),
336 test_start_time));
initial.commit3f4a7322008-07-27 06:49:38 +0900337
338 // Delete new file, we should see no files after cutoff now
339 EXPECT_TRUE(file_util::Delete(new_file_name, false));
evanm@google.com874d1672008-10-31 08:54:04 +0900340 EXPECT_EQ(0, file_util::CountFilesCreatedAfter(test_dir_.value(),
341 test_start_time));
initial.commit3f4a7322008-07-27 06:49:38 +0900342}
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900343#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900344
345// Tests that the Delete function works as expected, especially
346// the recursion flag. Also coincidentally tests PathExists.
347TEST_F(FileUtilTest, Delete) {
348 // Create a file
evanm@google.com874d1672008-10-31 08:54:04 +0900349 FilePath file_name = test_dir_.Append(FILE_PATH_LITERAL("Test File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900350 CreateTextFile(file_name, L"I'm cannon fodder.");
351
352 ASSERT_TRUE(file_util::PathExists(file_name));
353
evanm@google.com874d1672008-10-31 08:54:04 +0900354 FilePath subdir_path = test_dir_.Append(FILE_PATH_LITERAL("Subdirectory"));
355 file_util::CreateDirectory(subdir_path);
initial.commit3f4a7322008-07-27 06:49:38 +0900356
357 ASSERT_TRUE(file_util::PathExists(subdir_path));
358
evanm@google.com874d1672008-10-31 08:54:04 +0900359 FilePath directory_contents = test_dir_;
erikkay@google.com014161d2008-08-16 02:45:13 +0900360#if defined(OS_WIN)
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900361 // TODO(erikkay): see if anyone's actually using this feature of the API
evanm@google.com874d1672008-10-31 08:54:04 +0900362 directory_contents = directory_contents.Append(FILE_PATH_LITERAL("*"));
initial.commit3f4a7322008-07-27 06:49:38 +0900363 // Delete non-recursively and check that only the file is deleted
364 ASSERT_TRUE(file_util::Delete(directory_contents, false));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900365 EXPECT_FALSE(file_util::PathExists(file_name));
366 EXPECT_TRUE(file_util::PathExists(subdir_path));
367#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900368
369 // Delete recursively and make sure all contents are deleted
370 ASSERT_TRUE(file_util::Delete(directory_contents, true));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900371 EXPECT_FALSE(file_util::PathExists(file_name));
372 EXPECT_FALSE(file_util::PathExists(subdir_path));
initial.commit3f4a7322008-07-27 06:49:38 +0900373}
374
375TEST_F(FileUtilTest, Move) {
376 // Create a directory
evanm@google.com874d1672008-10-31 08:54:04 +0900377 FilePath dir_name_from =
378 test_dir_.Append(FILE_PATH_LITERAL("Move_From_Subdir"));
379 file_util::CreateDirectory(dir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900380 ASSERT_TRUE(file_util::PathExists(dir_name_from));
381
382 // Create a file under the directory
evanm@google.com874d1672008-10-31 08:54:04 +0900383 FilePath file_name_from =
384 dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900385 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
386 ASSERT_TRUE(file_util::PathExists(file_name_from));
387
388 // Move the directory
evanm@google.com874d1672008-10-31 08:54:04 +0900389 FilePath dir_name_to = test_dir_.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
390 FilePath file_name_to =
391 dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900392
393 ASSERT_FALSE(file_util::PathExists(dir_name_to));
394
395 EXPECT_TRUE(file_util::Move(dir_name_from, dir_name_to));
396
397 // Check everything has been moved.
398 EXPECT_FALSE(file_util::PathExists(dir_name_from));
399 EXPECT_FALSE(file_util::PathExists(file_name_from));
400 EXPECT_TRUE(file_util::PathExists(dir_name_to));
401 EXPECT_TRUE(file_util::PathExists(file_name_to));
402}
403
404TEST_F(FileUtilTest, CopyDirectoryRecursively) {
405 // Create a directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900406 FilePath dir_name_from =
407 test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
408 file_util::CreateDirectory(dir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900409 ASSERT_TRUE(file_util::PathExists(dir_name_from));
410
411 // Create a file under the directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900412 FilePath file_name_from =
413 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900414 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
415 ASSERT_TRUE(file_util::PathExists(file_name_from));
416
417 // Create a subdirectory.
evanm@google.com874d1672008-10-31 08:54:04 +0900418 FilePath subdir_name_from =
419 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
420 file_util::CreateDirectory(subdir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900421 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
422
423 // Create a file under the subdirectory.
evanm@google.com874d1672008-10-31 08:54:04 +0900424 FilePath file_name2_from =
425 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900426 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
427 ASSERT_TRUE(file_util::PathExists(file_name2_from));
428
429 // Copy the directory recursively.
evanm@google.com874d1672008-10-31 08:54:04 +0900430 FilePath dir_name_to =
431 test_dir_.Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
432 FilePath file_name_to =
433 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
434 FilePath subdir_name_to =
435 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
436 FilePath file_name2_to =
437 subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900438
439 ASSERT_FALSE(file_util::PathExists(dir_name_to));
440
441 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_to, true));
442
443 // Check everything has been copied.
444 EXPECT_TRUE(file_util::PathExists(dir_name_from));
445 EXPECT_TRUE(file_util::PathExists(file_name_from));
446 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
447 EXPECT_TRUE(file_util::PathExists(file_name2_from));
448 EXPECT_TRUE(file_util::PathExists(dir_name_to));
449 EXPECT_TRUE(file_util::PathExists(file_name_to));
450 EXPECT_TRUE(file_util::PathExists(subdir_name_to));
451 EXPECT_TRUE(file_util::PathExists(file_name2_to));
452}
453
454TEST_F(FileUtilTest, CopyDirectory) {
455 // Create a directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900456 FilePath dir_name_from =
457 test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
458 file_util::CreateDirectory(dir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900459 ASSERT_TRUE(file_util::PathExists(dir_name_from));
460
461 // Create a file under the directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900462 FilePath file_name_from =
463 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900464 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
465 ASSERT_TRUE(file_util::PathExists(file_name_from));
466
467 // Create a subdirectory.
evanm@google.com874d1672008-10-31 08:54:04 +0900468 FilePath subdir_name_from =
469 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
470 file_util::CreateDirectory(subdir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900471 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
472
473 // Create a file under the subdirectory.
evanm@google.com874d1672008-10-31 08:54:04 +0900474 FilePath file_name2_from =
475 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900476 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
477 ASSERT_TRUE(file_util::PathExists(file_name2_from));
478
479 // Copy the directory not recursively.
evanm@google.com874d1672008-10-31 08:54:04 +0900480 FilePath dir_name_to =
481 test_dir_.Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
482 FilePath file_name_to =
483 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
484 FilePath subdir_name_to =
485 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
initial.commit3f4a7322008-07-27 06:49:38 +0900486
487 ASSERT_FALSE(file_util::PathExists(dir_name_to));
488
489 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_to, false));
490
491 // Check everything has been copied.
492 EXPECT_TRUE(file_util::PathExists(dir_name_from));
493 EXPECT_TRUE(file_util::PathExists(file_name_from));
494 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
495 EXPECT_TRUE(file_util::PathExists(file_name2_from));
496 EXPECT_TRUE(file_util::PathExists(dir_name_to));
497 EXPECT_TRUE(file_util::PathExists(file_name_to));
498 EXPECT_FALSE(file_util::PathExists(subdir_name_to));
499}
500
501TEST_F(FileUtilTest, CopyFile) {
502 // Create a directory
evanm@google.com874d1672008-10-31 08:54:04 +0900503 FilePath dir_name_from =
504 test_dir_.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
505 file_util::CreateDirectory(dir_name_from);
initial.commit3f4a7322008-07-27 06:49:38 +0900506 ASSERT_TRUE(file_util::PathExists(dir_name_from));
507
508 // Create a file under the directory
evanm@google.com874d1672008-10-31 08:54:04 +0900509 FilePath file_name_from =
510 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900511 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
512 CreateTextFile(file_name_from, file_contents);
513 ASSERT_TRUE(file_util::PathExists(file_name_from));
514
515 // Copy the file.
evanm@google.com874d1672008-10-31 08:54:04 +0900516 FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900517 ASSERT_TRUE(file_util::CopyFile(file_name_from, dest_file));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900518
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900519 // Copy the file to another location using '..' in the path.
evanm@google.com874d1672008-10-31 08:54:04 +0900520 std::wstring dest_file2(dir_name_from.ToWStringHack());
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900521 file_util::AppendToPath(&dest_file2, L"..");
522 file_util::AppendToPath(&dest_file2, L"DestFile.txt");
evanm@google.com874d1672008-10-31 08:54:04 +0900523 ASSERT_TRUE(file_util::CopyFile(file_name_from,
524 FilePath::FromWStringHack(dest_file2)));
525 std::wstring dest_file2_test(dir_name_from.ToWStringHack());
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900526 file_util::UpOneDirectory(&dest_file2_test);
527 file_util::AppendToPath(&dest_file2_test, L"DestFile.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900528
529 // Check everything has been copied.
530 EXPECT_TRUE(file_util::PathExists(file_name_from));
531 EXPECT_TRUE(file_util::PathExists(dest_file));
532 const std::wstring read_contents = ReadTextFile(dest_file);
533 EXPECT_EQ(file_contents, read_contents);
evanm@google.com874d1672008-10-31 08:54:04 +0900534 EXPECT_TRUE(file_util::PathExists(
535 FilePath::FromWStringHack(dest_file2_test)));
536 EXPECT_TRUE(file_util::PathExists(FilePath::FromWStringHack(dest_file2)));
initial.commit3f4a7322008-07-27 06:49:38 +0900537}
538
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900539// TODO(erikkay): implement
erikkay@google.com014161d2008-08-16 02:45:13 +0900540#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900541TEST_F(FileUtilTest, GetFileCreationLocalTime) {
evanm@google.com874d1672008-10-31 08:54:04 +0900542 FilePath file_name = test_dir_.Append(L"Test File.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900543
544 SYSTEMTIME start_time;
545 GetLocalTime(&start_time);
546 Sleep(100);
547 CreateTextFile(file_name, L"New file!");
548 Sleep(100);
549 SYSTEMTIME end_time;
550 GetLocalTime(&end_time);
551
552 SYSTEMTIME file_creation_time;
evanm@google.com874d1672008-10-31 08:54:04 +0900553 file_util::GetFileCreationLocalTime(file_name.value(), &file_creation_time);
initial.commit3f4a7322008-07-27 06:49:38 +0900554
555 FILETIME start_filetime;
556 SystemTimeToFileTime(&start_time, &start_filetime);
557 FILETIME end_filetime;
558 SystemTimeToFileTime(&end_time, &end_filetime);
559 FILETIME file_creation_filetime;
560 SystemTimeToFileTime(&file_creation_time, &file_creation_filetime);
561
562 EXPECT_EQ(-1, CompareFileTime(&start_filetime, &file_creation_filetime)) <<
563 "start time: " << FileTimeAsUint64(start_filetime) << ", " <<
564 "creation time: " << FileTimeAsUint64(file_creation_filetime);
565
566 EXPECT_EQ(-1, CompareFileTime(&file_creation_filetime, &end_filetime)) <<
567 "creation time: " << FileTimeAsUint64(file_creation_filetime) << ", " <<
568 "end time: " << FileTimeAsUint64(end_filetime);
569
evanm@google.com874d1672008-10-31 08:54:04 +0900570 ASSERT_TRUE(DeleteFile(file_name.value().c_str()));
initial.commit3f4a7322008-07-27 06:49:38 +0900571}
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900572#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900573
erikkay@google.comf2406842008-08-21 00:59:49 +0900574// file_util winds up using autoreleased objects on the Mac, so this needs
evanm@google.com874d1672008-10-31 08:54:04 +0900575// to be a PlatformTest.
erikkay@google.comf2406842008-08-21 00:59:49 +0900576typedef PlatformTest ReadOnlyFileUtilTest;
initial.commit3f4a7322008-07-27 06:49:38 +0900577
erikkay@google.comf2406842008-08-21 00:59:49 +0900578TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
evanm@google.com874d1672008-10-31 08:54:04 +0900579 FilePath data_dir;
initial.commit3f4a7322008-07-27 06:49:38 +0900580 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
evanm@google.com874d1672008-10-31 08:54:04 +0900581 data_dir = data_dir.Append(FILE_PATH_LITERAL("base"))
582 .Append(FILE_PATH_LITERAL("data"))
583 .Append(FILE_PATH_LITERAL("file_util_unittest"));
initial.commit3f4a7322008-07-27 06:49:38 +0900584 ASSERT_TRUE(file_util::PathExists(data_dir));
585
evanm@google.com874d1672008-10-31 08:54:04 +0900586 FilePath original_file =
587 data_dir.Append(FILE_PATH_LITERAL("original.txt"));
588 FilePath same_file =
589 data_dir.Append(FILE_PATH_LITERAL("same.txt"));
590 FilePath same_length_file =
591 data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
592 FilePath different_file =
593 data_dir.Append(FILE_PATH_LITERAL("different.txt"));
594 FilePath different_first_file =
595 data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
596 FilePath different_last_file =
597 data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
598 FilePath empty1_file =
599 data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
600 FilePath empty2_file =
601 data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
602 FilePath shortened_file =
603 data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
604 FilePath binary_file =
605 data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
606 FilePath binary_file_same =
607 data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
608 FilePath binary_file_diff =
609 data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
initial.commit3f4a7322008-07-27 06:49:38 +0900610
611 EXPECT_TRUE(file_util::ContentsEqual(original_file, original_file));
612 EXPECT_TRUE(file_util::ContentsEqual(original_file, same_file));
613 EXPECT_FALSE(file_util::ContentsEqual(original_file, same_length_file));
614 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_file));
615 EXPECT_FALSE(file_util::ContentsEqual(L"bogusname", L"bogusname"));
616 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_first_file));
617 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_last_file));
618 EXPECT_TRUE(file_util::ContentsEqual(empty1_file, empty2_file));
619 EXPECT_FALSE(file_util::ContentsEqual(original_file, shortened_file));
620 EXPECT_FALSE(file_util::ContentsEqual(shortened_file, original_file));
621 EXPECT_TRUE(file_util::ContentsEqual(binary_file, binary_file_same));
622 EXPECT_FALSE(file_util::ContentsEqual(binary_file, binary_file_diff));
623}
624
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900625// We don't need equivalent functionality outside of Windows.
erikkay@google.com014161d2008-08-16 02:45:13 +0900626#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900627TEST_F(FileUtilTest, ResolveShortcutTest) {
evanm@google.com874d1672008-10-31 08:54:04 +0900628 FilePath target_file = test_dir_.Append(L"Target.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900629 CreateTextFile(target_file, L"This is the target.");
630
evanm@google.com874d1672008-10-31 08:54:04 +0900631 FilePath link_file = test_dir_.Append(L"Link.lnk");
initial.commit3f4a7322008-07-27 06:49:38 +0900632
633 HRESULT result;
634 IShellLink *shell = NULL;
635 IPersistFile *persist = NULL;
636
637 CoInitialize(NULL);
638 // Temporarily create a shortcut for test
639 result = CoCreateInstance(CLSID_ShellLink, NULL,
640 CLSCTX_INPROC_SERVER, IID_IShellLink,
641 reinterpret_cast<LPVOID*>(&shell));
642 EXPECT_TRUE(SUCCEEDED(result));
643 result = shell->QueryInterface(IID_IPersistFile,
644 reinterpret_cast<LPVOID*>(&persist));
645 EXPECT_TRUE(SUCCEEDED(result));
evanm@google.com874d1672008-10-31 08:54:04 +0900646 result = shell->SetPath(target_file.value().c_str());
initial.commit3f4a7322008-07-27 06:49:38 +0900647 EXPECT_TRUE(SUCCEEDED(result));
648 result = shell->SetDescription(L"ResolveShortcutTest");
649 EXPECT_TRUE(SUCCEEDED(result));
evanm@google.com874d1672008-10-31 08:54:04 +0900650 result = persist->Save(link_file.value().c_str(), TRUE);
initial.commit3f4a7322008-07-27 06:49:38 +0900651 EXPECT_TRUE(SUCCEEDED(result));
652 if (persist)
653 persist->Release();
654 if (shell)
655 shell->Release();
656
657 bool is_solved;
evanm@google.com874d1672008-10-31 08:54:04 +0900658 std::wstring link_file_str = link_file.value();
659 is_solved = file_util::ResolveShortcut(&link_file_str);
initial.commit3f4a7322008-07-27 06:49:38 +0900660 EXPECT_TRUE(is_solved);
661 std::wstring contents;
evanm@google.com874d1672008-10-31 08:54:04 +0900662 contents = ReadTextFile(FilePath(link_file_str));
initial.commit3f4a7322008-07-27 06:49:38 +0900663 EXPECT_EQ(L"This is the target.", contents);
664
ericroman@google.comdbff4f52008-08-19 01:00:38 +0900665 // Cleaning
evanm@google.com874d1672008-10-31 08:54:04 +0900666 DeleteFile(target_file.value().c_str());
667 DeleteFile(link_file_str.c_str());
initial.commit3f4a7322008-07-27 06:49:38 +0900668 CoUninitialize();
669}
670
671TEST_F(FileUtilTest, CreateShortcutTest) {
672 const wchar_t file_contents[] = L"This is another target.";
evanm@google.com874d1672008-10-31 08:54:04 +0900673 FilePath target_file = test_dir_.Append(L"Target1.txt");
initial.commit3f4a7322008-07-27 06:49:38 +0900674 CreateTextFile(target_file, file_contents);
675
evanm@google.com874d1672008-10-31 08:54:04 +0900676 FilePath link_file = test_dir_.Append(L"Link1.lnk");
initial.commit3f4a7322008-07-27 06:49:38 +0900677
678 CoInitialize(NULL);
evanm@google.com874d1672008-10-31 08:54:04 +0900679 EXPECT_TRUE(file_util::CreateShortcutLink(target_file.value().c_str(),
680 link_file.value().c_str(),
initial.commit3f4a7322008-07-27 06:49:38 +0900681 NULL, NULL, NULL, NULL, 0));
evanm@google.com874d1672008-10-31 08:54:04 +0900682 std::wstring resolved_name = link_file.value();
initial.commit3f4a7322008-07-27 06:49:38 +0900683 EXPECT_TRUE(file_util::ResolveShortcut(&resolved_name));
evanm@google.com874d1672008-10-31 08:54:04 +0900684 std::wstring read_contents = ReadTextFile(FilePath(resolved_name));
initial.commit3f4a7322008-07-27 06:49:38 +0900685 EXPECT_EQ(file_contents, read_contents);
686
evanm@google.com874d1672008-10-31 08:54:04 +0900687 DeleteFile(target_file.value().c_str());
688 DeleteFile(link_file.value().c_str());
initial.commit3f4a7322008-07-27 06:49:38 +0900689 CoUninitialize();
690}
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900691#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900692
693TEST_F(FileUtilTest, CreateTemporaryFileNameTest) {
694 std::wstring temp_file;
estade@chromium.orgf474a1b2008-11-11 09:01:38 +0900695 ASSERT_TRUE(file_util::CreateTemporaryFileName(&temp_file));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900696 EXPECT_TRUE(file_util::PathExists(temp_file));
697 EXPECT_TRUE(file_util::Delete(temp_file, false));
initial.commit3f4a7322008-07-27 06:49:38 +0900698}
699
700TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
701 std::wstring temp_dir;
estade@chromium.orgf474a1b2008-11-11 09:01:38 +0900702 ASSERT_TRUE(file_util::CreateNewTempDirectory(std::wstring(), &temp_dir));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900703 EXPECT_TRUE(file_util::PathExists(temp_dir));
704 EXPECT_TRUE(file_util::Delete(temp_dir, false));
initial.commit3f4a7322008-07-27 06:49:38 +0900705}
706
707TEST_F(FileUtilTest, CreateDirectoryTest) {
evanm@google.com874d1672008-10-31 08:54:04 +0900708 FilePath test_root =
709 test_dir_.Append(FILE_PATH_LITERAL("create_directory_test"));
erikkay@google.com014161d2008-08-16 02:45:13 +0900710#if defined(OS_WIN)
evanm@google.com874d1672008-10-31 08:54:04 +0900711 FilePath test_path =
712 test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900713#elif defined(OS_POSIX)
evanm@google.com874d1672008-10-31 08:54:04 +0900714 FilePath test_path =
715 test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900716#endif
mmoss@google.com733df6b2008-09-12 01:09:11 +0900717
718 EXPECT_FALSE(file_util::PathExists(test_path));
719 EXPECT_TRUE(file_util::CreateDirectory(test_path));
720 EXPECT_TRUE(file_util::PathExists(test_path));
721 // CreateDirectory returns true if the DirectoryExists returns true.
722 EXPECT_TRUE(file_util::CreateDirectory(test_path));
723
724 // Doesn't work to create it on top of a non-dir
evanm@google.com874d1672008-10-31 08:54:04 +0900725 test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900726 EXPECT_FALSE(file_util::PathExists(test_path));
727 CreateTextFile(test_path, L"test file");
728 EXPECT_TRUE(file_util::PathExists(test_path));
729 EXPECT_FALSE(file_util::CreateDirectory(test_path));
730
731 EXPECT_TRUE(file_util::Delete(test_root, true));
732 EXPECT_FALSE(file_util::PathExists(test_root));
733 EXPECT_FALSE(file_util::PathExists(test_path));
734}
735
736TEST_F(FileUtilTest, DetectDirectoryTest) {
737 // Check a directory
evanm@google.com874d1672008-10-31 08:54:04 +0900738 FilePath test_root =
739 test_dir_.Append(FILE_PATH_LITERAL("detect_directory_test"));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900740 EXPECT_FALSE(file_util::PathExists(test_root));
741 EXPECT_TRUE(file_util::CreateDirectory(test_root));
742 EXPECT_TRUE(file_util::PathExists(test_root));
743 EXPECT_TRUE(file_util::DirectoryExists(test_root));
744
745 // Check a file
evanm@google.com874d1672008-10-31 08:54:04 +0900746 FilePath test_path =
747 test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
mmoss@google.com733df6b2008-09-12 01:09:11 +0900748 EXPECT_FALSE(file_util::PathExists(test_path));
749 CreateTextFile(test_path, L"test file");
750 EXPECT_TRUE(file_util::PathExists(test_path));
751 EXPECT_FALSE(file_util::DirectoryExists(test_path));
752 EXPECT_TRUE(file_util::Delete(test_path, false));
753
754 EXPECT_TRUE(file_util::Delete(test_root, true));
initial.commit3f4a7322008-07-27 06:49:38 +0900755}
756
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900757static const struct goodbad_pair {
initial.commit3f4a7322008-07-27 06:49:38 +0900758 std::wstring bad_name;
759 std::wstring good_name;
760} kIllegalCharacterCases[] = {
761 {L"bad*file:name?.jpg", L"bad-file-name-.jpg"},
762 {L"**********::::.txt", L"--------------.txt"},
initial.commit3f4a7322008-07-27 06:49:38 +0900763 // We can't use UCNs (universal character names) for C0/C1 characters and
764 // U+007F, but \x escape is interpreted by MSVC and gcc as we intend.
765 {L"bad\x0003\x0091 file\u200E\u200Fname.png", L"bad-- file--name.png"},
erikkay@google.com014161d2008-08-16 02:45:13 +0900766#if defined(OS_WIN)
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900767 {L"bad*file\\name.jpg", L"bad-file-name.jpg"},
initial.commit3f4a7322008-07-27 06:49:38 +0900768 {L"\t bad*file\\name/.jpg ", L"bad-file-name-.jpg"},
769 {L"bad\uFFFFfile\U0010FFFEname.jpg ", L"bad-file-name.jpg"},
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900770#elif defined(OS_POSIX)
771 {L"bad*file?name.jpg", L"bad-file-name.jpg"},
772 {L"\t bad*file?name/.jpg ", L"bad-file-name-.jpg"},
773 {L"bad\uFFFFfile-name.jpg ", L"bad-file-name.jpg"},
774#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900775 {L"this_file_name is okay!.mp3", L"this_file_name is okay!.mp3"},
776 {L"\u4E00\uAC00.mp3", L"\u4E00\uAC00.mp3"},
777 {L"\u0635\u200C\u0644.mp3", L"\u0635\u200C\u0644.mp3"},
778 {L"\U00010330\U00010331.mp3", L"\U00010330\U00010331.mp3"},
779 // Unassigned codepoints are ok.
780 {L"\u0378\U00040001.mp3", L"\u0378\U00040001.mp3"},
781};
782
783TEST_F(FileUtilTest, ReplaceIllegalCharactersTest) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900784 for (unsigned int i = 0; i < arraysize(kIllegalCharacterCases); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900785 std::wstring bad_name(kIllegalCharacterCases[i].bad_name);
786 file_util::ReplaceIllegalCharacters(&bad_name, L'-');
787 EXPECT_EQ(kIllegalCharacterCases[i].good_name, bad_name);
788 }
789}
790
estade@chromium.org97e37822008-11-27 13:03:57 +0900791// TODO(port): enable this test for non-windows.
792#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900793static const struct ReplaceExtensionCase {
794 std::wstring file_name;
795 std::wstring extension;
796 std::wstring result;
797} kReplaceExtension[] = {
798 {L"", L"", L""},
799 {L"", L"txt", L".txt"},
800 {L".", L"txt", L".txt"},
801 {L".", L"", L""},
802 {L"foo.dll", L"txt", L"foo.txt"},
803 {L"foo.dll", L".txt", L"foo.txt"},
804 {L"foo", L"txt", L"foo.txt"},
805 {L"foo", L".txt", L"foo.txt"},
806 {L"foo.baz.dll", L"txt", L"foo.baz.txt"},
807 {L"foo.baz.dll", L".txt", L"foo.baz.txt"},
808 {L"foo.dll", L"", L"foo"},
809 {L"foo.dll", L".", L"foo"},
810 {L"foo", L"", L"foo"},
811 {L"foo", L".", L"foo"},
812 {L"foo.baz.dll", L"", L"foo.baz"},
813 {L"foo.baz.dll", L".", L"foo.baz"},
814};
815
816TEST_F(FileUtilTest, ReplaceExtensionTest) {
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900817 for (unsigned int i = 0; i < arraysize(kReplaceExtension); ++i) {
initial.commit3f4a7322008-07-27 06:49:38 +0900818 std::wstring file_name(kReplaceExtension[i].file_name);
819 file_util::ReplaceExtension(&file_name, kReplaceExtension[i].extension);
820 EXPECT_EQ(file_name, kReplaceExtension[i].result);
821 }
822}
823
sky@google.com71e7c6f2008-09-20 02:32:18 +0900824// Make sure ReplaceExtension doesn't replace an extension that occurs as one of
825// the directory names of the path.
826TEST_F(FileUtilTest, ReplaceExtensionTestWithPathSeparators) {
827 std::wstring path;
828 file_util::AppendToPath(&path, L"foo.bar");
829 file_util::AppendToPath(&path, L"foo");
830 // '/foo.bar/foo' with extension '.baz'
831 std::wstring result_path = path;
832 file_util::ReplaceExtension(&result_path, L".baz");
833 EXPECT_EQ(path + L".baz", result_path);
834}
estade@chromium.org97e37822008-11-27 13:03:57 +0900835#endif // defined(OS_WIN)
sky@google.com71e7c6f2008-09-20 02:32:18 +0900836
initial.commit3f4a7322008-07-27 06:49:38 +0900837TEST_F(FileUtilTest, FileEnumeratorTest) {
838 // Test an empty directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900839 file_util::FileEnumerator f0(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900840 file_util::FileEnumerator::FILES_AND_DIRECTORIES);
841 EXPECT_EQ(f0.Next(), L"");
842 EXPECT_EQ(f0.Next(), L"");
843
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900844 // create the directories
evanm@google.com874d1672008-10-31 08:54:04 +0900845 FilePath dir1 = test_dir_.Append(FILE_PATH_LITERAL("dir1"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900846 EXPECT_TRUE(file_util::CreateDirectory(dir1));
evanm@google.com874d1672008-10-31 08:54:04 +0900847 FilePath dir2 = test_dir_.Append(FILE_PATH_LITERAL("dir2"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900848 EXPECT_TRUE(file_util::CreateDirectory(dir2));
evanm@google.com874d1672008-10-31 08:54:04 +0900849 FilePath dir2inner = dir2.Append(FILE_PATH_LITERAL("inner"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900850 EXPECT_TRUE(file_util::CreateDirectory(dir2inner));
evanm@google.com874d1672008-10-31 08:54:04 +0900851
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900852 // create the files
evanm@google.com874d1672008-10-31 08:54:04 +0900853 FilePath dir2file = dir2.Append(FILE_PATH_LITERAL("dir2file.txt"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900854 CreateTextFile(dir2file, L"");
evanm@google.com874d1672008-10-31 08:54:04 +0900855 FilePath dir2innerfile = dir2inner.Append(FILE_PATH_LITERAL("innerfile.txt"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900856 CreateTextFile(dir2innerfile, L"");
evanm@google.com874d1672008-10-31 08:54:04 +0900857 FilePath file1 = test_dir_.Append(FILE_PATH_LITERAL("file1.txt"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900858 CreateTextFile(file1, L"");
evanm@google.com874d1672008-10-31 08:54:04 +0900859 FilePath file2_rel =
860 dir2.Append(FilePath::kParentDirectory)
861 .Append(FILE_PATH_LITERAL("file2.txt"));
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900862 CreateTextFile(file2_rel, L"");
evanm@google.com874d1672008-10-31 08:54:04 +0900863 FilePath file2_abs = test_dir_.Append(FILE_PATH_LITERAL("file2.txt"));
initial.commit3f4a7322008-07-27 06:49:38 +0900864
865 // Only enumerate files.
evanm@google.com874d1672008-10-31 08:54:04 +0900866 file_util::FileEnumerator f1(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900867 file_util::FileEnumerator::FILES);
868 FindResultCollector c1(f1);
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900869 EXPECT_TRUE(c1.HasFile(file1));
870 EXPECT_TRUE(c1.HasFile(file2_abs));
871 EXPECT_TRUE(c1.HasFile(dir2file));
872 EXPECT_TRUE(c1.HasFile(dir2innerfile));
873 EXPECT_EQ(c1.size(), 4);
initial.commit3f4a7322008-07-27 06:49:38 +0900874
875 // Only enumerate directories.
evanm@google.com874d1672008-10-31 08:54:04 +0900876 file_util::FileEnumerator f2(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900877 file_util::FileEnumerator::DIRECTORIES);
878 FindResultCollector c2(f2);
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900879 EXPECT_TRUE(c2.HasFile(dir1));
880 EXPECT_TRUE(c2.HasFile(dir2));
881 EXPECT_TRUE(c2.HasFile(dir2inner));
882 EXPECT_EQ(c2.size(), 3);
initial.commit3f4a7322008-07-27 06:49:38 +0900883
tim@chromium.org989d0972008-10-16 11:42:45 +0900884 // Only enumerate directories non-recursively.
885 file_util::FileEnumerator f2_non_recursive(
evanm@google.com874d1672008-10-31 08:54:04 +0900886 test_dir_.ToWStringHack(), false, file_util::FileEnumerator::DIRECTORIES);
tim@chromium.org989d0972008-10-16 11:42:45 +0900887 FindResultCollector c2_non_recursive(f2_non_recursive);
888 EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
889 EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
890 EXPECT_EQ(c2_non_recursive.size(), 2);
891
initial.commit3f4a7322008-07-27 06:49:38 +0900892 // Enumerate files and directories.
evanm@google.com874d1672008-10-31 08:54:04 +0900893 file_util::FileEnumerator f3(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900894 file_util::FileEnumerator::FILES_AND_DIRECTORIES);
895 FindResultCollector c3(f3);
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900896 EXPECT_TRUE(c3.HasFile(dir1));
897 EXPECT_TRUE(c3.HasFile(dir2));
898 EXPECT_TRUE(c3.HasFile(file1));
899 EXPECT_TRUE(c3.HasFile(file2_abs));
900 EXPECT_TRUE(c3.HasFile(dir2file));
901 EXPECT_TRUE(c3.HasFile(dir2inner));
902 EXPECT_TRUE(c3.HasFile(dir2innerfile));
903 EXPECT_EQ(c3.size(), 7);
initial.commit3f4a7322008-07-27 06:49:38 +0900904
905 // Non-recursive operation.
evanm@google.com874d1672008-10-31 08:54:04 +0900906 file_util::FileEnumerator f4(test_dir_.ToWStringHack(), false,
initial.commit3f4a7322008-07-27 06:49:38 +0900907 file_util::FileEnumerator::FILES_AND_DIRECTORIES);
908 FindResultCollector c4(f4);
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900909 EXPECT_TRUE(c4.HasFile(dir2));
910 EXPECT_TRUE(c4.HasFile(dir2));
911 EXPECT_TRUE(c4.HasFile(file1));
912 EXPECT_TRUE(c4.HasFile(file2_abs));
913 EXPECT_EQ(c4.size(), 4);
initial.commit3f4a7322008-07-27 06:49:38 +0900914
915 // Enumerate with a pattern.
evanm@google.com874d1672008-10-31 08:54:04 +0900916 file_util::FileEnumerator f5(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900917 file_util::FileEnumerator::FILES_AND_DIRECTORIES, L"dir*");
918 FindResultCollector c5(f5);
erikkay@google.comdfb51b22008-08-16 02:32:10 +0900919 EXPECT_TRUE(c5.HasFile(dir1));
920 EXPECT_TRUE(c5.HasFile(dir2));
921 EXPECT_TRUE(c5.HasFile(dir2file));
922 EXPECT_TRUE(c5.HasFile(dir2inner));
923 EXPECT_TRUE(c5.HasFile(dir2innerfile));
924 EXPECT_EQ(c5.size(), 5);
initial.commit3f4a7322008-07-27 06:49:38 +0900925
926 // Make sure the destructor closes the find handle while in the middle of a
927 // query to allow TearDown to delete the directory.
evanm@google.com874d1672008-10-31 08:54:04 +0900928 file_util::FileEnumerator f6(test_dir_.ToWStringHack(), true,
initial.commit3f4a7322008-07-27 06:49:38 +0900929 file_util::FileEnumerator::FILES_AND_DIRECTORIES);
930 EXPECT_FALSE(f6.Next().empty()); // Should have found something
931 // (we don't care what).
932}
license.botf003cfe2008-08-24 09:55:55 +0900933
estade@chromium.org97e37822008-11-27 13:03:57 +0900934
935void PathComponents(const std::wstring& path,
936 std::vector<std::wstring>* components) {
937 DCHECK(components != NULL);
938 if (components == NULL)
939 return;
940 std::wstring::size_type start = 0;
941 std::wstring::size_type end = path.find('/', start);
942
943 // Special case the "/" or "\" directory. On Windows with a drive letter,
944 // this code path won't hit, but the right thing should still happen.
945 // "E:\foo" will turn into "E:","foo".
946 if (end == start) {
947 components->push_back(std::wstring(path, 0, 1));
948 start = end + 1;
949 end = path.find('/', start);
950 }
951 while (end != std::wstring::npos) {
952 std::wstring component = std::wstring(path, start, end - start);
953 components->push_back(component);
954 start = end + 1;
955 end = path.find('/', start);
956 }
957 std::wstring component = std::wstring(path, start);
958 components->push_back(component);
959}
960
961static const struct PathComponentsCase {
962 std::wstring path;
963 FilePath::StringType result;
964} kPathComponents[] = {
965 {L"/foo/bar/baz/", FILE_PATH_LITERAL("/|foo|bar|baz|")},
966 {L"/foo/bar/baz", FILE_PATH_LITERAL("/|foo|bar|baz")},
967 {L"e:/foo", FILE_PATH_LITERAL("e:|foo")},
968};
969
970TEST_F(FileUtilTest, PathComponentsTest) {
971 for (size_t i = 0; i < arraysize(kPathComponents); ++i) {
972 FilePath path = FilePath::FromWStringHack(kPathComponents[i].path);
973 std::vector<FilePath::StringType> comps;
974 file_util::PathComponents(path, &comps);
975
976 FilePath::StringType result;
977 for (size_t j = 0; j < comps.size(); ++j) {
978 result.append(comps[j]);
979 if (j < comps.size() - 1)
980 result.append(FILE_PATH_LITERAL("|"), 1);
981 }
982 EXPECT_EQ(kPathComponents[i].result, result);
983 }
984}
985
mark@chromium.org17684802008-09-10 09:16:28 +0900986} // namespace