/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "AssembleVintfTest" #include #include #include #include #include #include #include "constants-private.h" #include "test_constants.h" using android::base::StringPrintf; namespace android { namespace vintf { static bool In(const std::string& sub, const std::string& str) { return str.find(sub) != std::string::npos; } #define EXPECT_IN(sub, str) EXPECT_TRUE(In((sub), (str))) << (str); class AssembleVintfTest : public ::testing::Test { public: virtual void SetUp() override { mInstance = AssembleVintf::newInstance(); auto s = makeStream(""); mOutputStream = s.get(); mInstance->setOutputStream(std::move(s)); s = makeStream(""); mErrorStream = s.get(); mInstance->setErrorStream(std::move(s)); getInstance()->setFakeEnv("PRODUCT_ENFORCE_VINTF_MANIFEST", "true"); } virtual void TearDown() override { mInstance = nullptr; } const std::unique_ptr& getInstance() { return mInstance; } std::string getOutput() { return mOutputStream->str(); } std::string getError() { return mErrorStream->str(); } void resetOutput() { mOutputStream->str(""); } void setFakeEnvs(const std::map& envs) { for (const auto& pair : envs) { getInstance()->setFakeEnv(pair.first, pair.second); } } void setFakeAidlMetadata(const std::vector& metadata) { getInstance()->setFakeAidlMetadata(metadata); } void setFakeAidlUseUnfrozen(bool use) { getInstance()->setFakeAidlUseUnfrozen(use); } void addInput(const std::string& name, const std::string& s) { getInstance()->addInputStream(name, makeStream(s)); } std::unique_ptr makeStream(const std::string& s) { return std::make_unique(s); } std::unique_ptr mInstance; // do not own this object. std::stringstream* mOutputStream; std::stringstream* mErrorStream; }; // clang-format off TEST_F(AssembleVintfTest, FrameworkMatrixEmpty) { std::string xmlEmpty = ""; std::string kernel318 = "CONFIG_FOO=y\n"; std::string kernel318_64 = "CONFIG_BAR=y\n"; std::string kernel44 = "# CONFIG_FOO is not set\n"; std::string kernel44_64 = "CONFIG_BAR=y\n"; addInput("compatibility_matrix.empty.xml", xmlEmpty); setFakeEnvs({ {"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"FRAMEWORK_VBMETA_VERSION", "1.0"}, }); getInstance()->addKernelConfigInputStream({3, 18, 0}, "android-base.config", makeStream(kernel318)); getInstance()->addKernelConfigInputStream({3, 18, 0}, "android-base-arm64.config", makeStream(kernel318_64)); getInstance()->addKernelConfigInputStream({4, 4, 0}, "android-base.config", makeStream(kernel44)); getInstance()->addKernelConfigInputStream({4, 4, 0}, "android-base-arm64.config", makeStream(kernel44_64)); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " \n" " CONFIG_FOO\n" " y\n" " \n" " \n" " \n" " \n" " \n" " CONFIG_ARM64\n" " y\n" " \n" " \n" " \n" " CONFIG_BAR\n" " y\n" " \n" " \n" " \n" " \n" " CONFIG_FOO\n" " n\n" " \n" " \n" " \n" " \n" " \n" " CONFIG_ARM64\n" " y\n" " \n" " \n" " \n" " CONFIG_BAR\n" " y\n" " \n" " \n" " \n" " 30\n" " 202404\n" " \n" " \n" " 1.0\n" " \n" "\n", getOutput()); } TEST_F(AssembleVintfTest, FrameworkMatrix) { std::string tail = " \n" " CONFIG_FOO\n" " y\n" " \n" " \n" " \n" " 30\n" " 202404\n" " \n" " \n" " 1.0\n" " \n" "\n"; std::string xmlEmpty = "\n" " \n" + tail; std::string xml1 = "\n" " \n" " android.hardware.foo\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" "\n"; std::string xml2 = "\n" " \n" " android.hardware.foo\n" " 1.0-1\n" " \n" " IFoo\n" " default\n" " \n" " \n" "\n"; std::string xml3 = "\n" " \n" " android.hardware.foo\n" " 2.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" "\n"; auto manifest = [](size_t level) { return "\n" + " \n" " android.hardware.foo\n" " 1.1\n" " hwbinder\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" " android.hardware.foo\n" " 2.0\n" " hwbinder\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" " 202404\n" " \n" "\n"; }; addInput("compatibility_matrix.1.xml", xml1); addInput("compatibility_matrix.2.xml", xml2); addInput("compatibility_matrix.3.xml", xml3); addInput("compatibility_matrix.empty.xml", xmlEmpty); getInstance()->setFakeEnv("PRODUCT_ENFORCE_VINTF_MANIFEST", "true"); resetOutput(); getInstance()->setCheckInputStream("check.xml", makeStream(manifest(1))); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " android.hardware.foo\n" " 1.0-1\n" " 2.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" + tail, getOutput()); resetOutput(); getInstance()->setCheckInputStream("check.xml", makeStream(manifest(2))); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " android.hardware.foo\n" " 1.0-1\n" " 2.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" + tail, getOutput()); resetOutput(); getInstance()->setCheckInputStream("check.xml", makeStream(manifest(3))); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " android.hardware.foo\n" " 2.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" + tail, getOutput()); } TEST_F(AssembleVintfTest, MatrixVendorNdk) { addInput("compatibility_matrix.xml", "\n"); getInstance()->setFakeEnv("REQUIRED_VNDK_VERSION", "P"); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " P\n" " \n" "\n", getOutput()); } TEST_F(AssembleVintfTest, ManifestVendorNdk) { addInput("manifest.xml", "\n"); getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 "); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " P\n" " \n" " \n" " 26\n" " \n" " \n" " 27\n" " \n" "\n", getOutput()); } TEST_F(AssembleVintfTest, VendorNdkCheckEmpty) { addInput("manifest.xml", "\n"); getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 "); std::string matrix = "\n"; getInstance()->setCheckInputStream("check.xml", makeStream(matrix)); EXPECT_TRUE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, VendorNdkCheckIncompat) { addInput("manifest.xml", "\n"); getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 "); std::string matrix = "\n" " \n" " O\n" " \n" "\n"; getInstance()->setCheckInputStream("check.xml", makeStream(matrix)); EXPECT_FALSE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, VendorNdkCheckCompat) { addInput("manifest.xml", "\n"); getInstance()->setFakeEnv("PROVIDED_VNDK_VERSIONS", "P 26 27 "); std::string matrix = "\n" " \n" " 27\n" " \n" "\n"; getInstance()->setCheckInputStream("check.xml", makeStream(matrix)); EXPECT_TRUE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, MatrixSystemSdk) { addInput("compatibility_matrix.xml", "\n"); getInstance()->setFakeEnv("BOARD_SYSTEMSDK_VERSIONS", "P 1 2 "); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " 1\n" " 2\n" " P\n" " \n" "\n", getOutput()); } TEST_F(AssembleVintfTest, ManifestSystemSdk) { addInput("manifest.xml", "\n"); getInstance()->setFakeEnv("PLATFORM_SYSTEMSDK_VERSIONS", "P 1 2 "); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " 1\n" " 2\n" " P\n" " \n" "\n", getOutput()); } const std::string gEmptyOutManifest = "\n" " \n" " 202404\n" " \n" "\n"; TEST_F(AssembleVintfTest, EmptyManifest) { const std::string emptyManifest = ""; setFakeEnvs({{"BOARD_SEPOLICY_VERS", "202404"}, {"IGNORE_TARGET_FCM_VERSION", "true"}}); addInput("manifest.empty.xml", emptyManifest); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN(gEmptyOutManifest, getOutput()); } TEST_F(AssembleVintfTest, DeviceFrameworkMatrixOptional) { setFakeEnvs({{"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"}, {"FRAMEWORK_VBMETA_VERSION", "1.0"}, {"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}}); getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest)); addInput("compatibility_matrix.empty.xml", "\n" " \n" " vendor.foo.bar\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" ""); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " vendor.foo.bar\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" " 30\n" " 26.0\n" " 27.0\n" " 202404\n" " \n" " \n" " 1.0\n" " \n" "", getOutput()); } TEST_F(AssembleVintfTest, DeviceFrameworkMatrixRequired) { setFakeEnvs({{"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"}, {"FRAMEWORK_VBMETA_VERSION", "1.0"}, {"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}}); getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest)); addInput("compatibility_matrix.empty.xml", "\n" " \n" " vendor.foo.bar\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" ""); EXPECT_FALSE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, DeviceFrameworkMatrixMultiple) { setFakeEnvs({{"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"PLATFORM_SEPOLICY_COMPAT_VERSIONS", "26.0 27.0"}, {"FRAMEWORK_VBMETA_VERSION", "1.0"}, {"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}}); getInstance()->setCheckInputStream("check.xml", makeStream(gEmptyOutManifest)); addInput("compatibility_matrix.foobar.xml", "\n" " \n" " vendor.foo.bar\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" ""); addInput("compatibility_matrix.bazquux.xml", "\n" " \n" " vendor.baz.quux\n" " 1.0\n" " \n" " IBaz\n" " default\n" " \n" " \n" ""); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "\n" " \n" " vendor.baz.quux\n" " 1.0\n" " \n" " IBaz\n" " default\n" " \n" " \n" " \n" " vendor.foo.bar\n" " 1.0\n" " \n" " IFoo\n" " default\n" " \n" " \n" " \n" " 30\n" " 26.0\n" " 27.0\n" " 202404\n" " \n" " \n" " 1.0\n" " \n" "", getOutput()); } TEST_F(AssembleVintfTest, OutputFileMatrixTest) { const std::string kFile = "file_name_1.xml"; const std::string kMatrix = ""; addInput(kFile, kMatrix); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN(kFile, getOutput()); } TEST_F(AssembleVintfTest, OutputFileManifestTest) { const std::string kFile = "file_name_1.xml"; std::string kManifest = ""; addInput(kFile, kManifest); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN(kFile, getOutput()); } TEST_F(AssembleVintfTest, AidlAndHidlNames) { addInput("manifest1.xml", "\n" " \n" " android.system.foo\n" " IFoo/default\n" " \n" "\n"); addInput("manifest2.xml", "\n" " \n" " android.system.foo\n" " hwbinder\n" " @1.0::IFoo/default\n" " \n" "\n"); std::vector aidl{ {.name = "android.system.foo", .types = {"android.system.foo.IFoo"}}}; setFakeAidlMetadata(aidl); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( " \n" " android.system.foo\n" " IFoo/default\n" " \n", getOutput()); EXPECT_IN( " \n" " android.system.foo\n" " hwbinder\n" " @1.0::IFoo/default\n" " \n", getOutput()); } // Merge kernel FCM from manually written device manifest and from // parsing kernel prebuilt. TEST_F(AssembleVintfTest, MergeKernelFcmAndConfigs) { addInput("manifest.xml", "\n" " \n" "\n"); getInstance()->addKernelConfigInputStream({3, 18, 10}, "android-base.config", makeStream("CONFIG_FOO=y")); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("", getOutput()); } TEST_F(AssembleVintfTest, NoAutoSetKernelFcm) { addInput("manifest.xml", "\n" " \n" "\n"); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("", getOutput()); } TEST_F(AssembleVintfTest, NoAutoSetKernelFcmWithConfig) { addInput("manifest.xml", "\n"); getInstance()->addKernelConfigInputStream({3, 18, 10}, "android-base.config", makeStream("CONFIG_FOO=y")); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("", getOutput()); } TEST_F(AssembleVintfTest, NoKernelFcmT) { addInput("manifest.xml", StringPrintf(R"( )", kMetaVersionStr.c_str(), to_string(details::kEnforceDeviceManifestNoKernelLevel).c_str())); EXPECT_FALSE(getInstance()->assemble()); } // Automatically add kernel FCM when parsing framework matrix for a single FCM version. TEST_F(AssembleVintfTest, AutoSetMatrixKernelFcm) { addInput("compatibility_matrix.xml", "\n" ); getInstance()->addKernelConfigInputStream({3, 18, 10}, "android-base.config", makeStream("")); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("", getOutput()); } TEST_F(AssembleVintfTest, WithKernelRequirements) { setFakeEnvs({{"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}}); addInput("compatibility_matrix.xml", "\n" " \n" " \n" " CONFIG_FOO\n" " y\n" " \n" " \n" "\n"); getInstance()->setCheckInputStream("check.xml", makeStream( "\n" " \n" " \n" " 202404\n" " \n" "\n")); EXPECT_FALSE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, NoKernelRequirements) { setFakeEnvs({{"POLICYVERS", "30"}, {"PLATFORM_SEPOLICY_VERSION", "202404"}, {"PRODUCT_ENFORCE_VINTF_MANIFEST", "true"}}); addInput("compatibility_matrix.xml", "\n" " \n" "\n"); getInstance()->setCheckInputStream("check.xml", makeStream( "\n" " \n" " \n" " 202404\n" " \n" "\n")); EXPECT_TRUE(getInstance()->setNoKernelRequirements()); EXPECT_TRUE(getInstance()->assemble()); } // clang-format on TEST_F(AssembleVintfTest, ManifestLevelConflictCorrectLocation) { addInput("manifest.xml", ")"); addInput("manifest_1.xml", ")"); addInput("manifest_2.xml", ")"); EXPECT_FALSE(getInstance()->assemble()); EXPECT_IN("File 'manifest_1.xml' has level 1", getError()); EXPECT_IN("File 'manifest_2.xml' has level 2", getError()); } TEST_F(AssembleVintfTest, PassMultipleManifestEntrySameModule) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); std::vector aidl{ {.name = "android.system.foo", .stability = "vintf", .versions = {1, 2}, .types = {"android.system.foobar.IFoo", "android.system.foobar.IBar"}}}; setFakeAidlMetadata(aidl); addInput("manifest1.xml", StringPrintf( R"( android.system.foobar\n" IFoo/default\n" IBar/default\n" 3\n" )", kMetaVersionStr.c_str())); EXPECT_TRUE(getInstance()->assemble()); } TEST_F(AssembleVintfTest, FailOnMultipleModulesInSameManifestEntry) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); std::vector aidl{{.name = "android.system.foo", .stability = "vintf", .versions = {1, 2}, .types = {"android.system.foobar.IFoo"}}, {.name = "android.system.bar", .stability = "vintf", .versions = {1, 2}, .types = {"android.system.foobar.IBar"}}}; setFakeAidlMetadata(aidl); addInput("manifest1.xml", StringPrintf( R"( android.system.foobar\n" IFoo/default\n" IBar/default\n" 3\n" )", kMetaVersionStr.c_str())); EXPECT_FALSE(getInstance()->assemble()); EXPECT_IN("HAL manifest entries must only contain", getError()); EXPECT_IN("android.system.foobar.IFoo is in android.system.foo", getError()); } TEST_F(AssembleVintfTest, ForceDowngradeVersion) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); std::vector aidl{ {.name = "foo_android.system.bar", .stability = "vintf", .types = {"android.system.bar.IFoo", "android.system.bar.MyFoo"}, .versions = {1, 2}, .has_development = true}}; setFakeAidlMetadata(aidl); setFakeAidlUseUnfrozen(false); addInput("manifest1.xml", StringPrintf( R"( android.system.bar\n" IFoo/default\n" 3\n" )", kMetaVersionStr.c_str())); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("2", getOutput()); } TEST_F(AssembleVintfTest, InfoDowngradeVersionTypo) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); std::vector aidl{ {.name = "foo_android.system.bar", .stability = "vintf", .types = {"android.system.bar.IFoo", "android.system.bar.MyFoo"}, .versions = {1, 2}, .has_development = true}}; setFakeAidlMetadata(aidl); setFakeAidlUseUnfrozen(false); addInput("manifest1.xml", StringPrintf( R"( android.system.bar\n" IFooooooooo/default\n" 3\n" )", kMetaVersionStr.c_str())); // It doesn't fail because there may be prebuilts, but make sure we do log it. EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN( "INFO: Couldn't find AIDL metadata for: android.system.bar.IFooooooooo in file " "manifest1.xml. " "Check " "spelling?", getError()); } TEST_F(AssembleVintfTest, AllowUnfrozenVersion) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); std::vector aidl{ {.name = "foo_android.system.bar", .stability = "vintf", .types = {"android.system.bar.IFoo", "android.system.bar.MyFoo"}, .versions = {1, 2}, .has_development = true}}; setFakeAidlMetadata(aidl); setFakeAidlUseUnfrozen(true); addInput("manifest1.xml", StringPrintf( R"( android.system.bar\n" IFoo/default\n" 3\n" )", kMetaVersionStr.c_str())); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("3", getOutput()); } TEST_F(AssembleVintfTest, KeepFrozenVersion) { setFakeEnvs({{"VINTF_IGNORE_TARGET_FCM_VERSION", "true"}}); // V3 is already frozen std::vector aidl{ {.name = "foo_android.system.bar", .stability = "vintf", .types = {"android.system.bar.IFoo", "android.system.bar.MyFoo"}, .versions = {1, 2, 3}, .has_development = true}}; setFakeAidlMetadata(aidl); setFakeAidlUseUnfrozen(false); addInput("manifest1.xml", StringPrintf( R"( android.system.bar\n" IFoo/default\n" 3\n" )", kMetaVersionStr.c_str())); EXPECT_TRUE(getInstance()->assemble()); EXPECT_IN("3", getOutput()); } } // namespace vintf } // namespace android