blob: 9cee8afc42bcf9c977c7e00c9e3b71c0df3b5018 [file] [log] [blame] [edit]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DIAGNOSTICS_BASE_FILE_TEST_UTILS_H_
#define DIAGNOSTICS_BASE_FILE_TEST_UTILS_H_
#include <initializer_list>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <gtest/gtest.h>
#include "diagnostics/base/file_utils.h"
#include "diagnostics/base/path_literal.h"
namespace diagnostics {
// Write |file_contents| into file located in |file_path|. Also will create all
// nested parent directories if necessary.
bool WriteFileAndCreateParentDirs(const base::FilePath& file_path,
const std::string& file_contents);
// Write |file_contents| into file located in |file_path|, then create a
// symbolic link which points to |file_path|. Will create all nested parent
// directories if necessary.
bool WriteFileAndCreateSymbolicLink(const base::FilePath& file_path,
const std::string& file_contents,
const base::FilePath& symlink_path);
// A helper class for creating file related unittest.
class BaseFileTest : public ::testing::Test {
protected:
// Unittest usually sets a lot of files with literal string constant filename.
// This helper class can help to convert those constants into
// |base::FilePath|. So the literal string constants can be used without
// converting.
class PathType {
public:
PathType() = delete;
PathType(const PathType& oth) = default;
PathType(PathType&& oth) = default;
PathType(const char* path) // NOLINT(runtime/explicit)
: file_path_(path) {}
PathType(const std::string& path) // NOLINT(runtime/explicit)
: file_path_(path) {}
PathType(const base::FilePath& path) // NOLINT(runtime/explicit)
: file_path_(path) {}
PathType(base::FilePath&& path) // NOLINT(runtime/explicit)
: file_path_(std::move(path)) {}
PathType(PathLiteral path) // NOLINT(runtime/explicit)
: file_path_(path.ToPath()) {}
template <std::size_t Size>
PathType(StaticPathLiteral<Size> path) // NOLINT(runtime/explicit)
: file_path_(path.ToPath()) {}
// Join each part of path into a single path. For example, {"a/b", "c"} =>
// "a/b/c". This is convenient for the following case:
// SetFile({kDir, kDir2, kFilename}, ...);
//
PathType(
std::initializer_list<std::string> paths); // NOLINT(runtime/explicit)
const base::FilePath& file_path() const { return file_path_; }
private:
base::FilePath file_path_;
};
public:
BaseFileTest(const BaseFileTest&) = delete;
BaseFileTest& operator=(const BaseFileTest&) = delete;
protected:
BaseFileTest() = default;
// Unsets a file or a directory in the test rootfs.
void UnsetPath(const PathType& path) const;
// Creates a symbolic link at |path| which points to |target|. The parent
// directories will be created if they don't exist.
void SetSymbolicLink(const PathType& target, const PathType& path);
// Turns the path into the path under the test rootfs. This should work for
// both absolute and relative path.
base::FilePath GetPathUnderRoot(const PathType& path) const;
// Creates a file in the test rootfs. The parent directories will be created
// if they don't exist. |ContentType| can be |std::string| or
// |base::span<const uint8_t>| (for binary data).
template <typename ContentType>
void SetFile(const PathType& path, ContentType&& content) const {
ASSERT_FALSE(GetRootDir().empty());
auto file = GetPathUnderRoot(path);
ASSERT_TRUE(base::CreateDirectory(file.DirName()));
ASSERT_TRUE(base::WriteFile(file, std::forward<ContentType>(content)));
}
// Sets fake cros config data. If `nullopt` is passed the cros config field
// will be removed.
void SetFakeCrosConfig(const PathType& path,
const std::optional<std::string>& data);
private:
std::unique_ptr<ScopedRootDirOverrides> scoped_root_dir_ =
std::make_unique<ScopedRootDirOverrides>();
};
} // namespace diagnostics
#endif // DIAGNOSTICS_BASE_FILE_TEST_UTILS_H_