Bug 1166274 - Part 2: Add test for wifi static ip. r=hchang
authorEdgar Chen <echen@mozilla.com>
Wed, 04 Feb 2015 23:26:11 +0800
changeset 269582 e532ebecafc6bedcf1024a90f5d3c985bee3ec3b
parent 269581 86ab6cc5a3ae6ae92d7924d96f57a9df3d615755
child 269583 23773d965ecc512fd6e2a36b41c739f9948ebab3
push id2540
push userwcosta@mozilla.com
push dateWed, 03 Jun 2015 20:55:41 +0000
reviewershchang
bugs1166274
milestone41.0a1
Bug 1166274 - Part 2: Add test for wifi static ip. r=hchang
dom/wifi/test/marionette/head.js
dom/wifi/test/marionette/manifest.ini
dom/wifi/test/marionette/test_wifi_static_ip.js
--- a/dom/wifi/test/marionette/head.js
+++ b/dom/wifi/test/marionette/head.js
@@ -429,16 +429,33 @@ let gTestSuite = (function() {
    */
   function getKnownNetworks() {
     let request = wifiManager.getKnownNetworks();
     return wrapDomRequestAsPromise(request)
       .then(event => event.target.result);
   }
 
   /**
+   * Set the given network to static ip mode.
+   *
+   * Resolve when we set static ip mode successfully; reject when any error
+   * occurs.
+   *
+   * Fulfill params: (none)
+   * Reject params: (none)
+   *
+   * @return A deferred promise.
+   */
+  function setStaticIpMode(aNetwork, aConfig) {
+    let request = wifiManager.setStaticIpMode(aNetwork, aConfig);
+    return wrapDomRequestAsPromise(request)
+      .then(event => event.target.result);
+  }
+
+  /**
    * Issue a request to scan all wifi available networks.
    *
    * Resolve when we get the scan result; reject when any error
    * occurs.
    *
    * Fulfill params: An array of MozWifiNetwork
    * Reject params: (none)
    *
@@ -1021,16 +1038,127 @@ let gTestSuite = (function() {
           return;
         }
         throw 'Unexpected number of running processes:' + aProcessName +
               ', expected: ' + aExpectedNum + ', actual: ' + detail.length;
       });
   }
 
   /**
+   * Execute 'netcfg' shell and parse the result.
+   *
+   * Resolve when the executing is successful and reject otherwise.
+   *
+   * Fulfill params: Command result object, each key of which is the interface
+   *                 name and value is { ip(string), prefix(string) }.
+   * Reject params: String that indicates the reason of rejection.
+   *
+   * @return A deferred promise.
+   */
+  function exeAndParseNetcfg() {
+    return runEmulatorShellSafe(['netcfg'])
+      .then(function (aLines) {
+        // Sample output:
+        //
+        // lo       UP     127.0.0.1/8   0x00000049 00:00:00:00:00:00
+        // eth0     UP     10.0.2.15/24  0x00001043 52:54:00:12:34:56
+        // rmnet1   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:58
+        // rmnet2   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:59
+        // rmnet3   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:5a
+        // wlan0    UP     192.168.1.1/24  0x00001043 52:54:00:12:34:5b
+        // sit0     DOWN   0.0.0.0/0   0x00000080 00:00:00:00:00:00
+        // rmnet0   UP     10.0.2.100/24  0x00001043 52:54:00:12:34:57
+        //
+        let netcfgResult = {};
+        aLines.forEach(function (aLine) {
+          let tokens = aLine.split(/\s+/);
+          if (tokens.length < 5) {
+            return;
+          }
+          let ifname = tokens[0];
+          let [ip, prefix] = tokens[2].split('/');
+          netcfgResult[ifname] = { ip: ip, prefix: prefix };
+        });
+        log("netcfg result:" + JSON.stringify(netcfgResult));
+
+        return netcfgResult;
+      });
+  }
+
+  /**
+   * Execute 'ip route' and parse the result.
+   *
+   * Resolve when the executing is successful and reject otherwise.
+   *
+   * Fulfill params: Command result object, each key of which is the interface
+   *                 name and value is { src(string), gateway(string),
+   *                 default(boolean) }.
+   * Reject params: String that indicates the reason of rejection.
+   *
+   * @return A deferred promise.
+   */
+  function exeAndParseIpRoute() {
+    return runEmulatorShellSafe(['ip', 'route'])
+      .then(function (aLines) {
+        // Sample output:
+        //
+        // 10.0.2.4 via 10.0.2.2 dev rmnet0
+        // 10.0.2.3 via 10.0.2.2 dev rmnet0
+        // 192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.1
+        // 10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
+        // 10.0.2.0/24 dev rmnet0  proto kernel  scope link  src 10.0.2.100
+        // default via 10.0.2.2 dev rmnet0
+        // default via 10.0.2.2 dev eth0  metric 2
+        //
+
+        let ipRouteResult = {};
+
+        // Parse source ip for each interface.
+        aLines.forEach(function (aLine) {
+          let tokens = aLine.trim().split(/\s+/);
+          let srcIndex = tokens.indexOf('src');
+          if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
+            return;
+          }
+          let ifname = tokens[2];
+          let src = tokens[srcIndex + 1];
+          ipRouteResult[ifname] = { src: src, default: false, gateway: null };
+        });
+
+        // Parse default interfaces.
+        aLines.forEach(function (aLine) {
+          let tokens = aLine.split(/\s+/);
+          if (tokens.length < 2) {
+            return;
+          }
+          if ('default' === tokens[0]) {
+            let ifnameIndex = tokens.indexOf('dev');
+            if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
+              return;
+            }
+            let ifname = tokens[ifnameIndex + 1];
+            if (!ipRouteResult[ifname]) {
+              return;
+            }
+            ipRouteResult[ifname].default = true;
+            let gwIndex = tokens.indexOf('via');
+            if (gwIndex < 0 || gwIndex + 1 >= tokens.length) {
+              return;
+            }
+            ipRouteResult[ifname].gateway = tokens[gwIndex + 1];
+            return;
+          }
+        });
+        log("ip route result:" + JSON.stringify(ipRouteResult));
+
+        return ipRouteResult;
+      });
+  }
+
+  /**
    * Verify everything about routing when the wifi tethering is either on or off.
    *
    * We use two unix commands to verify the routing: 'netcfg' and 'ip route'.
    * For now the following two things will be checked:
    *   1) The default route interface should be 'rmnet0'.
    *   2) wlan0 is up and its ip is set to a private subnet.
    *
    * We also verify iptables output as netd's NatController will execute
@@ -1039,97 +1167,18 @@ let gTestSuite = (function() {
    * Resolve when the verification is successful and reject otherwise.
    *
    * Fulfill params: (none)
    * Reject params: String that indicates the reason of rejection.
    *
    * @return A deferred promise.
    */
   function verifyTetheringRouting(aEnabled) {
-    let netcfgResult = {};
-    let ipRouteResult = {};
-
-    // Execute 'netcfg' and parse to |netcfgResult|, each key of which is the
-    // interface name and value is { ip(string) }.
-    function exeAndParseNetcfg() {
-      return runEmulatorShellSafe(['netcfg'])
-        .then(function (aLines) {
-          // Sample output:
-          //
-          // lo       UP     127.0.0.1/8   0x00000049 00:00:00:00:00:00
-          // eth0     UP     10.0.2.15/24  0x00001043 52:54:00:12:34:56
-          // rmnet1   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:58
-          // rmnet2   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:59
-          // rmnet3   DOWN   0.0.0.0/0   0x00001002 52:54:00:12:34:5a
-          // wlan0    UP     192.168.1.1/24  0x00001043 52:54:00:12:34:5b
-          // sit0     DOWN   0.0.0.0/0   0x00000080 00:00:00:00:00:00
-          // rmnet0   UP     10.0.2.100/24  0x00001043 52:54:00:12:34:57
-          //
-          aLines.forEach(function (aLine) {
-            let tokens = aLine.split(/\s+/);
-            if (tokens.length < 5) {
-              return;
-            }
-            let ifname = tokens[0];
-            let ip = (tokens[2].split('/'))[0];
-            netcfgResult[ifname] = { ip: ip };
-          });
-        });
-    }
-
-    // Execute 'ip route' and parse to |ipRouteResult|, each key of which is the
-    // interface name and value is { src(string), default(boolean) }.
-    function exeAndParseIpRoute() {
-      return runEmulatorShellSafe(['ip', 'route'])
-        .then(function (aLines) {
-          // Sample output:
-          //
-          // 10.0.2.4 via 10.0.2.2 dev rmnet0
-          // 10.0.2.3 via 10.0.2.2 dev rmnet0
-          // 192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.1
-          // 10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
-          // 10.0.2.0/24 dev rmnet0  proto kernel  scope link  src 10.0.2.100
-          // default via 10.0.2.2 dev rmnet0
-          // default via 10.0.2.2 dev eth0  metric 2
-          //
-
-          // Parse source ip for each interface.
-          aLines.forEach(function (aLine) {
-            let tokens = aLine.trim().split(/\s+/);
-            let srcIndex = tokens.indexOf('src');
-            if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
-              return;
-            }
-            let ifname = tokens[2];
-            let src = tokens[srcIndex + 1];
-            ipRouteResult[ifname] = { src: src, default: false };
-          });
-
-          // Parse default interfaces.
-          aLines.forEach(function (aLine) {
-            let tokens = aLine.split(/\s+/);
-            if (tokens.length < 2) {
-              return;
-            }
-            if ('default' === tokens[0]) {
-              let ifnameIndex = tokens.indexOf('dev');
-              if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
-                return;
-              }
-              let ifname = tokens[ifnameIndex + 1];
-              if (ipRouteResult[ifname]) {
-                ipRouteResult[ifname].default = true;
-              }
-              return;
-            }
-          });
-
-        });
-
-    }
+    let netcfgResult;
+    let ipRouteResult;
 
     // Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
     // when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
     // is disabled.
     function verifyIptables() {
       return runEmulatorShellSafe(['iptables', '-t', 'nat', '-L', 'POSTROUTING'])
         .then(function(aLines) {
           // $ iptables -t nat -L POSTROUTING
@@ -1153,32 +1202,31 @@ let gTestSuite = (function() {
           if ((aEnabled && !found) || (!aEnabled && found)) {
             throw 'MASQUERADE' + (found ? '' : ' not') + ' found while tethering is ' +
                   (aEnabled ? 'enabled' : 'disabled');
           }
         });
     }
 
     function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
-      log(JSON.stringify(ipRouteResult));
-      log(JSON.stringify(netcfgResult));
-
       if (aEnabled) {
         isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
         isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
 
         isOrThrow(ipRouteResult['wlan0'].src, netcfgResult['wlan0'].ip, 'wlan0.ip');
         isOrThrow(ipRouteResult['wlan0'].src, aExpectedWifiTetheringIp, 'expected ip');
         isOrThrow(ipRouteResult['wlan0'].default, false, 'wlan0.default');
       }
     }
 
     return verifyIptables()
       .then(exeAndParseNetcfg)
+      .then((aResult) => { netcfgResult = aResult; })
       .then(exeAndParseIpRoute)
+      .then((aResult) => { ipRouteResult = aResult; })
       .then(() => getSettings(SETTINGS_TETHERING_WIFI_IP))
       .then(ip => verifyDefaultRouteAndIp(ip));
   }
 
   /**
    * Clean up all the allocated resources and running services for the test.
    *
    * After the test no matter success or failure, we should
@@ -1239,26 +1287,29 @@ let gTestSuite = (function() {
   suite.killAllHostapd = killAllHostapd;
   suite.wrapDomRequestAsPromise = wrapDomRequestAsPromise;
   suite.waitForWifiManagerEventOnce = waitForWifiManagerEventOnce;
   suite.verifyNumOfProcesses = verifyNumOfProcesses;
   suite.testWifiScanWithRetry = testWifiScanWithRetry;
   suite.getFirstIndexBySsid = getFirstIndexBySsid;
   suite.testAssociate = testAssociate;
   suite.getKnownNetworks = getKnownNetworks;
+  suite.setStaticIpMode = setStaticIpMode;
   suite.requestWifiScan = requestWifiScan;
   suite.waitForConnected = waitForConnected;
   suite.forgetNetwork = forgetNetwork;
   suite.waitForTimeout = waitForTimeout;
   suite.waitForRilDataConnected = waitForRilDataConnected;
   suite.requestTetheringEnabled = requestTetheringEnabled;
   suite.importCert = importCert;
   suite.getImportedCerts = getImportedCerts;
   suite.deleteCert = deleteCert;
   suite.writeFile = writeFile;
+  suite.exeAndParseNetcfg = exeAndParseNetcfg;
+  suite.exeAndParseIpRoute = exeAndParseIpRoute;
 
   /**
    * Common test routine.
    *
    * Start a test with the given test case chain. The test environment will be
    * settled down before the test. After the test, all the affected things will
    * be restored.
    *
--- a/dom/wifi/test/marionette/manifest.ini
+++ b/dom/wifi/test/marionette/manifest.ini
@@ -3,16 +3,17 @@ b2g = true
 browser = false
 qemu = true
 
 [test_wifi_enable.js]
 [test_wifi_scan.js]
 [test_wifi_associate.js]
 [test_wifi_associate_wo_connect.js]
 [test_wifi_auto_connect.js]
+[test_wifi_static_ip.js]
 [test_wifi_tethering_wifi_disabled.js]
 [test_wifi_tethering_wifi_inactive.js]
 [test_wifi_tethering_wifi_active.js]
 [test_wifi_manage_server_certificate.js]
 [test_wifi_manage_user_certificate.js]
 [test_wifi_manage_pkcs12_certificate.js]
 [test_wifi_associate_WPA_EAP_PEAP.js]
 [test_wifi_associate_WPA_EAP_TTLS.js]
new file mode 100644
--- /dev/null
+++ b/dom/wifi/test/marionette/test_wifi_static_ip.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const STATIC_IP_CONFIG = {
+  enabled: true,
+  ipaddr: "192.168.111.222",
+  proxy: "",
+  maskLength: 24,
+  gateway: "192.168.111.1",
+  dns1: "8.8.8.8",
+  dns2: "8.8.4.4",
+};
+
+function testAssociateWithStaticIp(aNetwork, aStaticIpConfig) {
+  return gTestSuite.setStaticIpMode(aNetwork, aStaticIpConfig)
+    .then(() => gTestSuite.testAssociate(aNetwork))
+    // Check ip address and prefix.
+    .then(() => gTestSuite.exeAndParseNetcfg())
+    .then((aResult) => {
+      is(aResult["wlan0"].ip, aStaticIpConfig.ipaddr, "Check ip address");
+      is(aResult["wlan0"].prefix, aStaticIpConfig.maskLength, "Check prefix");
+    })
+    // Check routing.
+    .then(() => gTestSuite.exeAndParseIpRoute())
+    .then((aResult) => {
+      is(aResult["wlan0"].src, aStaticIpConfig.ipaddr, "Check ip address");
+      is(aResult["wlan0"].default, true, "Check default route");
+      is(aResult["wlan0"].gateway, aStaticIpConfig.gateway, "Check gateway");
+    });
+}
+
+// Start test.
+gTestSuite.doTest(function() {
+  return gTestSuite.ensureWifiEnabled(true)
+    .then(() => gTestSuite.requestWifiScan())
+    .then((aNetworks) => testAssociateWithStaticIp(aNetworks[0],
+                                                   STATIC_IP_CONFIG));
+});