blob: 94f7daf40b9152eca8ee29c66bef4b218f6a113c [file] [log] [blame]
// Copyright 2021 The Chromium OS 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 "arc/setup/arc_property_util.h"
#include <memory>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/stringprintf.h>
#include <chromeos-config/libcros_config/cros_config.h>
#include <chromeos-config/libcros_config/fake_cros_config.h>
#include <testing/gtest/include/gtest/gtest.h>
namespace arc {
namespace {
constexpr char kCrosConfigPropertiesPath[] = "/arc/build-properties";
class ArcPropertyUtilTest : public testing::Test {
public:
ArcPropertyUtilTest() = default;
~ArcPropertyUtilTest() override = default;
ArcPropertyUtilTest(const ArcPropertyUtilTest&) = delete;
ArcPropertyUtilTest& operator=(const ArcPropertyUtilTest&) = delete;
void SetUp() override { ASSERT_TRUE(dir_.CreateUniqueTempDir()); }
protected:
const base::FilePath& GetTempDir() const { return dir_.GetPath(); }
brillo::FakeCrosConfig* config() { return &config_; }
private:
brillo::FakeCrosConfig config_;
base::ScopedTempDir dir_;
};
TEST_F(ArcPropertyUtilTest, TestPropertyExpansions) {
config()->SetString("/arc/build-properties", "brand", "alphabet");
std::string expanded;
EXPECT_TRUE(ExpandPropertyContentsForTesting(
"ro.a=line1\nro.b={brand}\nro.c=line3\nro.d={brand} {brand}", config(),
/*debuggable=*/false, &expanded));
EXPECT_EQ("ro.a=line1\nro.b=alphabet\nro.c=line3\nro.d=alphabet alphabet\n",
expanded);
}
TEST_F(ArcPropertyUtilTest, TestPropertyExpansionsUnmatchedBrace) {
config()->SetString("/arc/build-properties", "brand", "alphabet");
std::string expanded;
EXPECT_FALSE(ExpandPropertyContentsForTesting(
"ro.a=line{1\nro.b=line}2\nro.c=line3", config(), /*debuggable=*/false,
&expanded));
}
TEST_F(ArcPropertyUtilTest, TestPropertyExpansionsRecursive) {
config()->SetString("/arc/build-properties", "brand", "alphabet");
config()->SetString("/arc/build-properties", "model", "{brand} soup");
std::string expanded;
EXPECT_TRUE(ExpandPropertyContentsForTesting(
"ro.a={model}", config(), /*debuggable=*/false, &expanded));
EXPECT_EQ("ro.a=alphabet soup\n", expanded);
}
TEST_F(ArcPropertyUtilTest, TestPropertyExpansionsMissingProperty) {
config()->SetString("/arc/build-properties", "model", "{brand} soup");
std::string expanded;
EXPECT_FALSE(ExpandPropertyContentsForTesting(
"ro.a={missing-property}", config(), /*debuggable=*/false, &expanded));
EXPECT_FALSE(ExpandPropertyContentsForTesting(
"ro.a={model}", config(), /*debuggable=*/false, &expanded));
}
// Verify that ro.product.board gets copied to ro.oem.key1 as well.
TEST_F(ArcPropertyUtilTest, TestPropertyExpansionBoard) {
config()->SetString("/arc/build-properties", "board", "testboard");
std::string expanded;
EXPECT_TRUE(ExpandPropertyContentsForTesting(
"ro.product.board={board}", config(), /*debuggable=*/false, &expanded));
EXPECT_EQ("ro.product.board=testboard\nro.oem.key1=testboard\n", expanded);
}
TEST_F(ArcPropertyUtilTest, TestPropertyExpansionDebuggable) {
std::string expanded;
EXPECT_TRUE(ExpandPropertyContentsForTesting(
"ro.debuggable=0", config(), /*debuggable=*/false, &expanded));
EXPECT_EQ("ro.debuggable=0\n", expanded);
EXPECT_TRUE(ExpandPropertyContentsForTesting(
"ro.debuggable=1", config(), /*debuggable=*/false, &expanded));
EXPECT_EQ("ro.debuggable=0\n", expanded);
EXPECT_TRUE(ExpandPropertyContentsForTesting("ro.debuggable=0", config(),
/*debuggable*/ true, &expanded));
EXPECT_EQ("ro.debuggable=1\n", expanded);
EXPECT_TRUE(ExpandPropertyContentsForTesting("ro.debuggable=1", config(),
/*debuggable*/ true, &expanded));
EXPECT_EQ("ro.debuggable=1\n", expanded);
}
// Non-fingerprint property should do simple truncation.
TEST_F(ArcPropertyUtilTest, TestPropertyTruncation) {
std::string truncated;
EXPECT_TRUE(TruncateAndroidPropertyForTesting(
"property.name="
"012345678901234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901",
&truncated));
EXPECT_EQ(
"property.name=0123456789012345678901234567890123456789"
"012345678901234567890123456789012345678901234567890",
truncated);
}
// Fingerprint truncation with /release-keys should do simple truncation.
TEST_F(ArcPropertyUtilTest, TestPropertyTruncationFingerprintRelease) {
std::string truncated;
EXPECT_TRUE(TruncateAndroidPropertyForTesting(
"ro.bootimage.build.fingerprint=google/toolongdevicename/"
"toolongdevicename_cheets:7.1.1/R65-10299.0.9999/4538390:user/"
"release-keys",
&truncated));
EXPECT_EQ(
"ro.bootimage.build.fingerprint=google/toolongdevicename/"
"toolongdevicename_cheets:7.1.1/R65-10299.0.9999/4538390:user/relea",
truncated);
}
// Fingerprint truncation with /dev-keys needs to preserve the /dev-keys.
TEST_F(ArcPropertyUtilTest, TestPropertyTruncationFingerprintDev) {
std::string truncated;
EXPECT_TRUE(TruncateAndroidPropertyForTesting(
"ro.bootimage.build.fingerprint=google/toolongdevicename/"
"toolongdevicename_cheets:7.1.1/R65-10299.0.9999/4538390:user/dev-keys",
&truncated));
EXPECT_EQ(
"ro.bootimage.build.fingerprint=google/toolongdevicena/"
"toolongdevicena_cheets/R65-10299.0.9999/4538390:user/dev-keys",
truncated);
}
// Fingerprint truncation with the wrong format should fail.
TEST_F(ArcPropertyUtilTest, TestPropertyTruncationBadFingerprint) {
std::string truncated;
EXPECT_FALSE(TruncateAndroidPropertyForTesting(
"ro.bootimage.build.fingerprint=google/toolongdevicename/"
"toolongdevicename_cheets:7.1.1:123456789012345678901234567890/dev-keys",
&truncated));
}
// Fingerprint truncation without enough room should fail.
TEST_F(ArcPropertyUtilTest, TestPropertyTruncationFingerprintShortDevice) {
std::string truncated;
EXPECT_FALSE(TruncateAndroidPropertyForTesting(
"ro.bootimage.build.fingerprint=google/dev/"
"dev_cheets:7.1.1/R65-10299.0.9999/453839012345678901234567890"
"12345678901234567890:user/dev-keys",
&truncated));
}
// Tests that ExpandPropertyFile works as intended when no property expantion
// is needed.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_NoExpansion) {
constexpr const char kValidProp[] = "ro.foo=bar\nro.baz=boo";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidProp, strlen(kValidProp));
const base::FilePath dest = GetTempDir().Append("new.prop");
EXPECT_TRUE(ExpandPropertyFileForTesting(path, dest, config()));
std::string content;
EXPECT_TRUE(base::ReadFileToString(dest, &content));
EXPECT_EQ(std::string(kValidProp) + "\n", content);
}
// Tests that ExpandPropertyFile works as intended when property expantion
// is needed.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_Expansion) {
config()->SetString(kCrosConfigPropertiesPath, "k1", "v1");
config()->SetString(kCrosConfigPropertiesPath, "k2", "v2");
constexpr const char kValidProp[] = "ro.foo={k1}\nro.baz={k2}";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidProp, strlen(kValidProp));
const base::FilePath dest = GetTempDir().Append("new.prop");
EXPECT_TRUE(ExpandPropertyFileForTesting(path, dest, config()));
std::string content;
EXPECT_TRUE(base::ReadFileToString(dest, &content));
EXPECT_EQ("ro.foo=v1\nro.baz=v2\n", content);
}
// Tests that ExpandPropertyFile works as intended when nested property
// expantion is needed.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_NestedExpansion) {
config()->SetString(kCrosConfigPropertiesPath, "k1", "{k2}");
config()->SetString(kCrosConfigPropertiesPath, "k2", "v2");
constexpr const char kValidProp[] = "ro.foo={k1}\nro.baz={k2}";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidProp, strlen(kValidProp));
const base::FilePath dest = GetTempDir().Append("new.prop");
EXPECT_TRUE(ExpandPropertyFileForTesting(path, dest, config()));
std::string content;
EXPECT_TRUE(base::ReadFileToString(dest, &content));
EXPECT_EQ("ro.foo=v2\nro.baz=v2\n", content);
}
// Test that ExpandPropertyFile handles the case where a property is not found.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_CannotExpand) {
constexpr const char kValidProp[] =
"ro.foo={nonexistent-property}\nro.baz=boo\n";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidProp, strlen(kValidProp));
const base::FilePath dest = GetTempDir().Append("new.prop");
EXPECT_FALSE(ExpandPropertyFileForTesting(path, dest, config()));
}
// Test that ExpandPropertyFile handles the case where the input file is not
// found.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_NoSourceFile) {
EXPECT_FALSE(ExpandPropertyFileForTesting(base::FilePath("/nonexistent"),
base::FilePath("/nonexistent2"),
config()));
}
// Test that ExpandPropertyFile handles the case where the output file cannot
// be written.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFile_CannotWrite) {
constexpr const char kValidProp[] = "ro.foo=bar\nro.baz=boo\n";
base::FilePath path;
ASSERT_TRUE(CreateTemporaryFileInDir(GetTempDir(), &path));
base::WriteFile(path, kValidProp, strlen(kValidProp));
EXPECT_FALSE(ExpandPropertyFileForTesting(
path, base::FilePath("/nonexistent2"), config()));
}
TEST_F(ArcPropertyUtilTest, ExpandPropertyFiles) {
// Both source and dest are not found.
EXPECT_FALSE(ExpandPropertyFiles(base::FilePath("/nonexistent1"),
base::FilePath("/nonexistent2"),
/*single_file=*/false,
/*add_native_bridge...=*/false,
/*debuggable=*/false));
// 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, false, false, false));
// Add default.prop to the source, but not build.prop.
base::FilePath default_prop = source_dir.Append("default.prop");
// Add a non-ro property to make sure that the property is NOT filetered out
// when not in the "append" mode.
constexpr const char kDefaultProp[] = "dalvik.a=b\nro.foo=bar\n";
base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp));
EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
// Add build.prop too. The call should not succeed still.
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_FALSE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
// Add vendor_build.prop too. Then the call should succeed.
base::FilePath vendor_build_prop = source_dir.Append("vendor_build.prop");
constexpr const char kVendorBuildProp[] = "ro.a=b\n";
base::WriteFile(vendor_build_prop, kVendorBuildProp,
strlen(kVendorBuildProp));
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
// Verify all dest files are there.
EXPECT_TRUE(base::PathExists(dest_dir.Append("default.prop")));
EXPECT_TRUE(base::PathExists(dest_dir.Append("build.prop")));
EXPECT_TRUE(base::PathExists(dest_dir.Append("vendor_build.prop")));
// Verify their content.
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);
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("vendor_build.prop"), &content));
EXPECT_EQ(std::string(kVendorBuildProp) + "\n", content);
// Expand it again, verify the previous result is cleared.
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("default.prop"), &content));
EXPECT_EQ(std::string(kDefaultProp) + "\n", content);
// If default.prop does not exist in the source path, it should still process
// the other files, while also ensuring that default.prop is removed from the
// destination path.
base::DeleteFile(dest_dir.Append("default.prop"));
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
EXPECT_TRUE(base::ReadFileToString(dest_dir.Append("build.prop"), &content));
EXPECT_EQ(std::string(kBuildProp) + "\n", content);
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("vendor_build.prop"), &content));
EXPECT_EQ(std::string(kVendorBuildProp) + "\n", content);
// Finally, test the case where source is valid but the dest is not.
EXPECT_FALSE(ExpandPropertyFiles(source_dir, base::FilePath("/nonexistent"),
false, false, false));
}
// Do the same as the previous test, but with |single_file| == true.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFiles_SingleFile) {
// Both source and dest are not found.
EXPECT_FALSE(ExpandPropertyFiles(base::FilePath("/nonexistent1"),
base::FilePath("/nonexistent2"),
/*single_file=*/true,
/*add_native_bridge...=*/false,
/*debuggable=*/false));
// 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_prop_file;
ASSERT_TRUE(
base::CreateTemporaryDirInDir(GetTempDir(), "test", &dest_prop_file));
dest_prop_file = dest_prop_file.Append("combined.prop");
EXPECT_FALSE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Add default.prop to the source, but not build.prop.
const base::FilePath default_prop = source_dir.Append("default.prop");
// Add a non-ro property to make sure that the property is filetered out when
// in the "append" mode.
constexpr const char kDefaultPropNonRo[] = "dalvik.a=b\n";
constexpr const char kDefaultProp[] = "ro.foo=bar\n";
base::WriteFile(default_prop,
base::StringPrintf("%s%s", kDefaultPropNonRo, kDefaultProp));
EXPECT_FALSE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Add build.prop too. The call should not succeed still.
const 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_FALSE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Add vendor_build.prop too. Then the call should succeed.
const base::FilePath vendor_build_prop =
source_dir.Append("vendor_build.prop");
constexpr const char kVendorBuildProp[] = "ro.a=b\n";
base::WriteFile(vendor_build_prop, kVendorBuildProp,
strlen(kVendorBuildProp));
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Add other optional files too. Then the call should succeed.
const base::FilePath system_ext_build_prop =
source_dir.Append("system_ext_build.prop");
constexpr const char kSystemExtBuildProp[] = "ro.c=d\n";
base::WriteFile(system_ext_build_prop, kSystemExtBuildProp,
strlen(kSystemExtBuildProp));
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
const base::FilePath odm_build_prop = source_dir.Append("odm_build.prop");
constexpr const char kOdmBuildProp[] = "ro.e=f\n";
base::WriteFile(odm_build_prop, kOdmBuildProp, strlen(kOdmBuildProp));
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
const base::FilePath product_build_prop =
source_dir.Append("product_build.prop");
constexpr const char kProductBuildProp[] = "ro.g=h\n";
base::WriteFile(product_build_prop, kProductBuildProp,
strlen(kProductBuildProp));
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Verify only one dest file exists.
EXPECT_FALSE(
base::PathExists(dest_prop_file.DirName().Append("default.prop")));
EXPECT_FALSE(base::PathExists(dest_prop_file.DirName().Append("build.prop")));
EXPECT_FALSE(
base::PathExists(dest_prop_file.DirName().Append("vendor_build.prop")));
EXPECT_FALSE(base::PathExists(
dest_prop_file.DirName().Append("system_ext_build.prop")));
EXPECT_FALSE(
base::PathExists(dest_prop_file.DirName().Append("odm_build.prop")));
EXPECT_FALSE(
base::PathExists(dest_prop_file.DirName().Append("product_build.prop")));
EXPECT_TRUE(base::PathExists(dest_prop_file));
// Verify the content.
std::string content;
EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
// Don't include kDefaultPropNonRo since that one should be filtered out.
EXPECT_EQ(base::StringPrintf("%s%s%s%s%s%s", kDefaultProp, kBuildProp,
kSystemExtBuildProp, kVendorBuildProp,
kOdmBuildProp, kProductBuildProp),
content);
// Expand it again, verify the previous result is cleared.
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
EXPECT_EQ(base::StringPrintf("%s%s%s%s%s%s", kDefaultProp, kBuildProp,
kSystemExtBuildProp, kVendorBuildProp,
kOdmBuildProp, kProductBuildProp),
content);
// If optional ones e.g. default.prop does not exist in the source path, it
// should still process the other files.
base::DeleteFile(source_dir.Append("default.prop"));
base::DeleteFile(source_dir.Append("odm_build.prop"));
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
EXPECT_EQ(base::StringPrintf("%s%s%s%s", kBuildProp, kSystemExtBuildProp,
kVendorBuildProp, kProductBuildProp),
content);
// Finally, test the case where source is valid but the dest is not.
EXPECT_FALSE(ExpandPropertyFiles(source_dir, base::FilePath("/nonexistent"),
true, false, false));
}
// Test that ExpandPropertyFiles handles properties related to native bridge
// 64-bit support properly.
TEST_F(ArcPropertyUtilTest, TestNativeBridge64Support) {
// Set up some properties files.
base::FilePath source_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &source_dir));
base::FilePath dest_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &dest_dir));
base::FilePath default_prop = source_dir.Append("default.prop");
constexpr const char kDefaultProp[] = "ro.foo=bar\n";
base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp));
base::FilePath build_prop = source_dir.Append("build.prop");
constexpr const char kBuildProp[] =
"ro.baz=boo\n"
"ro.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi\n"
"ro.product.cpu.abilist64=x86_64\n";
base::WriteFile(build_prop, kBuildProp, strlen(kBuildProp));
base::FilePath vendor_build_prop = source_dir.Append("vendor_build.prop");
constexpr const char kVendorBuildProp[] =
"ro.a=b\n"
"ro.vendor.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi\n"
"ro.vendor.product.cpu.abilist64=x86_64\n";
base::WriteFile(vendor_build_prop, kVendorBuildProp,
strlen(kVendorBuildProp));
// Expand with experiment off, verify properties are untouched.
std::string content;
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false, false, false));
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);
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("vendor_build.prop"), &content));
EXPECT_EQ(std::string(kVendorBuildProp) + "\n", content);
// Expand with experiment on, verify properties are added / modified in
// build.prop but not other files.
EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false, true, false));
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));
constexpr const char kBuildPropModifiedFirst[] =
"ro.baz=boo\n"
"ro.product.cpu.abilist=x86_64,x86,arm64-v8a,armeabi-v7a,armeabi\n"
"ro.product.cpu.abilist64=x86_64,arm64-v8a\n";
constexpr const char kBuildPropModifiedSecond[] =
"ro.dalvik.vm.isa.arm64=x86_64\n";
EXPECT_EQ(base::StringPrintf("%s\n%s", kBuildPropModifiedFirst,
kBuildPropModifiedSecond),
content);
EXPECT_TRUE(
base::ReadFileToString(dest_dir.Append("vendor_build.prop"), &content));
constexpr const char kVendorBuildPropModified[] =
"ro.a=b\n"
"ro.vendor.product.cpu.abilist=x86_64,x86,arm64-v8a,armeabi-v7a,armeabi\n"
"ro.vendor.product.cpu.abilist64=x86_64,arm64-v8a\n";
EXPECT_EQ(std::string(kVendorBuildPropModified) + "\n", content);
// Expand to a single file with experiment on, verify properties are added /
// modified as expected.
base::FilePath dest_prop_file;
ASSERT_TRUE(
base::CreateTemporaryDirInDir(GetTempDir(), "test", &dest_prop_file));
dest_prop_file = dest_prop_file.Append("combined.prop");
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, true, false));
// Verify the contents.
EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
EXPECT_EQ(
base::StringPrintf("%s%s%s%s", kDefaultProp, kBuildPropModifiedFirst,
kBuildPropModifiedSecond, kVendorBuildPropModified),
content);
// Verify that unexpected property values generate an error.
constexpr const char kBuildPropUnexpected[] =
"ro.baz=boo\n"
"ro.product.cpu.abilist=x86_64,armeabi-v7a,armeabi,unexpected-abi\n"
"ro.product.cpu.abilist64=x86_64\n";
base::WriteFile(build_prop, kBuildPropUnexpected,
strlen(kBuildPropUnexpected));
EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir, false, true, false));
constexpr const char kBuildPropUnexpected2[] =
"ro.baz=boo\n"
"ro.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi\n"
"ro.product.cpu.abilist64=x86_64,unexpected-abi_64\n";
base::WriteFile(build_prop, kBuildPropUnexpected2,
strlen(kBuildPropUnexpected2));
EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir, false, true, false));
}
// Verify that comments and non ro. properties are not written.
TEST_F(ArcPropertyUtilTest, ExpandPropertyFiles_SingleFile_NonRo) {
base::FilePath source_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &source_dir));
base::FilePath dest_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(GetTempDir(), "test", &dest_dir));
const base::FilePath default_prop = source_dir.Append("default.prop");
constexpr const char kDefaultProp[] = "###\ndalvik.foo=bar\nro.foo=bar\n";
base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp));
const base::FilePath build_prop = source_dir.Append("build.prop");
constexpr const char kBuildProp[] = "###\ndalvik.baz=boo\nro.baz=boo\n";
base::WriteFile(build_prop, kBuildProp, strlen(kBuildProp));
const base::FilePath vendor_build_prop =
source_dir.Append("vendor_build.prop");
constexpr const char kVendorBuildProp[] = "###\ndalvik.a=b\nro.a=b\n";
base::WriteFile(vendor_build_prop, kVendorBuildProp,
strlen(kVendorBuildProp));
const base::FilePath dest_prop_file = dest_dir.Append("combined.prop");
EXPECT_TRUE(
ExpandPropertyFiles(source_dir, dest_prop_file, true, false, false));
// Verify the content.
std::string content;
EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
EXPECT_EQ("ro.foo=bar\nro.baz=boo\nro.a=b\n", content);
}
} // namespace
} // namespace arc