Bug 1143596 - Part 2: Re-write with Promise. r=echen

This commit is contained in:
Bevis Tseng 2015-03-17 14:35:31 +08:00
Родитель ccbf6c4ca9
Коммит c44bd7e32b
1 изменённых файлов: 163 добавлений и 390 удалений

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

@ -1,409 +1,182 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 40000;
MARIONETTE_TIMEOUT = 90000;
MARIONETTE_HEAD_JS = 'head.js';
SpecialPowers.addPermission("sms", true, document);
SpecialPowers.setBoolPref("dom.sms.enabled", true);
let manager = window.navigator.mozMobileMessage;
ok(manager instanceof MozMobileMessageManager,
"manager is instance of " + manager.constructor);
let pendingEmulatorCmdCount = 0;
function sendSmsToEmulator(from, text, callback) {
++pendingEmulatorCmdCount;
let cmd = "sms send " + from + " " + text;
runEmulatorCmd(cmd, function(result) {
--pendingEmulatorCmdCount;
callback(result[0] == "OK");
/**
* Create messages to be tested.
*
* @param aMessages
* An array of
* { 'incoming': [false|true],
* 'address': [Phone Number]
* 'text': [Text Body] };
*
* @return A deferred promise.
*/
function createMessages(aMessages) {
let promise = Promise.resolve();
aMessages.forEach((aMessage) => {
promise = promise.then((aMessage.incoming) ?
() => sendTextSmsToEmulatorAndWait(aMessage.address, aMessage.text) :
() => sendSmsWithSuccess(aMessage.address, aMessage.text));
});
return promise;
}
let tasks = {
// List of test fuctions. Each of them should call |tasks.next()| when
// completed or |tasks.finish()| to jump to the last one.
_tasks: [],
_nextTaskIndex: 0,
function checkThreads(aMessages, aNotMerged) {
return getAllThreads().then((aThreads) => {
let threadCount = aThreads.length;
push: function(func) {
this._tasks.push(func);
},
next: function() {
let index = this._nextTaskIndex++;
let task = this._tasks[index];
try {
task.apply(null, Array.slice(arguments));
} catch (ex) {
ok(false, "test task[" + index + "] throws: " + ex);
// Run last task as clean up if possible.
if (index != this._tasks.length - 1) {
this.finish();
if (aNotMerged) {
// Threads are retrieved in reversed order of 'lastTimestamp'.
aThreads.reverse();
is(threadCount, aMessages.length, "Number of Threads.");
for (let i = 0; i < threadCount; i++) {
let thread = aThreads[i];
let message = aMessages[i];
is(thread.unreadCount, message.incoming ? 1 : 0, "Unread Count.");
is(thread.participants.length, 1, "Number of Participants.");
is(thread.participants[0], message.address, "Participants.");
is(thread.body, message.text, "Thread Body.");
}
}
},
finish: function() {
this._tasks[this._tasks.length - 1]();
},
run: function() {
this.next();
}
};
function getAllMessages(callback, filter, reverse) {
let messages = [];
let request = manager.getMessages(filter, reverse || false);
request.onsuccess = function(event) {
if (!request.done) {
messages.push(request.result);
request.continue();
return;
}
window.setTimeout(callback.bind(null, messages), 0);
}
}
function deleteAllMessages() {
getAllMessages(function deleteAll(messages) {
let message = messages.shift();
if (!message) {
ok(true, "all messages deleted");
tasks.next();
return;
}
let request = manager.delete(message.id);
request.onsuccess = deleteAll.bind(null, messages);
request.onerror = function(event) {
ok(false, "failed to delete all messages");
tasks.finish();
}
let lastBody = aMessages[aMessages.length - 1].text;
let unreadCount = 0;
let mergedThread = aThreads[0];
aMessages.forEach((aMessage) => {
if (aMessage.incoming) {
unreadCount++;
}
});
is(threadCount, 1, "Number of Threads.");
is(mergedThread.unreadCount, unreadCount, "Unread Count.");
is(mergedThread.participants.length, 1, "Number of Participants.");
is(mergedThread.participants[0], aMessages[0].address, "Participants.");
// Thread is updated according to the device 'timestamp' of the message record
// instead of the one from SMSC, so 'mergedThread.body' is expected to be the
// same to the body for the last saved SMS.
// See https://hg.mozilla.org/mozilla-central/annotate/436686833af0/dom/mobilemessage/gonk/MobileMessageDB.jsm#l2247
is(mergedThread.body, lastBody, "Thread Body.");
});
}
function sendMessage(to, body) {
manager.onsent = function() {
manager.onsent = null;
tasks.next();
};
let request = manager.send(to, body);
request.onerror = tasks.finish.bind(tasks);
function testGetThreads(aMessages, aNotMerged) {
aNotMerged = !!aNotMerged;
log("aMessages: " + JSON.stringify(aMessages));
log("aNotMerged: " + aNotMerged);
return createMessages(aMessages)
.then(() => checkThreads(aMessages, aNotMerged))
.then(() => deleteAllMessages());
}
function receiveMessage(from, body) {
manager.onreceived = function() {
manager.onreceived = null;
tasks.next();
};
sendSmsToEmulator(from, body, function(success) {
if (!success) {
tasks.finish();
}
});
}
function getAllThreads(callback) {
let threads = [];
let cursor = manager.getThreads();
ok(cursor instanceof DOMCursor,
"cursor is instanceof " + cursor.constructor);
cursor.onsuccess = function(event) {
if (!cursor.done) {
threads.push(cursor.result);
cursor.continue();
return;
}
window.setTimeout(callback.bind(null, threads), 0);
};
}
function checkThread(bodies, lastBody, unreadCount, participants,
thread, callback) {
log("Validating MozMobileMessageThread attributes " +
JSON.stringify([bodies, lastBody, unreadCount, participants]));
ok(thread, "current thread should be valid.");
ok(thread.id, "thread id", "thread.id");
log("Got thread " + thread.id);
if (lastBody != null) {
is(thread.body, lastBody, "thread.body");
}
is(thread.unreadCount, unreadCount, "thread.unreadCount");
ok(Array.isArray(thread.participants), "thread.participants is array");
is(thread.participants.length, participants.length,
"thread.participants.length");
for (let i = 0; i < participants.length; i++) {
is(thread.participants[i], participants[i],
"thread.participants[" + i + "]");
}
// Check whether the thread does contain all the messages it supposed to have.
let filter = { threadId: thread.id };
getAllMessages(function(messages) {
is(messages.length, bodies.length, "messages.length and bodies.length");
for (let message of messages) {
let index = bodies.indexOf(message.body);
ok(index >= 0, "message.body '" + message.body +
"' should be found in bodies array.");
bodies.splice(index, 1);
}
is(bodies.length, 0, "bodies array length");
window.setTimeout(callback, 0);
}, filter, false);
}
tasks.push(deleteAllMessages);
tasks.push(getAllThreads.bind(null, function(threads) {
is(threads.length, 0, "Empty thread list at beginning.");
tasks.next();
}));
// Populate MobileMessageDB with messages.
let checkFuncs = [];
// [Thread 1]
// One message only, body = "thread 1";
// All sent message, unreadCount = 0;
// One participant only, participants = ["5555211001"].
tasks.push(sendMessage.bind(null, "5555211001", "thread 1"));
checkFuncs.push(checkThread.bind(null, ["thread 1"],
"thread 1", 0, ["5555211001"]));
// [Thread 2]
// Two messages, body = "thread 2-2";
// All sent message, unreadCount = 0;
// One participant with two aliased addresses, participants = ["5555211002"].
tasks.push(sendMessage.bind(null, "5555211002", "thread 2-1"));
tasks.push(sendMessage.bind(null, "+15555211002", "thread 2-2"));
checkFuncs.push(checkThread.bind(null, ["thread 2-1", "thread 2-2"],
"thread 2-2", 0, ["5555211002"]));
// [Thread 3]
// Two messages, body = "thread 3-2";
// All sent message, unreadCount = 0;
// One participant with two aliased addresses, participants = ["+15555211003"].
tasks.push(sendMessage.bind(null, "+15555211003", "thread 3-1"));
tasks.push(sendMessage.bind(null, "5555211003", "thread 3-2"));
checkFuncs.push(checkThread.bind(null, ["thread 3-1", "thread 3-2"],
"thread 3-2", 0, ["+15555211003"]));
// [Thread 4]
// One message only, body = "thread 4";
// All received message, unreadCount = 1;
// One participant only, participants = ["5555211004"].
tasks.push(receiveMessage.bind(null, "5555211004", "thread 4"));
checkFuncs.push(checkThread.bind(null, ["thread 4"],
"thread 4", 1, ["5555211004"]));
// [Thread 5]
//
// Thread body should be set to text body of the last message in this
// thread. However due to BUG 840051, we're having SMSC time as message
// timestamp and SMSC time resolution is 1 second. So it's likely that the two
// messages have the same timestamp and we just can't tell which is the later
// one.
//
// All received message, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211005"].
tasks.push(receiveMessage.bind(null, "5555211005", "thread 5-1"));
tasks.push(receiveMessage.bind(null, "+15555211005", "thread 5-2"));
checkFuncs.push(checkThread.bind(null, ["thread 5-1", "thread 5-2"],
null, 2, ["5555211005"]));
// [Thread 6]
//
// Thread body should be set to text body of the last message in this
// thread. However due to BUG 840051, we're having SMSC time as message
// timestamp and SMSC time resolution is 1 second. So it's likely that the two
// messages have the same timestamp and we just can't tell which is the later
// one.
//
// All received message, unreadCount = 2;
// One participant with two aliased addresses, participants = ["+15555211006"].
tasks.push(receiveMessage.bind(null, "+15555211006", "thread 6-1"));
tasks.push(receiveMessage.bind(null, "5555211006", "thread 6-2"));
checkFuncs.push(checkThread.bind(null, ["thread 6-1", "thread 6-2"],
null, 2, ["+15555211006"]));
// [Thread 7]
//
// Thread body should be set to text body of the last message in this
// thread. However due to BUG 840051, there might be time difference between
// SMSC and device time. So the result of comparing the timestamps of sent and
// received message may not follow the order of requests and may result in
// UNEXPECTED-FAIL in following tests.
//
// Two received message, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211007"].
tasks.push(sendMessage.bind(null, "5555211007", "thread 7-1"));
tasks.push(sendMessage.bind(null, "+15555211007", "thread 7-2"));
tasks.push(receiveMessage.bind(null, "5555211007", "thread 7-3"));
tasks.push(receiveMessage.bind(null, "+15555211007", "thread 7-4"));
checkFuncs.push(checkThread.bind(null, ["thread 7-1", "thread 7-2",
"thread 7-3", "thread 7-4"],
null, 2, ["5555211007"]));
// [Thread 8]
//
// Thread body should be set to text body of the last message in this
// thread. However due to BUG 840051, there might be time difference between
// SMSC and device time. So the result of comparing the timestamps of sent and
// received message may not follow the order of requests and may result in
// UNEXPECTED-FAIL in following tests.
//
// Two received message, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211008"].
tasks.push(receiveMessage.bind(null, "5555211008", "thread 8-1"));
tasks.push(receiveMessage.bind(null, "+15555211008", "thread 8-2"));
tasks.push(sendMessage.bind(null, "5555211008", "thread 8-3"));
tasks.push(sendMessage.bind(null, "+15555211008", "thread 8-4"));
checkFuncs.push(checkThread.bind(null, ["thread 8-1", "thread 8-2",
"thread 8-3", "thread 8-4"],
null, 2, ["5555211008"]));
// [Thread 9]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["+15555211009"].
tasks.push(sendMessage.bind(null, "+15555211009", "thread 9-1"));
tasks.push(sendMessage.bind(null, "01115555211009", "thread 9-2"));
tasks.push(sendMessage.bind(null, "5555211009", "thread 9-3"));
checkFuncs.push(checkThread.bind(null, ["thread 9-1", "thread 9-2",
"thread 9-3"],
"thread 9-3", 0, ["+15555211009"]));
// [Thread 10]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["+15555211010"].
tasks.push(sendMessage.bind(null, "+15555211010", "thread 10-1"));
tasks.push(sendMessage.bind(null, "5555211010", "thread 10-2"));
tasks.push(sendMessage.bind(null, "01115555211010", "thread 10-3"));
checkFuncs.push(checkThread.bind(null, ["thread 10-1", "thread 10-2",
"thread 10-3"],
"thread 10-3", 0, ["+15555211010"]));
// [Thread 11]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["01115555211011"].
tasks.push(sendMessage.bind(null, "01115555211011", "thread 11-1"));
tasks.push(sendMessage.bind(null, "5555211011", "thread 11-2"));
tasks.push(sendMessage.bind(null, "+15555211011", "thread 11-3"));
checkFuncs.push(checkThread.bind(null, ["thread 11-1", "thread 11-2",
"thread 11-3"],
"thread 11-3", 0, ["01115555211011"]));
// [Thread 12]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["01115555211012"].
tasks.push(sendMessage.bind(null, "01115555211012", "thread 12-1"));
tasks.push(sendMessage.bind(null, "+15555211012", "thread 12-2"));
tasks.push(sendMessage.bind(null, "5555211012", "thread 12-3"));
checkFuncs.push(checkThread.bind(null, ["thread 12-1", "thread 12-2",
"thread 12-3"],
"thread 12-3", 0, ["01115555211012"]));
// [Thread 13]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["5555211013"].
tasks.push(sendMessage.bind(null, "5555211013", "thread 13-1"));
tasks.push(sendMessage.bind(null, "+15555211013", "thread 13-2"));
tasks.push(sendMessage.bind(null, "01115555211013", "thread 13-3"));
checkFuncs.push(checkThread.bind(null, ["thread 13-1", "thread 13-2",
"thread 13-3"],
"thread 13-3", 0, ["5555211013"]));
// [Thread 14]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["5555211014"].
tasks.push(sendMessage.bind(null, "5555211014", "thread 14-1"));
tasks.push(sendMessage.bind(null, "01115555211014", "thread 14-2"));
tasks.push(sendMessage.bind(null, "+15555211014", "thread 14-3"));
checkFuncs.push(checkThread.bind(null, ["thread 14-1", "thread 14-2",
"thread 14-3"],
"thread 14-3", 0, ["5555211014"]));
// [Thread 15]
// One sent message, unreadCount = 0;
// One participant but might be merged to 555211015, participants = ["5555211015"].
tasks.push(sendMessage.bind(null, "5555211015", "thread 15-1"));
checkFuncs.push(checkThread.bind(null, ["thread 15-1"],
"thread 15-1", 0, ["5555211015"]));
// [Thread 16]
// One sent message, unreadCount = 0;
// One participant but might be merged to 5555211015, participants = ["555211015"].
tasks.push(sendMessage.bind(null, "555211015", "thread 16-1"));
checkFuncs.push(checkThread.bind(null, ["thread 16-1"],
"thread 16-1", 0, ["555211015"]));
// [Thread 17]
// Brazil number format: +55-aa-nnnnnnnn. (2-digit area code and 8-digit number)
// Two sent messages, unreadCount = 0;
// One participant with two aliased addresses, participants = ["+551155211017"].
tasks.push(sendMessage.bind(null, "+551155211017", "thread 17-1"));
tasks.push(sendMessage.bind(null, "1155211017", "thread 17-2"));
checkFuncs.push(checkThread.bind(null, ["thread 17-1", "thread 17-2"],
"thread 17-2", 0, ["+551155211017"]));
// [Thread 18]
// Brazil number format: +55-aa-nnnnnnnn. (2-digit area code and 8-digit number)
// Two sent messages, unreadCount = 0;
// One participant with two aliased addresses, participants = ["1155211018"].
tasks.push(sendMessage.bind(null, "1155211018", "thread 18-1"));
tasks.push(sendMessage.bind(null, "+551155211018", "thread 18-2"));
checkFuncs.push(checkThread.bind(null, ["thread 18-1", "thread 18-2"],
"thread 18-2", 0, ["1155211018"]));
// Check threads.
tasks.push(getAllThreads.bind(null, function(threads) {
is(threads.length, checkFuncs.length, "number of threads got");
// Reverse threads as we iterate over them in reverse order
threads.reverse();
(function callback() {
if (!threads.length) {
tasks.next();
return;
}
checkFuncs.shift()(threads.shift(), callback);
})();
}));
tasks.push(deleteAllMessages);
tasks.push(getAllThreads.bind(null, function(threads) {
is(threads.length, 0, "Empty thread list at the end.");
tasks.next();
}));
// WARNING: All tasks should be pushed before this!!!
tasks.push(function cleanUp() {
if (pendingEmulatorCmdCount) {
window.setTimeout(cleanUp, 100);
return;
}
SpecialPowers.removePermission("sms", document);
SpecialPowers.clearUserPref("dom.sms.enabled");
finish();
startTestCommon(function testCaseMain() {
// [Thread 1]
// One message only, body = "thread 1";
// All sent message, unreadCount = 0;
// One participant only, participants = ["5555211001"].
return testGetThreads([{ incoming: false, address: "5555211001", text: "thread 1" }])
// [Thread 2]
// Two messages, body = "thread 2-2";
// All sent message, unreadCount = 0;
// One participant with two aliased addresses, participants = ["5555211002"].
.then(() => testGetThreads([{ incoming: false, address: "5555211002", text: "thread 2-1" },
{ incoming: false, address: "+15555211002", text: "thread 2-2" }]))
// [Thread 3]
// Two messages, body = "thread 3-2";
// All sent message, unreadCount = 0;
// One participant with two aliased addresses, participants = ["+15555211003"].
.then(() => testGetThreads([{ incoming: false, address: "+15555211003", text: "thread 3-1" },
{ incoming: false, address: "5555211003", text: "thread 3-2" }]))
// [Thread 4]
// One message only, body = "thread 4";
// All received message, unreadCount = 1;
// One participant only, participants = ["5555211004"].
.then(() => testGetThreads([{ incoming: true, address: "5555211004", text: "thread 4" }]))
// [Thread 5]
// All received messages, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211005"].
.then(() => testGetThreads([{ incoming: true, address: "5555211005", text: "thread 5-1" },
{ incoming: true, address: "+15555211005", text: "thread 5-2" },]))
// [Thread 6]
// All received messages, unreadCount = 2;
// One participant with two aliased addresses, participants = ["+15555211006"].
.then(() => testGetThreads([{ incoming: true, address: "+15555211006", text: "thread 6-1" },
{ incoming: true, address: "5555211006", text: "thread 6-2" }]))
// [Thread 7]
// 2 sent and then 2 received messages, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211007"].
.then(() => testGetThreads([{ incoming: false, address: "5555211007", text: "thread 7-1" },
{ incoming: false, address: "+15555211007", text: "thread 7-2" },
{ incoming: true, address: "5555211007", text: "thread 7-3" },
{ incoming: true, address: "+15555211007", text: "thread 7-4" }]))
// [Thread 8]
// 2 received and then 2 sent messages, unreadCount = 2;
// One participant with two aliased addresses, participants = ["5555211008"].
.then(() => testGetThreads([{ incoming: true, address: "5555211008", text: "thread 8-1" },
{ incoming: true, address: "+15555211008", text: "thread 8-2" },
{ incoming: false, address: "5555211008", text: "thread 8-3" },
{ incoming: false, address: "+15555211008", text: "thread 8-4" }]))
// [Thread 9]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["+15555211009"].
.then(() => testGetThreads([{ incoming: false, address: "+15555211009", text: "thread 9-1" },
{ incoming: false, address: "01115555211009", text: "thread 9-2" },
{ incoming: false, address: "5555211009", text: "thread 9-3" }]))
// [Thread 10]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["+15555211010"].
.then(() => testGetThreads([{ incoming: false, address: "+15555211010", text: "thread 10-1" },
{ incoming: false, address: "5555211010", text: "thread 10-2" },
{ incoming: false, address: "01115555211010", text: "thread 10-3" }]))
// [Thread 11]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["01115555211011"].
.then(() => testGetThreads([{ incoming: false, address: "01115555211011", text: "thread 11-1" },
{ incoming: false, address: "5555211011", text: "thread 11-2" },
{ incoming: false, address: "+15555211011", text: "thread 11-3" }]))
// [Thread 12]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["01115555211012"].
.then(() => testGetThreads([{ incoming: false, address: "01115555211012", text: "thread 12-1" },
{ incoming: false, address: "+15555211012", text: "thread 12-2" },
{ incoming: false, address: "5555211012", text: "thread 12-3" }]))
// [Thread 13]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["5555211013"].
.then(() => testGetThreads([{ incoming: false, address: "5555211013", text: "thread 13-1" },
{ incoming: false, address: "+15555211013", text: "thread 13-2" },
{ incoming: false, address: "01115555211013", text: "thread 13-3" }]))
// [Thread 14]
// Three sent message, unreadCount = 0;
// One participant with three aliased addresses, participants = ["5555211014"].
.then(() => testGetThreads([{ incoming: false, address: "5555211014", text: "thread 14-1" },
{ incoming: false, address: "01115555211014", text: "thread 14-2" },
{ incoming: false, address: "+15555211014", text: "thread 14-3" }]))
// [Thread 15]
// One sent message, unreadCount = 0;
// One participant but might be merged to 555211015, participants = ["5555211015"].
// [Thread 16]
// One sent message, unreadCount = 0;
// One participant but might be merged to 5555211015, participants = ["555211015"].
.then(() => testGetThreads([{ incoming: false, address: "5555211015", text: "thread 15-1" },
{ incoming: false, address: "555211015", text: "thread 16-1" }],
true))
// [Thread 17]
// Brazil number format: +55-aa-nnnnnnnn. (2-digit area code and 8-digit number)
// Two sent messages, unreadCount = 0;
// One participant with two aliased addresses, participants = ["+551155211017"].
.then(() => testGetThreads([{ incoming: false, address: "+551155211017", text: "thread 17-1" },
{ incoming: false, address: "1155211017", text: "thread 17-2" }]))
// [Thread 18]
// Brazil number format: +55-aa-nnnnnnnn. (2-digit area code and 8-digit number)
// All sent messages, unreadCount = 0;
// One participant with two aliased addresses, participants = ["1155211018"].
.then(() => testGetThreads([{ incoming: false, address: "1155211018", text: "thread 18-1" },
{ incoming: false, address: "+551155211018", text: "thread 18-2" }]));
});
tasks.run();