#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/files/file.h"
#include <stdint.h>
#include <utility>
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(ENABLE_BASE_TRACING)
#include "third_party/perfetto/include/perfetto/test/traced_value_test_support.h"
#endif
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/environment.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gtest_util.h"
#endif
File;
FilePath;
TEST(FileTest, Create) { … }
TEST(FileTest, SelfSwap) { … }
TEST(FileTest, Async) { … }
TEST(FileTest, DeleteOpenFile) { … }
TEST(FileTest, ReadWrite) { … }
TEST(FileTest, ReadWriteSpans) { … }
TEST(FileTest, GetLastFileError) { … }
TEST(FileTest, Append) { … }
TEST(FileTest, Length) { … }
#if BUILDFLAG(IS_ANDROID)
TEST(FileTest, TouchGetInfo) {
#else
TEST(FileTest, DISABLED_TouchGetInfo) { … }
TEST(FileTest, GetInfoForCreationTime) { … }
TEST(FileTest, ReadAtCurrentPosition) { … }
TEST(FileTest, ReadAtCurrentPositionSpans) { … }
TEST(FileTest, WriteAtCurrentPosition) { … }
TEST(FileTest, WriteAtCurrentPositionSpans) { … }
TEST(FileTest, Seek) { … }
TEST(FileTest, Duplicate) { … }
TEST(FileTest, DuplicateDeleteOnClose) { … }
#if BUILDFLAG(ENABLE_BASE_TRACING)
TEST(FileTest, TracedValueSupport) { … }
#endif
#if BUILDFLAG(IS_WIN)
#define MAYBE_WriteDataToLargeOffset …
#else
#define MAYBE_WriteDataToLargeOffset …
#endif
TEST(FileTest, MAYBE_WriteDataToLargeOffset) { … }
TEST(FileTest, AddFlagsForPassingToUntrustedProcess) { … }
#if BUILDFLAG(IS_WIN)
TEST(FileTest, GetInfoForDirectory) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
FilePath empty_dir =
temp_dir.GetPath().Append(FILE_PATH_LITERAL("gpfi_test"));
ASSERT_TRUE(CreateDirectory(empty_dir));
base::File dir(
::CreateFile(empty_dir.value().c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL));
ASSERT_TRUE(dir.IsValid());
base::File::Info info;
EXPECT_TRUE(dir.GetInfo(&info));
EXPECT_TRUE(info.is_directory);
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");
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");
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");
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");
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_WIN_SHARE_DELETE |
base::File::FLAG_CAN_DELETE_ON_CLOSE));
ASSERT_TRUE(file.IsValid());
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");
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_WIN_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_WIN_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");
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");
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_WIN_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");
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));
}
TEST(FileTest, UseSyncApiWithAsyncFile) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
FilePath file_path = temp_dir.GetPath().AppendASCII("file");
File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE |
base::File::FLAG_ASYNC);
File lying_file(file.TakePlatformFile(), false );
ASSERT_TRUE(lying_file.IsValid());
ASSERT_EQ(lying_file.WriteAtCurrentPos("12345", 5), -1);
}
TEST(FileDeathTest, InvalidFlags) {
EXPECT_CHECK_DEATH_WITH(
{
std::string tmp_folder;
ASSERT_TRUE(base::Environment::Create()->GetVar("TMP", &tmp_folder));
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(
base::FilePath(base::UTF8ToWide(tmp_folder))));
FilePath file_path = temp_dir.GetPath().AppendASCII("file");
File file(file_path,
base::File::FLAG_CREATE | base::File::FLAG_WIN_EXECUTE |
base::File::FLAG_READ | base::File::FLAG_WIN_NO_EXECUTE);
},
"FLAG_WIN_NO_EXECUTE");
}
#endif