file_unittest.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  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. #include "base/files/file.h"
  5. #include <stdint.h>
  6. #include <utility>
  7. #include "base/files/file_util.h"
  8. #include "base/files/memory_mapped_file.h"
  9. #include "base/files/scoped_temp_dir.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/time/time.h"
  12. #include "build/build_config.h"
  13. #include "build/buildflag.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #if BUILDFLAG(ENABLE_BASE_TRACING)
  16. #include "third_party/perfetto/include/perfetto/test/traced_value_test_support.h" // no-presubmit-check nogncheck
  17. #endif // BUILDFLAG(ENABLE_BASE_TRACING)
  18. #if BUILDFLAG(IS_WIN)
  19. #include <windows.h>
  20. #endif
  21. using base::File;
  22. using base::FilePath;
  23. TEST(FileTest, Create) {
  24. base::ScopedTempDir temp_dir;
  25. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  26. FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
  27. {
  28. // Don't create a File at all.
  29. File file;
  30. EXPECT_FALSE(file.IsValid());
  31. EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
  32. File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
  33. EXPECT_FALSE(file2.IsValid());
  34. EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
  35. }
  36. {
  37. // Open a file that doesn't exist.
  38. File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  39. EXPECT_FALSE(file.IsValid());
  40. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
  41. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, base::File::GetLastFileError());
  42. }
  43. {
  44. // Open or create a file.
  45. File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
  46. EXPECT_TRUE(file.IsValid());
  47. EXPECT_TRUE(file.created());
  48. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  49. }
  50. {
  51. // Open an existing file.
  52. File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  53. EXPECT_TRUE(file.IsValid());
  54. EXPECT_FALSE(file.created());
  55. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  56. // This time verify closing the file.
  57. file.Close();
  58. EXPECT_FALSE(file.IsValid());
  59. }
  60. {
  61. // Open an existing file through Initialize
  62. File file;
  63. file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  64. EXPECT_TRUE(file.IsValid());
  65. EXPECT_FALSE(file.created());
  66. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  67. // This time verify closing the file.
  68. file.Close();
  69. EXPECT_FALSE(file.IsValid());
  70. }
  71. {
  72. // Create a file that exists.
  73. File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
  74. EXPECT_FALSE(file.IsValid());
  75. EXPECT_FALSE(file.created());
  76. EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
  77. EXPECT_EQ(base::File::FILE_ERROR_EXISTS, base::File::GetLastFileError());
  78. }
  79. {
  80. // Create or overwrite a file.
  81. File file(file_path,
  82. base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  83. EXPECT_TRUE(file.IsValid());
  84. EXPECT_TRUE(file.created());
  85. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  86. }
  87. {
  88. // Create a delete-on-close file.
  89. file_path = temp_dir.GetPath().AppendASCII("create_file_2");
  90. File file(file_path,
  91. base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
  92. base::File::FLAG_DELETE_ON_CLOSE);
  93. EXPECT_TRUE(file.IsValid());
  94. EXPECT_TRUE(file.created());
  95. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  96. }
  97. EXPECT_FALSE(base::PathExists(file_path));
  98. }
  99. TEST(FileTest, SelfSwap) {
  100. base::ScopedTempDir temp_dir;
  101. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  102. FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
  103. File file(file_path,
  104. base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_DELETE_ON_CLOSE);
  105. std::swap(file, file);
  106. EXPECT_TRUE(file.IsValid());
  107. }
  108. TEST(FileTest, Async) {
  109. base::ScopedTempDir temp_dir;
  110. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  111. FilePath file_path = temp_dir.GetPath().AppendASCII("create_file");
  112. {
  113. File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
  114. EXPECT_TRUE(file.IsValid());
  115. EXPECT_TRUE(file.async());
  116. }
  117. {
  118. File file(file_path, base::File::FLAG_OPEN_ALWAYS);
  119. EXPECT_TRUE(file.IsValid());
  120. EXPECT_FALSE(file.async());
  121. }
  122. }
  123. TEST(FileTest, DeleteOpenFile) {
  124. base::ScopedTempDir temp_dir;
  125. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  126. FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
  127. // Create a file.
  128. File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
  129. base::File::FLAG_WIN_SHARE_DELETE);
  130. EXPECT_TRUE(file.IsValid());
  131. EXPECT_TRUE(file.created());
  132. EXPECT_EQ(base::File::FILE_OK, file.error_details());
  133. // Open an existing file and mark it as delete on close.
  134. File same_file(file_path,
  135. base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
  136. base::File::FLAG_READ);
  137. EXPECT_TRUE(file.IsValid());
  138. EXPECT_FALSE(same_file.created());
  139. EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
  140. // Close both handles and check that the file is gone.
  141. file.Close();
  142. same_file.Close();
  143. EXPECT_FALSE(base::PathExists(file_path));
  144. }
  145. TEST(FileTest, ReadWrite) {
  146. base::ScopedTempDir temp_dir;
  147. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  148. FilePath file_path = temp_dir.GetPath().AppendASCII("read_write_file");
  149. File file(file_path,
  150. base::File::FLAG_CREATE | base::File::FLAG_READ |
  151. base::File::FLAG_WRITE);
  152. ASSERT_TRUE(file.IsValid());
  153. char data_to_write[] = "test";
  154. const int kTestDataSize = 4;
  155. // Write 0 bytes to the file.
  156. int bytes_written = file.Write(0, data_to_write, 0);
  157. EXPECT_EQ(0, bytes_written);
  158. // Write 0 bytes, with buf=nullptr.
  159. bytes_written = file.Write(0, nullptr, 0);
  160. EXPECT_EQ(0, bytes_written);
  161. // Write "test" to the file.
  162. bytes_written = file.Write(0, data_to_write, kTestDataSize);
  163. EXPECT_EQ(kTestDataSize, bytes_written);
  164. // Read from EOF.
  165. char data_read_1[32];
  166. int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
  167. EXPECT_EQ(0, bytes_read);
  168. // Read from somewhere in the middle of the file.
  169. const int kPartialReadOffset = 1;
  170. bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
  171. EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
  172. for (int i = 0; i < bytes_read; i++)
  173. EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
  174. // Read 0 bytes.
  175. bytes_read = file.Read(0, data_read_1, 0);
  176. EXPECT_EQ(0, bytes_read);
  177. // Read the entire file.
  178. bytes_read = file.Read(0, data_read_1, kTestDataSize);
  179. EXPECT_EQ(kTestDataSize, bytes_read);
  180. for (int i = 0; i < bytes_read; i++)
  181. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  182. // Read again, but using the trivial native wrapper.
  183. bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
  184. EXPECT_LE(bytes_read, kTestDataSize);
  185. for (int i = 0; i < bytes_read; i++)
  186. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  187. // Write past the end of the file.
  188. const int kOffsetBeyondEndOfFile = 10;
  189. const int kPartialWriteLength = 2;
  190. bytes_written = file.Write(kOffsetBeyondEndOfFile,
  191. data_to_write, kPartialWriteLength);
  192. EXPECT_EQ(kPartialWriteLength, bytes_written);
  193. // Make sure the file was extended.
  194. int64_t file_size = 0;
  195. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  196. EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
  197. // Make sure the file was zero-padded.
  198. char data_read_2[32];
  199. bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
  200. EXPECT_EQ(file_size, bytes_read);
  201. for (int i = 0; i < kTestDataSize; i++)
  202. EXPECT_EQ(data_to_write[i], data_read_2[i]);
  203. for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
  204. EXPECT_EQ(0, data_read_2[i]);
  205. for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
  206. EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
  207. }
  208. TEST(FileTest, GetLastFileError) {
  209. #if BUILDFLAG(IS_WIN)
  210. ::SetLastError(ERROR_ACCESS_DENIED);
  211. #else
  212. errno = EACCES;
  213. #endif
  214. EXPECT_EQ(File::FILE_ERROR_ACCESS_DENIED, File::GetLastFileError());
  215. base::ScopedTempDir temp_dir;
  216. EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
  217. FilePath nonexistent_path(temp_dir.GetPath().AppendASCII("nonexistent"));
  218. File file(nonexistent_path, File::FLAG_OPEN | File::FLAG_READ);
  219. File::Error last_error = File::GetLastFileError();
  220. EXPECT_FALSE(file.IsValid());
  221. EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, file.error_details());
  222. EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, last_error);
  223. }
  224. TEST(FileTest, Append) {
  225. base::ScopedTempDir temp_dir;
  226. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  227. FilePath file_path = temp_dir.GetPath().AppendASCII("append_file");
  228. File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
  229. ASSERT_TRUE(file.IsValid());
  230. char data_to_write[] = "test";
  231. const int kTestDataSize = 4;
  232. // Write 0 bytes to the file.
  233. int bytes_written = file.Write(0, data_to_write, 0);
  234. EXPECT_EQ(0, bytes_written);
  235. // Write 0 bytes, with buf=nullptr.
  236. bytes_written = file.Write(0, nullptr, 0);
  237. EXPECT_EQ(0, bytes_written);
  238. // Write "test" to the file.
  239. bytes_written = file.Write(0, data_to_write, kTestDataSize);
  240. EXPECT_EQ(kTestDataSize, bytes_written);
  241. file.Close();
  242. File file2(file_path,
  243. base::File::FLAG_OPEN | base::File::FLAG_READ |
  244. base::File::FLAG_APPEND);
  245. ASSERT_TRUE(file2.IsValid());
  246. // Test passing the file around.
  247. file = std::move(file2);
  248. EXPECT_FALSE(file2.IsValid());
  249. ASSERT_TRUE(file.IsValid());
  250. char append_data_to_write[] = "78";
  251. const int kAppendDataSize = 2;
  252. // Append "78" to the file.
  253. bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
  254. EXPECT_EQ(kAppendDataSize, bytes_written);
  255. // Read the entire file.
  256. char data_read_1[32];
  257. int bytes_read = file.Read(0, data_read_1,
  258. kTestDataSize + kAppendDataSize);
  259. EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
  260. for (int i = 0; i < kTestDataSize; i++)
  261. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  262. for (int i = 0; i < kAppendDataSize; i++)
  263. EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
  264. }
  265. TEST(FileTest, Length) {
  266. base::ScopedTempDir temp_dir;
  267. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  268. FilePath file_path = temp_dir.GetPath().AppendASCII("truncate_file");
  269. File file(file_path,
  270. base::File::FLAG_CREATE | base::File::FLAG_READ |
  271. base::File::FLAG_WRITE);
  272. ASSERT_TRUE(file.IsValid());
  273. EXPECT_EQ(0, file.GetLength());
  274. // Write "test" to the file.
  275. char data_to_write[] = "test";
  276. int kTestDataSize = 4;
  277. int bytes_written = file.Write(0, data_to_write, kTestDataSize);
  278. EXPECT_EQ(kTestDataSize, bytes_written);
  279. // Extend the file.
  280. const int kExtendedFileLength = 10;
  281. int64_t file_size = 0;
  282. EXPECT_TRUE(file.SetLength(kExtendedFileLength));
  283. EXPECT_EQ(kExtendedFileLength, file.GetLength());
  284. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  285. EXPECT_EQ(kExtendedFileLength, file_size);
  286. // Make sure the file was zero-padded.
  287. char data_read[32];
  288. int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
  289. EXPECT_EQ(file_size, bytes_read);
  290. for (int i = 0; i < kTestDataSize; i++)
  291. EXPECT_EQ(data_to_write[i], data_read[i]);
  292. for (int i = kTestDataSize; i < file_size; i++)
  293. EXPECT_EQ(0, data_read[i]);
  294. // Truncate the file.
  295. const int kTruncatedFileLength = 2;
  296. EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
  297. EXPECT_EQ(kTruncatedFileLength, file.GetLength());
  298. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  299. EXPECT_EQ(kTruncatedFileLength, file_size);
  300. // Make sure the file was truncated.
  301. bytes_read = file.Read(0, data_read, kTestDataSize);
  302. EXPECT_EQ(file_size, bytes_read);
  303. for (int i = 0; i < file_size; i++)
  304. EXPECT_EQ(data_to_write[i], data_read[i]);
  305. #if !BUILDFLAG(IS_FUCHSIA) // Fuchsia doesn't seem to support big files.
  306. // Expand the file past the 4 GB limit.
  307. const int64_t kBigFileLength = 5'000'000'000;
  308. EXPECT_TRUE(file.SetLength(kBigFileLength));
  309. EXPECT_EQ(kBigFileLength, file.GetLength());
  310. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  311. EXPECT_EQ(kBigFileLength, file_size);
  312. #endif
  313. // Close the file and reopen with base::File::FLAG_CREATE_ALWAYS, and make
  314. // sure the file is empty (old file was overridden).
  315. file.Close();
  316. file.Initialize(file_path,
  317. base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  318. EXPECT_EQ(0, file.GetLength());
  319. }
  320. // Flakily fails: http://crbug.com/86494
  321. #if BUILDFLAG(IS_ANDROID)
  322. TEST(FileTest, TouchGetInfo) {
  323. #else
  324. TEST(FileTest, DISABLED_TouchGetInfo) {
  325. #endif
  326. base::ScopedTempDir temp_dir;
  327. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  328. File file(temp_dir.GetPath().AppendASCII("touch_get_info_file"),
  329. base::File::FLAG_CREATE | base::File::FLAG_WRITE |
  330. base::File::FLAG_WRITE_ATTRIBUTES);
  331. ASSERT_TRUE(file.IsValid());
  332. // Get info for a newly created file.
  333. base::File::Info info;
  334. EXPECT_TRUE(file.GetInfo(&info));
  335. // Add 2 seconds to account for possible rounding errors on
  336. // filesystems that use a 1s or 2s timestamp granularity.
  337. base::Time now = base::Time::Now() + base::Seconds(2);
  338. EXPECT_EQ(0, info.size);
  339. EXPECT_FALSE(info.is_directory);
  340. EXPECT_FALSE(info.is_symbolic_link);
  341. EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
  342. EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
  343. EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
  344. base::Time creation_time = info.creation_time;
  345. // Write "test" to the file.
  346. char data[] = "test";
  347. const int kTestDataSize = 4;
  348. int bytes_written = file.Write(0, data, kTestDataSize);
  349. EXPECT_EQ(kTestDataSize, bytes_written);
  350. // Change the last_accessed and last_modified dates.
  351. // It's best to add values that are multiples of 2 (in seconds)
  352. // to the current last_accessed and last_modified times, because
  353. // FATxx uses a 2s timestamp granularity.
  354. base::Time new_last_accessed = info.last_accessed + base::Seconds(234);
  355. base::Time new_last_modified = info.last_modified + base::Minutes(567);
  356. EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
  357. // Make sure the file info was updated accordingly.
  358. EXPECT_TRUE(file.GetInfo(&info));
  359. EXPECT_EQ(info.size, kTestDataSize);
  360. EXPECT_FALSE(info.is_directory);
  361. EXPECT_FALSE(info.is_symbolic_link);
  362. // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
  363. #if BUILDFLAG(IS_POSIX)
  364. EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
  365. new_last_accessed.ToTimeVal().tv_sec);
  366. EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
  367. new_last_modified.ToTimeVal().tv_sec);
  368. #else
  369. EXPECT_EQ(info.last_accessed.ToInternalValue(),
  370. new_last_accessed.ToInternalValue());
  371. EXPECT_EQ(info.last_modified.ToInternalValue(),
  372. new_last_modified.ToInternalValue());
  373. #endif
  374. EXPECT_EQ(info.creation_time.ToInternalValue(),
  375. creation_time.ToInternalValue());
  376. }
  377. // Test we can retrieve the file's creation time through File::GetInfo().
  378. TEST(FileTest, GetInfoForCreationTime) {
  379. int64_t before_creation_time_s =
  380. base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds();
  381. base::ScopedTempDir temp_dir;
  382. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  383. FilePath file_path = temp_dir.GetPath().AppendASCII("test_file");
  384. File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ |
  385. base::File::FLAG_WRITE);
  386. EXPECT_TRUE(file.IsValid());
  387. int64_t after_creation_time_s =
  388. base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds();
  389. base::File::Info info;
  390. EXPECT_TRUE(file.GetInfo(&info));
  391. EXPECT_GE(info.creation_time.ToDeltaSinceWindowsEpoch().InSeconds(),
  392. before_creation_time_s);
  393. EXPECT_LE(info.creation_time.ToDeltaSinceWindowsEpoch().InSeconds(),
  394. after_creation_time_s);
  395. }
  396. TEST(FileTest, ReadAtCurrentPosition) {
  397. base::ScopedTempDir temp_dir;
  398. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  399. FilePath file_path =
  400. temp_dir.GetPath().AppendASCII("read_at_current_position");
  401. File file(file_path,
  402. base::File::FLAG_CREATE | base::File::FLAG_READ |
  403. base::File::FLAG_WRITE);
  404. EXPECT_TRUE(file.IsValid());
  405. const char kData[] = "test";
  406. const int kDataSize = sizeof(kData) - 1;
  407. EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
  408. EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
  409. char buffer[kDataSize];
  410. int first_chunk_size = kDataSize / 2;
  411. EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
  412. EXPECT_EQ(kDataSize - first_chunk_size,
  413. file.ReadAtCurrentPos(buffer + first_chunk_size,
  414. kDataSize - first_chunk_size));
  415. EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
  416. }
  417. TEST(FileTest, WriteAtCurrentPosition) {
  418. base::ScopedTempDir temp_dir;
  419. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  420. FilePath file_path =
  421. temp_dir.GetPath().AppendASCII("write_at_current_position");
  422. File file(file_path,
  423. base::File::FLAG_CREATE | base::File::FLAG_READ |
  424. base::File::FLAG_WRITE);
  425. EXPECT_TRUE(file.IsValid());
  426. const char kData[] = "test";
  427. const int kDataSize = sizeof(kData) - 1;
  428. int first_chunk_size = kDataSize / 2;
  429. EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
  430. EXPECT_EQ(kDataSize - first_chunk_size,
  431. file.WriteAtCurrentPos(kData + first_chunk_size,
  432. kDataSize - first_chunk_size));
  433. char buffer[kDataSize];
  434. EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
  435. EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
  436. }
  437. TEST(FileTest, Seek) {
  438. base::ScopedTempDir temp_dir;
  439. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  440. FilePath file_path = temp_dir.GetPath().AppendASCII("seek_file");
  441. File file(file_path,
  442. base::File::FLAG_CREATE | base::File::FLAG_READ |
  443. base::File::FLAG_WRITE);
  444. ASSERT_TRUE(file.IsValid());
  445. const int64_t kOffset = 10;
  446. EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
  447. EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
  448. EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
  449. EXPECT_TRUE(file.SetLength(kOffset * 2));
  450. EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
  451. }
  452. TEST(FileTest, Duplicate) {
  453. base::ScopedTempDir temp_dir;
  454. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  455. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  456. File file(file_path,(base::File::FLAG_CREATE |
  457. base::File::FLAG_READ |
  458. base::File::FLAG_WRITE));
  459. ASSERT_TRUE(file.IsValid());
  460. File file2(file.Duplicate());
  461. ASSERT_TRUE(file2.IsValid());
  462. // Write through one handle, close it, read through the other.
  463. static const char kData[] = "now is a good time.";
  464. static const int kDataLen = sizeof(kData) - 1;
  465. ASSERT_EQ(0, file.Seek(base::File::FROM_CURRENT, 0));
  466. ASSERT_EQ(0, file2.Seek(base::File::FROM_CURRENT, 0));
  467. ASSERT_EQ(kDataLen, file.WriteAtCurrentPos(kData, kDataLen));
  468. ASSERT_EQ(kDataLen, file.Seek(base::File::FROM_CURRENT, 0));
  469. ASSERT_EQ(kDataLen, file2.Seek(base::File::FROM_CURRENT, 0));
  470. file.Close();
  471. char buf[kDataLen];
  472. ASSERT_EQ(kDataLen, file2.Read(0, &buf[0], kDataLen));
  473. ASSERT_EQ(std::string(kData, kDataLen), std::string(&buf[0], kDataLen));
  474. }
  475. TEST(FileTest, DuplicateDeleteOnClose) {
  476. base::ScopedTempDir temp_dir;
  477. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  478. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  479. File file(file_path,(base::File::FLAG_CREATE |
  480. base::File::FLAG_READ |
  481. base::File::FLAG_WRITE |
  482. base::File::FLAG_DELETE_ON_CLOSE));
  483. ASSERT_TRUE(file.IsValid());
  484. File file2(file.Duplicate());
  485. ASSERT_TRUE(file2.IsValid());
  486. file.Close();
  487. file2.Close();
  488. ASSERT_FALSE(base::PathExists(file_path));
  489. }
  490. #if BUILDFLAG(ENABLE_BASE_TRACING)
  491. TEST(FileTest, TracedValueSupport) {
  492. base::ScopedTempDir temp_dir;
  493. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  494. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  495. File file(file_path,
  496. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  497. base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE));
  498. ASSERT_TRUE(file.IsValid());
  499. EXPECT_EQ(perfetto::TracedValueToString(file),
  500. "{is_valid:true,created:true,async:false,error_details:FILE_OK}");
  501. }
  502. #endif // BUILDFLAG(ENABLE_BASE_TRACING)
  503. #if BUILDFLAG(IS_WIN)
  504. // Flakily times out on Windows, see http://crbug.com/846276.
  505. #define MAYBE_WriteDataToLargeOffset DISABLED_WriteDataToLargeOffset
  506. #else
  507. #define MAYBE_WriteDataToLargeOffset WriteDataToLargeOffset
  508. #endif
  509. TEST(FileTest, MAYBE_WriteDataToLargeOffset) {
  510. base::ScopedTempDir temp_dir;
  511. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  512. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  513. File file(file_path,
  514. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  515. base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE));
  516. ASSERT_TRUE(file.IsValid());
  517. const char kData[] = "this file is sparse.";
  518. const int kDataLen = sizeof(kData) - 1;
  519. const int64_t kLargeFileOffset = (1LL << 31);
  520. // If the file fails to write, it is probably we are running out of disk space
  521. // and the file system doesn't support sparse file.
  522. if (file.Write(kLargeFileOffset - kDataLen - 1, kData, kDataLen) < 0)
  523. return;
  524. ASSERT_EQ(kDataLen, file.Write(kLargeFileOffset + 1, kData, kDataLen));
  525. }
  526. #if BUILDFLAG(IS_WIN)
  527. TEST(FileTest, GetInfoForDirectory) {
  528. base::ScopedTempDir temp_dir;
  529. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  530. FilePath empty_dir =
  531. temp_dir.GetPath().Append(FILE_PATH_LITERAL("gpfi_test"));
  532. ASSERT_TRUE(CreateDirectory(empty_dir));
  533. base::File dir(
  534. ::CreateFile(empty_dir.value().c_str(), GENERIC_READ | GENERIC_WRITE,
  535. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
  536. OPEN_EXISTING,
  537. FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
  538. NULL));
  539. ASSERT_TRUE(dir.IsValid());
  540. base::File::Info info;
  541. EXPECT_TRUE(dir.GetInfo(&info));
  542. EXPECT_TRUE(info.is_directory);
  543. EXPECT_FALSE(info.is_symbolic_link);
  544. EXPECT_EQ(0, info.size);
  545. }
  546. TEST(FileTest, DeleteNoop) {
  547. base::ScopedTempDir temp_dir;
  548. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  549. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  550. // Creating and closing a file with DELETE perms should do nothing special.
  551. File file(file_path,
  552. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  553. base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
  554. ASSERT_TRUE(file.IsValid());
  555. file.Close();
  556. ASSERT_TRUE(base::PathExists(file_path));
  557. }
  558. TEST(FileTest, Delete) {
  559. base::ScopedTempDir temp_dir;
  560. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  561. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  562. // Creating a file with DELETE and then marking for delete on close should
  563. // delete it.
  564. File file(file_path,
  565. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  566. base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
  567. ASSERT_TRUE(file.IsValid());
  568. ASSERT_TRUE(file.DeleteOnClose(true));
  569. file.Close();
  570. ASSERT_FALSE(base::PathExists(file_path));
  571. }
  572. TEST(FileTest, DeleteThenRevoke) {
  573. base::ScopedTempDir temp_dir;
  574. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  575. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  576. // Creating a file with DELETE, marking it for delete, then clearing delete on
  577. // close should not delete it.
  578. File file(file_path,
  579. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  580. base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
  581. ASSERT_TRUE(file.IsValid());
  582. ASSERT_TRUE(file.DeleteOnClose(true));
  583. ASSERT_TRUE(file.DeleteOnClose(false));
  584. file.Close();
  585. ASSERT_TRUE(base::PathExists(file_path));
  586. }
  587. TEST(FileTest, IrrevokableDeleteOnClose) {
  588. base::ScopedTempDir temp_dir;
  589. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  590. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  591. // DELETE_ON_CLOSE cannot be revoked by this opener.
  592. File file(file_path,
  593. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  594. base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
  595. base::File::FLAG_WIN_SHARE_DELETE |
  596. base::File::FLAG_CAN_DELETE_ON_CLOSE));
  597. ASSERT_TRUE(file.IsValid());
  598. // https://msdn.microsoft.com/library/windows/desktop/aa364221.aspx says that
  599. // setting the dispositon has no effect if the handle was opened with
  600. // FLAG_DELETE_ON_CLOSE. Do not make the test's success dependent on whether
  601. // or not SetFileInformationByHandle indicates success or failure. (It happens
  602. // to indicate success on Windows 10.)
  603. file.DeleteOnClose(false);
  604. file.Close();
  605. ASSERT_FALSE(base::PathExists(file_path));
  606. }
  607. TEST(FileTest, IrrevokableDeleteOnCloseOther) {
  608. base::ScopedTempDir temp_dir;
  609. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  610. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  611. // DELETE_ON_CLOSE cannot be revoked by another opener.
  612. File file(file_path,
  613. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  614. base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
  615. base::File::FLAG_WIN_SHARE_DELETE |
  616. base::File::FLAG_CAN_DELETE_ON_CLOSE));
  617. ASSERT_TRUE(file.IsValid());
  618. File file2(file_path,
  619. (base::File::FLAG_OPEN | base::File::FLAG_READ |
  620. base::File::FLAG_WRITE | base::File::FLAG_WIN_SHARE_DELETE |
  621. base::File::FLAG_CAN_DELETE_ON_CLOSE));
  622. ASSERT_TRUE(file2.IsValid());
  623. file2.DeleteOnClose(false);
  624. file2.Close();
  625. ASSERT_TRUE(base::PathExists(file_path));
  626. file.Close();
  627. ASSERT_FALSE(base::PathExists(file_path));
  628. }
  629. TEST(FileTest, DeleteWithoutPermission) {
  630. base::ScopedTempDir temp_dir;
  631. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  632. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  633. // It should not be possible to mark a file for deletion when it was not
  634. // created/opened with DELETE.
  635. File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
  636. base::File::FLAG_WRITE));
  637. ASSERT_TRUE(file.IsValid());
  638. ASSERT_FALSE(file.DeleteOnClose(true));
  639. file.Close();
  640. ASSERT_TRUE(base::PathExists(file_path));
  641. }
  642. TEST(FileTest, UnsharedDeleteOnClose) {
  643. base::ScopedTempDir temp_dir;
  644. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  645. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  646. // Opening with DELETE_ON_CLOSE when a previous opener hasn't enabled sharing
  647. // will fail.
  648. File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
  649. base::File::FLAG_WRITE));
  650. ASSERT_TRUE(file.IsValid());
  651. File file2(
  652. file_path,
  653. (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
  654. base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_WIN_SHARE_DELETE));
  655. ASSERT_FALSE(file2.IsValid());
  656. file.Close();
  657. ASSERT_TRUE(base::PathExists(file_path));
  658. }
  659. TEST(FileTest, NoDeleteOnCloseWithMappedFile) {
  660. base::ScopedTempDir temp_dir;
  661. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  662. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  663. // Mapping a file into memory blocks DeleteOnClose.
  664. File file(file_path,
  665. (base::File::FLAG_CREATE | base::File::FLAG_READ |
  666. base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
  667. ASSERT_TRUE(file.IsValid());
  668. ASSERT_EQ(5, file.WriteAtCurrentPos("12345", 5));
  669. {
  670. base::MemoryMappedFile mapping;
  671. ASSERT_TRUE(mapping.Initialize(file.Duplicate()));
  672. ASSERT_EQ(5U, mapping.length());
  673. EXPECT_FALSE(file.DeleteOnClose(true));
  674. }
  675. file.Close();
  676. ASSERT_TRUE(base::PathExists(file_path));
  677. }
  678. // Check that we handle the async bit being set incorrectly in a sane way.
  679. TEST(FileTest, UseSyncApiWithAsyncFile) {
  680. base::ScopedTempDir temp_dir;
  681. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  682. FilePath file_path = temp_dir.GetPath().AppendASCII("file");
  683. File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE |
  684. base::File::FLAG_ASYNC);
  685. File lying_file(file.TakePlatformFile(), false /* async */);
  686. ASSERT_TRUE(lying_file.IsValid());
  687. ASSERT_EQ(lying_file.WriteAtCurrentPos("12345", 5), -1);
  688. }
  689. #endif // BUILDFLAG(IS_WIN)