blob: b2e855da1a048c877630f0d67808b685e3e88131 [file] [log] [blame]
rvargas@google.comb1ae3192013-11-28 10:31:31 +09001// 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 "base/file_util.h"
rvargas@chromium.org12938d72013-12-04 09:46:32 +09006#include "base/files/file.h"
rvargas@google.comb1ae3192013-11-28 10:31:31 +09007#include "base/files/scoped_temp_dir.h"
rvargas@google.comb1ae3192013-11-28 10:31:31 +09008#include "base/time/time.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
rvargas@chromium.org12938d72013-12-04 09:46:32 +090011using base::File;
rvargas@google.comb1ae3192013-11-28 10:31:31 +090012using base::FilePath;
13
rvargas@chromium.org12938d72013-12-04 09:46:32 +090014TEST(File, Create) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +090015 base::ScopedTempDir temp_dir;
16 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
17 FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
18
rvargas@chromium.org12938d72013-12-04 09:46:32 +090019 {
20 // Open a file that doesn't exist.
21 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
22 EXPECT_FALSE(file.IsValid());
23 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error());
24 }
rvargas@google.comb1ae3192013-11-28 10:31:31 +090025
rvargas@chromium.org12938d72013-12-04 09:46:32 +090026 {
27 // Open or create a file.
28 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
29 EXPECT_TRUE(file.IsValid());
30 EXPECT_TRUE(file.created());
31 EXPECT_EQ(base::File::FILE_OK, file.error());
32 }
rvargas@google.comb1ae3192013-11-28 10:31:31 +090033
rvargas@chromium.org12938d72013-12-04 09:46:32 +090034 {
35 // Open an existing file.
36 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
37 EXPECT_TRUE(file.IsValid());
38 EXPECT_FALSE(file.created());
39 EXPECT_EQ(base::File::FILE_OK, file.error());
rvargas@google.comb1ae3192013-11-28 10:31:31 +090040
rvargas@chromium.org12938d72013-12-04 09:46:32 +090041 // This time verify closing the file.
42 file.Close();
43 EXPECT_FALSE(file.IsValid());
44 }
rvargas@google.comb1ae3192013-11-28 10:31:31 +090045
rvargas@chromium.org12938d72013-12-04 09:46:32 +090046 {
47 // Create a file that exists.
48 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
49 EXPECT_FALSE(file.IsValid());
50 EXPECT_FALSE(file.created());
51 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error());
52 }
rvargas@google.comb1ae3192013-11-28 10:31:31 +090053
rvargas@chromium.org12938d72013-12-04 09:46:32 +090054 {
55 // Create or overwrite a file.
56 File file(file_path,
57 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ);
58 EXPECT_TRUE(file.IsValid());
59 EXPECT_TRUE(file.created());
60 EXPECT_EQ(base::File::FILE_OK, file.error());
61 }
rvargas@google.comb1ae3192013-11-28 10:31:31 +090062
rvargas@chromium.org12938d72013-12-04 09:46:32 +090063 {
64 // Create a delete-on-close file.
65 file_path = temp_dir.path().AppendASCII("create_file_2");
66 File file(file_path,
67 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
68 base::File::FLAG_DELETE_ON_CLOSE);
69 EXPECT_TRUE(file.IsValid());
70 EXPECT_TRUE(file.created());
71 EXPECT_EQ(base::File::FILE_OK, file.error());
72 }
73
rvargas@google.comb1ae3192013-11-28 10:31:31 +090074 EXPECT_FALSE(base::PathExists(file_path));
75}
76
rvargas@chromium.org12938d72013-12-04 09:46:32 +090077TEST(File, DeleteOpenFile) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +090078 base::ScopedTempDir temp_dir;
79 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
80 FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
81
82 // Create a file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +090083 File file(file_path,
84 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
85 base::File::FLAG_SHARE_DELETE);
86 EXPECT_TRUE(file.IsValid());
87 EXPECT_TRUE(file.created());
88 EXPECT_EQ(base::File::FILE_OK, file.error());
rvargas@google.comb1ae3192013-11-28 10:31:31 +090089
90 // Open an existing file and mark it as delete on close.
rvargas@chromium.org12938d72013-12-04 09:46:32 +090091 File same_file(file_path,
92 base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
93 base::File::FLAG_READ);
94 EXPECT_TRUE(file.IsValid());
95 EXPECT_FALSE(same_file.created());
96 EXPECT_EQ(base::File::FILE_OK, same_file.error());
rvargas@google.comb1ae3192013-11-28 10:31:31 +090097
98 // Close both handles and check that the file is gone.
rvargas@chromium.org12938d72013-12-04 09:46:32 +090099 file.Close();
100 same_file.Close();
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900101 EXPECT_FALSE(base::PathExists(file_path));
102}
103
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900104TEST(File, ReadWrite) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900105 base::ScopedTempDir temp_dir;
106 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
107 FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900108 File file(file_path,
109 base::File::FLAG_CREATE | base::File::FLAG_READ |
110 base::File::FLAG_WRITE);
111 ASSERT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900112
113 char data_to_write[] = "test";
114 const int kTestDataSize = 4;
115
116 // Write 0 bytes to the file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900117 int bytes_written = file.Write(0, data_to_write, 0);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900118 EXPECT_EQ(0, bytes_written);
119
120 // Write "test" to the file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900121 bytes_written = file.Write(0, data_to_write, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900122 EXPECT_EQ(kTestDataSize, bytes_written);
123
124 // Read from EOF.
125 char data_read_1[32];
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900126 int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900127 EXPECT_EQ(0, bytes_read);
128
129 // Read from somewhere in the middle of the file.
130 const int kPartialReadOffset = 1;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900131 bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900132 EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
133 for (int i = 0; i < bytes_read; i++)
134 EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
135
136 // Read 0 bytes.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900137 bytes_read = file.Read(0, data_read_1, 0);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900138 EXPECT_EQ(0, bytes_read);
139
140 // Read the entire file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900141 bytes_read = file.Read(0, data_read_1, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900142 EXPECT_EQ(kTestDataSize, bytes_read);
143 for (int i = 0; i < bytes_read; i++)
144 EXPECT_EQ(data_to_write[i], data_read_1[i]);
145
146 // Read again, but using the trivial native wrapper.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900147 bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900148 EXPECT_LE(bytes_read, kTestDataSize);
149 for (int i = 0; i < bytes_read; i++)
150 EXPECT_EQ(data_to_write[i], data_read_1[i]);
151
152 // Write past the end of the file.
153 const int kOffsetBeyondEndOfFile = 10;
154 const int kPartialWriteLength = 2;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900155 bytes_written = file.Write(kOffsetBeyondEndOfFile,
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900156 data_to_write, kPartialWriteLength);
157 EXPECT_EQ(kPartialWriteLength, bytes_written);
158
159 // Make sure the file was extended.
160 int64 file_size = 0;
brettw@chromium.org70684242013-12-05 03:22:49 +0900161 EXPECT_TRUE(GetFileSize(file_path, &file_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900162 EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
163
164 // Make sure the file was zero-padded.
165 char data_read_2[32];
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900166 bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900167 EXPECT_EQ(file_size, bytes_read);
168 for (int i = 0; i < kTestDataSize; i++)
169 EXPECT_EQ(data_to_write[i], data_read_2[i]);
170 for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
171 EXPECT_EQ(0, data_read_2[i]);
172 for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
173 EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900174}
175
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900176TEST(File, Append) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900177 base::ScopedTempDir temp_dir;
178 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
179 FilePath file_path = temp_dir.path().AppendASCII("append_file");
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900180 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
181 ASSERT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900182
183 char data_to_write[] = "test";
184 const int kTestDataSize = 4;
185
186 // Write 0 bytes to the file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900187 int bytes_written = file.Write(0, data_to_write, 0);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900188 EXPECT_EQ(0, bytes_written);
189
190 // Write "test" to the file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900191 bytes_written = file.Write(0, data_to_write, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900192 EXPECT_EQ(kTestDataSize, bytes_written);
193
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900194 file.Close();
195 File file2(file_path,
196 base::File::FLAG_OPEN | base::File::FLAG_READ |
197 base::File::FLAG_APPEND);
198 ASSERT_TRUE(file2.IsValid());
199
200 // Test passing the file around.
201 file = file2.Pass();
202 EXPECT_FALSE(file2.IsValid());
203 ASSERT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900204
205 char append_data_to_write[] = "78";
206 const int kAppendDataSize = 2;
207
208 // Append "78" to the file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900209 bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900210 EXPECT_EQ(kAppendDataSize, bytes_written);
211
212 // Read the entire file.
213 char data_read_1[32];
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900214 int bytes_read = file.Read(0, data_read_1,
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900215 kTestDataSize + kAppendDataSize);
216 EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
217 for (int i = 0; i < kTestDataSize; i++)
218 EXPECT_EQ(data_to_write[i], data_read_1[i]);
219 for (int i = 0; i < kAppendDataSize; i++)
220 EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900221}
222
223
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900224TEST(File, Truncate) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900225 base::ScopedTempDir temp_dir;
226 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
227 FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900228 File file(file_path,
229 base::File::FLAG_CREATE | base::File::FLAG_READ |
230 base::File::FLAG_WRITE);
231 ASSERT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900232
233 // Write "test" to the file.
234 char data_to_write[] = "test";
235 int kTestDataSize = 4;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900236 int bytes_written = file.Write(0, data_to_write, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900237 EXPECT_EQ(kTestDataSize, bytes_written);
238
239 // Extend the file.
240 const int kExtendedFileLength = 10;
241 int64 file_size = 0;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900242 EXPECT_TRUE(file.Truncate(kExtendedFileLength));
brettw@chromium.org70684242013-12-05 03:22:49 +0900243 EXPECT_TRUE(GetFileSize(file_path, &file_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900244 EXPECT_EQ(kExtendedFileLength, file_size);
245
246 // Make sure the file was zero-padded.
247 char data_read[32];
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900248 int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900249 EXPECT_EQ(file_size, bytes_read);
250 for (int i = 0; i < kTestDataSize; i++)
251 EXPECT_EQ(data_to_write[i], data_read[i]);
252 for (int i = kTestDataSize; i < file_size; i++)
253 EXPECT_EQ(0, data_read[i]);
254
255 // Truncate the file.
256 const int kTruncatedFileLength = 2;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900257 EXPECT_TRUE(file.Truncate(kTruncatedFileLength));
brettw@chromium.org70684242013-12-05 03:22:49 +0900258 EXPECT_TRUE(GetFileSize(file_path, &file_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900259 EXPECT_EQ(kTruncatedFileLength, file_size);
260
261 // Make sure the file was truncated.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900262 bytes_read = file.Read(0, data_read, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900263 EXPECT_EQ(file_size, bytes_read);
264 for (int i = 0; i < file_size; i++)
265 EXPECT_EQ(data_to_write[i], data_read[i]);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900266}
267
268// Flakily fails: http://crbug.com/86494
269#if defined(OS_ANDROID)
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900270TEST(File, TouchGetInfo) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900271#else
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900272TEST(File, DISABLED_TouchGetInfo) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900273#endif
274 base::ScopedTempDir temp_dir;
275 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900276 File file(temp_dir.path().AppendASCII("touch_get_info_file"),
277 base::File::FLAG_CREATE | base::File::FLAG_WRITE |
278 base::File::FLAG_WRITE_ATTRIBUTES);
279 ASSERT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900280
281 // Get info for a newly created file.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900282 base::File::Info info;
283 EXPECT_TRUE(file.GetInfo(&info));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900284
285 // Add 2 seconds to account for possible rounding errors on
286 // filesystems that use a 1s or 2s timestamp granularity.
287 base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
288 EXPECT_EQ(0, info.size);
289 EXPECT_FALSE(info.is_directory);
290 EXPECT_FALSE(info.is_symbolic_link);
291 EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
292 EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
293 EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
294 base::Time creation_time = info.creation_time;
295
296 // Write "test" to the file.
297 char data[] = "test";
298 const int kTestDataSize = 4;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900299 int bytes_written = file.Write(0, data, kTestDataSize);
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900300 EXPECT_EQ(kTestDataSize, bytes_written);
301
302 // Change the last_accessed and last_modified dates.
303 // It's best to add values that are multiples of 2 (in seconds)
304 // to the current last_accessed and last_modified times, because
305 // FATxx uses a 2s timestamp granularity.
306 base::Time new_last_accessed =
307 info.last_accessed + base::TimeDelta::FromSeconds(234);
308 base::Time new_last_modified =
309 info.last_modified + base::TimeDelta::FromMinutes(567);
310
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900311 EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900312
313 // Make sure the file info was updated accordingly.
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900314 EXPECT_TRUE(file.GetInfo(&info));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900315 EXPECT_EQ(info.size, kTestDataSize);
316 EXPECT_FALSE(info.is_directory);
317 EXPECT_FALSE(info.is_symbolic_link);
318
319 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
320#if defined(OS_POSIX)
321 EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
322 new_last_accessed.ToTimeVal().tv_sec);
323 EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
324 new_last_modified.ToTimeVal().tv_sec);
325#else
326 EXPECT_EQ(info.last_accessed.ToInternalValue(),
327 new_last_accessed.ToInternalValue());
328 EXPECT_EQ(info.last_modified.ToInternalValue(),
329 new_last_modified.ToInternalValue());
330#endif
331
332 EXPECT_EQ(info.creation_time.ToInternalValue(),
333 creation_time.ToInternalValue());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900334}
335
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900336TEST(File, ReadFileAtCurrentPosition) {
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900337 base::ScopedTempDir temp_dir;
338 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
339 FilePath file_path =
340 temp_dir.path().AppendASCII("read_file_at_current_position");
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900341 File file(file_path,
342 base::File::FLAG_CREATE | base::File::FLAG_READ |
343 base::File::FLAG_WRITE);
344 EXPECT_TRUE(file.IsValid());
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900345
346 const char kData[] = "test";
347 const int kDataSize = arraysize(kData) - 1;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900348 EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900349
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900350 EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900351
352 char buffer[kDataSize];
353 int first_chunk_size = kDataSize / 2;
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900354 EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900355 EXPECT_EQ(kDataSize - first_chunk_size,
rvargas@chromium.org12938d72013-12-04 09:46:32 +0900356 file.ReadAtCurrentPos(buffer + first_chunk_size,
357 kDataSize - first_chunk_size));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900358 EXPECT_EQ(std::string(buffer, buffer + kDataSize),
359 std::string(kData));
rvargas@google.comb1ae3192013-11-28 10:31:31 +0900360}