regex-instance: tests for regex instances
Adds tests to libvintf_test and vintf_object_test to test the
following:
* HalManifest::checkUnusedHals
* HalManifest::checkCompatibility
* CompatibilityMatrix::combine
* VintfObject::CheckDeprecation
Bug: 73738616
Test: libvintf_test
Test: vintf_object_test
Test: vts_treble_vintf_test
Change-Id: Ia376d55be3394761d193a044a11229a55944cf9b
Merged-In: Ia376d55be3394761d193a044a11229a55944cf9b
diff --git a/test/LibVintfTest.cpp b/test/LibVintfTest.cpp
index 245cf27..4c7aa23 100644
--- a/test/LibVintfTest.cpp
+++ b/test/LibVintfTest.cpp
@@ -27,6 +27,7 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/strings.h>
#include <gtest/gtest.h>
namespace android {
@@ -111,6 +112,9 @@
std::string* e) {
return cm1->addAllXmlFilesAsOptional(cm2, e);
}
+ std::set<std::string> checkUnusedHals(const HalManifest& m, const CompatibilityMatrix& cm) {
+ return m.checkUnusedHals(cm);
+ }
std::map<std::string, HalInterface> testHalInterfaces() {
HalInterface intf("IFoo", {"default"});
@@ -3285,6 +3289,144 @@
EXPECT_IN("n07 4 v4l1d 1n73rf4c3", error);
}
+TEST_F(LibVintfTest, RegexInstanceValid) {
+ CompatibilityMatrix matrix;
+ std::string error;
+
+ std::string xml =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <regex-instance>legacy/[0-9]+</regex-instance>\n"
+ " <regex-instance>slot[0-9]+</regex-instance>\n"
+ " <regex-instance>.*</regex-instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</compatibility-matrix>\n";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&matrix, xml, &error)) << error;
+}
+
+TEST_F(LibVintfTest, RegexInstanceInvalid) {
+ CompatibilityMatrix matrix;
+ std::string error;
+ std::string xml =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <regex-instance>e{1,2,3}</regex-instance>\n"
+ " <regex-instance>*</regex-instance>\n"
+ " <regex-instance>+</regex-instance>\n"
+ " <regex-instance>[0-9]+</regex-instance>\n"
+ " <regex-instance>[0-9]+</regex-instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</compatibility-matrix>\n";
+ EXPECT_FALSE(gCompatibilityMatrixConverter(&matrix, xml, &error));
+ EXPECT_IN("Invalid regular expression 'e{1,2,3}'", error);
+ EXPECT_IN("Invalid regular expression '*'", error);
+ EXPECT_IN("Invalid regular expression '+'", error);
+ EXPECT_IN("Duplicated regex-instance '[0-9]+'", error);
+}
+
+TEST_F(LibVintfTest, RegexInstanceCompat) {
+ CompatibilityMatrix matrix;
+ std::string error;
+
+ std::string xml =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " <version>3.1-2</version>\n"
+ " <interface>\n"
+ " <name>IFoo</name>\n"
+ " <instance>default</instance>\n"
+ " <regex-instance>legacy/[0-9]+</regex-instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <sepolicy>\n"
+ " <kernel-sepolicy-version>0</kernel-sepolicy-version>\n"
+ " <sepolicy-version>0.0</sepolicy-version>\n"
+ " </sepolicy>\n"
+ "</compatibility-matrix>\n";
+ EXPECT_TRUE(gCompatibilityMatrixConverter(&matrix, xml))
+ << gCompatibilityMatrixConverter.lastError();
+
+ {
+ std::string xml =
+ "<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>IFoo</name>\n"
+ " <instance>default</instance>\n"
+ " <instance>legacy/0</instance>\n"
+ " <instance>legacy/1</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+ HalManifest manifest;
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml));
+ EXPECT_TRUE(manifest.checkCompatibility(matrix, &error)) << error;
+
+ auto unused = checkUnusedHals(manifest, matrix);
+ EXPECT_TRUE(unused.empty())
+ << "Contains unused HALs: " << android::base::Join(unused, "\n");
+ }
+
+ {
+ std::string xml =
+ "<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>IFoo</name>\n"
+ " <instance>default</instance>\n"
+ " <instance>legacy0</instance>\n"
+ " <instance>nonmatch/legacy/0</instance>\n"
+ " <instance>legacy/0/nonmatch</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ "</manifest>\n";
+
+ HalManifest manifest;
+ EXPECT_TRUE(gHalManifestConverter(&manifest, xml));
+ EXPECT_FALSE(manifest.checkCompatibility(matrix, &error))
+ << "Should not be compatible because no legacy/[0-9]+ is provided.";
+
+ auto unused = checkUnusedHals(manifest, matrix);
+ EXPECT_EQ((std::set<std::string>{"android.hardware.foo@1.0::IFoo/nonmatch/legacy/0",
+ "android.hardware.foo@1.0::IFoo/legacy/0/nonmatch",
+ "android.hardware.foo@1.0::IFoo/legacy0"}),
+ unused);
+ }
+}
+
+TEST_F(LibVintfTest, Regex) {
+ details::Regex regex;
+
+ EXPECT_FALSE(regex.compile("+"));
+ EXPECT_FALSE(regex.compile("*"));
+
+ ASSERT_TRUE(regex.compile("legacy/[0-9]+"));
+ EXPECT_TRUE(regex.matches("legacy/0"));
+ EXPECT_TRUE(regex.matches("legacy/000"));
+ EXPECT_FALSE(regex.matches("legacy/"));
+ EXPECT_FALSE(regex.matches("ssslegacy/0"));
+ EXPECT_FALSE(regex.matches("legacy/0sss"));
+}
+
} // namespace vintf
} // namespace android
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 27c04a5..48623b8 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -227,6 +227,54 @@
" </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"};
+
// Setup the MockFileFetcher 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,
@@ -332,6 +380,16 @@
}));
}
+ // 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);
@@ -959,6 +1017,201 @@
<< "major@1.0 should be deprecated. " << error;
}
+class RegexTest : public VintfObjectTestBase {
+ protected:
+ static std::string getFileName(size_t i) {
+ return "compatibility_matrix." + std::to_string(static_cast<Level>(i)) + ".xml";
+ }
+ virtual void SetUp() override {
+ EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
+ .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
+ size_t i = 1;
+ for (const auto& content : systemMatrixRegexXmls) {
+ (void)content;
+ out->push_back(getFileName(i));
+ ++i;
+ }
+ return ::android::OK;
+ }));
+ size_t i = 1;
+ for (const auto& content : systemMatrixRegexXmls) {
+ expectFetchRepeatedly(kSystemVintfDir + getFileName(i), content);
+ ++i;
+ }
+ expectSystemMatrix(0);
+ 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 */);
+ }
+};
+
+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.";
+ }
+}
+
int main(int argc, char** argv) {
::testing::InitGoogleMock(&argc, argv);