Add hardcoded version checks for netutils-wrapper

Each version bump of netutils-wrapper lose some functionality,
and hence only the major version is bumped. Also, vendor code
should only depend on a single version of netutils-wrapper.
Hardcode this requirement in host-side libvintf to check
compatibility when framework manifest and device compatibility
matrix is built.

Test: host libvintf_test
Test: target libvintf_test
Test: host vintf_object_test
Test: target vintf_object_test
Test: m system_manifest.xml compatibility_matrix.xml
Test: boots

Bug: 64447338
Change-Id: I75c28f3e021d16860e4577c3ecfaec2bd89d8a3d
Merged-In: I75c28f3e021d16860e4577c3ecfaec2bd89d8a3d
diff --git a/test/main.cpp b/test/main.cpp
index 42932e5..d8cfaf3 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -39,6 +39,12 @@
 extern const XmlConverter<HalManifest> &gHalManifestConverter;
 extern const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter;
 
+static bool Contains(const std::string& str, const std::string& sub) {
+    return str.find(sub) != std::string::npos;
+}
+#define EXPECT_CONTAINS(str, sub) \
+    EXPECT_TRUE(Contains((str), (sub))) << "Cannot find \"" << (sub) << "\" in \"" << (str) << "\""
+
 struct LibVintfTest : public ::testing::Test {
 public:
     virtual void SetUp() override {
@@ -1421,6 +1427,113 @@
     EXPECT_EQ(configs.find("CONFIG_NOT_SET")->second, "n");
 }
 
+TEST_F(LibVintfTest, NetutilsWrapperMatrix) {
+    std::string matrixXml;
+    CompatibilityMatrix matrix;
+
+    matrixXml =
+        "<compatibility-matrix version=\"1.0\" type=\"device\">"
+        "    <hal format=\"native\" optional=\"false\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.0</version>"
+        "    </hal>"
+        "</compatibility-matrix>";
+    EXPECT_TRUE(gCompatibilityMatrixConverter(&matrix, matrixXml))
+        << gCompatibilityMatrixConverter.lastError();
+
+// only host libvintf hardcodes netutils-wrapper version requirements
+#ifdef LIBVINTF_HOST
+
+    matrixXml =
+        "<compatibility-matrix version=\"1.0\" type=\"device\">"
+        "    <hal format=\"native\" optional=\"false\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.0-1</version>"
+        "    </hal>"
+        "</compatibility-matrix>";
+    EXPECT_FALSE(gCompatibilityMatrixConverter(&matrix, matrixXml));
+    EXPECT_CONTAINS(
+        gCompatibilityMatrixConverter.lastError(),
+        "netutils-wrapper HAL must specify exactly one version x.0, but a range is provided. "
+        "Perhaps you mean '1.0'?");
+
+    matrixXml =
+        "<compatibility-matrix version=\"1.0\" type=\"device\">"
+        "    <hal format=\"native\" optional=\"false\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.1</version>"
+        "    </hal>"
+        "</compatibility-matrix>";
+    EXPECT_FALSE(gCompatibilityMatrixConverter(&matrix, matrixXml));
+    EXPECT_CONTAINS(
+        gCompatibilityMatrixConverter.lastError(),
+        "netutils-wrapper HAL must specify exactly one version x.0, but minor version is not 0. "
+        "Perhaps you mean '1.0'?");
+
+    matrixXml =
+        "<compatibility-matrix version=\"1.0\" type=\"device\">"
+        "    <hal format=\"native\" optional=\"false\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.0</version>"
+        "        <version>2.0</version>"
+        "    </hal>"
+        "</compatibility-matrix>";
+    EXPECT_FALSE(gCompatibilityMatrixConverter(&matrix, matrixXml));
+    EXPECT_CONTAINS(
+        gCompatibilityMatrixConverter.lastError(),
+        "netutils-wrapper HAL must specify exactly one version x.0, but multiple <version> element "
+        "is specified.");
+
+#endif  // LIBVINTF_HOST
+}
+
+TEST_F(LibVintfTest, NetutilsWrapperManifest) {
+    std::string manifestXml;
+    HalManifest manifest;
+
+    manifestXml =
+        "<manifest version=\"1.0\" type=\"framework\">"
+        "    <hal format=\"native\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.0</version>"
+        "        <version>2.0</version>"
+        "    </hal>"
+        "</manifest>";
+    EXPECT_TRUE(gHalManifestConverter(&manifest, manifestXml)) << gHalManifestConverter.lastError();
+
+// only host libvintf hardcodes netutils-wrapper version requirements
+#ifdef LIBVINTF_HOST
+
+    manifestXml =
+        "<manifest version=\"1.0\" type=\"framework\">"
+        "    <hal format=\"native\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.1</version>"
+        "    </hal>"
+        "</manifest>";
+    EXPECT_FALSE(gHalManifestConverter(&manifest, manifestXml));
+    EXPECT_CONTAINS(
+        gCompatibilityMatrixConverter.lastError(),
+        "netutils-wrapper HAL must specify exactly one version x.0, but multiple <version> element "
+        "is specified.");
+
+    manifestXml =
+        "<manifest version=\"1.0\" type=\"framework\">"
+        "    <hal format=\"native\">"
+        "        <name>netutils-wrapper</name>"
+        "        <version>1.0</version>"
+        "        <version>2.1</version>"
+        "    </hal>"
+        "</manifest>";
+    EXPECT_FALSE(gHalManifestConverter(&manifest, manifestXml));
+    EXPECT_CONTAINS(
+        gCompatibilityMatrixConverter.lastError(),
+        "netutils-wrapper HAL must specify exactly one version x.0, but multiple <version> element "
+        "is specified.");
+
+#endif  // LIBVINTF_HOST
+}
+
 // Run KernelConfigParserInvalidTest on processComments = {true, false}
 class KernelConfigParserInvalidTest : public ::testing::TestWithParam<bool> {};