/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* 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/. */
/*
* Tests that the object-state-preservation mechanism works correctly.
*/
ChromeUtils.defineLazyGetter(
this,
"PATH",
function () {
return "http://localhost:" + srv.identity.primaryPort + "/object-state.sjs";
});
var srv;
function run_test() {
srv = createServer();
var sjsDir = do_get_file(
"data/sjs/");
srv.registerDirectory(
"/", sjsDir);
srv.registerContentType(
"sjs",
"sjs");
srv.start(-1);
do_test_pending();
new HTTPTestLoader(PATH +
"?state=initial", initialStart, initialStop);
}
/** ******************
* OBSERVER METHODS *
********************/
/*
* In practice the current implementation will guarantee an exact ordering of
* all start and stop callbacks. However, in the interests of robustness, this
* test will pass given any valid ordering of callbacks. Any ordering of calls
* which obeys the partial ordering shown by this directed acyclic graph will be
* handled correctly:
*
* initialStart
* |
* V
* intermediateStart
* |
* V
* intermediateStop
* | \
* | V
* | initialStop
* V
* triggerStart
* |
* V
* triggerStop
*
*/
var initialStarted =
false;
function initialStart() {
dumpn(
"*** initialStart");
if (initialStarted) {
do_throw(
"initialStart: initialStarted is true?!?!");
}
initialStarted =
true;
new HTTPTestLoader(
PATH +
"?state=intermediate",
intermediateStart,
intermediateStop
);
}
var initialStopped =
false;
function initialStop(ch, status, data) {
dumpn(
"*** initialStop");
Assert.equal(
data
.map(
function (v) {
return String.fromCharCode(v);
})
.join(
""),
"done"
);
Assert.equal(srv.getObjectState(
"object-state-test"),
null);
if (!initialStarted) {
do_throw(
"initialStop: initialStarted is false?!?!");
}
if (initialStopped) {
do_throw(
"initialStop: initialStopped is true?!?!");
}
if (!intermediateStarted) {
do_throw(
"initialStop: intermediateStarted is false?!?!");
}
if (!intermediateStopped) {
do_throw(
"initialStop: intermediateStopped is false?!?!");
}
initialStopped =
true;
checkForFinish();
}
var intermediateStarted =
false;
function intermediateStart() {
dumpn(
"*** intermediateStart");
Assert.notEqual(srv.getObjectState(
"object-state-test"),
null);
if (!initialStarted) {
do_throw(
"intermediateStart: initialStarted is false?!?!");
}
if (intermediateStarted) {
do_throw(
"intermediateStart: intermediateStarted is true?!?!");
}
intermediateStarted =
true;
}
var intermediateStopped =
false;
function intermediateStop(ch, status, data) {
dumpn(
"*** intermediateStop");
Assert.equal(
data
.map(
function (v) {
return String.fromCharCode(v);
})
.join(
""),
"intermediate"
);
Assert.notEqual(srv.getObjectState(
"object-state-test"),
null);
if (!initialStarted) {
do_throw(
"intermediateStop: initialStarted is false?!?!");
}
if (!intermediateStarted) {
do_throw(
"intermediateStop: intermediateStarted is false?!?!");
}
if (intermediateStopped) {
do_throw(
"intermediateStop: intermediateStopped is true?!?!");
}
intermediateStopped =
true;
new HTTPTestLoader(PATH +
"?state=trigger", triggerStart, triggerStop);
}
var triggerStarted =
false;
function triggerStart() {
dumpn(
"*** triggerStart");
if (!initialStarted) {
do_throw(
"triggerStart: initialStarted is false?!?!");
}
if (!intermediateStarted) {
do_throw(
"triggerStart: intermediateStarted is false?!?!");
}
if (!intermediateStopped) {
do_throw(
"triggerStart: intermediateStopped is false?!?!");
}
if (triggerStarted) {
do_throw(
"triggerStart: triggerStarted is true?!?!");
}
triggerStarted =
true;
}
var triggerStopped =
false;
function triggerStop(ch, status, data) {
dumpn(
"*** triggerStop");
Assert.equal(
data
.map(
function (v) {
return String.fromCharCode(v);
})
.join(
""),
"trigger"
);
if (!initialStarted) {
do_throw(
"triggerStop: initialStarted is false?!?!");
}
if (!intermediateStarted) {
do_throw(
"triggerStop: intermediateStarted is false?!?!");
}
if (!intermediateStopped) {
do_throw(
"triggerStop: intermediateStopped is false?!?!");
}
if (!triggerStarted) {
do_throw(
"triggerStop: triggerStarted is false?!?!");
}
if (triggerStopped) {
do_throw(
"triggerStop: triggerStopped is false?!?!");
}
triggerStopped =
true;
checkForFinish();
}
var finished =
false;
function checkForFinish() {
if (finished) {
try {
do_throw(
"uh-oh, how are we being finished twice?!?!");
}
finally {
// eslint-disable-next-line no-undef
quit(1);
}
}
if (triggerStopped && initialStopped) {
finished =
true;
try {
Assert.equal(srv.getObjectState(
"object-state-test"),
null);
if (!initialStarted) {
do_throw(
"checkForFinish: initialStarted is false?!?!");
}
if (!intermediateStarted) {
do_throw(
"checkForFinish: intermediateStarted is false?!?!");
}
if (!intermediateStopped) {
do_throw(
"checkForFinish: intermediateStopped is false?!?!");
}
if (!triggerStarted) {
do_throw(
"checkForFinish: triggerStarted is false?!?!");
}
}
finally {
srv.stop(do_test_finished);
}
}
}
/** *******************************
* UTILITY OBSERVABLE URL LOADER *
*********************************/
/** Stream listener for the channels. */
function HTTPTestLoader(path, start, stop) {
/** Path to load. */
this._path = path;
/** Array of bytes of data in body of response. */
this._data = [];
/** onStartRequest callback. */
this._start = start;
/** onStopRequest callback. */
this._stop = stop;
var channel = makeChannel(path);
channel.asyncOpen(
this);
}
HTTPTestLoader.prototype = {
onStartRequest(request) {
dumpn(
"*** HTTPTestLoader.onStartRequest for " +
this._path);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
try {
try {
this._start(ch);
}
catch (e) {
do_throw(
this._path +
": error in onStartRequest: " + e);
}
}
catch (e) {
dumpn(
"!!! swallowing onStartRequest exception so onStopRequest is " +
"called..."
);
}
},
onDataAvailable(request, inputStream, offset, count) {
dumpn(
"*** HTTPTestLoader.onDataAvailable for " +
this._path);
Array.prototype.push.apply(
this._data,
makeBIS(inputStream).readByteArray(count)
);
},
onStopRequest(request, status) {
dumpn(
"*** HTTPTestLoader.onStopRequest for " +
this._path);
var ch = request
.QueryInterface(Ci.nsIHttpChannel)
.QueryInterface(Ci.nsIHttpChannelInternal);
this._stop(ch, status,
this._data);
},
QueryInterface: ChromeUtils.generateQI([
"nsIStreamListener",
"nsIRequestObserver",
]),
};