Make the VTS tests for the INetd HAL 1.0 more realistic.

The VTS test for the netd HAL creates an OEM network, but it
doesn't check whether the network exists. Fix that by using
the native multinetwork API calls to select the network.
Also, check that when an OEM network is created, there are no IP
rules that select for its fwmark. There should be none because
a network that has just been created has no interfaces.

Put utility code into a new VtsHalNetNetdTestUtils static library
to avoid code duplication when we add new tests for future HALversions.

Bug: 73032258
Test: VtsHalNetNetdV1_0TargetTest passes on marlin
Change-Id: I345b9b27d7c2c8bdd6ce6d60430490dac8c3a989
Merged-In: Ie574990f7640fdc7d83ccd58baf6dfe1069a3654
(cherry picked from commit 79f693702c35dca81f7390d1619736a204e61a70)
diff --git a/net/netd/1.0/vts/functional/Android.bp b/net/netd/1.0/vts/functional/Android.bp
index c79d116..80e157a 100644
--- a/net/netd/1.0/vts/functional/Android.bp
+++ b/net/netd/1.0/vts/functional/Android.bp
@@ -1,19 +1,37 @@
+//
+// Copyright (C) 2018 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.
+
 cc_test {
     name: "VtsHalNetNetdV1_0TargetTest",
     srcs: [
         "VtsHalNetNetdV1_0TargetTest.cpp",
     ],
     shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
         "android.system.net.netd@1.0",
+        "libandroid_net",
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libutils",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "VtsHalNetNetdTestUtils",
+    ],
     cflags: [
-        "-O0",
-        "-g",
+        "-Og",
         "-Wall",
         "-Werror",
     ],
diff --git a/net/netd/1.0/vts/functional/VtsHalNetNetdV1_0TargetTest.cpp b/net/netd/1.0/vts/functional/VtsHalNetNetdV1_0TargetTest.cpp
index c332c10..0c52900 100644
--- a/net/netd/1.0/vts/functional/VtsHalNetNetdV1_0TargetTest.cpp
+++ b/net/netd/1.0/vts/functional/VtsHalNetNetdV1_0TargetTest.cpp
@@ -20,15 +20,33 @@
 #include <android/system/net/netd/1.0/INetd.h>
 #include <log/log.h>
 
+#include "VtsHalNetNetdTestUtils.h"
+
 using ::android::system::net::netd::V1_0::INetd;
 using ::android::hardware::Return;
 using ::android::sp;
 
+// Test environment for Netd HIDL HAL.
+class NetdHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static NetdHidlEnvironment* Instance() {
+        static NetdHidlEnvironment* instance = new NetdHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<INetd>(); }
+
+   private:
+    NetdHidlEnvironment() {}
+};
+
 class NetdHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
-        netd = ::testing::VtsHalHidlTargetTestBase::getService<INetd>();
-        ASSERT_NE(nullptr, netd.get()) << "Could not get HIDL instance";
+        netd = ::testing::VtsHalHidlTargetTestBase::getService<INetd>(
+            NetdHidlEnvironment::Instance()->getServiceName<INetd>());
+        ASSERT_NE(netd, nullptr) << "Could not get HIDL instance";
     }
 
     sp<INetd> netd;
@@ -36,17 +54,28 @@
 
 // positive test. Ensure netd creates an oem network and returns valid netHandle, and destroys it.
 TEST_F(NetdHidlTest, TestCreateAndDestroyOemNetworkOk) {
-    auto cb = [this](uint64_t netHandle, uint32_t packetMark, INetd::StatusCode status) {
-        ASSERT_EQ(INetd::StatusCode::OK, status);
-        ASSERT_NE((uint64_t)0, netHandle);
-        ASSERT_NE((uint32_t)0, packetMark);
+    net_handle_t netHandle;
+    uint32_t packetMark;
+    INetd::StatusCode status;
 
-        Return<INetd::StatusCode> retStatus = netd->destroyOemNetwork(netHandle);
-        ASSERT_EQ(INetd::StatusCode::OK, retStatus);
-    };
+    Return<void> ret = netd->createOemNetwork([&](net_handle_t n, uint32_t p, INetd::StatusCode s) {
+        status = s;
+        netHandle = n;
+        packetMark = p;
+    });
 
-    Return<void> ret = netd->createOemNetwork(cb);
     ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(INetd::StatusCode::OK, status);
+    ASSERT_NE(NETWORK_UNSPECIFIED, netHandle);
+    ASSERT_NE((uint32_t)0, packetMark);
+
+    ASSERT_EQ(0, checkNetworkExists(netHandle));
+    ASSERT_EQ(0, countRulesForFwmark(packetMark));
+
+    Return<INetd::StatusCode> retStatus = netd->destroyOemNetwork(netHandle);
+    ASSERT_EQ(INetd::StatusCode::OK, retStatus);
+
+    ASSERT_EQ(-ENONET, checkNetworkExists(netHandle));
 }
 
 // negative test. Ensure destroy for invalid OEM network fails appropriately
