Bug 1006317 - Write a marionette test for BT on/off based on bluetooth API v2. r=btian

This commit is contained in:
Jamin Liu 2014-07-08 14:57:01 +08:00
Родитель 3592021eab
Коммит 9b53b688d5
3 изменённых файлов: 192 добавлений и 3 удалений

Просмотреть файл

@ -342,7 +342,7 @@ function setBluetoothEnabled(aEnabled) {
/**
* Wait for one named BluetoothManager event.
*
* Resolve if that named event occurs. Never reject.
* Resolve if that named event occurs. Never reject.
*
* Fulfill params: the DOMEvent passed.
*
@ -367,7 +367,7 @@ function waitForManagerEvent(aEventName) {
/**
* Wait for one named BluetoothAdapter event.
*
* Resolve if that named event occurs. Never reject.
* Resolve if that named event occurs. Never reject.
*
* Fulfill params: the DOMEvent passed.
*
@ -391,6 +391,118 @@ function waitForAdapterEvent(aAdapter, aEventName) {
return deferred.promise;
}
/**
* Wait for 'onattributechanged' events for state changes of BluetoothAdapter
* with specified order.
*
* Resolve if those expected events occur in order. Never reject.
*
* Fulfill params: an array which contains every changed attributes during
* the waiting.
*
* @param aAdapter
* The BluetoothAdapter you want to use.
* @param aStateChangesInOrder
* An array which contains an expected order of BluetoothAdapterState.
* Example 1: [enabling, enabled]
* Example 2: [disabling, disabled]
*
* @return A deferred promise.
*/
function waitForAdapterStateChanged(aAdapter, aStateChangesInOrder) {
let deferred = Promise.defer();
let stateIndex = 0;
let prevStateIndex = 0;
let statesArray = [];
let changedAttrs = [];
aAdapter.onattributechanged = function(aEvent) {
for (let i in aEvent.attrs) {
changedAttrs.push(aEvent.attrs[i]);
switch (aEvent.attrs[i]) {
case "state":
log(" 'state' changed to " + aAdapter.state);
// Received state change order may differ from expected one even though
// state changes in expected order, because the value of state may change
// again before we receive prior 'onattributechanged' event.
//
// For example, expected state change order [A,B,C] may result in
// received ones:
// - [A,C,C] if state becomes C before we receive 2nd 'onattributechanged'
// - [B,B,C] if state becomes B before we receive 1st 'onattributechanged'
// - [C,C,C] if state becomes C before we receive 1st 'onattributechanged'
// - [A,B,C] if all 'onattributechanged' are received in perfect timing
//
// As a result, we ensure only following conditions instead of exactly
// matching received and expected state change order.
// - Received state change order never reverse expected one. For example,
// [B,A,C] should never occur with expected state change order [A,B,C].
// - The changed value of state in received state change order never
// appears later than that in expected one. For example, [A,A,C] should
// never occur with expected state change order [A,B,C].
let stateIndex = aStateChangesInOrder.indexOf(aAdapter.state);
if (stateIndex >= prevStateIndex && stateIndex + 1 > statesArray.length) {
statesArray.push(aAdapter.state);
prevStateIndex = stateIndex;
if (statesArray.length == aStateChangesInOrder.length) {
aAdapter.onattributechanged = null;
ok(true, "BluetoothAdapter event 'onattributechanged' got.");
deferred.resolve(changedAttrs);
}
} else {
ok(false, "The order of 'onattributechanged' events is unexpected.");
}
break;
case "name":
log(" 'name' changed to " + aAdapter.name);
if (aAdapter.state == "enabling") {
isnot(aAdapter.name, "", "adapter.name");
}
else if (aAdapter.state == "disabling") {
is(aAdapter.name, "", "adapter.name");
}
break;
case "address":
log(" 'address' changed to " + aAdapter.address);
if (aAdapter.state == "enabling") {
isnot(aAdapter.address, "", "adapter.address");
}
else if (aAdapter.state == "disabling") {
is(aAdapter.address, "", "adapter.address");
}
break;
case "discoverable":
log(" 'discoverable' changed to " + aAdapter.discoverable);
if (aAdapter.state == "enabling") {
is(aAdapter.discoverable, true, "adapter.discoverable");
}
else if (aAdapter.state == "disabling") {
is(aAdapter.discoverable, false, "adapter.discoverable");
}
break;
case "discovering":
log(" 'discovering' changed to " + aAdapter.discovering);
if (aAdapter.state == "enabling") {
is(aAdapter.discovering, true, "adapter.discovering");
}
else if (aAdapter.state == "disabling") {
is(aAdapter.discovering, false, "adapter.discovering");
}
break;
case "unknown":
default:
ok(false, "Unknown attribute '" + aEvent.attrs[i] + "' changed." );
break;
}
}
};
return deferred.promise;
}
/**
* Flush permission settings and call |finish()|.
*/
@ -417,7 +529,7 @@ function startBluetoothTestBase(aPermissions, aTestCaseMain) {
}
function startBluetoothTest(aReenable, aTestCaseMain) {
startBluetoothTestBase(["settings-read", "settings-write"], function() {
startBluetoothTestBase([], function() {
let origEnabled, needEnable;
return Promise.resolve()
.then(function() {

Просмотреть файл

@ -4,3 +4,4 @@ browser = false
qemu = false
[test_dom_BluetoothManager_API2.js]
[test_dom_BluetoothAdapter_enable_API2.js]

Просмотреть файл

@ -0,0 +1,76 @@
/* 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 enable/disable process of BluetoothAdapter is correct.
//
// Test Procedure:
// [0] Set Bluetooth permission and enable default adapter.
// [1] Disable Bluetooth and check the correctness of 'onattributechanged'.
// [2] Enable Bluetooth and check the correctness of 'onattributechanged'.
//
// Test Coverage:
// - BluetoothAdapter.enable()
// - BluetoothAdapter.disable()
// - BluetoothAdapter.onattributechanged()
// - BluetoothAdapter.address
// - BluetoothAdapter.state
//
///////////////////////////////////////////////////////////////////////////////
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
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");
// TODO: Check the correctness of name and address if we use emulator.
// is(aAdapter.name, EMULATOR_NAME, "adapter.name");
// is(aAdapter.address, EMULATOR_ADDRESS, "adapter.address");
log(" adapter.address: " + aAdapter.address);
log(" adapter.name: " + aAdapter.name);
let originalAddr = aAdapter.address;
let originalName = aAdapter.name;
return Promise.resolve()
.then(function() {
log("[1] Disable Bluetooth and check the correctness of 'onattributechanged'");
let promises = [];
promises.push(waitForAdapterStateChanged(aAdapter, ["disabling", "disabled"]));
promises.push(aAdapter.disable());
return Promise.all(promises);
})
.then(function(aResults) {
isnot(aResults[0].indexOf("address"), -1, "Indicator of 'address' changed event");
if (originalName != "") {
isnot(aResults[0].indexOf("name"), -1, "Indicator of 'name' changed event");
}
is(aAdapter.address, "", "adapter.address");
is(aAdapter.name, "", "adapter.name");
})
.then(function() {
log("[2] Enable Bluetooth and check the correctness of 'onattributechanged'");
let promises = [];
promises.push(waitForAdapterStateChanged(aAdapter, ["enabling", "enabled"]));
promises.push(aAdapter.enable());
return Promise.all(promises);
})
.then(function(aResults) {
isnot(aResults[0].indexOf("address"), -1, "Indicator of 'address' changed event");
if (originalName != "") {
isnot(aResults[0].indexOf("name"), -1, "Indicator of 'name' changed event");
}
is(aAdapter.address, originalAddr, "adapter.address");
is(aAdapter.name, originalName, "adapter.name");
})
});