Bug 1000040 - Part 3: Test cases. r=vchang, f=vyang
authorJohn Shih <jshih@mozilla.com>
Thu, 12 Jun 2014 16:07:23 +0800
changeset 192587 506038ddee2c864921317eb7cc23a0731ace94e2
parent 192586 78ba6f47a5a7369a2cc8eb682ded9225ea1dac1a
child 192588 6b69ed92aa6c6559b78fccad2a47082fea070ca8
push id27090
push usercbook@mozilla.com
push dateMon, 07 Jul 2014 13:07:36 +0000
treeherdermozilla-central@085eea991bb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvchang
bugs1000040
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1000040 - Part 3: Test cases. r=vchang, f=vyang
dom/network/tests/marionette/head.js
dom/network/tests/marionette/manifest.ini
dom/network/tests/marionette/test_ethernet_add_interface.js
dom/network/tests/marionette/test_ethernet_connect_with_dhcp.js
dom/network/tests/marionette/test_ethernet_connect_with_static_ip.js
dom/network/tests/marionette/test_ethernet_disable.js
dom/network/tests/marionette/test_ethernet_disconnect.js
dom/network/tests/marionette/test_ethernet_enable.js
dom/network/tests/marionette/test_ethernet_ip_mode_change.js
dom/network/tests/marionette/test_ethernet_reconnect_with_dhcp.js
dom/network/tests/marionette/test_ethernet_reconnect_with_static_ip.js
dom/network/tests/marionette/test_ethernet_remove_interface.js
testing/marionette/client/marionette/tests/unit-tests.ini
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/head.js
@@ -0,0 +1,551 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let Promise = SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise;
+
+const ETHERNET_MANAGER_CONTRACT_ID = "@mozilla.org/ethernetManager;1";
+
+const INTERFACE_UP = "UP";
+const INTERFACE_DOWN = "DOWN";
+
+let gTestSuite = (function() {
+  let suite = {};
+
+  // Private member variables of the returned object |suite|.
+  let ethernetManager = SpecialPowers.Cc[ETHERNET_MANAGER_CONTRACT_ID]
+                                     .getService(SpecialPowers.Ci.nsIEthernetManager);
+  let pendingEmulatorShellCount = 0;
+
+  /**
+   * Send emulator shell command with safe guard.
+   *
+   * We should only call |finish()| after all emulator command transactions
+   * end, so here comes with the pending counter.  Resolve when the emulator
+   * gives positive response, and reject otherwise.
+   *
+   * Fulfill params: an array of emulator response lines.
+   * Reject params: an array of emulator response lines.
+   *
+   * @param command
+   *        A string command to be passed to emulator through its telnet console.
+   *
+   * @return A deferred promise.
+   */
+  function runEmulatorShellSafe(command) {
+    let deferred = Promise.defer();
+
+    ++pendingEmulatorShellCount;
+    runEmulatorShell(command, function(aResult) {
+      --pendingEmulatorShellCount;
+
+      ok(true, "Emulator shell response: " + JSON.stringify(aResult));
+      if (Array.isArray(aResult)) {
+        deferred.resolve(aResult);
+      } else {
+        deferred.reject(aResult);
+      }
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Get the system network conifg by the given interface name.
+   *
+   * Use shell command 'netcfg' to get the list of network cofig.
+   *
+   * Fulfill params: An object of { name, flag, ip }
+   *
+   * @parm ifname
+   *       Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function getNetworkConfig(ifname) {
+    return runEmulatorShellSafe(['netcfg'])
+      .then(result => {
+        // Sample 'netcfg' 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
+        // eth1     DOWN                                   0.0.0.0/0   0x00001002 52:54:00:12:34:57
+        // rmnet1   DOWN                                   0.0.0.0/0   0x00001002 52:54:00:12:34:59
+
+        let config;
+
+        for (let i = 0; i < result.length; i++) {
+          let tokens = result[i].split(/\s+/);
+          let name = tokens[0];
+          let flag = tokens[1];
+          let ip = tokens[2].split(/\/+/)[0];
+          if (name == ifname) {
+            config = { name: name, flag: flag, ip: ip };
+            break;
+          }
+        }
+
+        return config;
+      });
+  }
+
+  /**
+   * Get the ip assigned by dhcp server of a given interface name.
+   *
+   * Get the ip from android property 'dhcp.[ifname].ipaddress'.
+   *
+   * Fulfill params: A string of ip address.
+   *
+   * @parm ifname
+   *       Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function getDhcpIpAddr(ifname) {
+    return runEmulatorShellSafe(['getprop', 'dhcp.' + ifname + '.ipaddress'])
+      .then(function(ipAddr) {
+        return ipAddr[0];
+      });
+  }
+
+  /**
+   * Get the gateway assigned by dhcp server of a given interface name.
+   *
+   * Get the ip from android property 'dhcp.[ifname].gateway'.
+   *
+   * Fulfill params: A string of gateway.
+   *
+   * @parm ifname
+   *       Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function getDhcpGateway(ifname) {
+    return runEmulatorShellSafe(['getprop', 'dhcp.' + ifname + '.gateway'])
+      .then(function(gateway) {
+        return gateway[0];
+      });
+  }
+
+  /**
+   * Get the default route.
+   *
+   * Use shell command 'ip route' to get the default of device.
+   *
+   * Fulfill params: An array of { name, gateway }
+   *
+   * @return A deferred promise.
+   */
+  function getDefaultRoute() {
+    return runEmulatorShellSafe(['ip', 'route'])
+      .then(result => {
+        // Sample 'ip route' output:
+        //
+        // 10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
+        // default via 10.0.2.2 dev eth0  metric 2
+
+        let routeInfo = [];
+
+        for (let i = 0; i < result.length; i++) {
+          if (!result[i].match('default')) {
+            continue;
+          }
+
+          let tokens = result[i].split(/\s+/);
+          let name = tokens[4];
+          let gateway = tokens[2];
+          routeInfo.push({ name: name, gateway: gateway });
+        }
+
+        return routeInfo;
+      });
+  }
+
+  /**
+   * Check a specific interface is enabled or not.
+   *
+   * @parm ifname
+   *       Interface name.
+   * @parm enabled
+   *       A boolean value used to check interface is disable or not.
+   *
+   * @return A deferred promise.
+   */
+  function checkInterfaceIsEnabled(ifname, enabled) {
+    return getNetworkConfig(ifname)
+      .then(function(config) {
+        if (enabled) {
+          is(config.flag, INTERFACE_UP, "Interface is enabled as expectation.");
+        } else {
+          is(config.flag, INTERFACE_DOWN, "Interface is disabled as expectation.");
+        }
+      });
+  }
+
+  /**
+   * Check the ip of a specific interface is equal to given ip or not.
+   *
+   * @parm ifname
+   *       Interface name.
+   * @parm ip
+   *       Given ip address.
+   *
+   * @return A deferred promise.
+   */
+  function checkInterfaceIpAddr(ifname, ip) {
+    return getNetworkConfig(ifname)
+      .then(function(config) {
+        is(config.ip, ip, "IP is right as expectation.");
+      });
+  }
+
+  /**
+   * Check the default gateway of a specific interface is equal to given gateway
+   * or not.
+   *
+   * @parm ifname
+   *       Interface name.
+   * @parm gateway
+   *       Given gateway.
+   *
+   * @return A deferred promise.
+   */
+  function checkDefaultRoute(ifname, gateway) {
+    return getDefaultRoute()
+      .then(function(routeInfo) {
+        for (let i = 0; i < routeInfo.length; i++) {
+          if (routeInfo[i].name == ifname) {
+            is(routeInfo[i].gateway, gateway,
+               "Default gateway is right as expectation.");
+            return true;
+          }
+        }
+
+        if (!gateway) {
+          ok(true, "Default route is cleared.");
+          return true;
+        }
+
+        return false;
+      });
+  }
+
+  /**
+   * Check the length of interface list in EthernetManager is equal to given
+   * length or not.
+   *
+   * @parm length
+   *       Given length.
+   */
+  function checkInterfaceListLength(length) {
+    let list = ethernetManager.interfaceList;
+    is(length, list.length, "List length is equal as expectation.");
+  }
+
+  /**
+   * Check the given interface exists on device or not.
+   *
+   * @parm ifname
+   *       Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function checkInterfaceExist(ifname) {
+    return scanInterfaces()
+      .then(list => {
+        let index = list.indexOf(ifname);
+        if (index < 0) {
+          throw "Interface " + ifname + " not found.";
+        }
+
+        ok(true, ifname + " exists.")
+      });
+  }
+
+  /**
+   * Scan for available ethernet interfaces.
+   *
+   * Fulfill params: A list of available interfaces found in device.
+   *
+   * @return A deferred promise.
+   */
+  function scanInterfaces() {
+    let deferred = Promise.defer();
+
+    ethernetManager.scan(function onScan(list) {
+      deferred.resolve(list);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Add an interface into interface list.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function addInterface(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.addInterface(ifname, function onAdd(success, message) {
+      ok(success, "Add interface " + ifname + " success.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Remove an interface form the interface list.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function removeInterface(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.removeInterface(ifname, function onRemove(success, message) {
+      ok(success, "Remove interface " + ifname + " success.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Enable networking of an interface in the interface list.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function enableInterface(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.enable(ifname, function onEnable(success, message) {
+      ok(success, "Enable interface " + ifname + " success.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Disable networking of an interface in the interface list.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function disableInterface(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.disable(ifname, function onDisable(success, message) {
+      ok(success, "Disable interface " + ifname + " success.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Make an interface connect to network.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function makeInterfaceConnect(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.connect(ifname, function onConnect(success, message) {
+      ok(success, "Interface " + ifname + " is connected successfully.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Make an interface disconnect to network.
+   *
+   * Fulfill params: A boolean value indicates success or not.
+   *
+   * @param ifname
+   *        Interface name.
+   *
+   * @return A deferred promise.
+   */
+  function makeInterfaceDisconnect(ifname) {
+    let deferred = Promise.defer();
+
+    ethernetManager.disconnect(ifname, function onDisconnect(success, message) {
+      ok(success, "Interface " + ifname + " is disconnected successfully.");
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Update the config the an interface in the interface list.
+   *
+   * @param ifname
+   *        Interface name.
+   * @param config
+   *        .ip: ip address.
+   *        .prefixLength: mask length.
+   *        .gateway: gateway.
+   *        .dnses: dnses.
+   *        .httpProxyHost: http proxy host.
+   *        .httpProxyPort: http porxy port.
+   *        .usingDhcp: an boolean value indicates using dhcp or not.
+   *
+   * @return A deferred promise.
+   */
+  function updateInterfaceConfig(ifname, config) {
+    let deferred = Promise.defer();
+
+    ethernetManager.updateInterfaceConfig(ifname, config,
+                                          function onUpdated(success, message) {
+      ok(success, "Interface " + ifname + " config is updated successfully " +
+                  " with " + JSON.stringify(config));
+      is(message, "ok", "Message is as expectation.");
+
+      deferred.resolve(success);
+    });
+
+    return deferred.promise;
+  }
+
+  /**
+   * Wait for timeout.
+   *
+   * @param timeout
+   *        Time in ms.
+   *
+   * @return A deferred promise.
+   */
+  function waitForTimeout(timeout) {
+    let deferred = Promise.defer();
+
+    setTimeout(function() {
+      ok(true, "waitForTimeout " + timeout);
+      deferred.resolve();
+    }, timeout);
+
+    return deferred.promise;
+  }
+
+  /**
+   * Wait for default route of a specific interface being set and
+   * check.
+   *
+   * @param ifname
+   *        Interface name.
+   * @param gateway
+   *        Target gateway.
+   *
+   * @return A deferred promise.
+   */
+  function waitForDefaultRouteSet(ifname, gateway) {
+    return gTestSuite.waitForTimeout(500)
+      .then(() => gTestSuite.checkDefaultRoute(ifname, gateway))
+      .then(success => {
+        if (success) {
+          ok(true, "Default route is set as expectation " + gateway);
+          return;
+        }
+
+        ok(true, "Default route is not set yet, check again. " + success);
+        return waitForDefaultRouteSet(ifname, gateway);
+      });
+  }
+
+  //---------------------------------------------------
+  // Public test suite functions
+  //---------------------------------------------------
+  suite.scanInterfaces = scanInterfaces;
+  suite.addInterface = addInterface;
+  suite.removeInterface = removeInterface;
+  suite.enableInterface = enableInterface;
+  suite.disableInterface = disableInterface;
+  suite.makeInterfaceConnect = makeInterfaceConnect;
+  suite.makeInterfaceDisconnect = makeInterfaceDisconnect;
+  suite.updateInterfaceConfig = updateInterfaceConfig;
+  suite.getDhcpIpAddr = getDhcpIpAddr;
+  suite.getDhcpGateway = getDhcpGateway;
+  suite.checkInterfaceExist = checkInterfaceExist;
+  suite.checkInterfaceIsEnabled = checkInterfaceIsEnabled;
+  suite.checkInterfaceIpAddr = checkInterfaceIpAddr;
+  suite.checkDefaultRoute = checkDefaultRoute;
+  suite.checkInterfaceListLength = checkInterfaceListLength;
+  suite.waitForTimeout = waitForTimeout;
+  suite.waitForDefaultRouteSet = waitForDefaultRouteSet;
+
+  /**
+   * End up the test run.
+   *
+   * Wait until all pending emulator shell commands are done and then |finish|
+   * will be called in the end.
+   */
+  function cleanUp() {
+    waitFor(finish, function() {
+      return pendingEmulatorShellCount === 0;
+    });
+  }
+
+  /**
+   * 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.
+   *
+   * @param aTestCaseChain
+   *        The test case entry point, which can be a function or a promise.
+   *
+   * @return A deferred promise.
+   */
+  suite.doTest = function(aTestCaseChain) {
+    return Promise.resolve()
+      .then(aTestCaseChain)
+      .then(function onresolve() {
+        cleanUp();
+      }, function onreject(aReason) {
+        ok(false, 'Promise rejects during test' + (aReason ? '(' + aReason + ')' : ''));
+        cleanUp();
+      });
+  };
+
+  return suite;
+})();
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/manifest.ini
@@ -0,0 +1,15 @@
+[DEFAULT]
+b2g = true
+browser = false
+qemu = true
+
+[test_ethernet_add_interface.js]
+[test_ethernet_remove_interface.js]
+[test_ethernet_enable.js]
+[test_ethernet_disable.js]
+[test_ethernet_connect_with_dhcp.js]
+[test_ethernet_connect_with_static_ip.js]
+[test_ethernet_reconnect_with_dhcp.js]
+[test_ethernet_reconnect_with_static_ip.js]
+[test_ethernet_ip_mode_change.js]
+[test_ethernet_disconnect.js]
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_add_interface.js
@@ -0,0 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceListLength(0))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceListLength(1))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_connect_with_dhcp.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+function checkDhcpResult(ifname) {
+  return gTestSuite.getDhcpIpAddr(ifname)
+    .then(ip => gTestSuite.checkInterfaceIpAddr(ifname, ip))
+    .then(() => gTestSuite.getDhcpGateway(ifname))
+    .then(gateway => gTestSuite.waitForDefaultRouteSet(ifname, gateway));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkDhcpResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_connect_with_static_ip.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+let staticConfig = {
+  ip: "1.2.3.4",
+  gateway: "1.2.3.5",
+  prefixLength: 24,
+  dnses: ["1.2.3.6"],
+  ipMode: "static"
+};
+
+function checkStaticResult(ifname) {
+  return gTestSuite.checkInterfaceIpAddr(ifname, staticConfig.ip)
+    .then(() => gTestSuite.checkDefaultRoute(ifname, staticConfig.gateway));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.updateInterfaceConfig(ETHERNET_INTERFACE_NAME, staticConfig))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkStaticResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_disable.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceIsEnabled(ETHERNET_INTERFACE_NAME, false))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_disconnect.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+const INTERFACE_IP_NONE = "0.0.0.0";
+
+function checkIpAddrIsReset(ifname) {
+  return gTestSuite.checkInterfaceIpAddr(ifname, INTERFACE_IP_NONE)
+    .then(() => gTestSuite.checkDefaultRoute(ifname));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkIpAddrIsReset(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_enable.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceIsEnabled(ETHERNET_INTERFACE_NAME, true))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_ip_mode_change.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+let staticConfig = {
+  ip: "1.2.3.4",
+  gateway: "1.2.3.5",
+  prefixLength: 24,
+  dnses: ["1.2.3.6"],
+  ipMode: "static"
+};
+
+function checkStaticResult(ifname) {
+  return gTestSuite.checkInterfaceIpAddr(ifname, staticConfig.ip)
+    .then(() => gTestSuite.waitForDefaultRouteSet(ifname, staticConfig.gateway));
+}
+
+function checkDhcpResult(ifname) {
+  return gTestSuite.getDhcpIpAddr(ifname)
+    .then(ip => gTestSuite.checkInterfaceIpAddr(ifname, ip))
+    .then(() => gTestSuite.getDhcpGateway(ifname))
+    .then(gateway => gTestSuite.waitForDefaultRouteSet(ifname, gateway));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkDhcpResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.updateInterfaceConfig(ETHERNET_INTERFACE_NAME, staticConfig))
+    .then(() => checkStaticResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.updateInterfaceConfig(ETHERNET_INTERFACE_NAME, { ipMode: "dhcp"}))
+    .then(() => checkDhcpResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_reconnect_with_dhcp.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+function checkDhcpResult(ifname) {
+  return gTestSuite.getDhcpIpAddr(ifname)
+    .then(ip => gTestSuite.checkInterfaceIpAddr(ifname, ip))
+    .then(() => gTestSuite.getDhcpGateway(ifname))
+    .then(gateway => gTestSuite.waitForDefaultRouteSet(ifname, gateway));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkDhcpResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkDhcpResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_reconnect_with_static_ip.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+let staticConfig = {
+  ip: "1.2.3.4",
+  gateway: "1.2.3.5",
+  prefixLength: 24,
+  dnses: ["1.2.3.6"],
+  ipMode: "static"
+};
+
+function checkStaticResult(ifname) {
+  return gTestSuite.checkInterfaceIpAddr(ifname, staticConfig.ip)
+    .then(() => gTestSuite.checkDefaultRoute(ifname, staticConfig.gateway));
+}
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.enableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.updateInterfaceConfig(ETHERNET_INTERFACE_NAME, staticConfig))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkStaticResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceConnect(ETHERNET_INTERFACE_NAME))
+    .then(() => checkStaticResult(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.makeInterfaceDisconnect(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.disableInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME));
+});
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_ethernet_remove_interface.js
@@ -0,0 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const ETHERNET_INTERFACE_NAME = "eth1";
+
+gTestSuite.doTest(function() {
+  return Promise.resolve()
+    .then(() => gTestSuite.checkInterfaceExist(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.addInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceListLength(1))
+    .then(() => gTestSuite.removeInterface(ETHERNET_INTERFACE_NAME))
+    .then(() => gTestSuite.checkInterfaceListLength(0));
+});
\ No newline at end of file
--- a/testing/marionette/client/marionette/tests/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit-tests.ini
@@ -23,14 +23,15 @@ skip = false
 [include:../../../../../dom/mobileconnection/tests/marionette/manifest.ini]
 [include:../../../../../dom/system/gonk/tests/marionette/manifest.ini]
 [include:../../../../../dom/icc/tests/marionette/manifest.ini]
 [include:../../../../../dom/system/tests/marionette/manifest.ini]
 [include:../../../../../dom/nfc/tests/marionette/manifest.ini]
 [include:../../../../../dom/events/test/marionette/manifest.ini]
 [include:../../../../../dom/wifi/test/marionette/manifest.ini]
 [include:../../../../../dom/cellbroadcast/tests/marionette/manifest.ini]
+[include:../../../../../dom/network/tests/marionette/manifest.ini]
 
 ; layout tests
 [include:../../../../../layout/base/tests/marionette/manifest.ini]
 
 ; loop tests
 [include:../../../../../browser/components/loop/manifest.ini]