@@ -58,7 +87,9 @@
 }
 
 int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NetdHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
+    NetdHidlEnvironment::Instance()->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     ALOGE("Test result with status=%d", status);
     return status;
diff --git a/net/netd/testutils/Android.bp b/net/netd/testutils/Android.bp
new file mode 100644
index 0000000..a7c33a5
--- /dev/null
+++ b/net/netd/testutils/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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.
+
+cc_library {
+    name: "VtsHalNetNetdTestUtils",
+    srcs: [
+        "VtsHalNetNetdTestUtils.cpp",
+    ],
+    export_include_dirs: ["."],
+    shared_libs: [
+        "libbase",
+        "libandroid_net",
+    ],
+    cflags: [
+        "-Og",
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/net/netd/testutils/VtsHalNetNetdTestUtils.cpp b/net/netd/testutils/VtsHalNetNetdTestUtils.cpp
new file mode 100644
index 0000000..1f7db2b
--- /dev/null
+++ b/net/netd/testutils/VtsHalNetNetdTestUtils.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 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 <regex>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/stringprintf.h>
+#include <android/multinetwork.h>
+
+#include "VtsHalNetNetdTestUtils.h"
+
+using android::base::StringPrintf;
+
+int checkNetworkExists(net_handle_t netHandle) {
+    int sock = socket(AF_INET6, SOCK_STREAM, 0);
+    if (sock == -1) {
+        return -ENOTSOCK;
+    }
+    int ret = android_setsocknetwork(netHandle, sock);
+    if (ret) {
+        ret = -errno;
+    }
+    close(sock);
+    return ret;
+}
+
+// TODO: deduplicate this with system/netd/server/binder_test.cpp.
+static std::vector<std::string> runCommand(const std::string& command) {
+    std::vector<std::string> lines;
+    FILE* f;
+
+    if ((f = popen(command.c_str(), "r")) == nullptr) {
+        perror("popen");
+        return lines;
+    }
+
+    char* line = nullptr;
+    size_t bufsize = 0;
+    ssize_t linelen = 0;
+    while ((linelen = getline(&line, &bufsize, f)) >= 0) {
+        lines.push_back(std::string(line, linelen));
+    }
+
+    free(line);
+    pclose(f);
+    return lines;
+}
+
+static std::vector<std::string> listIpRules(const char* ipVersion) {
+    std::string command = StringPrintf("%s %s rule list", IP_PATH, ipVersion);
+    return runCommand(command);
+}
+
+static int countMatchingIpRules(const std::string& regexString) {
+    const std::regex regex(regexString, std::regex_constants::extended);
+    int matches = 0;
+
+    for (const char* version : {"-4", "-6"}) {
+        std::vector<std::string> rules = listIpRules(version);
+        for (const auto& rule : rules) {
+            if (std::regex_search(rule, regex)) {
+                matches++;
+            }
+        }
+    }
+
+    return matches;
+}
+
+int countRulesForFwmark(const uint32_t fwmark) {
+    std::string regex = StringPrintf("from all fwmark 0x%x/.* lookup ", fwmark);
+    return countMatchingIpRules(regex);
+}
diff --git a/net/netd/testutils/VtsHalNetNetdTestUtils.h b/net/netd/testutils/VtsHalNetNetdTestUtils.h
new file mode 100644
index 0000000..71d9174
--- /dev/null
+++ b/net/netd/testutils/VtsHalNetNetdTestUtils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef VTS_HAL_NET_NETD_TEST_UTILS_H
+#define VTS_HAL_NET_NETD_TEST_UTILS_H
+
+#include <android/multinetwork.h>
+
+#define IP_PATH "/system/bin/ip"
+
+// Checks that the given network exists.
+// Returns 0 if it exists or -errno if it does not.
+int checkNetworkExists(net_handle_t netHandle);
+
+// Counts the number of IPv4 and IPv6 routing rules that select the specified fwmark.
+int countRulesForFwmark(const uint32_t fwmark);
+
+#endif