Bug 1035651 - Write a marionette test for BluetoothDevice based on Bluetooth API v2. r=btian
authorJamin Liu <jaliu@mozilla.com>
Thu, 17 Jul 2014 11:08:02 +0800
changeset 216414 ef6a44c2fa8b22f783b30c4275b1a65fa62d180c
parent 216413 02b211b2b82f6332144f4f6c82974f71a794d6f1
child 216415 1a6c1fcb92129670775aa4856012c36363e3ec87
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbtian
bugs1035651
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 1035651 - Write a marionette test for BluetoothDevice based on Bluetooth API v2. r=btian
dom/bluetooth2/tests/marionette/head.js
dom/bluetooth2/tests/marionette/manifest.ini
dom/bluetooth2/tests/marionette/test_dom_BluetoothDevice_API2.js
--- a/dom/bluetooth2/tests/marionette/head.js
+++ b/dom/bluetooth2/tests/marionette/head.js
@@ -568,17 +568,17 @@ function waitForAdapterAttributeChanged(
  *
  * Fulfill params: an array which contains BluetoothDeviceEvents that we
  *                 received from the BluetoothDiscoveryHandle.
  *
  * @param aDiscoveryHandle
  *        A BluetoothDiscoveryHandle which is used to notify application of
  *        discovered remote bluetooth devices.
  * @param aExpectedNumberOfDevices
- *        The number of remote devices we expect to discovery.
+ *        The number of remote devices we expect to discover.
  *
  * @return A deferred promise.
  */
 function waitForDevicesFound(aDiscoveryHandle, aExpectedNumberOfDevices) {
   let deferred = Promise.defer();
 
   ok(aDiscoveryHandle instanceof BluetoothDiscoveryHandle,
     "discoveryHandle should be a BluetoothDiscoveryHandle");
@@ -594,16 +594,43 @@ function waitForDevicesFound(aDiscoveryH
       deferred.resolve(devicesArray);
     }
   };
 
   return deferred.promise;
 }
 
 /**
+ * Compare two uuid arrays to see if them are the same.
+ *
+ * @param aUuidArray1
+ *        An array which contains uuid strings.
+ * @param aUuidArray2
+ *        Another array which contains uuid strings.
+ *
+ * @return A boolean value.
+ */
+function isUuidsEqual(aUuidArray1, aUuidArray2) {
+  if (!Array.isArray(aUuidArray1) || !Array.isArray(aUuidArray2)) {
+    return false;
+  }
+
+  if (aUuidArray1.length != aUuidArray2.length) {
+    return false;
+  }
+
+  for (let i = 0, l = aUuidArray1.length; i < l; i++) {
+    if (aUuidArray1[i] != aUuidArray2[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
  * Flush permission settings and call |finish()|.
  */
 function cleanUp() {
   waitFor(function() {
     SpecialPowers.flushPermissions(function() {
       // Use ok here so that we have at least one test run.
       ok(true, "permissions flushed");
 
--- a/dom/bluetooth2/tests/marionette/manifest.ini
+++ b/dom/bluetooth2/tests/marionette/manifest.ini
@@ -2,8 +2,9 @@
 b2g = true
 browser = false
 qemu = false
 
 [test_dom_BluetoothManager_API2.js]
 [test_dom_BluetoothAdapter_enable_API2.js]
 [test_dom_BluetoothAdapter_setters_API2.js]
 [test_dom_BluetoothAdapter_discovery_API2.js]
+[test_dom_BluetoothDevice_API2.js]
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/tests/marionette/test_dom_BluetoothDevice_API2.js
@@ -0,0 +1,146 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+///////////////////////////////////////////////////////////////////////////////
+// Test Purpose:
+//   To verify that all properties of BluetoothDevice is correct when they've
+//   been discovered by adapter and delivered by BluetoothDeviceEvent.
+//   Testers have to put the B2G devices in an environment which is surrounded
+//   by N discoverable remote devices. To pass this test, the number N has to be
+//   be greater than (or equal to) EXPECTED_NUMBER_OF_REMOTE_DEVICES.
+//
+// Test Procedure:
+//   [0] Set Bluetooth permission and enable default adapter.
+//   [1] Start discovery.
+//   [2] Wait for 'devicefound' events.
+//   [3] Type checking for BluetoothDeviceEvent and BluetoothDevice.
+//   [4] Attach the 'onattributechanged' handler for the first device.
+//   [5] Fetch the UUIDs of the first device.
+//   [6] Verify the UUIDs.
+//   [7] Stop discovery.
+//
+// Test Coverage:
+//   - BluetoothDevice.address
+//   - BluetoothDevice.cod
+//   - BluetoothDevice.name
+//   - BluetoothDevice.paired
+//   - BluetoothDevice.uuids
+//   - BluetoothDevice.onattributechanged()
+//   - BluetoothDevice.fetchUuids()
+//   - BluetoothDeviceEvent.address
+//   - BluetoothDeviceEvent.device
+//
+///////////////////////////////////////////////////////////////////////////////
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const EXPECTED_NUMBER_OF_REMOTE_DEVICES = 1;
+
+let hasReceivedUuidsChanged = false;
+let originalUuids;
+
+startBluetoothTest(true, function testCaseMain(aAdapter) {
+  log("Checking adapter attributes ...");
+
+  is(aAdapter.state, "enabled", "adapter.state");
+  isnot(aAdapter.address, "", "adapter.address");
+
+  // Since adapter has just been re-enabled, these properties should be 'false'.
+  is(aAdapter.discovering, false, "adapter.discovering");
+  is(aAdapter.discoverable, false, "adapter.discoverable at step [0]");
+
+  log("adapter.address: " + aAdapter.address);
+  log("adapter.name: " + aAdapter.name);
+
+  return Promise.resolve()
+    .then(function(discoveryHandle) {
+      log("[1] Start discovery ... ");
+      return aAdapter.startDiscovery();
+    })
+    .then(function(discoveryHandle) {
+      log("[2] Wait for 'devicefound' events ... ");
+      return waitForDevicesFound(discoveryHandle, EXPECTED_NUMBER_OF_REMOTE_DEVICES);
+    })
+    .then(function(deviceEvents) {
+      log("[3] Type checking for BluetoothDeviceEvent and BluetoothDevice ... ");
+
+      for (let i in deviceEvents) {
+        let deviceEvt = deviceEvents[i];
+        is(deviceEvt.address, null, "deviceEvt.address");
+        isnot(deviceEvt.device, null, "deviceEvt.device");
+        ok(deviceEvt.device instanceof BluetoothDevice,
+          "deviceEvt.device should be a BluetoothDevice");
+
+        let device = deviceEvt.device;
+        ok(typeof device.address === 'string', "type checking for address.");
+        ok(typeof device.name === 'string', "type checking for name.");
+        ok(device.cod instanceof BluetoothClassOfDevice, "type checking for cod.");
+        ok(typeof device.paired === 'boolean', "type checking for paired.");
+        ok(Array.isArray(device.uuids), "type checking for uuids.");
+
+        originalUuids = device.uuids;
+
+        log("  - BluetoothDevice.address: " + device.address);
+        log("  - BluetoothDevice.name: " + device.name);
+        log("  - BluetoothDevice.cod: " + device.cod);
+        log("  - BluetoothDevice.paired: " + device.paired);
+        log("  - BluetoothDevice.uuids: " + device.uuids);
+      }
+      return deviceEvents[0].device;
+    })
+    .then(function(device) {
+      log("[4] Attach the 'onattributechanged' handler for the remote device ... ");
+      device.onattributechanged = function(aEvent) {
+        for (let i in aEvent.attrs) {
+          switch (aEvent.attrs[i]) {
+            case "cod":
+              log("  'cod' changed to " + device.cod);
+              break;
+            case "name":
+              log("  'name' changed to " + device.name);
+              break;
+            case "paired":
+              log("  'paired' changed to " + device.paired);
+              break;
+            case "uuids":
+              log("  'uuids' changed to " + device.uuids);
+              hasReceivedUuidsChanged = true;
+              break;
+            case "unknown":
+            default:
+              ok(false, "Unknown attribute '" + aEvent.attrs[i] + "' changed." );
+              break;
+          }
+        }
+      };
+      return device;
+    })
+    .then(function(device) {
+      log("[5] Fetch the UUIDs of remote device ... ");
+      let promises = [];
+      promises.push(Promise.resolve(device));
+      promises.push(device.fetchUuids());
+      return Promise.all(promises);
+    })
+    .then(function(aResults) {
+      log("[6] Verify the UUIDs ... ");
+      let device = aResults[0];
+      let uuids = aResults[1];
+
+      ok(Array.isArray(uuids), "type checking for 'fetchUuids'.");
+
+      ok(isUuidsEqual(uuids, device.uuids),
+        "device.uuids should equal to the result from 'fetchUuids'");
+
+      bool isUuidsChanged = !isUuidsEqual(originalUuids, device.uuids);
+      is(isUuidsChanged, hasReceivedUuidsChanged, "device.uuids has changed.");
+
+      device.onattributechanged = null;
+    })
+    .then(function() {
+      log("[7] Stop discovery ... ");
+      return aAdapter.stopDiscovery();
+    })
+});