Add tests to add/remove/re-add a NAT.

This is in preparation of work to support multiple upstreams.

Test: netd_unit_test still passes with current behavior.
Bug: 38218697
Bug: 64382985
Bug: 64976379
Bug: 64995262
Change-Id: I16bdb69fa151c72d77663025bed82259f34a9608
diff --git a/server/TetherControllerTest.cpp b/server/TetherControllerTest.cpp
index b92dc24..ba101fd 100644
--- a/server/TetherControllerTest.cpp
+++ b/server/TetherControllerTest.cpp
@@ -94,22 +94,35 @@
                 "COMMIT\n" },
     };
 
-    ExpectedIptablesCommands firstNatCommands(const char *extIf) {
+    ExpectedIptablesCommands firstIPv4UpstreamCommands(const char *extIf) {
         std::string v4Cmd = StringPrintf(
             "*nat\n"
             "-A tetherctrl_nat_POSTROUTING -o %s -j MASQUERADE\n"
             "COMMIT\n", extIf);
+        return {
+            { V4, v4Cmd },
+        };
+    }
+
+    ExpectedIptablesCommands firstIPv6UpstreamCommands() {
         std::string v6Cmd =
             "*filter\n"
             "-A tetherctrl_FORWARD -g tetherctrl_counters\n"
             "COMMIT\n";
         return {
-            { V4, v4Cmd },
             { V6, v6Cmd },
         };
     }
 
-    ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf) {
+    template<typename T>
+    void appendAll(std::vector<T>& cmds, const std::vector<T>& appendCmds) {
+        for (auto& cmd : appendCmds) {
+            cmds.push_back(cmd);
+        }
+    }
+
+    ExpectedIptablesCommands startNatCommands(const char *intIf, const char *extIf,
+            bool withCounterChainRules) {
         std::string rpfilterCmd = StringPrintf(
             "*raw\n"
             "-A tetherctrl_raw_PREROUTING -i %s -m rpfilter --invert ! -s fe80::/64 -j DROP\n"
@@ -123,20 +136,30 @@
                          intIf, extIf),
             StringPrintf("-A tetherctrl_FORWARD -i %s -o %s -g tetherctrl_counters",
                          intIf, extIf),
-            StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
-            StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
-            "-D tetherctrl_FORWARD -j DROP",
-            "-A tetherctrl_FORWARD -j DROP",
-            "COMMIT\n",
         };
 
         std::vector<std::string> v6Cmds = {
             "*filter",
-            StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
-            StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
-            "COMMIT\n",
         };
 
+        if (withCounterChainRules) {
+            const std::vector<std::string> counterRules = {
+                StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", intIf, extIf),
+                StringPrintf("-A tetherctrl_counters -i %s -o %s -j RETURN", extIf, intIf),
+            };
+
+            appendAll(v4Cmds, counterRules);
+            appendAll(v6Cmds, counterRules);
+        }
+
+        appendAll(v4Cmds, {
+            "-D tetherctrl_FORWARD -j DROP",
+            "-A tetherctrl_FORWARD -j DROP",
+            "COMMIT\n",
+        });
+
+        v6Cmds.push_back("COMMIT\n");
+
         return {
             { V6, rpfilterCmd },
             { V4, Join(v4Cmds, '\n') },
@@ -180,26 +203,49 @@
 }
 
 TEST_F(TetherControllerTest, TestAddAndRemoveNat) {
-    ExpectedIptablesCommands expected;
-    ExpectedIptablesCommands setupFirstNatCommands = firstNatCommands("rmnet0");
-    ExpectedIptablesCommands startFirstNatCommands = startNatCommands("wlan0", "rmnet0");
-    expected.insert(expected.end(), setupFirstNatCommands.begin(), setupFirstNatCommands.end());
-    expected.insert(expected.end(), startFirstNatCommands.begin(), startFirstNatCommands.end());
+    // Start first NAT on first upstream interface. Expect the upstream and NAT rules to be created.
+    ExpectedIptablesCommands firstNat;
+    ExpectedIptablesCommands setupFirstIPv4Commands = firstIPv4UpstreamCommands("rmnet0");
+    ExpectedIptablesCommands setupFirstIPv6Commands = firstIPv6UpstreamCommands();
+    ExpectedIptablesCommands startFirstNatCommands = startNatCommands("wlan0", "rmnet0", true);
+    appendAll(firstNat, setupFirstIPv4Commands);
+    appendAll(firstNat, setupFirstIPv6Commands);
+    appendAll(firstNat, startFirstNatCommands);
     mTetherCtrl.enableNat("wlan0", "rmnet0");
-    expectIptablesRestoreCommands(expected);
+    expectIptablesRestoreCommands(firstNat);
 
-    ExpectedIptablesCommands startOtherNat = startNatCommands("usb0", "rmnet0");
+    // Start second NAT on same upstream. Expect only the counter rules to be created.
+    ExpectedIptablesCommands startOtherNatOnSameUpstream = startNatCommands("usb0", "rmnet0", true);
     mTetherCtrl.enableNat("usb0", "rmnet0");
-    expectIptablesRestoreCommands(startOtherNat);
+    expectIptablesRestoreCommands(startOtherNatOnSameUpstream);
 
-    ExpectedIptablesCommands stopOtherNat = stopNatCommands("wlan0", "rmnet0");
+    // Remove the first NAT.
+    ExpectedIptablesCommands stopFirstNat = stopNatCommands("wlan0", "rmnet0");
     mTetherCtrl.disableNat("wlan0", "rmnet0");
-    expectIptablesRestoreCommands(stopOtherNat);
+    expectIptablesRestoreCommands(stopFirstNat);
 
-    expected = stopNatCommands("usb0", "rmnet0");
-    expected.insert(expected.end(), FLUSH_COMMANDS.begin(), FLUSH_COMMANDS.end());
+    // Remove the last NAT. Expect rules to be cleared.
+    ExpectedIptablesCommands stopLastNat = stopNatCommands("usb0", "rmnet0");
+
+    appendAll(stopLastNat, FLUSH_COMMANDS);
     mTetherCtrl.disableNat("usb0", "rmnet0");
-    expectIptablesRestoreCommands(expected);
+    expectIptablesRestoreCommands(stopLastNat);
+
+    // Re-add a NAT removed previously
+    firstNat = {};
+    // tetherctrl_counters chain rules are not re-added
+    startFirstNatCommands = startNatCommands("wlan0", "rmnet0", false);
+    appendAll(firstNat, setupFirstIPv4Commands);
+    appendAll(firstNat, setupFirstIPv6Commands);
+    appendAll(firstNat, startFirstNatCommands);
+    mTetherCtrl.enableNat("wlan0", "rmnet0");
+    expectIptablesRestoreCommands(firstNat);
+
+    // Remove it again. Expect rules to be cleared.
+    stopLastNat = stopNatCommands("wlan0", "rmnet0");
+    appendAll(stopLastNat, FLUSH_COMMANDS);
+    mTetherCtrl.disableNat("wlan0", "rmnet0");
+    expectIptablesRestoreCommands(stopLastNat);
 }
 
 std::string kTetherCounterHeaders = Join(std::vector<std::string> {