blob: c1666926f954cc66562902a0b2aac2c7b2b28235 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "components/arc/session/file_system_status.h"
#include <string.h>
#include <string>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
namespace {
class FileSystemStatusTest : public testing::Test {
public:
FileSystemStatusTest() = default;
~FileSystemStatusTest() override = default;
FileSystemStatusTest(const FileSystemStatusTest&) = delete;
FileSystemStatusTest& operator=(const FileSystemStatusTest&) = delete;
void SetUp() override { ASSERT_TRUE(dir_.CreateUniqueTempDir()); }
protected:
static bool IsAndroidDebuggable(const base::FilePath& json_path) {
return FileSystemStatus::IsAndroidDebuggableForTesting(json_path);
}
static bool ExpandPropertyFiles(const base::FilePath& source_path,
const base::FilePath& dest_path) {
return FileSystemStatus::ExpandPropertyFilesForTesting(source_path,
dest_path);
}
static bool IsSystemImageExtFormat(const base::FilePath& path) {
return FileSystemStatus::IsSystemImageExtFormatForTesting(path);
}
const base::FilePath& GetTempDir() const { return dir_.GetPath(); }
private:
base::ScopedTempDir dir_;
};
// Tests if androidboot.debuggable is set properly.
TEST_F(FileSystemStatusTest, IsAndroidDebuggable) {
constexpr const char kAndroidDebuggableTrueJson[] = R"json({
"ANDROID_DEBUGGABLE": true
})json";
constexpr const char kAndroidDebuggableFalseJson[] = R"json({
"ANDROID_DEBUGGABLE": false
})json";
constexpr const char kInvalidTypeJson[] = R"json([
42
])json";
constexpr const char kInvalidJson[] = R"json({
"ANDROID_DEBUGGABLE": true,
})json";
constexpr const char kKeyNotFoundJson[] = R"json({
"BADKEY": "a"
})json";
constexpr const char kNonBooleanValue[] = R"json({
"ANDROID_DEBUGGABLE": "a"
})json";
constexpr const char kBadKeyType[] = R"json({
42: true
})json";
auto test = [](const base::FilePath& dir, const std::string& str) {
base::FilePath path;
if (!CreateTemporaryFileInDir(dir, &path))
return false;
base::WriteFile(path, str.data(), str.size());
return IsAndroidDebuggable(path);
};
EXPECT_TRUE(test(GetTempDir(), kAndroidDebuggableTrueJson));
EXPECT_FALSE(test(GetTempDir(), kAndroidDebuggableFalseJson));
EXPECT_FALSE(test(GetTempDir(), kInvalidTypeJson));
EXPECT_FALSE(test(GetTempDir(), kInvalidJson));
EXPECT_FALSE(test(GetTempDir(), kKeyNotFoundJson));
EXPECT_FALSE(test(GetTempDir(), kNonBooleanValue));
EXPECT_FALSE(test(GetTempDir(), kBadKeyType));
}
// Tests the case where the json file doesn't exist.
TEST_F(FileSystemStatusTest, IsAndroidDebuggable_NonExistent) {
EXPECT_FALSE(IsAndroidDebuggable(base::FilePath("/nonexistent-path")));
}
// Tests the case where the json file is not readable.
TEST_F(FileSystemStatusTest, IsAndroidDebuggable_CannotRead) {
constexpr const char kValidJson[] = R"json({
"ANDROID_DEBUGGABLE": true
})json";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidJson, strlen(kValidJson));
base::SetPosixFilePermissions(path, 0300); // not readable
EXPECT_FALSE(IsAndroidDebuggable(path));
}
TEST_F(FileSystemStatusTest, ExpandPropertyFiles_NoSource) {
// Both source and dest are not found.
EXPECT_FALSE(ExpandPropertyFiles(base::FilePath("/nonexistent1"),
base::FilePath("/nonexistent2")));
// Both source and dest exist, but the source directory is empty.
base::FilePath source_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &source_dir));
base::FilePath dest_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &dest_dir));
EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir));
// Add default.prop to the source, but not build.prop.
base::FilePath default_prop = source_dir.Append("default.prop");
constexpr const char kDefaultProp[] = "ro.foo=bar\n";
base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp));
EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir));
// Add build.prop too. Then the call should succeed.
base::FilePath build_prop = source_dir.Append("build.prop");
constexpr const char kBuildProp[] = "ro.baz=boo\n";
base::WriteFile(build_prop, kBuildProp, strlen(kBuildProp));
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir));
// Verify two dest files are there.
EXPECT_TRUE(base::PathExists(dest_dir.Append("default.prop")));
EXPECT_TRUE(base::PathExists(dest_dir.Append("build.prop")));
// Verify their content.
// Note: ExpandPropertyFile() adds a trailing LF.
std::string content;
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("default.prop"), &content));
EXPECT_EQ(std::string(kDefaultProp) + "\n", content);
EXPECT_TRUE(base::ReadFileToString(dest_dir.Append("build.prop"), &content));
EXPECT_EQ(std::string(kBuildProp) + "\n", content);
// Finally, test the case where source is valid but the dest is not.
EXPECT_FALSE(ExpandPropertyFiles(source_dir, base::FilePath("/nonexistent")));
}
TEST_F(FileSystemStatusTest, IsSystemImageExtFormat_FileMissing) {
EXPECT_FALSE(IsSystemImageExtFormat(base::FilePath("/nonexistent")));
}
TEST_F(FileSystemStatusTest, IsSystemImageExtFormat_FileSizeTooSmall) {
base::FilePath file;
ASSERT_TRUE(base::CreateTemporaryFile(&file));
char data[100];
memset(data, 0, sizeof(data));
base::WriteFile(file, data, sizeof(data));
EXPECT_FALSE(IsSystemImageExtFormat(file));
}
TEST_F(FileSystemStatusTest, IsSystemImageExtFormat_MagicNumberDoesNotMatch) {
base::FilePath file;
ASSERT_TRUE(base::CreateTemporaryFile(&file));
char data[2048];
memset(data, 0, sizeof(data));
base::WriteFile(file, data, sizeof(data));
EXPECT_FALSE(IsSystemImageExtFormat(file));
}
TEST_F(FileSystemStatusTest, IsSystemImageExtFormat_MagicNumberMatches) {
base::FilePath file;
ASSERT_TRUE(base::CreateTemporaryFile(&file));
char data[2048];
memset(data, 0, sizeof(data));
// Magic signature (0xEF53) is in little-endian order.
data[0x400 + 0x38] = 0x53;
data[0x400 + 0x39] = 0xEF;
base::WriteFile(file, data, sizeof(data));
EXPECT_TRUE(IsSystemImageExtFormat(file));
}
} // namespace
} // namespace arc