/*
* 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.
*/
#include <android-base/logging.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <unistd.h>
#include <android-base/strings.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>
#include "utils-fake.h"
#include <hidl-util/FQName.h>
using namespace ::testing;
using android::FqInstance;
static AssertionResult In(const std::string& sub, const std::string& str) {
return (str.find(sub) != std::string::npos ? AssertionSuccess() : AssertionFailure())
<< "Value is " << str;
}
#define EXPECT_IN(sub, str) EXPECT_TRUE(In((sub), (str)))
#define EXPECT_NOT_IN(sub, str) EXPECT_FALSE(In((sub), (str)))
namespace android {
namespace vintf {
namespace testing {
using namespace ::android::vintf::details;
//
// Set of Xml1 metadata compatible with each other.
//
const std::string systemMatrixXml1 =
"<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.camera</name>\n"
" <version>2.0-5</version>\n"
" <version>3.4-16</version>\n"
" </hal>\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.nfc</name>\n"
" <version>1.0</version>\n"
" <version>2.0</version>\n"
" </hal>\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.foo</name>\n"
" <version>1.0</version>\n"
" </hal>\n"
" <kernel version=\"3.18.31\"></kernel>\n"
" <sepolicy>\n"
" <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
" <sepolicy-version>25.5</sepolicy-version>\n"
" <sepolicy-version>26.0-3</sepolicy-version>\n"
" </sepolicy>\n"
" <avb>\n"
" <vbmeta-version>0.0</vbmeta-version>\n"
" </avb>\n"
"</compatibility-matrix>\n";
const std::string vendorManifestXml1 =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.camera</name>\n"
" <transport>hwbinder</transport>\n"
" <version>3.5</version>\n"
" <interface>\n"
" <name>IBetterCamera</name>\n"
" <instance>camera</instance>\n"
" </interface>\n"
" <interface>\n"
" <name>ICamera</name>\n"
" <instance>default</instance>\n"
" <instance>legacy/0</instance>\n"
" </interface>\n"
" </hal>\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.nfc</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>INfc</name>\n"
" <instance>nfc_nci</instance>\n"
" </interface>\n"
" </hal>\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.nfc</name>\n"
" <transport>hwbinder</transport>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>INfc</name>\n"
" <instance>default</instance>\n"
" <instance>nfc_nci</instance>\n"
" </interface>\n"
" </hal>\n"
" <sepolicy>\n"
" <version>25.5</version>\n"
" </sepolicy>\n"
"</manifest>\n";
const std::string systemManifestXml1 =
"<manifest version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hidl.manager</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IServiceManager</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
" <vndk>\n"
" <version>25.0.5</version>\n"
" <library>libbase.so</library>\n"
" <library>libjpeg.so</library>\n"
" </vndk>\n"
"</manifest>\n";
const std::string vendorMatrixXml1 =
"<compatibility-matrix version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hidl.manager</name>\n"
" <version>1.0</version>\n"
" </hal>\n"
" <vndk>\n"
" <version>25.0.1-5</version>\n"
" <library>libbase.so</library>\n"
" <library>libjpeg.so</library>\n"
" </vndk>\n"
"</compatibility-matrix>\n";
//
// Set of Xml2 metadata compatible with each other.
//
const std::string systemMatrixXml2 =
"<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <version>1.0</version>\n"
" </hal>\n"
" <kernel version=\"3.18.31\"></kernel>\n"
" <sepolicy>\n"
" <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
" <sepolicy-version>25.5</sepolicy-version>\n"
" <sepolicy-version>26.0-3</sepolicy-version>\n"
" </sepolicy>\n"
" <avb>\n"
" <vbmeta-version>0.0</vbmeta-version>\n"
" </avb>\n"
"</compatibility-matrix>\n";
const std::string vendorManifestXml2 =
"<manifest version=\"1.0\" type=\"device\">"
" <hal>"
" <name>android.hardware.foo</name>"
" <transport>hwbinder</transport>"
" <version>1.0</version>"
" </hal>"
" <sepolicy>\n"
" <version>25.5</version>\n"
" </sepolicy>\n"
"</manifest>";
//
// Set of framework matrices of different FCM version.
//
const std::string systemMatrixLevel1 =
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.major</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IMajor</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.removed</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IRemoved</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.minor</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IMinor</name>\n"
" <instance>default</instance>\n"
" <instance>legacy</instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n";
const std::string systemMatrixLevel2 =
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.major</name>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IMajor</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.minor</name>\n"
" <version>1.1</version>\n"
" <interface>\n"
" <name>IMinor</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n";
//
// Set of framework matrices of different FCM version with regex.
//
const static std::vector<std::string> systemMatrixRegexXmls = {
// 1.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.0-1</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>default</instance>\n"
" <instance>special/1.0</instance>\n"
" <regex-instance>regex/1.0/[0-9]+</regex-instance>\n"
" <regex-instance>regex_common/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n",
// 2.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.1-2</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>default</instance>\n"
" <instance>special/1.1</instance>\n"
" <regex-instance>regex/1.1/[0-9]+</regex-instance>\n"
" <regex-instance>[a-z]+_[a-z]+/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n",
// 3.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"3\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>default</instance>\n"
" <instance>special/2.0</instance>\n"
" <regex-instance>regex/2.0/[0-9]+</regex-instance>\n"
" <regex-instance>regex_[a-z]+/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n"};
//
// Set of metadata at different FCM version that has requirements
//
const std::vector<std::string> systemMatrixRequire = {
// 1.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.foo</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IFoo</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n",
// 2.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.bar</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IBar</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n"};
const std::string vendorManifestRequire1 =
"<manifest version=\"1.0\" type=\"device\" target-level=\"1\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::IFoo/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
const std::string vendorManifestRequire2 =
"<manifest version=\"1.0\" type=\"device\" target-level=\"2\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.bar</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::IBar/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
//
// Set of metadata for kernel requirements
//
const std::string vendorManifestKernel318 =
"<manifest version=\"1.0\" type=\"device\">\n"
" <kernel version=\"3.18.999\" />\n"
" <sepolicy>\n"
" <version>25.5</version>\n"
" </sepolicy>\n"
"</manifest>\n";
const std::string systemMatrixKernel318 =
"<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
" <kernel version=\"3.18.999\"></kernel>\n"
" <sepolicy>\n"
" <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
" <sepolicy-version>25.5</sepolicy-version>\n"
" </sepolicy>\n"
"</compatibility-matrix>\n";
class VintfObjectTestBase : public ::testing::Test {
protected:
MockFileSystem& fetcher() {
return static_cast<MockFileSystem&>(*vintfObject->getFileSystem());
}
MockPropertyFetcher& propertyFetcher() {
return static_cast<MockPropertyFetcher&>(*vintfObject->getPropertyFetcher());
}
// Setup the MockFileSystem used by the fetchAllInformation template
// so it returns the given metadata info instead of fetching from device.
void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
const std::string& systemManifestXml, const std::string& vendorMatrixXml,
const std::string& productModel) {
ON_CALL(fetcher(), listFiles(StrEq(kVendorManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
ON_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
ON_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
ON_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
.WillByDefault(Return(::android::OK));
if (!productModel.empty()) {
ON_CALL(fetcher(),
fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
ON_CALL(fetcher(), fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
}
ON_CALL(fetcher(), fetch(StrEq(kOdmLegacyManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
ON_CALL(fetcher(), fetch(StrEq(kOdmManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
ON_CALL(fetcher(), fetch(StrEq(kVendorManifest), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyManifest), _))
.WillByDefault(
Invoke([vendorManifestXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = vendorManifestXml;
return 0;
}));
ON_CALL(fetcher(), fetch(StrEq(kSystemManifest), _))
.WillByDefault(
Invoke([systemManifestXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = systemManifestXml;
return 0;
}));
ON_CALL(fetcher(), fetch(StrEq(kVendorMatrix), _))
.WillByDefault(Return(::android::NAME_NOT_FOUND));
ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyMatrix), _))
.WillByDefault(Invoke([vendorMatrixXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = vendorMatrixXml;
return 0;
}));
ON_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _))
.WillByDefault(Invoke([systemMatrixXml](const std::string& path, std::string& fetched) {
(void)path;
fetched = systemMatrixXml;
return 0;
}));
// Don't list /system/etc/vintf unless otherwise specified.
ON_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillByDefault(Return(::android::OK));
// Don't fetch product matrix unless otherwise specified.
ON_CALL(fetcher(), fetch(StrEq(kProductMatrix), _)).WillByDefault(Return(NAME_NOT_FOUND));
// Don't fetch product manifest unless otherwise specified.
ON_CALL(fetcher(), fetch(StrEq(kProductManifest), _)).WillByDefault(Return(NAME_NOT_FOUND));
}
void setFakeProperties() {
productModel = "fake_sku";
ON_CALL(propertyFetcher(), getProperty("ro.boot.product.hardware.sku", _))
.WillByDefault(Return(productModel));
}
virtual void SetUp() {
vintfObject = VintfObject::Builder()
.setFileSystem(std::make_unique<NiceMock<MockFileSystem>>())
.setRuntimeInfoFactory(std::make_unique<NiceMock<MockRuntimeInfoFactory>>(
std::make_shared<NiceMock<MockRuntimeInfo>>()))
.setPropertyFetcher(std::make_unique<NiceMock<MockPropertyFetcher>>())
.build();
}
virtual void TearDown() {
Mock::VerifyAndClear(&fetcher());
}
void expectVendorManifest(size_t times = 1) {
EXPECT_CALL(fetcher(), fetch(StrEq(kVendorManifest), _)).Times(times);
if (!productModel.empty()) {
EXPECT_CALL(fetcher(),
fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
.Times(times);
EXPECT_CALL(fetcher(),
fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
.Times(times);
}
EXPECT_CALL(fetcher(), fetch(StrEq(kOdmLegacyManifest), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kOdmManifest), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kVendorLegacyManifest), _)).Times(times);
}
void expectSystemManifest(size_t times = 1) {
EXPECT_CALL(fetcher(), fetch(StrEq(kSystemManifest), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kProductManifest), _)).Times(times);
}
void expectVendorMatrix(size_t times = 1) {
EXPECT_CALL(fetcher(), fetch(StrEq(kVendorMatrix), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kVendorLegacyMatrix), _)).Times(times);
}
void expectSystemMatrix(size_t times = 1) {
EXPECT_CALL(fetcher(), fetch(StrEq(kProductMatrix), _)).Times(times);
EXPECT_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _)).Times(times);
}
// Expect that a file exist and should be fetched once.
void expectFetch(const std::string& path, const std::string& content) {
EXPECT_CALL(fetcher(), fetch(StrEq(path), _))
.WillOnce(Invoke([content](const auto&, auto& out) {
out = content;
return ::android::OK;
}));
}
// Expect that a file exist and can be fetched 0 or more times.
void expectFetchRepeatedly(const std::string& path, const std::string& content) {
EXPECT_CALL(fetcher(), fetch(StrEq(path), _))
.Times(AnyNumber())
.WillRepeatedly(Invoke([content](const auto&, auto& out) {
out = content;
return ::android::OK;
}));
}
// Expect that the file should never be fetched (whether it exists or not).
void expectNeverFetch(const std::string& path) {
EXPECT_CALL(fetcher(), fetch(StrEq(path), _)).Times(0);
}
// Expect that the file does not exist, and can be fetched 0 or more times.
template <typename Matcher>
void expectFileNotExist(const Matcher& matcher) {
EXPECT_CALL(fetcher(), fetch(matcher, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::NAME_NOT_FOUND));
}
// Access to private method.
int checkCompatibility(const std::vector<std::string>& xmls, std::string* error) {
return vintfObject->checkCompatibility(xmls, error);
}
std::string productModel;
std::unique_ptr<VintfObject> vintfObject;
};
// Test fixture that provides compatible metadata from the mock device.
class VintfObjectCompatibleTest : public VintfObjectTestBase {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
setFakeProperties();
setupMockFetcher(vendorManifestXml1, systemMatrixXml1, systemManifestXml1, vendorMatrixXml1,
productModel);
}
};
// Tests that local info is checked.
TEST_F(VintfObjectCompatibleTest, TestDeviceCompatibility) {
std::string error;
std::vector<std::string> packageInfo;
expectVendorManifest();
expectSystemManifest();
expectVendorMatrix();
expectSystemMatrix();
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
// Check that nothing was ignored.
ASSERT_STREQ(error.c_str(), "");
}
// Tests that input info is checked against device and passes.
TEST_F(VintfObjectCompatibleTest, TestInputVsDeviceSuccess) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml1};
expectVendorManifest();
expectSystemManifest();
expectVendorMatrix();
expectSystemMatrix(0);
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
ASSERT_STREQ(error.c_str(), "");
}
// Tests that input info is checked against device and fails.
TEST_F(VintfObjectCompatibleTest, TestInputVsDeviceFail) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml2};
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
EXPECT_IN(
"Device manifest and framework compatibility matrix are incompatible: HALs "
"incompatible.",
error);
EXPECT_IN("android.hardware.foo", error);
}
// Tests that complementary info is checked against itself.
TEST_F(VintfObjectCompatibleTest, TestInputSuccess) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml2, vendorManifestXml2};
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
ASSERT_STREQ(error.c_str(), "");
}
TEST_F(VintfObjectCompatibleTest, TestFrameworkOnlyOta) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml1, systemManifestXml1};
expectVendorManifest();
expectSystemManifest(0);
expectVendorMatrix();
expectSystemMatrix(0);
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
ASSERT_STREQ(error.c_str(), "");
}
TEST_F(VintfObjectCompatibleTest, TestFullOta) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml1, systemManifestXml1,
vendorMatrixXml1, vendorManifestXml1};
expectVendorManifest(0);
expectSystemManifest(0);
expectVendorMatrix(0);
expectSystemMatrix(0);
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
ASSERT_STREQ(error.c_str(), "");
}
// Test that framework-only OTA fails when kernel is not compatible with incoming system.
TEST_F(VintfObjectCompatibleTest, KernelInfoIncompatible) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixKernel318};
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, INCOMPATIBLE) << "Should have failed.";
EXPECT_IN("Framework is incompatible with kernel version 3.18.31", error);
}
// Test that full OTA is successful when the OTA package provides a compatible kernel.
TEST_F(VintfObjectCompatibleTest, UpdateKernel) {
std::string error;
std::vector<std::string> packageInfo = {vendorManifestKernel318, systemMatrixKernel318};
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, COMPATIBLE) << "Fail message:" << error;
ASSERT_STREQ(error.c_str(), "");
}
// Test fixture that provides incompatible metadata from the mock device.
class VintfObjectIncompatibleTest : public VintfObjectTestBase {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
setFakeProperties();
setupMockFetcher(vendorManifestXml1, systemMatrixXml2, systemManifestXml1, vendorMatrixXml1,
productModel);
}
};
// Fetch all metadata from device and ensure that it fails.
TEST_F(VintfObjectIncompatibleTest, TestDeviceCompatibility) {
std::string error;
std::vector<std::string> packageInfo;
expectVendorManifest();
expectSystemManifest();
expectVendorMatrix();
expectSystemMatrix();
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
}
// Pass in new metadata that fixes the incompatibility.
TEST_F(VintfObjectIncompatibleTest, TestInputVsDeviceSuccess) {
std::string error;
std::vector<std::string> packageInfo = {systemMatrixXml1};
expectVendorManifest();
expectSystemManifest();
expectVendorMatrix();
expectSystemMatrix(0);
int result = checkCompatibility(packageInfo, &error);
ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
ASSERT_STREQ(error.c_str(), "");
}
// Test fixture that provides compatible metadata from the mock device.
class VintfObjectRuntimeInfoTest : public VintfObjectTestBase {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
// clear fetch flags
runtimeInfoFactory().getInfo()->failNextFetch();
vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
}
virtual void TearDown() {
Mock::VerifyAndClear(&runtimeInfoFactory());
Mock::VerifyAndClear(runtimeInfoFactory().getInfo().get());
}
MockRuntimeInfoFactory& runtimeInfoFactory() {
return static_cast<MockRuntimeInfoFactory&>(*vintfObject->getRuntimeInfoFactory());
}
};
TEST_F(VintfObjectRuntimeInfoTest, GetRuntimeInfo) {
InSequence s;
EXPECT_CALL(*runtimeInfoFactory().getInfo(),
fetchAllInformation(RuntimeInfo::FetchFlag::CPU_VERSION));
EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::NONE));
EXPECT_CALL(*runtimeInfoFactory().getInfo(),
fetchAllInformation(RuntimeInfo::FetchFlag::CPU_VERSION));
EXPECT_CALL(
*runtimeInfoFactory().getInfo(),
fetchAllInformation(RuntimeInfo::FetchFlag::ALL & ~RuntimeInfo::FetchFlag::CPU_VERSION));
EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::ALL));
EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::NONE));
vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
}
// Test fixture that provides incompatible metadata from the mock device.
class VintfObjectTest : public VintfObjectTestBase {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
// By default use empty filesystem
EXPECT_CALL(fetcher(), listFiles(_, _, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::OK));
EXPECT_CALL(fetcher(), fetch(_, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::NAME_NOT_FOUND));
}
};
// Test framework compatibility matrix is combined at runtime
TEST_F(VintfObjectTest, FrameworkCompatibilityMatrixCombine) {
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillOnce(Invoke([](const auto&, auto* out, auto*) {
*out = {
"compatibility_matrix.1.xml",
"compatibility_matrix.empty.xml",
};
return ::android::OK;
}));
expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml",
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>");
expectFetch(kSystemVintfDir + "compatibility_matrix.empty.xml",
"<compatibility-matrix version=\"1.0\" type=\"framework\"/>");
expectFileNotExist(StrEq(kProductMatrix));
expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" />\n");
expectNeverFetch(kSystemLegacyMatrix);
EXPECT_NE(nullptr, vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */));
}
// Test product compatibility matrix is fetched
TEST_F(VintfObjectTest, ProductCompatibilityMatrix) {
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillOnce(Invoke([](const auto&, auto* out, auto*) {
*out = {
"compatibility_matrix.1.xml",
"compatibility_matrix.empty.xml",
};
return ::android::OK;
}));
expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml",
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>");
expectFetch(kSystemVintfDir + "compatibility_matrix.empty.xml",
"<compatibility-matrix version=\"1.0\" type=\"framework\"/>");
expectFetch(kProductMatrix,
"<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.foo</name>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IFoo</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</compatibility-matrix>\n");
expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" />\n");
expectNeverFetch(kSystemLegacyMatrix);
auto fcm = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
ASSERT_NE(nullptr, fcm);
FqInstance expectInstance;
EXPECT_TRUE(expectInstance.setTo("android.hardware.foo@1.0::IFoo/default"));
bool found = false;
fcm->forEachInstance([&found, &expectInstance](const auto& matrixInstance) {
found |= matrixInstance.isSatisfiedBy(expectInstance);
return !found; // continue if not found
});
EXPECT_TRUE(found) << "android.hardware.foo@1.0::IFoo/default should be found in matrix:\n"
<< gCompatibilityMatrixConverter(*fcm);
}
const std::string vendorEtcManifest =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.0</version>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IVendorEtc</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</manifest>\n";
const std::string vendorManifest =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.0</version>\n"
" <interface>\n"
" <name>IVendor</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</manifest>\n";
const std::string odmProductManifest =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\" override=\"true\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.1</version>\n"
" <interface>\n"
" <name>IOdmProduct</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</manifest>\n";
const std::string odmManifest =
"<manifest version=\"1.0\" type=\"device\">\n"
" <hal format=\"hidl\" override=\"true\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <version>1.1</version>\n"
" <interface>\n"
" <name>IOdm</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n"
"</manifest>\n";
bool containsVendorManifest(const std::shared_ptr<const HalManifest>& p) {
return !p->getInstances("android.hardware.foo", {1, 0}, "IVendor").empty();
}
bool containsVendorEtcManifest(const std::shared_ptr<const HalManifest>& p) {
return !p->getInstances("android.hardware.foo", {2, 0}, "IVendorEtc").empty();
}
bool vendorEtcManifestOverridden(const std::shared_ptr<const HalManifest>& p) {
return p->getInstances("android.hardware.foo", {1, 0}, "IVendorEtc").empty();
}
bool containsOdmManifest(const std::shared_ptr<const HalManifest>& p) {
return !p->getInstances("android.hardware.foo", {1, 1}, "IOdm").empty();
}
bool containsOdmProductManifest(const std::shared_ptr<const HalManifest>& p) {
return !p->getInstances("android.hardware.foo", {1, 1}, "IOdmProduct").empty();
}
class DeviceManifestTest : public VintfObjectTestBase {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
setFakeProperties();
}
// Expect that /vendor/etc/vintf/manifest.xml is fetched.
void expectVendorManifest() { expectFetch(kVendorManifest, vendorEtcManifest); }
// /vendor/etc/vintf/manifest.xml does not exist.
void noVendorManifest() { expectFileNotExist(StrEq(kVendorManifest)); }
// Expect some ODM manifest is fetched.
void expectOdmManifest() {
if (!productModel.empty()) {
expectFileNotExist(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"));
}
expectFetch(kOdmManifest, odmManifest);
}
void noOdmManifest() { expectFileNotExist(StartsWith("/odm/")); }
std::shared_ptr<const HalManifest> get() {
return vintfObject->getDeviceHalManifest(true /* skipCache */);
}
};
// Test /vendor/etc/vintf/manifest.xml + ODM manifest
TEST_F(DeviceManifestTest, Combine1) {
expectVendorManifest();
expectOdmManifest();
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsVendorEtcManifest(p));
EXPECT_TRUE(vendorEtcManifestOverridden(p));
EXPECT_TRUE(containsOdmManifest(p));
EXPECT_FALSE(containsVendorManifest(p));
}
// Test /vendor/etc/vintf/manifest.xml
TEST_F(DeviceManifestTest, Combine2) {
expectVendorManifest();
noOdmManifest();
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsVendorEtcManifest(p));
EXPECT_FALSE(vendorEtcManifestOverridden(p));
EXPECT_FALSE(containsOdmManifest(p));
EXPECT_FALSE(containsVendorManifest(p));
}
// Test ODM manifest
TEST_F(DeviceManifestTest, Combine3) {
noVendorManifest();
expectOdmManifest();
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_FALSE(containsVendorEtcManifest(p));
EXPECT_TRUE(vendorEtcManifestOverridden(p));
EXPECT_TRUE(containsOdmManifest(p));
EXPECT_FALSE(containsVendorManifest(p));
}
// Test /vendor/manifest.xml
TEST_F(DeviceManifestTest, Combine4) {
noVendorManifest();
noOdmManifest();
expectFetch(kVendorLegacyManifest, vendorManifest);
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_FALSE(containsVendorEtcManifest(p));
EXPECT_TRUE(vendorEtcManifestOverridden(p));
EXPECT_FALSE(containsOdmManifest(p));
EXPECT_TRUE(containsVendorManifest(p));
}
class OdmManifestTest : public VintfObjectTestBase {
protected:
virtual void SetUp() override {
VintfObjectTestBase::SetUp();
// Assume /vendor/etc/vintf/manifest.xml does not exist to simplify
// testing logic.
expectFileNotExist(StrEq(kVendorManifest));
// Expect that the legacy /vendor/manifest.xml is never fetched.
expectNeverFetch(kVendorLegacyManifest);
// Assume no files exist under /odm/ unless otherwise specified.
expectFileNotExist(StartsWith("/odm/"));
}
std::shared_ptr<const HalManifest> get() {
return vintfObject->getDeviceHalManifest(true /* skipCache */);
}
};
TEST_F(OdmManifestTest, OdmProductManifest) {
if (productModel.empty()) return;
expectFetch(kOdmVintfDir + "manifest_" + productModel + ".xml", odmProductManifest);
// /odm/etc/vintf/manifest.xml should not be fetched when the product variant exists.
expectNeverFetch(kOdmManifest);
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsOdmProductManifest(p));
}
TEST_F(OdmManifestTest, OdmManifest) {
expectFetch(kOdmManifest, odmManifest);
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsOdmManifest(p));
}
TEST_F(OdmManifestTest, OdmLegacyProductManifest) {
if (productModel.empty()) return;
expectFetch(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", odmProductManifest);
// /odm/manifest.xml should not be fetched when the product variant exists.
expectNeverFetch(kOdmLegacyManifest);
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsOdmProductManifest(p));
}
TEST_F(OdmManifestTest, OdmLegacyManifest) {
expectFetch(kOdmLegacyManifest, odmManifest);
auto p = get();
ASSERT_NE(nullptr, p);
EXPECT_TRUE(containsOdmManifest(p));
}
struct CheckedFqInstance : FqInstance {
CheckedFqInstance(const char* s) : CheckedFqInstance(std::string(s)) {}
CheckedFqInstance(const std::string& s) { CHECK(setTo(s)) << s; }
Version getVersion() const { return FqInstance::getVersion(); }
};
static VintfObject::ListInstances getInstanceListFunc(
const std::vector<CheckedFqInstance>& instances) {
return [instances](const std::string& package, Version version, const std::string& interface,
const auto& /* instanceHint */) {
std::vector<std::pair<std::string, Version>> ret;
for (auto&& existing : instances) {
if (existing.getPackage() == package && existing.getVersion().minorAtLeast(version) &&
existing.getInterface() == interface) {
ret.push_back(std::make_pair(existing.getInstance(), existing.getVersion()));
}
}
return ret;
};
}
class DeprecateTest : public VintfObjectTestBase {
protected:
virtual void SetUp() override {
VintfObjectTestBase::SetUp();
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
*out = {
"compatibility_matrix.1.xml",
"compatibility_matrix.2.xml",
};
return ::android::OK;
}));
EXPECT_CALL(fetcher(), listFiles(StrEq(kVendorManifestFragmentDir), _, _))
.WillOnce(Return(::android::OK));
EXPECT_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
.WillOnce(Return(::android::OK));
expectFetch(kSystemVintfDir + "compatibility_matrix.1.xml", systemMatrixLevel1);
expectFetch(kSystemVintfDir + "compatibility_matrix.2.xml", systemMatrixLevel2);
expectFileNotExist(StrEq(kProductMatrix));
expectNeverFetch(kSystemLegacyMatrix);
expectFetch(kVendorManifest,
"<manifest version=\"1.0\" type=\"device\" target-level=\"2\"/>");
expectFileNotExist(StartsWith("/odm/"));
// Update the device manifest cache because CheckDeprecate does not fetch
// device manifest again if cache exist.
vintfObject->getDeviceHalManifest(true /* skipCache */);
}
};
TEST_F(DeprecateTest, CheckNoDeprecate) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
}
TEST_F(DeprecateTest, CheckRemoved) {
auto pred = getInstanceListFunc({
"android.hardware.removed@1.0::IRemoved/default",
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "removed@1.0 should be deprecated. " << error;
}
TEST_F(DeprecateTest, CheckMinor) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.0::IMinor/default",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "minor@1.0 should be deprecated. " << error;
}
TEST_F(DeprecateTest, CheckMinorDeprecatedInstance1) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.0::IMinor/legacy",
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "minor@1.0::IMinor/legacy should be deprecated. " << error;
}
TEST_F(DeprecateTest, CheckMinorDeprecatedInstance2) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.minor@1.1::IMinor/legacy",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "minor@1.1::IMinor/legacy should be deprecated. " << error;
}
TEST_F(DeprecateTest, CheckMajor1) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.major@1.0::IMajor/default",
"android.hardware.major@2.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "major@1.0 should be deprecated. " << error;
}
TEST_F(DeprecateTest, CheckMajor2) {
auto pred = getInstanceListFunc({
"android.hardware.minor@1.1::IMinor/default",
"android.hardware.major@1.0::IMajor/default",
});
std::string error;
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< "major@1.0 should be deprecated. " << error;
}
class MultiMatrixTest : public VintfObjectTestBase {
protected:
static std::string getFileName(size_t i) {
return "compatibility_matrix." + std::to_string(static_cast<Level>(i)) + ".xml";
}
void SetUpMockSystemMatrices(const std::vector<std::string>& xmls) {
EXPECT_CALL(fetcher(), listFiles(_, _, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::OK));
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
.WillRepeatedly(Invoke([=](const auto&, auto* out, auto*) {
size_t i = 1;
for (const auto& content : xmls) {
(void)content;
out->push_back(getFileName(i));
++i;
}
return ::android::OK;
}));
size_t i = 1;
for (const auto& content : xmls) {
expectFetchRepeatedly(kSystemVintfDir + getFileName(i), content);
++i;
}
expectFileNotExist(kProductMatrix);
expectNeverFetch(kSystemLegacyMatrix);
expectFileNotExist(StartsWith("/odm/"));
}
void expectTargetFcmVersion(size_t level) {
expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" target-level=\"" +
to_string(static_cast<Level>(level)) + "\"/>");
vintfObject->getDeviceHalManifest(true /* skipCache */);
}
};
class RegexTest : public MultiMatrixTest {
protected:
virtual void SetUp() {
MultiMatrixTest::SetUp();
SetUpMockSystemMatrices(systemMatrixRegexXmls);
}
};
TEST_F(RegexTest, CombineLevel1) {
expectTargetFcmVersion(1);
auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
ASSERT_NE(nullptr, matrix);
std::string xml = gCompatibilityMatrixConverter(*matrix);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.0-2</version>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n",
xml);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.0-1</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>special/1.0</instance>\n"
" <regex-instance>regex/1.0/[0-9]+</regex-instance>\n"
" <regex-instance>regex_common/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n",
xml);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.1-2</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>special/1.1</instance>\n"
" <regex-instance>[a-z]+_[a-z]+/[0-9]+</regex-instance>\n"
" <regex-instance>regex/1.1/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n",
xml);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.regex</name>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>special/2.0</instance>\n"
" <regex-instance>regex/2.0/[0-9]+</regex-instance>\n"
" <regex-instance>regex_[a-z]+/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n",
xml);
}
TEST_F(RegexTest, CombineLevel2) {
expectTargetFcmVersion(2);
auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
ASSERT_NE(nullptr, matrix);
std::string xml = gCompatibilityMatrixConverter(*matrix);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.1-2</version>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>default</instance>\n"
" </interface>\n"
" </hal>\n",
xml);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"false\">\n"
" <name>android.hardware.regex</name>\n"
" <version>1.1-2</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>special/1.1</instance>\n"
" <regex-instance>[a-z]+_[a-z]+/[0-9]+</regex-instance>\n"
" <regex-instance>regex/1.1/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n",
xml);
EXPECT_IN(
" <hal format=\"hidl\" optional=\"true\">\n"
" <name>android.hardware.regex</name>\n"
" <version>2.0</version>\n"
" <interface>\n"
" <name>IRegex</name>\n"
" <instance>special/2.0</instance>\n"
" <regex-instance>regex/2.0/[0-9]+</regex-instance>\n"
" <regex-instance>regex_[a-z]+/[0-9]+</regex-instance>\n"
" </interface>\n"
" </hal>\n",
xml);
}
TEST_F(RegexTest, DeprecateLevel2) {
std::string error;
expectTargetFcmVersion(2);
auto pred = getInstanceListFunc({
"android.hardware.regex@1.1::IRegex/default",
"android.hardware.regex@1.1::IRegex/special/1.1",
"android.hardware.regex@1.1::IRegex/regex/1.1/1",
"android.hardware.regex@1.1::IRegex/regex_common/0",
"android.hardware.regex@2.0::IRegex/default",
});
EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
for (const auto& deprecated : {
"android.hardware.regex@1.0::IRegex/default",
"android.hardware.regex@1.0::IRegex/special/1.0",
"android.hardware.regex@1.0::IRegex/regex/1.0/1",
"android.hardware.regex@1.0::IRegex/regex_common/0",
"android.hardware.regex@1.1::IRegex/special/1.0",
"android.hardware.regex@1.1::IRegex/regex/1.0/1",
}) {
// 2.0/default ensures compatibility.
pred = getInstanceListFunc({
deprecated,
"android.hardware.regex@2.0::IRegex/default",
});
error.clear();
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< deprecated << " should be deprecated. " << error;
}
}
TEST_F(RegexTest, DeprecateLevel3) {
std::string error;
expectTargetFcmVersion(3);
auto pred = getInstanceListFunc({
"android.hardware.regex@2.0::IRegex/special/2.0",
"android.hardware.regex@2.0::IRegex/regex/2.0/1",
"android.hardware.regex@2.0::IRegex/default",
});
EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
for (const auto& deprecated : {
"android.hardware.regex@1.0::IRegex/default",
"android.hardware.regex@1.0::IRegex/special/1.0",
"android.hardware.regex@1.0::IRegex/regex/1.0/1",
"android.hardware.regex@1.0::IRegex/regex_common/0",
"android.hardware.regex@1.1::IRegex/special/1.0",
"android.hardware.regex@1.1::IRegex/regex/1.0/1",
"android.hardware.regex@1.1::IRegex/special/1.1",
"android.hardware.regex@1.1::IRegex/regex/1.1/1",
"android.hardware.regex@1.1::IRegex/regex_common/0",
}) {
// 2.0/default ensures compatibility.
pred = getInstanceListFunc({
deprecated,
"android.hardware.regex@2.0::IRegex/default",
});
error.clear();
EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
<< deprecated << " should be deprecated.";
}
}
//
// Set of framework matrices of different FCM version with <kernel>.
//
#define FAKE_KERNEL(__version__, __key__) \
" <kernel version=\"" __version__ "\">\n" \
" <config>\n" \
" <key>CONFIG_" __key__ "</key>\n" \
" <value type=\"tristate\">y</value>\n" \
" </config>\n" \
" </kernel>\n"
const static std::vector<std::string> systemMatrixKernelXmls = {
// 1.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\">\n"
FAKE_KERNEL("1.0.0", "A1")
FAKE_KERNEL("2.0.0", "B1")
"</compatibility-matrix>\n",
// 2.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"2\">\n"
FAKE_KERNEL("2.0.0", "B2")
FAKE_KERNEL("3.0.0", "C2")
FAKE_KERNEL("4.0.0", "D2")
"</compatibility-matrix>\n",
// 3.xml
"<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"3\">\n"
FAKE_KERNEL("4.0.0", "D3")
FAKE_KERNEL("5.0.0", "E3")
"</compatibility-matrix>\n",
};
class KernelTest : public MultiMatrixTest {};
// Assume that we are developing level 2. Test that old <kernel> requirements should
// not change and new <kernel> versions are added.
TEST_F(KernelTest, Level1AndLevel2) {
SetUpMockSystemMatrices({systemMatrixKernelXmls[0], systemMatrixKernelXmls[1]});
expectTargetFcmVersion(1);
auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
ASSERT_NE(nullptr, matrix);
std::string xml = gCompatibilityMatrixConverter(*matrix);
EXPECT_IN(FAKE_KERNEL("1.0.0", "A1"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("2.0.0", "B1"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("3.0.0", "C2"), xml) << "\nShould see <kernel> from new matrices";
EXPECT_IN(FAKE_KERNEL("4.0.0", "D2"), xml) << "\nShould see <kernel> from new matrices";
EXPECT_NOT_IN(FAKE_KERNEL("2.0.0", "B2"), xml) << "\nOld requirements must not change";
}
// Assume that we are developing level 3. Test that old <kernel> requirements should
// not change and new <kernel> versions are added.
TEST_F(KernelTest, Level1AndMore) {
SetUpMockSystemMatrices({systemMatrixKernelXmls});
expectTargetFcmVersion(1);
auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
ASSERT_NE(nullptr, matrix);
std::string xml = gCompatibilityMatrixConverter(*matrix);
EXPECT_IN(FAKE_KERNEL("1.0.0", "A1"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("2.0.0", "B1"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("3.0.0", "C2"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("4.0.0", "D2"), xml) << "\nOld requirements must not change.";
EXPECT_IN(FAKE_KERNEL("5.0.0", "E3"), xml) << "\nShould see <kernel> from new matrices";
EXPECT_NOT_IN(FAKE_KERNEL("2.0.0", "B2"), xml) << "\nOld requirements must not change";
EXPECT_NOT_IN(FAKE_KERNEL("4.0.0", "D3"), xml) << "\nOld requirements must not change";
}
class VintfObjectPartialUpdateTest : public MultiMatrixTest {
protected:
void SetUp() override {
MultiMatrixTest::SetUp();
setFakeProperties();
}
};
TEST_F(VintfObjectPartialUpdateTest, DeviceCompatibility) {
setupMockFetcher(vendorManifestRequire1, "", systemManifestXml1, vendorMatrixXml1,
productModel);
SetUpMockSystemMatrices(systemMatrixRequire);
expectSystemManifest();
expectVendorMatrix();
expectVendorManifest();
std::string error;
EXPECT_TRUE(checkCompatibility({}, &error)) << error;
}
TEST_F(VintfObjectPartialUpdateTest, VendorOnlyCompatible) {
setupMockFetcher("", "", systemManifestXml1, vendorMatrixXml1, productModel);
SetUpMockSystemMatrices(systemMatrixRequire);
expectSystemManifest();
expectVendorMatrix();
// Should not load vendor manifest from device
expectVendorManifest(0);
std::string error;
EXPECT_TRUE(checkCompatibility({vendorManifestRequire2}, &error)) << error;
}
const std::string systemEtcManifest =
"<manifest version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::ISystemEtc/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
const std::string systemEtcManifestFrag =
"<manifest version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::ISystemEtcFragment/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
const std::string productEtcManifest =
"<manifest version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::IProductEtc/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
const std::string productEtcManifestFrag =
"<manifest version=\"1.0\" type=\"framework\">\n"
" <hal format=\"hidl\">\n"
" <name>android.hardware.foo</name>\n"
" <transport>hwbinder</transport>\n"
" <fqname>@1.0::IProductEtcFragment/default</fqname>\n"
" </hal>\n"
"</manifest>\n";
using FrameworkManifestTestParam =
std::tuple<bool /* Existence of /system/etc/vintf/manifest.xml */,
bool /* Existence of /system/etc/vintf/manifest/fragment.xml */,
bool /* Existence of /product/etc/vintf/manifest.xml */,
bool /* Existence of /product/etc/vintf/manifest/fragment.xml */>;
class FrameworkManifestTest : public VintfObjectTestBase,
public ::testing::WithParamInterface<FrameworkManifestTestParam> {
protected:
virtual void SetUp() {
VintfObjectTestBase::SetUp();
setFakeProperties();
}
// Set the existence of /system/etc/vintf/manifest.xml
void expectSystemManifest(bool exists) {
if (exists) {
expectFetchRepeatedly(kSystemManifest, systemEtcManifest);
} else {
expectFileNotExist(StrEq(kSystemManifest));
}
expectFileNotExist(StrEq(kSystemLegacyManifest));
}
// Set the existence of /system/etc/vintf/manifest/fragment.xml
void expectSystemManifestFragment(bool exists) {
if (exists) {
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
*out = {"fragment.xml"};
return ::android::OK;
}));
expectFetchRepeatedly(kSystemManifestFragmentDir + "fragment.xml",
systemEtcManifestFrag);
} else {
EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::OK));
expectFileNotExist(kSystemManifestFragmentDir + "fragment.xml");
}
}
// Set the existence of /product/etc/vintf/manifest.xml
void expectProductManifest(bool exists) {
if (exists) {
expectFetchRepeatedly(kProductManifest, productEtcManifest);
} else {
expectFileNotExist(kProductManifest);
}
}
// Set the existence of /product/etc/vintf/manifest/fragment.xml
void expectProductManifestFragment(bool exists) {
if (exists) {
EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
*out = {"fragment.xml"};
return ::android::OK;
}));
expectFetchRepeatedly(kProductManifestFragmentDir + "fragment.xml",
productEtcManifestFrag);
} else {
EXPECT_CALL(fetcher(), listFiles(StrEq(kProductManifestFragmentDir), _, _))
.Times(AnyNumber())
.WillRepeatedly(Return(::android::OK));
expectFileNotExist(kProductManifestFragmentDir + "fragment.xml");
}
}
void expectContainsInterface(const std::string& interface, bool contains = true) {
auto manifest = vintfObject->getFrameworkHalManifest();
ASSERT_NE(nullptr, manifest);
EXPECT_NE(manifest->getInstances("android.hardware.foo", {1, 0}, interface).empty(),
contains)
<< interface << " is missing.";
}
};
TEST_P(FrameworkManifestTest, Existence) {
expectSystemManifest(std::get<0>(GetParam()));
expectSystemManifestFragment(std::get<1>(GetParam()));
expectProductManifest(std::get<2>(GetParam()));
expectProductManifestFragment(std::get<3>(GetParam()));
if (!std::get<0>(GetParam())) {
EXPECT_EQ(nullptr, vintfObject->getFrameworkHalManifest())
<< "getFrameworkHalManifest must return nullptr if " << kSystemManifest
<< " does not exist";
} else {
expectContainsInterface("ISystemEtc", std::get<0>(GetParam()));
expectContainsInterface("ISystemEtcFragment", std::get<1>(GetParam()));
expectContainsInterface("IProductEtc", std::get<2>(GetParam()));
expectContainsInterface("IProductEtcFragment", std::get<3>(GetParam()));
}
}
INSTANTIATE_TEST_SUITE_P(, FrameworkManifestTest,
::testing::Combine(Bool(), Bool(), Bool(), Bool()));
} // namespace testing
} // namespace vintf
} // namespace android
int main(int argc, char** argv) {
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}