blob: c1ed8f63731c43a603a4d769ce55645a6577c018 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <vector>
#include "gtest/gtest.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/file.h"
#include "flutter/fml/mapping.h"
static bool WriteStringToFile(const fml::UniqueFD& fd,
const std::string& contents) {
if (!fml::TruncateFile(fd, contents.size())) {
return false;
}
fml::FileMapping mapping(fd, {fml::FileMapping::Protection::kWrite});
if (mapping.GetSize() != contents.size()) {
return false;
}
if (mapping.GetMutableMapping() == nullptr) {
return false;
}
::memmove(mapping.GetMutableMapping(), contents.data(), contents.size());
return true;
}
static std::string ReadStringFromFile(const fml::UniqueFD& fd) {
fml::FileMapping mapping(fd);
if (mapping.GetMapping() == nullptr) {
return nullptr;
}
return {reinterpret_cast<const char*>(mapping.GetMapping()),
mapping.GetSize()};
}
TEST(FileTest, CreateTemporaryAndUnlink) {
auto dir_name = fml::CreateTemporaryDirectory();
ASSERT_NE(dir_name, "");
auto dir =
fml::OpenDirectory(dir_name.c_str(), false, fml::FilePermission::kRead);
ASSERT_TRUE(dir.is_valid());
dir.reset();
ASSERT_TRUE(fml::UnlinkDirectory(dir_name.c_str()));
}
TEST(FileTest, ScopedTempDirIsValid) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
}
TEST(FileTest, CanOpenFileForWriting) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
auto fd =
fml::OpenFile(dir.fd(), "some.txt", true, fml::FilePermission::kWrite);
ASSERT_TRUE(fd.is_valid());
fd.reset();
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), "some.txt"));
}
TEST(FileTest, CanTruncateAndWrite) {
fml::ScopedTemporaryDirectory dir;
ASSERT_TRUE(dir.fd().is_valid());
std::string contents = "some contents here";
{
auto fd = fml::OpenFile(dir.fd(), "some.txt", true,
fml::FilePermission::kReadWrite);
ASSERT_TRUE(fd.is_valid());
ASSERT_TRUE(fml::TruncateFile(fd, contents.size()));
fml::FileMapping mapping(fd, {fml::FileMapping::Protection::kWrite});
ASSERT_EQ(mapping.GetSize(), contents.size());
ASSERT_NE(mapping.GetMutableMapping(), nullptr);
::memcpy(mapping.GetMutableMapping(), contents.data(), contents.size());
}
{
auto fd =
fml::OpenFile(dir.fd(), "some.txt", false, fml::FilePermission::kRead);
ASSERT_TRUE(fd.is_valid());
fml::FileMapping mapping(fd);
ASSERT_EQ(mapping.GetSize(), contents.size());
ASSERT_EQ(0,
::memcmp(mapping.GetMapping(), contents.data(), contents.size()));
}
fml::UnlinkFile(dir.fd(), "some.txt");
}
TEST(FileTest, CreateDirectoryStructure) {
fml::ScopedTemporaryDirectory dir;
std::string contents = "These are my contents";
{
auto sub = fml::CreateDirectory(dir.fd(), {"a", "b", "c"},
fml::FilePermission::kReadWrite);
ASSERT_TRUE(sub.is_valid());
auto file = fml::OpenFile(sub, "my_contents", true,
fml::FilePermission::kReadWrite);
ASSERT_TRUE(file.is_valid());
ASSERT_TRUE(WriteStringToFile(file, contents));
}
const char* file_path = "a/b/c/my_contents";
{
auto contents_file =
fml::OpenFile(dir.fd(), file_path, false, fml::FilePermission::kRead);
ASSERT_EQ(ReadStringFromFile(contents_file), contents);
}
// Cleanup.
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), file_path));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a/b/c"));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a/b"));
ASSERT_TRUE(fml::UnlinkDirectory(dir.fd(), "a"));
}
#if OS_WIN
#define AtomicWriteTest DISABLED_AtomicWriteTest
#else
#define AtomicWriteTest AtomicWriteTest
#endif
TEST(FileTest, AtomicWriteTest) {
fml::ScopedTemporaryDirectory dir;
const std::string contents = "These are my contents.";
auto data = std::make_unique<fml::DataMapping>(
std::vector<uint8_t>{contents.begin(), contents.end()});
// Write.
ASSERT_TRUE(fml::WriteAtomically(dir.fd(), "precious_data", *data));
// Read and verify.
ASSERT_EQ(contents,
ReadStringFromFile(fml::OpenFile(dir.fd(), "precious_data", false,
fml::FilePermission::kRead)));
// Cleanup.
ASSERT_TRUE(fml::UnlinkFile(dir.fd(), "precious_data"));
}