local_file_util_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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 <stdint.h>
  5. #include <memory>
  6. #include <string>
  7. #include "base/files/file.h"
  8. #include "base/files/file_path.h"
  9. #include "base/files/file_util.h"
  10. #include "base/files/scoped_temp_dir.h"
  11. #include "base/run_loop.h"
  12. #include "base/test/task_environment.h"
  13. #include "build/build_config.h"
  14. #include "storage/browser/file_system/async_file_util_adapter.h"
  15. #include "storage/browser/file_system/file_system_context.h"
  16. #include "storage/browser/file_system/file_system_file_util.h"
  17. #include "storage/browser/file_system/file_system_operation_context.h"
  18. #include "storage/browser/file_system/local_file_util.h"
  19. #include "storage/browser/file_system/native_file_util.h"
  20. #include "storage/browser/quota/quota_manager_proxy.h"
  21. #include "storage/browser/test/async_file_test_helper.h"
  22. #include "storage/browser/test/test_file_system_context.h"
  23. #include "storage/common/file_system/file_system_types.h"
  24. #include "testing/gtest/include/gtest/gtest.h"
  25. #include "third_party/blink/public/common/storage_key/storage_key.h"
  26. #include "url/gurl.h"
  27. #include "url/origin.h"
  28. namespace storage {
  29. namespace {
  30. const FileSystemType kFileSystemType = kFileSystemTypeTest;
  31. } // namespace
  32. class LocalFileUtilTest : public testing::Test {
  33. public:
  34. LocalFileUtilTest() = default;
  35. LocalFileUtilTest(const LocalFileUtilTest&) = delete;
  36. LocalFileUtilTest& operator=(const LocalFileUtilTest&) = delete;
  37. void SetUp() override {
  38. ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
  39. file_system_context_ = CreateFileSystemContextForTesting(
  40. /*quota_manager_proxy=*/nullptr, data_dir_.GetPath());
  41. }
  42. void TearDown() override {
  43. file_system_context_ = nullptr;
  44. base::RunLoop().RunUntilIdle();
  45. }
  46. protected:
  47. std::unique_ptr<FileSystemOperationContext> NewContext() {
  48. auto context = std::make_unique<FileSystemOperationContext>(
  49. file_system_context_.get());
  50. context->set_update_observers(
  51. *file_system_context_->GetUpdateObservers(kFileSystemType));
  52. return context;
  53. }
  54. LocalFileUtil* file_util() {
  55. AsyncFileUtilAdapter* adapter = static_cast<AsyncFileUtilAdapter*>(
  56. file_system_context_->GetAsyncFileUtil(kFileSystemType));
  57. return static_cast<LocalFileUtil*>(adapter->sync_file_util());
  58. }
  59. FileSystemURL CreateURL(const std::string& file_name) {
  60. return file_system_context_->CreateCrackedFileSystemURL(
  61. blink::StorageKey::CreateFromStringForTesting("http://foo/"),
  62. kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
  63. }
  64. base::FilePath LocalPath(const char* file_name) {
  65. base::FilePath path;
  66. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  67. file_util()->GetLocalFilePath(context.get(), CreateURL(file_name), &path);
  68. return path;
  69. }
  70. bool FileExists(const char* file_name) {
  71. return base::PathExists(LocalPath(file_name)) &&
  72. !base::DirectoryExists(LocalPath(file_name));
  73. }
  74. bool DirectoryExists(const char* file_name) {
  75. return base::DirectoryExists(LocalPath(file_name));
  76. }
  77. int64_t GetSize(const char* file_name) {
  78. base::File::Info info;
  79. base::GetFileInfo(LocalPath(file_name), &info);
  80. return info.size;
  81. }
  82. base::File CreateFile(const char* file_name) {
  83. int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE |
  84. base::File::FLAG_ASYNC;
  85. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  86. return file_util()->CreateOrOpen(context.get(), CreateURL(file_name),
  87. file_flags);
  88. }
  89. base::File::Error EnsureFileExists(const char* file_name, bool* created) {
  90. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  91. return file_util()->EnsureFileExists(context.get(), CreateURL(file_name),
  92. created);
  93. }
  94. FileSystemContext* file_system_context() {
  95. return file_system_context_.get();
  96. }
  97. private:
  98. base::test::TaskEnvironment task_environment_;
  99. scoped_refptr<FileSystemContext> file_system_context_;
  100. base::ScopedTempDir data_dir_;
  101. };
  102. TEST_F(LocalFileUtilTest, CreateAndClose) {
  103. const char* file_name = "test_file";
  104. base::File file = CreateFile(file_name);
  105. ASSERT_TRUE(file.IsValid());
  106. ASSERT_TRUE(file.created());
  107. EXPECT_TRUE(FileExists(file_name));
  108. EXPECT_EQ(0, GetSize(file_name));
  109. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  110. }
  111. // base::CreateSymbolicLink is supported on most POSIX, but not on Fuchsia.
  112. #if BUILDFLAG(IS_POSIX)
  113. TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
  114. // Create symlink target file.
  115. const char* target_name = "symlink_target";
  116. base::File target_file = CreateFile(target_name);
  117. ASSERT_TRUE(target_file.IsValid());
  118. ASSERT_TRUE(target_file.created());
  119. base::FilePath target_path = LocalPath(target_name);
  120. // Create symlink where target must be real file.
  121. const char* symlink_name = "symlink_file";
  122. base::FilePath symlink_path = LocalPath(symlink_name);
  123. ASSERT_TRUE(base::CreateSymbolicLink(target_path, symlink_path));
  124. ASSERT_TRUE(FileExists(symlink_name));
  125. // Try to open the symlink file which should fail.
  126. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  127. FileSystemURL url = CreateURL(symlink_name);
  128. int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
  129. base::File file = file_util()->CreateOrOpen(context.get(), url, file_flags);
  130. ASSERT_FALSE(file.IsValid());
  131. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
  132. }
  133. #endif
  134. TEST_F(LocalFileUtilTest, EnsureFileExists) {
  135. const char* file_name = "foobar";
  136. bool created;
  137. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(file_name, &created));
  138. ASSERT_TRUE(created);
  139. EXPECT_TRUE(FileExists(file_name));
  140. EXPECT_EQ(0, GetSize(file_name));
  141. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(file_name, &created));
  142. EXPECT_FALSE(created);
  143. }
  144. // TODO(https://crbug.com/702990): Remove this test once last_access_time has
  145. // been removed after PPAPI has been deprecated. Fuchsia does not support touch,
  146. // which breaks this test that relies on it. Since PPAPI is being deprecated,
  147. // this test is excluded from the Fuchsia build.
  148. // See https://crbug.com/1077456 for details.
  149. #if !BUILDFLAG(IS_FUCHSIA)
  150. TEST_F(LocalFileUtilTest, TouchFile) {
  151. const char* file_name = "test_file";
  152. base::File file = CreateFile(file_name);
  153. ASSERT_TRUE(file.IsValid());
  154. ASSERT_TRUE(file.created());
  155. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  156. base::File::Info info;
  157. ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info));
  158. const base::Time new_accessed = info.last_accessed + base::Hours(10);
  159. const base::Time new_modified = info.last_modified + base::Hours(5);
  160. EXPECT_EQ(base::File::FILE_OK,
  161. file_util()->Touch(context.get(), CreateURL(file_name),
  162. new_accessed, new_modified));
  163. ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info));
  164. EXPECT_EQ(new_accessed, info.last_accessed);
  165. EXPECT_EQ(new_modified, info.last_modified);
  166. }
  167. TEST_F(LocalFileUtilTest, TouchDirectory) {
  168. const char* dir_name = "test_dir";
  169. std::unique_ptr<FileSystemOperationContext> context(NewContext());
  170. ASSERT_EQ(base::File::FILE_OK,
  171. file_util()->CreateDirectory(context.get(), CreateURL(dir_name),
  172. false /* exclusive */,
  173. false /* recursive */));
  174. base::File::Info info;
  175. ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info));
  176. const base::Time new_accessed = info.last_accessed + base::Hours(10);
  177. const base::Time new_modified = info.last_modified + base::Hours(5);
  178. EXPECT_EQ(base::File::FILE_OK,
  179. file_util()->Touch(context.get(), CreateURL(dir_name), new_accessed,
  180. new_modified));
  181. ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info));
  182. EXPECT_EQ(new_accessed, info.last_accessed);
  183. EXPECT_EQ(new_modified, info.last_modified);
  184. }
  185. #endif // !BUILDFLAG(IS_FUCHSIA)
  186. TEST_F(LocalFileUtilTest, Truncate) {
  187. const char* file_name = "truncated";
  188. bool created;
  189. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(file_name, &created));
  190. ASSERT_TRUE(created);
  191. std::unique_ptr<FileSystemOperationContext> context;
  192. context = NewContext();
  193. ASSERT_EQ(base::File::FILE_OK,
  194. file_util()->Truncate(context.get(), CreateURL(file_name), 1020));
  195. EXPECT_TRUE(FileExists(file_name));
  196. EXPECT_EQ(1020, GetSize(file_name));
  197. }
  198. TEST_F(LocalFileUtilTest, CopyFile) {
  199. const char* from_file = "fromfile";
  200. const char* to_file1 = "tofile1";
  201. const char* to_file2 = "tofile2";
  202. bool created;
  203. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
  204. ASSERT_TRUE(created);
  205. std::unique_ptr<FileSystemOperationContext> context;
  206. context = NewContext();
  207. ASSERT_EQ(base::File::FILE_OK,
  208. file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
  209. EXPECT_TRUE(FileExists(from_file));
  210. EXPECT_EQ(1020, GetSize(from_file));
  211. ASSERT_EQ(
  212. base::File::FILE_OK,
  213. AsyncFileTestHelper::Copy(file_system_context(), CreateURL(from_file),
  214. CreateURL(to_file1)));
  215. context = NewContext();
  216. ASSERT_EQ(
  217. base::File::FILE_OK,
  218. AsyncFileTestHelper::Copy(file_system_context(), CreateURL(from_file),
  219. CreateURL(to_file2)));
  220. EXPECT_TRUE(FileExists(from_file));
  221. EXPECT_EQ(1020, GetSize(from_file));
  222. EXPECT_TRUE(FileExists(to_file1));
  223. EXPECT_EQ(1020, GetSize(to_file1));
  224. EXPECT_TRUE(FileExists(to_file2));
  225. EXPECT_EQ(1020, GetSize(to_file2));
  226. }
  227. TEST_F(LocalFileUtilTest, CopyDirectory) {
  228. const char* from_dir = "fromdir";
  229. const char* from_file = "fromdir/fromfile";
  230. const char* to_dir = "todir";
  231. const char* to_file = "todir/fromfile";
  232. bool created;
  233. std::unique_ptr<FileSystemOperationContext> context;
  234. context = NewContext();
  235. ASSERT_EQ(base::File::FILE_OK,
  236. file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
  237. false, false));
  238. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
  239. ASSERT_TRUE(created);
  240. context = NewContext();
  241. ASSERT_EQ(base::File::FILE_OK,
  242. file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
  243. EXPECT_TRUE(DirectoryExists(from_dir));
  244. EXPECT_TRUE(FileExists(from_file));
  245. EXPECT_EQ(1020, GetSize(from_file));
  246. EXPECT_FALSE(DirectoryExists(to_dir));
  247. context = NewContext();
  248. ASSERT_EQ(base::File::FILE_OK,
  249. AsyncFileTestHelper::Copy(file_system_context(),
  250. CreateURL(from_dir), CreateURL(to_dir)));
  251. EXPECT_TRUE(DirectoryExists(from_dir));
  252. EXPECT_TRUE(FileExists(from_file));
  253. EXPECT_EQ(1020, GetSize(from_file));
  254. EXPECT_TRUE(DirectoryExists(to_dir));
  255. EXPECT_TRUE(FileExists(to_file));
  256. EXPECT_EQ(1020, GetSize(to_file));
  257. }
  258. TEST_F(LocalFileUtilTest, MoveFile) {
  259. const char* from_file = "fromfile";
  260. const char* to_file = "tofile";
  261. bool created;
  262. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
  263. ASSERT_TRUE(created);
  264. std::unique_ptr<FileSystemOperationContext> context;
  265. context = NewContext();
  266. ASSERT_EQ(base::File::FILE_OK,
  267. file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
  268. EXPECT_TRUE(FileExists(from_file));
  269. EXPECT_EQ(1020, GetSize(from_file));
  270. context = NewContext();
  271. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::Move(
  272. file_system_context(),
  273. CreateURL(from_file), CreateURL(to_file)));
  274. EXPECT_FALSE(FileExists(from_file));
  275. EXPECT_TRUE(FileExists(to_file));
  276. EXPECT_EQ(1020, GetSize(to_file));
  277. }
  278. TEST_F(LocalFileUtilTest, MoveDirectory) {
  279. const char* from_dir = "fromdir";
  280. const char* from_file = "fromdir/fromfile";
  281. const char* to_dir = "todir";
  282. const char* to_file = "todir/fromfile";
  283. bool created;
  284. std::unique_ptr<FileSystemOperationContext> context;
  285. context = NewContext();
  286. ASSERT_EQ(base::File::FILE_OK,
  287. file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
  288. false, false));
  289. ASSERT_EQ(base::File::FILE_OK, EnsureFileExists(from_file, &created));
  290. ASSERT_TRUE(created);
  291. context = NewContext();
  292. ASSERT_EQ(base::File::FILE_OK,
  293. file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
  294. EXPECT_TRUE(DirectoryExists(from_dir));
  295. EXPECT_TRUE(FileExists(from_file));
  296. EXPECT_EQ(1020, GetSize(from_file));
  297. EXPECT_FALSE(DirectoryExists(to_dir));
  298. context = NewContext();
  299. ASSERT_EQ(base::File::FILE_OK,
  300. AsyncFileTestHelper::Move(file_system_context(),
  301. CreateURL(from_dir), CreateURL(to_dir)));
  302. EXPECT_FALSE(DirectoryExists(from_dir));
  303. EXPECT_TRUE(DirectoryExists(to_dir));
  304. EXPECT_TRUE(FileExists(to_file));
  305. EXPECT_EQ(1020, GetSize(to_file));
  306. }
  307. } // namespace storage