file_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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 "butil/file_util.h"
  5. #include "butil/files/file.h"
  6. #include "butil/files/scoped_temp_dir.h"
  7. #include "butil/time/time.h"
  8. #include <gtest/gtest.h>
  9. using butil::File;
  10. using butil::FilePath;
  11. TEST(FileTest, Create) {
  12. butil::ScopedTempDir temp_dir;
  13. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  14. FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
  15. {
  16. // Don't create a File at all.
  17. File file;
  18. EXPECT_FALSE(file.IsValid());
  19. EXPECT_EQ(butil::File::FILE_ERROR_FAILED, file.error_details());
  20. File file2(butil::File::FILE_ERROR_TOO_MANY_OPENED);
  21. EXPECT_FALSE(file2.IsValid());
  22. EXPECT_EQ(butil::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
  23. }
  24. {
  25. // Open a file that doesn't exist.
  26. File file(file_path, butil::File::FLAG_OPEN | butil::File::FLAG_READ);
  27. EXPECT_FALSE(file.IsValid());
  28. EXPECT_EQ(butil::File::FILE_ERROR_NOT_FOUND, file.error_details());
  29. }
  30. {
  31. // Open or create a file.
  32. File file(file_path, butil::File::FLAG_OPEN_ALWAYS | butil::File::FLAG_READ);
  33. EXPECT_TRUE(file.IsValid());
  34. EXPECT_TRUE(file.created());
  35. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  36. }
  37. {
  38. // Open an existing file.
  39. File file(file_path, butil::File::FLAG_OPEN | butil::File::FLAG_READ);
  40. EXPECT_TRUE(file.IsValid());
  41. EXPECT_FALSE(file.created());
  42. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  43. // This time verify closing the file.
  44. file.Close();
  45. EXPECT_FALSE(file.IsValid());
  46. }
  47. {
  48. // Open an existing file through Initialize
  49. File file;
  50. file.Initialize(file_path, butil::File::FLAG_OPEN | butil::File::FLAG_READ);
  51. EXPECT_TRUE(file.IsValid());
  52. EXPECT_FALSE(file.created());
  53. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  54. // This time verify closing the file.
  55. file.Close();
  56. EXPECT_FALSE(file.IsValid());
  57. }
  58. {
  59. // Create a file that exists.
  60. File file(file_path, butil::File::FLAG_CREATE | butil::File::FLAG_READ);
  61. EXPECT_FALSE(file.IsValid());
  62. EXPECT_FALSE(file.created());
  63. EXPECT_EQ(butil::File::FILE_ERROR_EXISTS, file.error_details());
  64. }
  65. {
  66. // Create or overwrite a file.
  67. File file(file_path,
  68. butil::File::FLAG_CREATE_ALWAYS | butil::File::FLAG_WRITE);
  69. EXPECT_TRUE(file.IsValid());
  70. EXPECT_TRUE(file.created());
  71. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  72. }
  73. {
  74. // Create a delete-on-close file.
  75. file_path = temp_dir.path().AppendASCII("create_file_2");
  76. File file(file_path,
  77. butil::File::FLAG_OPEN_ALWAYS | butil::File::FLAG_READ |
  78. butil::File::FLAG_DELETE_ON_CLOSE);
  79. EXPECT_TRUE(file.IsValid());
  80. EXPECT_TRUE(file.created());
  81. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  82. }
  83. EXPECT_FALSE(butil::PathExists(file_path));
  84. }
  85. TEST(FileTest, Async) {
  86. butil::ScopedTempDir temp_dir;
  87. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  88. FilePath file_path = temp_dir.path().AppendASCII("create_file");
  89. {
  90. File file(file_path, butil::File::FLAG_OPEN_ALWAYS | butil::File::FLAG_ASYNC);
  91. EXPECT_TRUE(file.IsValid());
  92. EXPECT_TRUE(file.async());
  93. }
  94. {
  95. File file(file_path, butil::File::FLAG_OPEN_ALWAYS);
  96. EXPECT_TRUE(file.IsValid());
  97. EXPECT_FALSE(file.async());
  98. }
  99. }
  100. TEST(FileTest, DeleteOpenFile) {
  101. butil::ScopedTempDir temp_dir;
  102. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  103. FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
  104. // Create a file.
  105. File file(file_path,
  106. butil::File::FLAG_OPEN_ALWAYS | butil::File::FLAG_READ |
  107. butil::File::FLAG_SHARE_DELETE);
  108. EXPECT_TRUE(file.IsValid());
  109. EXPECT_TRUE(file.created());
  110. EXPECT_EQ(butil::File::FILE_OK, file.error_details());
  111. // Open an existing file and mark it as delete on close.
  112. File same_file(file_path,
  113. butil::File::FLAG_OPEN | butil::File::FLAG_DELETE_ON_CLOSE |
  114. butil::File::FLAG_READ);
  115. EXPECT_TRUE(file.IsValid());
  116. EXPECT_FALSE(same_file.created());
  117. EXPECT_EQ(butil::File::FILE_OK, same_file.error_details());
  118. // Close both handles and check that the file is gone.
  119. file.Close();
  120. same_file.Close();
  121. EXPECT_FALSE(butil::PathExists(file_path));
  122. }
  123. TEST(FileTest, ReadWrite) {
  124. butil::ScopedTempDir temp_dir;
  125. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  126. FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
  127. File file(file_path,
  128. butil::File::FLAG_CREATE | butil::File::FLAG_READ |
  129. butil::File::FLAG_WRITE);
  130. ASSERT_TRUE(file.IsValid());
  131. char data_to_write[] = "test";
  132. const int kTestDataSize = 4;
  133. // Write 0 bytes to the file.
  134. int bytes_written = file.Write(0, data_to_write, 0);
  135. EXPECT_EQ(0, bytes_written);
  136. // Write "test" to the file.
  137. bytes_written = file.Write(0, data_to_write, kTestDataSize);
  138. EXPECT_EQ(kTestDataSize, bytes_written);
  139. // Read from EOF.
  140. char data_read_1[32];
  141. int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
  142. EXPECT_EQ(0, bytes_read);
  143. // Read from somewhere in the middle of the file.
  144. const int kPartialReadOffset = 1;
  145. bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
  146. EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
  147. for (int i = 0; i < bytes_read; i++)
  148. EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
  149. // Read 0 bytes.
  150. bytes_read = file.Read(0, data_read_1, 0);
  151. EXPECT_EQ(0, bytes_read);
  152. // Read the entire file.
  153. bytes_read = file.Read(0, data_read_1, kTestDataSize);
  154. EXPECT_EQ(kTestDataSize, bytes_read);
  155. for (int i = 0; i < bytes_read; i++)
  156. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  157. // Read again, but using the trivial native wrapper.
  158. bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
  159. EXPECT_LE(bytes_read, kTestDataSize);
  160. for (int i = 0; i < bytes_read; i++)
  161. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  162. // Write past the end of the file.
  163. const int kOffsetBeyondEndOfFile = 10;
  164. const int kPartialWriteLength = 2;
  165. bytes_written = file.Write(kOffsetBeyondEndOfFile,
  166. data_to_write, kPartialWriteLength);
  167. EXPECT_EQ(kPartialWriteLength, bytes_written);
  168. // Make sure the file was extended.
  169. int64_t file_size = 0;
  170. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  171. EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
  172. // Make sure the file was zero-padded.
  173. char data_read_2[32];
  174. bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
  175. EXPECT_EQ(file_size, bytes_read);
  176. for (int i = 0; i < kTestDataSize; i++)
  177. EXPECT_EQ(data_to_write[i], data_read_2[i]);
  178. for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
  179. EXPECT_EQ(0, data_read_2[i]);
  180. for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
  181. EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
  182. }
  183. TEST(FileTest, Append) {
  184. butil::ScopedTempDir temp_dir;
  185. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  186. FilePath file_path = temp_dir.path().AppendASCII("append_file");
  187. File file(file_path, butil::File::FLAG_CREATE | butil::File::FLAG_APPEND);
  188. ASSERT_TRUE(file.IsValid());
  189. char data_to_write[] = "test";
  190. const int kTestDataSize = 4;
  191. // Write 0 bytes to the file.
  192. int bytes_written = file.Write(0, data_to_write, 0);
  193. EXPECT_EQ(0, bytes_written);
  194. // Write "test" to the file.
  195. bytes_written = file.Write(0, data_to_write, kTestDataSize);
  196. EXPECT_EQ(kTestDataSize, bytes_written);
  197. file.Close();
  198. File file2(file_path,
  199. butil::File::FLAG_OPEN | butil::File::FLAG_READ |
  200. butil::File::FLAG_APPEND);
  201. ASSERT_TRUE(file2.IsValid());
  202. // Test passing the file around.
  203. file = file2.Pass();
  204. EXPECT_FALSE(file2.IsValid());
  205. ASSERT_TRUE(file.IsValid());
  206. char append_data_to_write[] = "78";
  207. const int kAppendDataSize = 2;
  208. // Append "78" to the file.
  209. bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
  210. EXPECT_EQ(kAppendDataSize, bytes_written);
  211. // Read the entire file.
  212. char data_read_1[32];
  213. int bytes_read = file.Read(0, data_read_1,
  214. kTestDataSize + kAppendDataSize);
  215. EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
  216. for (int i = 0; i < kTestDataSize; i++)
  217. EXPECT_EQ(data_to_write[i], data_read_1[i]);
  218. for (int i = 0; i < kAppendDataSize; i++)
  219. EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
  220. }
  221. TEST(FileTest, Length) {
  222. butil::ScopedTempDir temp_dir;
  223. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  224. FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
  225. File file(file_path,
  226. butil::File::FLAG_CREATE | butil::File::FLAG_READ |
  227. butil::File::FLAG_WRITE);
  228. ASSERT_TRUE(file.IsValid());
  229. EXPECT_EQ(0, file.GetLength());
  230. // Write "test" to the file.
  231. char data_to_write[] = "test";
  232. int kTestDataSize = 4;
  233. int bytes_written = file.Write(0, data_to_write, kTestDataSize);
  234. EXPECT_EQ(kTestDataSize, bytes_written);
  235. // Extend the file.
  236. const int kExtendedFileLength = 10;
  237. int64_t file_size = 0;
  238. EXPECT_TRUE(file.SetLength(kExtendedFileLength));
  239. EXPECT_EQ(kExtendedFileLength, file.GetLength());
  240. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  241. EXPECT_EQ(kExtendedFileLength, file_size);
  242. // Make sure the file was zero-padded.
  243. char data_read[32];
  244. int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
  245. EXPECT_EQ(file_size, bytes_read);
  246. for (int i = 0; i < kTestDataSize; i++)
  247. EXPECT_EQ(data_to_write[i], data_read[i]);
  248. for (int i = kTestDataSize; i < file_size; i++)
  249. EXPECT_EQ(0, data_read[i]);
  250. // Truncate the file.
  251. const int kTruncatedFileLength = 2;
  252. EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
  253. EXPECT_EQ(kTruncatedFileLength, file.GetLength());
  254. EXPECT_TRUE(GetFileSize(file_path, &file_size));
  255. EXPECT_EQ(kTruncatedFileLength, file_size);
  256. // Make sure the file was truncated.
  257. bytes_read = file.Read(0, data_read, kTestDataSize);
  258. EXPECT_EQ(file_size, bytes_read);
  259. for (int i = 0; i < file_size; i++)
  260. EXPECT_EQ(data_to_write[i], data_read[i]);
  261. }
  262. // Flakily fails: http://crbug.com/86494
  263. #if defined(OS_ANDROID)
  264. TEST(FileTest, TouchGetInfo) {
  265. #else
  266. TEST(FileTest, DISABLED_TouchGetInfo) {
  267. #endif
  268. butil::ScopedTempDir temp_dir;
  269. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  270. File file(temp_dir.path().AppendASCII("touch_get_info_file"),
  271. butil::File::FLAG_CREATE | butil::File::FLAG_WRITE |
  272. butil::File::FLAG_WRITE_ATTRIBUTES);
  273. ASSERT_TRUE(file.IsValid());
  274. // Get info for a newly created file.
  275. butil::File::Info info;
  276. EXPECT_TRUE(file.GetInfo(&info));
  277. // Add 2 seconds to account for possible rounding errors on
  278. // filesystems that use a 1s or 2s timestamp granularity.
  279. butil::Time now = butil::Time::Now() + butil::TimeDelta::FromSeconds(2);
  280. EXPECT_EQ(0, info.size);
  281. EXPECT_FALSE(info.is_directory);
  282. EXPECT_FALSE(info.is_symbolic_link);
  283. EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
  284. EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
  285. EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
  286. butil::Time creation_time = info.creation_time;
  287. // Write "test" to the file.
  288. char data[] = "test";
  289. const int kTestDataSize = 4;
  290. int bytes_written = file.Write(0, data, kTestDataSize);
  291. EXPECT_EQ(kTestDataSize, bytes_written);
  292. // Change the last_accessed and last_modified dates.
  293. // It's best to add values that are multiples of 2 (in seconds)
  294. // to the current last_accessed and last_modified times, because
  295. // FATxx uses a 2s timestamp granularity.
  296. butil::Time new_last_accessed =
  297. info.last_accessed + butil::TimeDelta::FromSeconds(234);
  298. butil::Time new_last_modified =
  299. info.last_modified + butil::TimeDelta::FromMinutes(567);
  300. EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
  301. // Make sure the file info was updated accordingly.
  302. EXPECT_TRUE(file.GetInfo(&info));
  303. EXPECT_EQ(info.size, kTestDataSize);
  304. EXPECT_FALSE(info.is_directory);
  305. EXPECT_FALSE(info.is_symbolic_link);
  306. // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
  307. #if defined(OS_POSIX)
  308. EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
  309. new_last_accessed.ToTimeVal().tv_sec);
  310. EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
  311. new_last_modified.ToTimeVal().tv_sec);
  312. #else
  313. EXPECT_EQ(info.last_accessed.ToInternalValue(),
  314. new_last_accessed.ToInternalValue());
  315. EXPECT_EQ(info.last_modified.ToInternalValue(),
  316. new_last_modified.ToInternalValue());
  317. #endif
  318. EXPECT_EQ(info.creation_time.ToInternalValue(),
  319. creation_time.ToInternalValue());
  320. }
  321. TEST(FileTest, ReadAtCurrentPosition) {
  322. butil::ScopedTempDir temp_dir;
  323. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  324. FilePath file_path = temp_dir.path().AppendASCII("read_at_current_position");
  325. File file(file_path,
  326. butil::File::FLAG_CREATE | butil::File::FLAG_READ |
  327. butil::File::FLAG_WRITE);
  328. EXPECT_TRUE(file.IsValid());
  329. const char kData[] = "test";
  330. const int kDataSize = sizeof(kData) - 1;
  331. EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
  332. EXPECT_EQ(0, file.Seek(butil::File::FROM_BEGIN, 0));
  333. char buffer[kDataSize];
  334. int first_chunk_size = kDataSize / 2;
  335. EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
  336. EXPECT_EQ(kDataSize - first_chunk_size,
  337. file.ReadAtCurrentPos(buffer + first_chunk_size,
  338. kDataSize - first_chunk_size));
  339. EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
  340. }
  341. TEST(FileTest, WriteAtCurrentPosition) {
  342. butil::ScopedTempDir temp_dir;
  343. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  344. FilePath file_path = temp_dir.path().AppendASCII("write_at_current_position");
  345. File file(file_path,
  346. butil::File::FLAG_CREATE | butil::File::FLAG_READ |
  347. butil::File::FLAG_WRITE);
  348. EXPECT_TRUE(file.IsValid());
  349. const char kData[] = "test";
  350. const int kDataSize = sizeof(kData) - 1;
  351. int first_chunk_size = kDataSize / 2;
  352. EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
  353. EXPECT_EQ(kDataSize - first_chunk_size,
  354. file.WriteAtCurrentPos(kData + first_chunk_size,
  355. kDataSize - first_chunk_size));
  356. char buffer[kDataSize];
  357. EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
  358. EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
  359. }
  360. TEST(FileTest, Seek) {
  361. butil::ScopedTempDir temp_dir;
  362. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  363. FilePath file_path = temp_dir.path().AppendASCII("seek_file");
  364. File file(file_path,
  365. butil::File::FLAG_CREATE | butil::File::FLAG_READ |
  366. butil::File::FLAG_WRITE);
  367. ASSERT_TRUE(file.IsValid());
  368. const int64_t kOffset = 10;
  369. EXPECT_EQ(kOffset, file.Seek(butil::File::FROM_BEGIN, kOffset));
  370. EXPECT_EQ(2 * kOffset, file.Seek(butil::File::FROM_CURRENT, kOffset));
  371. EXPECT_EQ(kOffset, file.Seek(butil::File::FROM_CURRENT, -kOffset));
  372. EXPECT_TRUE(file.SetLength(kOffset * 2));
  373. EXPECT_EQ(kOffset, file.Seek(butil::File::FROM_END, -kOffset));
  374. }
  375. #if defined(OS_WIN)
  376. TEST(FileTest, GetInfoForDirectory) {
  377. butil::ScopedTempDir temp_dir;
  378. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  379. FilePath empty_dir = temp_dir.path().Append(FILE_PATH_LITERAL("gpfi_test"));
  380. ASSERT_TRUE(CreateDirectory(empty_dir));
  381. butil::File dir(
  382. ::CreateFile(empty_dir.value().c_str(),
  383. FILE_ALL_ACCESS,
  384. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  385. NULL,
  386. OPEN_EXISTING,
  387. FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
  388. NULL));
  389. ASSERT_TRUE(dir.IsValid());
  390. butil::File::Info info;
  391. EXPECT_TRUE(dir.GetInfo(&info));
  392. EXPECT_TRUE(info.is_directory);
  393. EXPECT_FALSE(info.is_symbolic_link);
  394. EXPECT_EQ(0, info.size);
  395. }
  396. #endif // defined(OS_WIN)