| // 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 <tuple> |
| #include <utility> |
| |
| #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 <cdm_oemcrypto/proto_bindings/client_information.pb.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <chromeos-config/libcros_config/cros_config.h> |
| #include <chromeos-config/libcros_config/fake_cros_config.h> |
| #include <dbus/mock_bus.h> |
| #include <dbus/mock_object_proxy.h> |
| #include <gmock/gmock.h> |
| #include <testing/gtest/include/gtest/gtest.h> |
| |
| using ::testing::_; |
| using ::testing::ByMove; |
| using ::testing::Return; |
| using ::testing::StartsWith; |
| |
| 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()); |
| dbus::Bus::Options options; |
| options.bus_type = dbus::Bus::SYSTEM; |
| bus_ = new dbus::MockBus(options); |
| cdm_factory_daemon_object_proxy_ = new dbus::MockObjectProxy( |
| bus_.get(), cdm_oemcrypto::kCdmFactoryDaemonServiceName, |
| dbus::ObjectPath(cdm_oemcrypto::kCdmFactoryDaemonServicePath)); |
| } |
| |
| protected: |
| const base::FilePath& GetTempDir() const { return dir_.GetPath(); } |
| |
| brillo::FakeCrosConfig* config() { return &config_; } |
| |
| scoped_refptr<dbus::MockBus> bus_; |
| scoped_refptr<dbus::MockObjectProxy> cdm_factory_daemon_object_proxy_; |
| |
| 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, |
| /*hw_oemcrypto_support=*/false, |
| /*debuggable=*/false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| 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, |
| false, nullptr)); |
| |
| 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, false, nullptr)); |
| } |
| |
| // 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, |
| /*hw_oemcrypto_support=*/false, |
| /*debuggable=*/false, nullptr)); |
| |
| // 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, false, nullptr)); |
| |
| // 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, false, nullptr)); |
| |
| // 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, false, nullptr)); |
| |
| // 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, false, nullptr)); |
| |
| // 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, false, nullptr)); |
| |
| 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, false, nullptr)); |
| |
| 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, false, nullptr)); |
| |
| // 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, false, nullptr)); |
| 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, false, nullptr)); |
| 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, false, nullptr)); |
| } |
| |
| // 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, |
| false, nullptr)); |
| 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, |
| false, nullptr)); |
| 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, |
| false, nullptr)); |
| |
| // 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, |
| false, nullptr)); |
| 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, |
| false, nullptr)); |
| } |
| |
| // 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, false, nullptr)); |
| |
| // 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); |
| } |
| |
| // Verify that the CDM properties received from cdm-oemcrypto over D-Bus are |
| // written to the properties file. |
| TEST_F(ArcPropertyUtilTest, TestAddingCdmProperties) { |
| 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"; |
| 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"; |
| base::WriteFile(vendor_build_prop, kVendorBuildProp, |
| strlen(kVendorBuildProp)); |
| |
| base::FilePath product_build_prop = source_dir.Append("product_build.prop"); |
| constexpr const char kProductBuildProp[] = "ro.c=d\n"; |
| base::WriteFile(product_build_prop, kProductBuildProp, |
| strlen(kProductBuildProp)); |
| |
| EXPECT_CALL(*bus_, GetObjectProxy(_, _)) |
| .WillOnce(Return(cdm_factory_daemon_object_proxy_.get())); |
| |
| std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); |
| dbus::MessageWriter writer(response.get()); |
| chromeos::cdm::ClientInformation client_info; |
| constexpr char kManufacturer[] = "fake_manufacturer"; |
| constexpr char kMake[] = "fake_make"; |
| constexpr char kModel[] = "fake_model"; |
| client_info.set_manufacturer(kManufacturer); |
| client_info.set_make(kMake); |
| client_info.set_model(kModel); |
| writer.AppendProtoAsArrayOfBytes(client_info); |
| EXPECT_CALL(*cdm_factory_daemon_object_proxy_, |
| CallMethodAndBlockWithErrorDetails(_, _, _)) |
| .WillOnce(Return(ByMove(std::move(response)))); |
| |
| const base::FilePath dest_prop_file = dest_dir.Append("combined.prop"); |
| EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_prop_file, true, false, true, |
| false, bus_)); |
| |
| // Verify the content. |
| std::string content; |
| EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content)); |
| EXPECT_EQ(std::string() + kDefaultProp + kBuildProp + kVendorBuildProp + |
| kProductBuildProp + "ro.product.cdm.manufacturer=" + |
| kManufacturer + "\nro.product.cdm.model=" + kModel + |
| "\nro.product.cdm.device=" + kMake + "\n", |
| content); |
| } |
| |
| // Verify that a failure reading the CDM properties from cdm-oemcrypto over |
| // D-Bus is handled properly and doesn't change the properties file. |
| TEST_F(ArcPropertyUtilTest, TestAddingCdmProperties_DbusFailure) { |
| 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"; |
| 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"; |
| base::WriteFile(vendor_build_prop, kVendorBuildProp, |
| strlen(kVendorBuildProp)); |
| |
| base::FilePath product_build_prop = source_dir.Append("product_build.prop"); |
| constexpr const char kProductBuildProp[] = "ro.c=d\n"; |
| base::WriteFile(product_build_prop, kProductBuildProp, |
| strlen(kProductBuildProp)); |
| |
| EXPECT_CALL(*bus_, GetObjectProxy(_, _)) |
| .WillOnce(Return(cdm_factory_daemon_object_proxy_.get())); |
| |
| std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty(); |
| EXPECT_CALL(*cdm_factory_daemon_object_proxy_, |
| CallMethodAndBlockWithErrorDetails(_, _, _)) |
| .WillOnce(Return(ByMove(std::move(response)))); |
| |
| const base::FilePath dest_prop_file = dest_dir.Append("combined.prop"); |
| EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_prop_file, true, false, true, |
| false, bus_)); |
| |
| // Verify the content. |
| std::string content; |
| EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content)); |
| EXPECT_EQ(std::string() + kDefaultProp + kBuildProp + kVendorBuildProp + |
| kProductBuildProp, |
| content); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendX86SocProperties) { |
| int case_no = 0; |
| |
| for (auto& testcase : |
| {std::tuple<const char*, const char*>{ |
| "nomatch\nmodel name\t: Intel(R) Core(TM) i5-10510U CPU @ 999GHz\n", |
| "ro.soc.manufacturer=Intel\nro.soc.model=i5-10510U\n"}, |
| {"xyz\nmodel name\t\t: Intel(R) Core(TM) i7-920 CPU @ 2.67GHz\nabc\n", |
| "ro.soc.manufacturer=Intel\nro.soc.model=i7-920\n"}, |
| {"nomatch\nnomatch\nnomatch\n", ""}, |
| |
| // For an Asuka board. |
| {"model name\t: Intel(R) Celeron(R) CPU 3855U @ 1.60GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=3855U\n"}, |
| |
| // For a Bob board. Note additional space around model name. |
| {"model name\t: Intel(R) Celeron(R) CPU N3060 @ 1.60GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=N3060\n"}, |
| |
| // Apparently starting from 11th-gen Intel i#'s, we see the gen no. is |
| // called out explicitly. |
| |
| // For a Volteer (copano) board. |
| {"model name\t: 11th Gen Intel(R) Core(TM) i3-1110G4 @ 1.80GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=i3-1110G4\n"}, |
| |
| // Many Brya boards use 12th-gen Intels, which actually end the model |
| // name line with the important part (the actual ID), without a clock |
| // freq. following. |
| {"model name\t: 12th Gen Intel(R) Core(TM) i3-1215U\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=i3-1215U\n"}, |
| {"model name\t: 12th Gen Intel(R) Core(TM) i5-1250P\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=i5-1250P\n"}, |
| |
| // For a Brya (redrix) board. Note missing C in "Core". |
| {"model name\t: 12th Gen Intel(R) ore(TM) i5-1245U\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=i5-1245U\n"}, |
| |
| // For a Brya (primus) board. |
| {"model name\t: Intel(R) Pentium(R) Gold 8505\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=8505\n"}, |
| |
| // For a Dedede board (beetley). "CPU" is absent. |
| {"model name\t: Intel(R) Celeron(R) N4500 @ 1.10GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=N4500\n"}, |
| |
| // For a Dedede board (blipper). |
| {"model name\t: Intel(R) Pentium(R) Silver N6000 @ 1.10GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=N6000\n"}, |
| |
| // For a Dedede board (kled). |
| {"model name\t: Intel(R) Pentium(R) CPU 6405U @ 2.40GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=6405U\n"}, |
| |
| // For a Zork board. |
| {"line1\n" |
| "model name\t: AMD Ryzen 3 3250C 15W with Radeon Graphics\n" |
| "line3\n", |
| "ro.soc.manufacturer=AMD\n" |
| "ro.soc.model=Ryzen 3 3250C\n"}, |
| |
| // For a Zork board. (includes dirinboz, ezkinil, and morphius devices) |
| {"model name\t: AMD 3015Ce with Radeon Graphics\n", |
| "ro.soc.manufacturer=AMD\n" |
| "ro.soc.model=3015Ce\n"}, |
| |
| // For a Zork board (morphius). |
| {"model name\t: AMD Athlon Gold 3150C with Radeon Graphics\n", |
| "ro.soc.manufacturer=AMD\n" |
| "ro.soc.model=3150C\n"}, |
| |
| // For a Grunt board. |
| {"model name\t: AMD A4-9120C RADEON R4, 5 COMPUTE CORES 2C+3G\n", |
| "ro.soc.manufacturer=AMD\n" |
| "ro.soc.model=A4-9120C\n"}, |
| |
| // For a Guybrush board (nipperkin). |
| {"model name\t: AMD Ryzen 5 5625C with Radeon Graphics\n", |
| "ro.soc.manufacturer=AMD\n" |
| "ro.soc.model=Ryzen 5 5625C\n"}, |
| |
| // For an Octopus board (blooguard). |
| {"model name\t: Intel(R) Pentium(R) Silver N5000 CPU @ 1.10GHz\n", |
| "ro.soc.manufacturer=Intel\n" |
| "ro.soc.model=N5000\n"}, |
| |
| // For an Octopus board. |
| {"model name: Intel(R) Celeron(R) N4000 CPU @ 1.10GHz\n", |
| "ro.soc.manufacturer=Intel\nro.soc.model=N4000\n"}}) { |
| base::StringPiece cpuinfo = std::get<0>(testcase); |
| base::StringPiece expected = std::get<1>(testcase); |
| auto cpuinfo_path = |
| GetTempDir().Append(base::StringPrintf("cpuinfo%d", case_no++)); |
| |
| ASSERT_TRUE(base::WriteFile(cpuinfo_path, cpuinfo)); |
| |
| // Make sure the file is opened read-only by turning off the writable perms. |
| ASSERT_EQ(chmod(cpuinfo_path.value().c_str(), 0444), 0); |
| |
| std::string actual; |
| AppendX86SocProperties(cpuinfo_path, &actual); |
| |
| // Without the trailing `<< actual`, EXPECT_EQ treats `actual` as binary |
| // and truncates it. |
| EXPECT_EQ(expected, actual) << actual; |
| } |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendX86SocPropertiesDoesNotOverwrite) { |
| auto cpuinfo_path = GetTempDir().Append("cpuinfo"); |
| |
| ASSERT_TRUE(base::WriteFile(cpuinfo_path, |
| "model name : Intel(R) Core(TM) i7-5200U CPU\n")); |
| |
| std::string dest = "xyz=123\n"; |
| AppendX86SocProperties(cpuinfo_path, &dest); |
| EXPECT_THAT(dest, StartsWith("xyz=123\nro.soc.")); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendX86SocPropertiesPentiumWithSpaceInModel) { |
| // Make sure we don't support model names with spaces, rather than match them. |
| auto cpuinfo_path = GetTempDir().Append("cpuinfo"); |
| |
| ASSERT_TRUE(base::WriteFile( |
| cpuinfo_path, "model name : Intel(R) Pentium(R) Gold N1000 SecondEd\n")); |
| |
| std::string dest; |
| AppendX86SocProperties(cpuinfo_path, &dest); |
| EXPECT_EQ(dest, ""); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendArmSocPropertiesNoMatch) { |
| auto socinfo_devices_dir = GetTempDir(); |
| auto soc0_path = socinfo_devices_dir.Append("soc0"); |
| auto machine_path = soc0_path.Append("machine"); |
| auto family_path = soc0_path.Append("family"); |
| |
| ASSERT_TRUE(base::CreateDirectory(soc0_path)); |
| ASSERT_TRUE(base::WriteFile(machine_path, "unknown486\n")); |
| ASSERT_TRUE(base::WriteFile(family_path, "unknownFamily\n")); |
| |
| std::string dest = "4=2+2\n"; |
| AppendArmSocProperties(socinfo_devices_dir, &dest); |
| EXPECT_EQ(dest, "4=2+2\n"); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendArmSocPropertiesMatch) { |
| auto socinfo_devices_dir = GetTempDir(); |
| auto soc0_path = socinfo_devices_dir.Append("soc0"); |
| auto machine_path = soc0_path.Append("machine"); |
| auto family_path = soc0_path.Append("family"); |
| |
| ASSERT_TRUE(base::CreateDirectory(soc0_path)); |
| ASSERT_TRUE(base::WriteFile(machine_path, "SC7180\n")); |
| ASSERT_TRUE(base::WriteFile(family_path, "Snapdragon\n")); |
| |
| // Make sure the file is opened read-only by turning off the writable perms. |
| ASSERT_EQ(chmod(machine_path.value().c_str(), 0444), 0); |
| ASSERT_EQ(chmod(family_path.value().c_str(), 0444), 0); |
| |
| std::string dest = "jkl=aoe\n"; |
| AppendArmSocProperties(socinfo_devices_dir, &dest); |
| EXPECT_EQ(dest, |
| "jkl=aoe\n" |
| "ro.soc.manufacturer=Qualcomm\n" |
| "ro.soc.model=SC7180\n"); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendArmSocPropertiesSymlink) { |
| auto sysfs_dir = GetTempDir(); |
| auto devices_dir = sysfs_dir.Append("devices"); |
| auto soc0_path = devices_dir.Append("soc0"); |
| auto machine_path = soc0_path.Append("machine"); |
| auto family_path = soc0_path.Append("family"); |
| auto bus_dir = sysfs_dir.Append("bus"); |
| auto socinfo_dir = bus_dir.Append("soc"); |
| auto socinfo_devices_dir = bus_dir.Append("devices"); |
| auto socinfo_soc0_path = socinfo_devices_dir.Append("soc0"); |
| |
| // Try to replicate something akin to the real structure of sysfs, which has |
| // symlinks. This helps confirm we aren't using "safe" functions to read. |
| ASSERT_TRUE(base::CreateDirectory(devices_dir)); |
| ASSERT_TRUE(base::CreateDirectory(soc0_path)); |
| ASSERT_TRUE(base::WriteFile(machine_path, "SC7180\n")); |
| ASSERT_TRUE(base::WriteFile(family_path, "Snapdragon\n")); |
| ASSERT_TRUE(base::CreateDirectory(bus_dir)); |
| ASSERT_TRUE(base::CreateDirectory(socinfo_dir)); |
| ASSERT_TRUE(base::CreateDirectory(socinfo_devices_dir)); |
| ASSERT_TRUE(base::CreateSymbolicLink(soc0_path, socinfo_soc0_path)); |
| |
| // Make sure the file is opened read-only by turning off the writable perms. |
| ASSERT_EQ(chmod(machine_path.value().c_str(), 0444), 0); |
| |
| std::string dest = "symlinks=fun\n"; |
| AppendArmSocProperties(socinfo_devices_dir, &dest); |
| EXPECT_EQ(dest, |
| "symlinks=fun\n" |
| "ro.soc.manufacturer=Qualcomm\n" |
| "ro.soc.model=SC7180\n"); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendArmSocPropertiesTwo) { |
| auto socinfo_devices_dir = GetTempDir(); |
| auto soc0_path = socinfo_devices_dir.Append("soc0"); |
| auto soc_id0_path = soc0_path.Append("soc_id"); |
| auto family0_path = soc0_path.Append("family"); |
| auto soc1_path = socinfo_devices_dir.Append("soc1"); |
| auto soc_id1_path = soc1_path.Append("soc_id"); |
| auto machine1_path = soc1_path.Append("machine"); |
| auto family1_path = soc1_path.Append("family"); |
| |
| // soc0 will exist, but _not_ have a machine file. It will represent the |
| // generic version of the driver that directly exposes the firmware. |
| ASSERT_TRUE(base::CreateDirectory(soc0_path)); |
| ASSERT_TRUE(base::WriteFile(soc_id0_path, "jep106:0070:7180\n")); |
| ASSERT_TRUE(base::WriteFile(family0_path, "jep106:0070\n")); |
| |
| // soc1 will be exposing a "nicer" SoC-specific driver. |
| ASSERT_TRUE(base::CreateDirectory(soc1_path)); |
| ASSERT_TRUE(base::WriteFile(soc_id1_path, "425\n")); |
| ASSERT_TRUE(base::WriteFile(machine1_path, "SC7180\n")); |
| ASSERT_TRUE(base::WriteFile(family1_path, "Snapdragon\n")); |
| |
| // Make sure the file is opened read-only by turning off the writable perms. |
| ASSERT_EQ(chmod(soc_id1_path.value().c_str(), 0444), 0); |
| ASSERT_EQ(chmod(machine1_path.value().c_str(), 0444), 0); |
| ASSERT_EQ(chmod(family1_path.value().c_str(), 0444), 0); |
| |
| std::string dest = "one=two\n"; |
| AppendArmSocProperties(socinfo_devices_dir, &dest); |
| EXPECT_EQ(dest, |
| "one=two\n" |
| "ro.soc.manufacturer=Qualcomm\n" |
| "ro.soc.model=SC7180\n"); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendX86SocPropertiesCannotOpenCpuinfo) { |
| auto cpuinfo_path = GetTempDir().Append("cpuinfo.nothere"); |
| |
| std::string dest; |
| AppendX86SocProperties(cpuinfo_path, &dest); |
| EXPECT_EQ(dest, ""); |
| } |
| |
| TEST_F(ArcPropertyUtilTest, AppendArmSocPropertiesCannotOpenMachineFile) { |
| auto temp_dir = GetTempDir(); |
| auto socinfo_path = temp_dir.Append("directory.nothere"); |
| |
| std::string dest; |
| AppendArmSocProperties(socinfo_path, &dest); |
| EXPECT_EQ(dest, ""); |
| } |
| |
| } // namespace |
| } // namespace arc |