196 lines
6.5 KiB
JavaScript
196 lines
6.5 KiB
JavaScript
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
|
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/**
|
|
* Provides infrastructure for automated download components tests.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Globals
|
|
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
const Cr = Components.results;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
|
|
"resource://gre/modules/Downloads.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
|
"resource://gre/modules/FileUtils.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
|
|
"resource://testing-common/httpd.js");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
|
"resource://gre/modules/NetUtil.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
|
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
|
"resource://gre/modules/Task.jsm");
|
|
|
|
const ServerSocket = Components.Constructor(
|
|
"@mozilla.org/network/server-socket;1",
|
|
"nsIServerSocket",
|
|
"init");
|
|
|
|
const HTTP_SERVER_PORT = 4444;
|
|
const HTTP_BASE = "http://localhost:" + HTTP_SERVER_PORT;
|
|
|
|
const FAKE_SERVER_PORT = 4445;
|
|
const FAKE_BASE = "http://localhost:" + FAKE_SERVER_PORT;
|
|
|
|
const TEST_SOURCE_URI = NetUtil.newURI(HTTP_BASE + "/source.txt");
|
|
const TEST_FAKE_SOURCE_URI = NetUtil.newURI(FAKE_BASE + "/source.txt");
|
|
|
|
const TEST_INTERRUPTIBLE_PATH = "/interruptible.txt";
|
|
const TEST_INTERRUPTIBLE_URI = NetUtil.newURI(HTTP_BASE +
|
|
TEST_INTERRUPTIBLE_PATH);
|
|
|
|
const TEST_TARGET_FILE_NAME = "test-download.txt";
|
|
const TEST_DATA_SHORT = "This test string is downloaded.";
|
|
|
|
/**
|
|
* All the tests are implemented with add_task, this starts them automatically.
|
|
*/
|
|
function run_test()
|
|
{
|
|
run_next_test();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Support functions
|
|
|
|
/**
|
|
* Returns a reference to a temporary file. The file is deleted if it already
|
|
* exists. If the file is then created by the test suite, it will be removed
|
|
* when tests in this file finish.
|
|
*/
|
|
function getTempFile(aLeafName)
|
|
{
|
|
let file = FileUtils.getFile("TmpD", [aLeafName]);
|
|
function GTF_removeFile()
|
|
{
|
|
if (file.exists()) {
|
|
file.remove(false);
|
|
}
|
|
}
|
|
|
|
// Remove the file in case a previous test created it.
|
|
GTF_removeFile();
|
|
|
|
// Remove the file at the end of the test suite.
|
|
do_register_cleanup(GTF_removeFile);
|
|
|
|
return file;
|
|
}
|
|
|
|
/**
|
|
* Ensures that the given file contents are equal to the given string.
|
|
*
|
|
* @param aFile
|
|
* nsIFile whose contents should be verified.
|
|
* @param aExpectedContents
|
|
* String containing the octets that are expected in the file.
|
|
*
|
|
* @return {Promise}
|
|
* @resolves When the operation completes.
|
|
* @rejects Never.
|
|
*/
|
|
function promiseVerifyContents(aFile, aExpectedContents)
|
|
{
|
|
let deferred = Promise.defer();
|
|
NetUtil.asyncFetch(aFile, function(aInputStream, aStatus) {
|
|
do_check_true(Components.isSuccessCode(aStatus));
|
|
let contents = NetUtil.readInputStreamToString(aInputStream,
|
|
aInputStream.available());
|
|
if (contents.length <= TEST_DATA_SHORT.length * 2) {
|
|
do_check_eq(contents, aExpectedContents);
|
|
} else {
|
|
// Do not print the entire content string to the test log.
|
|
do_check_eq(contents.length, aExpectedContents.length);
|
|
do_check_true(contents == aExpectedContents);
|
|
}
|
|
deferred.resolve();
|
|
});
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* Starts a socket listener that closes each incoming connection.
|
|
*
|
|
* @returns nsIServerSocket that listens for connections. Call its "close"
|
|
* method to stop listening and free the server port.
|
|
*/
|
|
function startFakeServer()
|
|
{
|
|
let serverSocket = new ServerSocket(FAKE_SERVER_PORT, true, -1);
|
|
serverSocket.asyncListen({
|
|
onSocketAccepted: function (aServ, aTransport) {
|
|
aTransport.close(Cr.NS_BINDING_ABORTED);
|
|
},
|
|
onStopListening: function () { },
|
|
});
|
|
return serverSocket;
|
|
}
|
|
|
|
/**
|
|
* This function allows testing events or actions that need to happen in the
|
|
* middle of a download.
|
|
*
|
|
* Calling this function registers a new request handler in the internal HTTP
|
|
* server, accessible at the TEST_INTERRUPTIBLE_URI address. The HTTP handler
|
|
* returns the TEST_DATA_SHORT text, then waits until the "resolve" method is
|
|
* called on the object returned by the function. At this point, the handler
|
|
* sends the TEST_DATA_SHORT text again to complete the response.
|
|
*
|
|
* You can also call the "reject" method on the returned object to interrupt the
|
|
* response midway. Because of how the network layer is implemented, this does
|
|
* not cause the socket to return an error.
|
|
*
|
|
* The handler is unregistered when the response finishes or is interrupted.
|
|
*
|
|
* @returns Deferred object used to control the response.
|
|
*/
|
|
function startInterruptibleResponseHandler()
|
|
{
|
|
let deferResponse = Promise.defer();
|
|
gHttpServer.registerPathHandler(TEST_INTERRUPTIBLE_PATH,
|
|
function (aRequest, aResponse)
|
|
{
|
|
aResponse.processAsync();
|
|
aResponse.setHeader("Content-Type", "text/plain", false);
|
|
aResponse.setHeader("Content-Length", "" + (TEST_DATA_SHORT.length * 2),
|
|
false);
|
|
aResponse.write(TEST_DATA_SHORT);
|
|
|
|
deferResponse.promise.then(function SIRH_onSuccess() {
|
|
aResponse.write(TEST_DATA_SHORT);
|
|
aResponse.finish();
|
|
gHttpServer.registerPathHandler(TEST_INTERRUPTIBLE_PATH, null);
|
|
}, function SIRH_onFailure() {
|
|
aResponse.abort();
|
|
gHttpServer.registerPathHandler(TEST_INTERRUPTIBLE_PATH, null);
|
|
});
|
|
});
|
|
return deferResponse;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Initialization functions common to all tests
|
|
|
|
let gHttpServer;
|
|
|
|
add_task(function test_common_initialize()
|
|
{
|
|
// Start the HTTP server.
|
|
gHttpServer = new HttpServer();
|
|
gHttpServer.registerDirectory("/", do_get_file("../data"));
|
|
gHttpServer.start(HTTP_SERVER_PORT);
|
|
});
|