Index: base/files/file_unittest.cc |
diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc |
index d3a5cdfa9b7770d8cfad8f085e80a6ed4898768e..66c312b60d4cff0d296384d829e529db94a74d28 100644 |
--- a/base/files/file_unittest.cc |
+++ b/base/files/file_unittest.cc |
@@ -9,6 +9,7 @@ |
#include <utility> |
#include "base/files/file_util.h" |
+#include "base/files/memory_mapped_file.h" |
#include "base/files/scoped_temp_dir.h" |
#include "base/time/time.h" |
#include "build/build_config.h" |
@@ -517,4 +518,158 @@ TEST(FileTest, GetInfoForDirectory) { |
EXPECT_FALSE(info.is_symbolic_link); |
EXPECT_EQ(0, info.size); |
} |
+ |
+TEST(FileTest, DeleteNoop) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // Creating and closing a file with DELETE perms should do nothing special. |
+ File file(file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ file.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, Delete) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // Creating a file with DELETE and then marking for delete on close should |
+ // delete it. |
+ File file(file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ ASSERT_TRUE(file.DeleteOnClose(true)); |
+ file.Close(); |
+ ASSERT_FALSE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, DeleteThenRevoke) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // Creating a file with DELETE, marking it for delete, then clearing delete on |
+ // close should not delete it. |
+ File file(file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ ASSERT_TRUE(file.DeleteOnClose(true)); |
+ ASSERT_TRUE(file.DeleteOnClose(false)); |
+ file.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, IrrevokableDeleteOnClose) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // DELETE_ON_CLOSE cannot be revoked by this opener. |
+ File file( |
+ file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE | |
+ base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ // https://msdn.microsoft.com/library/windows/desktop/aa364221.aspx says that |
+ // setting the dispositon has no effect if the handle was opened with |
+ // FLAG_DELETE_ON_CLOSE. Do not make the test's success dependent on whether |
+ // or not SetFileInformationByHandle indicates success or failure. (It happens |
+ // to indicate success on Windows 10.) |
+ file.DeleteOnClose(false); |
+ file.Close(); |
+ ASSERT_FALSE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, IrrevokableDeleteOnCloseOther) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // DELETE_ON_CLOSE cannot be revoked by another opener. |
+ File file( |
+ file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE | |
+ base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ |
+ File file2( |
+ file_path, |
+ (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE | |
+ base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file2.IsValid()); |
+ |
+ file2.DeleteOnClose(false); |
+ file2.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+ file.Close(); |
+ ASSERT_FALSE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, DeleteWithoutPermission) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // It should not be possible to mark a file for deletion when it was not |
+ // created/opened with DELETE. |
+ File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ ASSERT_FALSE(file.DeleteOnClose(true)); |
+ file.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, UnsharedDeleteOnClose) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // Opening with DELETE_ON_CLOSE when a previous opener hasn't enabled sharing |
+ // will fail. |
+ File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ File file2( |
+ file_path, |
+ (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE | |
+ base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_SHARE_DELETE)); |
+ ASSERT_FALSE(file2.IsValid()); |
+ |
+ file.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+} |
+ |
+TEST(FileTest, NoDeleteOnCloseWithMappedFile) { |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ FilePath file_path = temp_dir.GetPath().AppendASCII("file"); |
+ |
+ // Mapping a file into memory blocks DeleteOnClose. |
+ File file(file_path, |
+ (base::File::FLAG_CREATE | base::File::FLAG_READ | |
+ base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE)); |
+ ASSERT_TRUE(file.IsValid()); |
+ ASSERT_EQ(5, file.WriteAtCurrentPos("12345", 5)); |
+ |
+ { |
+ base::MemoryMappedFile mapping; |
+ ASSERT_TRUE(mapping.Initialize(file.Duplicate())); |
+ ASSERT_EQ(5U, mapping.length()); |
+ |
+ EXPECT_FALSE(file.DeleteOnClose(true)); |
+ } |
+ |
+ file.Close(); |
+ ASSERT_TRUE(base::PathExists(file_path)); |
+} |
#endif // defined(OS_WIN) |