dragged_file_util_unittest.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. // Copyright 2013 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 "storage/browser/file_system/dragged_file_util.h"
  5. #include <stddef.h>
  6. #include <map>
  7. #include <memory>
  8. #include <set>
  9. #include <string>
  10. #include <vector>
  11. #include "base/check.h"
  12. #include "base/containers/queue.h"
  13. #include "base/files/file_enumerator.h"
  14. #include "base/files/file_util.h"
  15. #include "base/files/scoped_temp_dir.h"
  16. #include "base/test/task_environment.h"
  17. #include "base/time/time.h"
  18. #include "build/build_config.h"
  19. #include "components/services/filesystem/public/mojom/types.mojom.h"
  20. #include "storage/browser/file_system/file_system_context.h"
  21. #include "storage/browser/file_system/file_system_operation_context.h"
  22. #include "storage/browser/file_system/isolated_context.h"
  23. #include "storage/browser/file_system/local_file_util.h"
  24. #include "storage/browser/file_system/native_file_util.h"
  25. #include "storage/browser/quota/quota_manager_proxy.h"
  26. #include "storage/browser/test/async_file_test_helper.h"
  27. #include "storage/browser/test/file_system_test_file_set.h"
  28. #include "storage/browser/test/mock_quota_manager.h"
  29. #include "storage/browser/test/mock_quota_manager_proxy.h"
  30. #include "storage/browser/test/mock_special_storage_policy.h"
  31. #include "storage/browser/test/test_file_system_context.h"
  32. #include "testing/gmock/include/gmock/gmock.h"
  33. #include "testing/gtest/include/gtest/gtest.h"
  34. #include "third_party/blink/public/common/storage_key/storage_key.h"
  35. #include "url/gurl.h"
  36. namespace storage {
  37. namespace {
  38. using FileEntryList = AsyncFileTestHelper::FileEntryList;
  39. // Used in DraggedFileUtilTest::SimulateDropFiles().
  40. // Random root paths in which we create each file/directory of the
  41. // RegularTestCases (so that we can simulate a drop with files/directories
  42. // from multiple directories).
  43. constexpr const base::FilePath::CharType* kRootPaths[] = {
  44. FILE_PATH_LITERAL("a"),
  45. FILE_PATH_LITERAL("b/c"),
  46. FILE_PATH_LITERAL("etc"),
  47. };
  48. base::FilePath GetTopLevelPath(const base::FilePath& path) {
  49. return base::FilePath(path.GetComponents()[0]);
  50. }
  51. bool IsDirectoryEmpty(FileSystemContext* context, const FileSystemURL& url) {
  52. FileEntryList entries;
  53. EXPECT_EQ(base::File::FILE_OK,
  54. AsyncFileTestHelper::ReadDirectory(context, url, &entries));
  55. return entries.empty();
  56. }
  57. FileSystemURL GetEntryURL(FileSystemContext* file_system_context,
  58. const FileSystemURL& dir,
  59. const base::FilePath::StringType& name) {
  60. return file_system_context->CreateCrackedFileSystemURL(
  61. dir.storage_key(), dir.mount_type(), dir.virtual_path().Append(name));
  62. }
  63. base::FilePath GetRelativeVirtualPath(const FileSystemURL& root,
  64. const FileSystemURL& url) {
  65. if (root.virtual_path().empty())
  66. return url.virtual_path();
  67. base::FilePath relative;
  68. const bool success =
  69. root.virtual_path().AppendRelativePath(url.virtual_path(), &relative);
  70. DCHECK(success);
  71. return relative;
  72. }
  73. FileSystemURL GetOtherURL(FileSystemContext* file_system_context,
  74. const FileSystemURL& root,
  75. const FileSystemURL& other_root,
  76. const FileSystemURL& url) {
  77. return file_system_context->CreateCrackedFileSystemURL(
  78. other_root.storage_key(), other_root.mount_type(),
  79. other_root.virtual_path().Append(GetRelativeVirtualPath(root, url)));
  80. }
  81. } // namespace
  82. class DraggedFileUtilTest : public testing::Test {
  83. public:
  84. DraggedFileUtilTest() = default;
  85. DraggedFileUtilTest(const DraggedFileUtilTest&) = delete;
  86. DraggedFileUtilTest& operator=(const DraggedFileUtilTest&) = delete;
  87. void SetUp() override {
  88. ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
  89. ASSERT_TRUE(partition_dir_.CreateUniqueTempDir());
  90. file_util_ = std::make_unique<DraggedFileUtil>();
  91. // Register the files/directories of RegularTestCases (with random
  92. // root paths) as dropped files.
  93. SimulateDropFiles();
  94. base::FilePath partition_path = partition_dir_.GetPath();
  95. quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>(
  96. /*is_incognito=*/false, partition_path,
  97. base::ThreadTaskRunnerHandle::Get(),
  98. base::MakeRefCounted<storage::MockSpecialStoragePolicy>());
  99. quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>(
  100. quota_manager_.get(), base::ThreadTaskRunnerHandle::Get());
  101. // Prepare file system.
  102. file_system_context_ = storage::CreateFileSystemContextForTesting(
  103. quota_manager_proxy_.get(), partition_path);
  104. isolated_context()->AddReference(filesystem_id_);
  105. }
  106. void TearDown() override {
  107. isolated_context()->RemoveReference(filesystem_id_);
  108. }
  109. protected:
  110. IsolatedContext* isolated_context() const {
  111. return IsolatedContext::GetInstance();
  112. }
  113. const base::FilePath& root_path() const { return data_dir_.GetPath(); }
  114. FileSystemContext* file_system_context() const {
  115. return file_system_context_.get();
  116. }
  117. FileSystemFileUtil* file_util() const { return file_util_.get(); }
  118. std::string filesystem_id() const { return filesystem_id_; }
  119. base::FilePath GetTestCasePlatformPath(
  120. const base::FilePath::StringType& path) {
  121. return toplevel_root_map_[GetTopLevelPath(base::FilePath(path))]
  122. .Append(path)
  123. .NormalizePathSeparators();
  124. }
  125. base::FilePath GetTestCaseLocalPath(const base::FilePath& path) {
  126. base::FilePath relative;
  127. if (data_dir_.GetPath().AppendRelativePath(path, &relative))
  128. return relative;
  129. return path;
  130. }
  131. FileSystemURL GetFileSystemURL(const base::FilePath& path) const {
  132. base::FilePath virtual_path =
  133. isolated_context()->CreateVirtualRootPath(filesystem_id()).Append(path);
  134. return file_system_context_->CreateCrackedFileSystemURL(
  135. blink::StorageKey::CreateFromStringForTesting("http://example.com"),
  136. kFileSystemTypeIsolated, virtual_path);
  137. }
  138. FileSystemURL GetOtherFileSystemURL(const base::FilePath& path) const {
  139. return file_system_context()->CreateCrackedFileSystemURL(
  140. blink::StorageKey::CreateFromStringForTesting("http://example.com"),
  141. kFileSystemTypeTemporary,
  142. base::FilePath().AppendASCII("dest").Append(path));
  143. }
  144. void VerifyFilesHaveSameContent(const FileSystemURL& url1,
  145. const FileSystemURL& url2) {
  146. // Get the file info and the platform path for url1.
  147. base::File::Info info1;
  148. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::GetMetadata(
  149. file_system_context(), url1, &info1));
  150. base::FilePath platform_path1;
  151. ASSERT_EQ(base::File::FILE_OK,
  152. AsyncFileTestHelper::GetPlatformPath(file_system_context(), url1,
  153. &platform_path1));
  154. // Get the file info and the platform path for url2.
  155. base::File::Info info2;
  156. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::GetMetadata(
  157. file_system_context(), url2, &info2));
  158. base::FilePath platform_path2;
  159. ASSERT_EQ(base::File::FILE_OK,
  160. AsyncFileTestHelper::GetPlatformPath(file_system_context(), url2,
  161. &platform_path2));
  162. // See if file info matches with the other one.
  163. EXPECT_EQ(info1.is_directory, info2.is_directory);
  164. EXPECT_EQ(info1.size, info2.size);
  165. EXPECT_EQ(info1.is_symbolic_link, info2.is_symbolic_link);
  166. EXPECT_NE(platform_path1, platform_path2);
  167. std::string content1, content2;
  168. EXPECT_TRUE(base::ReadFileToString(platform_path1, &content1));
  169. EXPECT_TRUE(base::ReadFileToString(platform_path2, &content2));
  170. EXPECT_EQ(content1, content2);
  171. }
  172. void VerifyDirectoriesHaveSameContent(const FileSystemURL& root1,
  173. const FileSystemURL& root2) {
  174. base::FilePath root_path1 = root1.path();
  175. base::FilePath root_path2 = root2.path();
  176. FileEntryList entries;
  177. base::queue<FileSystemURL> directories;
  178. directories.push(root1);
  179. std::set<base::FilePath> file_set1;
  180. while (!directories.empty()) {
  181. FileSystemURL dir = directories.front();
  182. directories.pop();
  183. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::ReadDirectory(
  184. file_system_context(), dir, &entries));
  185. for (size_t i = 0; i < entries.size(); ++i) {
  186. FileSystemURL url =
  187. GetEntryURL(file_system_context(), dir, entries[i].name.value());
  188. if (entries[i].type == filesystem::mojom::FsFileType::DIRECTORY) {
  189. directories.push(url);
  190. continue;
  191. }
  192. file_set1.insert(GetRelativeVirtualPath(root1, url));
  193. }
  194. }
  195. directories.push(root2);
  196. while (!directories.empty()) {
  197. FileSystemURL dir = directories.front();
  198. directories.pop();
  199. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::ReadDirectory(
  200. file_system_context(), dir, &entries));
  201. for (size_t i = 0; i < entries.size(); ++i) {
  202. FileSystemURL url2 =
  203. GetEntryURL(file_system_context(), dir, entries[i].name.value());
  204. FileSystemURL url1 =
  205. GetOtherURL(file_system_context(), root2, root1, url2);
  206. if (entries[i].type == filesystem::mojom::FsFileType::DIRECTORY) {
  207. directories.push(url2);
  208. EXPECT_EQ(IsDirectoryEmpty(file_system_context(), url1),
  209. IsDirectoryEmpty(file_system_context(), url2));
  210. continue;
  211. }
  212. base::FilePath relative = GetRelativeVirtualPath(root2, url2);
  213. EXPECT_TRUE(file_set1.find(relative) != file_set1.end());
  214. VerifyFilesHaveSameContent(url1, url2);
  215. }
  216. }
  217. }
  218. std::unique_ptr<FileSystemOperationContext> GetOperationContext() {
  219. return std::make_unique<FileSystemOperationContext>(file_system_context());
  220. }
  221. private:
  222. void SimulateDropFiles() {
  223. size_t root_path_index = 0;
  224. IsolatedContext::FileInfoSet toplevels;
  225. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  226. const FileSystemTestCaseRecord& test_case =
  227. kRegularFileSystemTestCases[i];
  228. base::FilePath path(test_case.path);
  229. base::FilePath toplevel = GetTopLevelPath(path);
  230. // We create the test case files under one of the kRootPaths
  231. // to simulate a drop with multiple directories.
  232. if (toplevel_root_map_.find(toplevel) == toplevel_root_map_.end()) {
  233. base::FilePath root = root_path().Append(
  234. kRootPaths[(root_path_index++) % std::size(kRootPaths)]);
  235. toplevel_root_map_[toplevel] = root;
  236. toplevels.AddPath(root.Append(path), nullptr);
  237. }
  238. SetUpOneFileSystemTestCase(toplevel_root_map_[toplevel], test_case);
  239. }
  240. // Register the toplevel entries.
  241. filesystem_id_ = isolated_context()->RegisterDraggedFileSystem(toplevels);
  242. }
  243. base::ScopedTempDir data_dir_;
  244. base::ScopedTempDir partition_dir_;
  245. base::test::TaskEnvironment task_environment_{
  246. base::test::TaskEnvironment::MainThreadType::IO};
  247. std::string filesystem_id_;
  248. scoped_refptr<storage::MockQuotaManager> quota_manager_;
  249. scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_;
  250. scoped_refptr<FileSystemContext> file_system_context_;
  251. std::map<base::FilePath, base::FilePath> toplevel_root_map_;
  252. std::unique_ptr<DraggedFileUtil> file_util_;
  253. };
  254. TEST_F(DraggedFileUtilTest, BasicTest) {
  255. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  256. SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i);
  257. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  258. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  259. // See if we can query the file info via the isolated FileUtil.
  260. // (This should succeed since we have registered all the top-level
  261. // entries of the test cases in SetUp())
  262. base::File::Info info;
  263. base::FilePath platform_path;
  264. FileSystemOperationContext context(file_system_context());
  265. ASSERT_EQ(base::File::FILE_OK,
  266. file_util()->GetFileInfo(&context, url, &info, &platform_path));
  267. // See if the obtained file info is correct.
  268. if (!test_case.is_directory)
  269. ASSERT_EQ(test_case.data_file_size, info.size);
  270. ASSERT_EQ(test_case.is_directory, info.is_directory);
  271. ASSERT_EQ(GetTestCasePlatformPath(test_case.path),
  272. platform_path.NormalizePathSeparators());
  273. }
  274. }
  275. TEST_F(DraggedFileUtilTest, UnregisteredPathsTest) {
  276. static const FileSystemTestCaseRecord kUnregisteredCases[] = {
  277. {true, FILE_PATH_LITERAL("nonexistent"), 0},
  278. {true, FILE_PATH_LITERAL("nonexistent/dir foo"), 0},
  279. {false, FILE_PATH_LITERAL("nonexistent/false"), 0},
  280. {false, FILE_PATH_LITERAL("foo"), 30},
  281. {false, FILE_PATH_LITERAL("bar"), 20},
  282. };
  283. for (size_t i = 0; i < std::size(kUnregisteredCases); ++i) {
  284. SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
  285. const FileSystemTestCaseRecord& test_case = kUnregisteredCases[i];
  286. // Prepare the test file/directory.
  287. SetUpOneFileSystemTestCase(root_path(), test_case);
  288. // Make sure regular GetFileInfo succeeds.
  289. base::File::Info info;
  290. ASSERT_TRUE(base::GetFileInfo(root_path().Append(test_case.path), &info));
  291. if (!test_case.is_directory)
  292. ASSERT_EQ(test_case.data_file_size, info.size);
  293. ASSERT_EQ(test_case.is_directory, info.is_directory);
  294. }
  295. for (size_t i = 0; i < std::size(kUnregisteredCases); ++i) {
  296. SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
  297. const FileSystemTestCaseRecord& test_case = kUnregisteredCases[i];
  298. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  299. // We should not be able to get the valid URL for unregistered files.
  300. ASSERT_FALSE(url.is_valid());
  301. }
  302. }
  303. TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
  304. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  305. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  306. if (!test_case.is_directory)
  307. continue;
  308. SCOPED_TRACE(testing::Message()
  309. << "Testing RegularTestCases " << i << ": " << test_case.path);
  310. // Read entries in the directory to construct the expected results map.
  311. using EntryMap =
  312. std::map<base::FilePath::StringType, filesystem::mojom::DirectoryEntry>;
  313. EntryMap expected_entry_map;
  314. base::FilePath dir_path = GetTestCasePlatformPath(test_case.path);
  315. base::FileEnumerator file_enum(
  316. dir_path, false /* not recursive */,
  317. base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
  318. base::FilePath current;
  319. while (!(current = file_enum.Next()).empty()) {
  320. base::FileEnumerator::FileInfo file_info = file_enum.GetInfo();
  321. filesystem::mojom::DirectoryEntry entry;
  322. entry.type = file_info.IsDirectory()
  323. ? filesystem::mojom::FsFileType::DIRECTORY
  324. : filesystem::mojom::FsFileType::REGULAR_FILE;
  325. entry.name = current.BaseName();
  326. expected_entry_map[entry.name.value()] = entry;
  327. #if BUILDFLAG(IS_POSIX)
  328. // Creates a symlink for each file/directory.
  329. // They should be ignored by ReadDirectory, so we don't add them
  330. // to expected_entry_map.
  331. base::CreateSymbolicLink(current,
  332. dir_path.Append(current.BaseName().AddExtension(
  333. FILE_PATH_LITERAL("link"))));
  334. #endif
  335. }
  336. // Perform ReadDirectory in the isolated filesystem.
  337. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  338. FileEntryList entries;
  339. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::ReadDirectory(
  340. file_system_context(), url, &entries));
  341. EXPECT_EQ(expected_entry_map.size(), entries.size());
  342. for (const auto& entry : entries) {
  343. auto found = expected_entry_map.find(entry.name.value());
  344. EXPECT_TRUE(found != expected_entry_map.end());
  345. EXPECT_EQ(found->second.name, entry.name);
  346. EXPECT_EQ(found->second.type, entry.type);
  347. }
  348. }
  349. }
  350. TEST_F(DraggedFileUtilTest, GetLocalFilePathTest) {
  351. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  352. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  353. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  354. FileSystemOperationContext context(file_system_context());
  355. base::FilePath local_file_path;
  356. EXPECT_EQ(base::File::FILE_OK,
  357. file_util()->GetLocalFilePath(&context, url, &local_file_path));
  358. EXPECT_EQ(GetTestCasePlatformPath(test_case.path).value(),
  359. local_file_path.value());
  360. }
  361. }
  362. TEST_F(DraggedFileUtilTest, CopyOutFileTest) {
  363. FileSystemURL src_root = GetFileSystemURL(base::FilePath());
  364. FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
  365. FileEntryList entries;
  366. base::queue<FileSystemURL> directories;
  367. directories.push(src_root);
  368. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateDirectory(
  369. file_system_context(), dest_root));
  370. while (!directories.empty()) {
  371. FileSystemURL dir = directories.front();
  372. directories.pop();
  373. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::ReadDirectory(
  374. file_system_context(), dir, &entries));
  375. for (size_t i = 0; i < entries.size(); ++i) {
  376. FileSystemURL src_url =
  377. GetEntryURL(file_system_context(), dir, entries[i].name.value());
  378. FileSystemURL dest_url =
  379. GetOtherURL(file_system_context(), src_root, dest_root, src_url);
  380. if (entries[i].type == filesystem::mojom::FsFileType::DIRECTORY) {
  381. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateDirectory(
  382. file_system_context(), dest_url));
  383. directories.push(src_url);
  384. continue;
  385. }
  386. SCOPED_TRACE(testing::Message()
  387. << "Testing file copy " << src_url.path().value());
  388. ASSERT_EQ(
  389. base::File::FILE_OK,
  390. AsyncFileTestHelper::Copy(file_system_context(), src_url, dest_url));
  391. VerifyFilesHaveSameContent(src_url, dest_url);
  392. }
  393. }
  394. }
  395. TEST_F(DraggedFileUtilTest, CopyOutDirectoryTest) {
  396. FileSystemURL src_root = GetFileSystemURL(base::FilePath());
  397. FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
  398. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateDirectory(
  399. file_system_context(), dest_root));
  400. FileEntryList entries;
  401. ASSERT_EQ(base::File::FILE_OK,
  402. AsyncFileTestHelper::ReadDirectory(file_system_context(), src_root,
  403. &entries));
  404. for (size_t i = 0; i < entries.size(); ++i) {
  405. if (entries[i].type != filesystem::mojom::FsFileType::DIRECTORY)
  406. continue;
  407. FileSystemURL src_url =
  408. GetEntryURL(file_system_context(), src_root, entries[i].name.value());
  409. FileSystemURL dest_url =
  410. GetOtherURL(file_system_context(), src_root, dest_root, src_url);
  411. SCOPED_TRACE(testing::Message()
  412. << "Testing file copy " << src_url.path().value());
  413. ASSERT_EQ(
  414. base::File::FILE_OK,
  415. AsyncFileTestHelper::Copy(file_system_context(), src_url, dest_url));
  416. VerifyDirectoriesHaveSameContent(src_url, dest_url);
  417. }
  418. }
  419. // TODO(https://crbug.com/702990): Remove this test once last_access_time has
  420. // been removed after PPAPI has been deprecated. Fuchsia does not support touch,
  421. // which breaks this test that relies on it. Since PPAPI is being deprecated,
  422. // this test is excluded from the Fuchsia build.
  423. // See https://crbug.com/1077456 for details.
  424. #if !BUILDFLAG(IS_FUCHSIA)
  425. TEST_F(DraggedFileUtilTest, TouchTest) {
  426. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  427. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  428. if (test_case.is_directory)
  429. continue;
  430. SCOPED_TRACE(testing::Message() << test_case.path);
  431. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  432. base::Time last_access_time = base::Time::FromTimeT(1000);
  433. base::Time last_modified_time = base::Time::FromTimeT(2000);
  434. EXPECT_EQ(base::File::FILE_OK,
  435. file_util()->Touch(GetOperationContext().get(), url,
  436. last_access_time, last_modified_time));
  437. // Verification.
  438. base::File::Info info;
  439. base::FilePath platform_path;
  440. ASSERT_EQ(base::File::FILE_OK,
  441. file_util()->GetFileInfo(GetOperationContext().get(), url, &info,
  442. &platform_path));
  443. EXPECT_EQ(last_access_time.ToTimeT(), info.last_accessed.ToTimeT());
  444. EXPECT_EQ(last_modified_time.ToTimeT(), info.last_modified.ToTimeT());
  445. }
  446. }
  447. #endif // !BUILDFLAG(IS_FUCHSIA)
  448. TEST_F(DraggedFileUtilTest, TruncateTest) {
  449. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  450. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  451. if (test_case.is_directory)
  452. continue;
  453. SCOPED_TRACE(testing::Message() << test_case.path);
  454. FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
  455. // Truncate to 0.
  456. base::File::Info info;
  457. base::FilePath platform_path;
  458. EXPECT_EQ(base::File::FILE_OK,
  459. file_util()->Truncate(GetOperationContext().get(), url, 0));
  460. ASSERT_EQ(base::File::FILE_OK,
  461. file_util()->GetFileInfo(GetOperationContext().get(), url, &info,
  462. &platform_path));
  463. EXPECT_EQ(0, info.size);
  464. // Truncate (extend) to 999.
  465. EXPECT_EQ(base::File::FILE_OK,
  466. file_util()->Truncate(GetOperationContext().get(), url, 999));
  467. ASSERT_EQ(base::File::FILE_OK,
  468. file_util()->GetFileInfo(GetOperationContext().get(), url, &info,
  469. &platform_path));
  470. EXPECT_EQ(999, info.size);
  471. }
  472. }
  473. TEST_F(DraggedFileUtilTest, EnumerateTest) {
  474. FileSystemURL url =
  475. GetFileSystemURL(base::FilePath(FILE_PATH_LITERAL("dir a")));
  476. auto enumerator = file_util()->CreateFileEnumerator(
  477. GetOperationContext().get(), url, false);
  478. std::vector<base::FilePath> contents;
  479. for (base::FilePath path = enumerator->Next(); !path.empty();
  480. path = enumerator->Next()) {
  481. base::FilePath relative;
  482. root_path()
  483. .Append(base::FilePath(FILE_PATH_LITERAL("a")))
  484. .AppendRelativePath(path, &relative);
  485. contents.push_back(relative);
  486. }
  487. EXPECT_THAT(contents, testing::UnorderedElementsAre(
  488. base::FilePath(FILE_PATH_LITERAL("dir a/dir A"))
  489. .NormalizePathSeparators(),
  490. base::FilePath(FILE_PATH_LITERAL("dir a/dir d"))
  491. .NormalizePathSeparators(),
  492. base::FilePath(FILE_PATH_LITERAL("dir a/file 0"))
  493. .NormalizePathSeparators()));
  494. }
  495. TEST_F(DraggedFileUtilTest, EnumerateRecursivelyTest) {
  496. FileSystemURL url =
  497. GetFileSystemURL(base::FilePath(FILE_PATH_LITERAL("dir a")));
  498. auto enumerator =
  499. file_util()->CreateFileEnumerator(GetOperationContext().get(), url, true);
  500. std::vector<base::FilePath> contents;
  501. for (base::FilePath path = enumerator->Next(); !path.empty();
  502. path = enumerator->Next()) {
  503. base::FilePath relative;
  504. root_path()
  505. .Append(base::FilePath(FILE_PATH_LITERAL("a")))
  506. .AppendRelativePath(path, &relative);
  507. contents.push_back(relative);
  508. }
  509. EXPECT_THAT(
  510. contents,
  511. testing::UnorderedElementsAre(
  512. base::FilePath(FILE_PATH_LITERAL("dir a/dir A"))
  513. .NormalizePathSeparators(),
  514. base::FilePath(FILE_PATH_LITERAL("dir a/dir d"))
  515. .NormalizePathSeparators(),
  516. base::FilePath(FILE_PATH_LITERAL("dir a/file 0"))
  517. .NormalizePathSeparators(),
  518. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e"))
  519. .NormalizePathSeparators(),
  520. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir f"))
  521. .NormalizePathSeparators(),
  522. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir g"))
  523. .NormalizePathSeparators(),
  524. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 0"))
  525. .NormalizePathSeparators(),
  526. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 1"))
  527. .NormalizePathSeparators(),
  528. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 2"))
  529. .NormalizePathSeparators(),
  530. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir g/file 3"))
  531. .NormalizePathSeparators(),
  532. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir h"))
  533. .NormalizePathSeparators(),
  534. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir h/file 0"))
  535. .NormalizePathSeparators(),
  536. base::FilePath(FILE_PATH_LITERAL("dir a/dir d/dir e/dir h/file 1"))
  537. .NormalizePathSeparators()));
  538. }
  539. } // namespace storage