Bug 364043. Remove dependency on Python for HTTP server to serve mochitests. Patch by Jeff Walden <jwalden+bmo@mit.edu> and Robert Sayre <sayrer@gmail.com>. r=rcampbell

This commit is contained in:
sayrer%gmail.com 2007-01-26 18:44:58 +00:00
Родитель 646ef36184
Коммит 23ba5ce55d
26 изменённых файлов: 1398 добавлений и 338 удалений

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

@ -54,5 +54,30 @@ _SERV_FILES = runtests.pl \
gen_template.pl \
$(NULL)
_DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir)
# XXXsayrer will work on making this work better with other apps
ifeq ($(OS_ARCH),Darwin)
ifdef DEBUG
browser_path = \"../$(DIST)/MinefieldDebug.app/Contents/MacOS/firefox\"
else
browser_path = \"../$(DIST)/Minefield.app/Contents/MacOS/firefox\"
endif
else
browser_path = \"../$(DIST)/bin/firefox\"
endif
# These go in _tests/ so they need to go up an extra path segement
TEST_DRIVER_PPARGS = -DBROWSER_PATH=$(browser_path) \
-DXPC_BIN_PATH=\"../$(DIST)/bin\" \
-DTOPSRCDIR=\"$(topsrcdir)\" \
$(NULL)
runtests.pl: runtests.pl.in
$(PERL) $(MOZILLA_DIR)/config/preprocessor.pl \
$(TEST_DRIVER_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
libs:: $(_SERV_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/$(relativesrcdir)
$(INSTALL) $^ $(_DEST_DIR)

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

@ -4,36 +4,17 @@
Steps to get started:
1.) Right now, you will need to edit some constants in runtests.pl. Windows
is not yet supported.
1.) Run the runtests.pl script to start the server.
Currently, the test script automatically determines the location
of *Firefox*.
2.) Start the python server in a separate console:
%> python server.py
It runs at http://localhost:8888/. Control-C will kill it. We are looking
at other server options, because we don't want to require python.
3.) New test cases can be added to the tests/ directory. We are working on
easy test navigation and automated test addition.
4.) gen_template.pl will generate test templates for HTML, XUL, and XHTML.
2.) gen_template.pl will generate test templates for HTML, XUL, and XHTML.
Read the comment at the top of the file for usage instructions.
5.) Write a test.
3.) Write a test.
Checkin rules:
1.) Any module owner/peer/member should feel free to check in a test case.
2.) Tests should always be passing, and failing tests will make the tree
turn orange (very soon). If you have tests that you know are going to
fail, use the todo() function.
3.) Modifications to Makefiles, Perl, or JS code need a bugzilla bug with
davel and sayrer cc'd.
Example test:
<!DOCTYPE HTML>

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

@ -1,93 +0,0 @@
#!/usr/bin/perl
use File::Path;
# URL parameters:
#
# autorun -- kick off tests automatically
# closeWhenDone -- runs quit.js after tests
# logFile -- logs test run to an absolute path
# quiet -- turns of console dumps
#
# consoleLevel, fileLevel: set the logging level of the console and
# file logs, if activated.
# <http://mochikit.com/doc/html/MochiKit/Logging.html>
$test_url = "http://localhost:8888/tests/index.html?autorun=1";
# XXXsayrer these are specific to my mac, need to make them general
#$app = "/Users/sayrer/Desktop/Minefield.app/Contents/MacOS/firefox-bin";
$app = "/home/sayrer/firefox/mozilla/fb-debug/dist/bin/firefox";
$profile = "dhtml_test_profile";
$profile_dir = "/tmp/$profile";
$chrome_dir = "$profile_dir/chrome";
$pref_content = <<PREFEND;
user_pref("browser.dom.window.dump.enabled", true);
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p1.id", "http://localhost:8888");
user_pref("capability.principal.codebase.p1.subjectName", "");
user_pref("dom.disable_open_during_load", false);
user_pref("signed.applets.codebase_principal_support", true);
user_pref("security.warn_submit_insecure", false);
user_pref("browser.shell.checkDefaultBrowser", false);
PREFEND
$chrome_content = <<CHROMEEND;
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
toolbar,
toolbarpalette {
background-repeat: repeat-x !important;
background-position: top right !important;
background-color: rgb(235, 235, 235) !important;
background-image: url("chrome://browser/skin/bookmark_toolbar_background.gif") !important;
}
toolbar#nav-bar {
background-image: none !important;
}
CHROMEEND
# set env vars so Firefox doesn't quit weirdly and break the script
$ENV{'MOZ_NO_REMOTE'} = '1';
$ENV{'NO_EM_RESTART'} = '1';
$ENV{'XPCOM_DEBUG_BREAK'} = 'stack';
# mark the start
$start = localtime;
mkdir($profile_dir);
mkdir($chrome_dir);
# first create our profile
@args = ($app, '-CreateProfile', "$profile $profile_dir");
$rc = 0xffff & system @args;
if ($rc != 0) {
die("FAIL Creating profile failed!\n");
} else {
print "Creating profile succeeded\n";
}
# append magic prefs to user.js
open(PREFOUTFILE, ">>$profile_dir/user.js") || die("Could not open user.js file $!");
print PREFOUTFILE ($pref_content);
close(PREFOUTFILE);
# add userChrome.css
open(CRHOMEOUTFILE, ">>$chrome_dir/userChrome.css") || die("Could not open userChrome.css file $!");
print CRHOMEOUTFILE ($chrome_content);
close(CRHOMEOUTFILE);
# now run with the profile we created
@runargs = ($app, '-P', "$profile", $test_url);
$rc = 0xffff & system @runargs;
if ($rc != 0) {
print "FAIL Exited with code $rc during test run\n";
}
# remove the profile we created
rmtree($profile_dir, 0, 0);
# print test run times
$finish = localtime;
print " started: $start\n";
print "finished: $finish\n";

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

@ -0,0 +1,453 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 1998
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Robert Sayre <sayrer@gmail.com>
# Jeff Walden <jwalden+bmo@mit.edu>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# Win32 path munging for msys courtesy the Curl project under an
# MIT/X license http://curl.haxx.se/
#
# Copyright (c) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>.
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software for
# any purpose with or without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of a copyright holder
# shall not be used in advertising or otherwise to promote the sale,
# use or other dealings in this Software without prior written
# authorization of the copyright holder.
# Perl script to start server and browser
# For usage instructions, run:
# perl runtests.pl --help
use FindBin;
use File::Path;
use File::Spec;
use Getopt::Long;
use Cwd 'abs_path';
use POSIX qw(sys_wait_h strftime);
use strict;
# URL parameters to test URL:
#
# autorun -- kick off tests automatically
# closeWhenDone -- runs quit.js after tests
# logFile -- logs test run to an absolute path
#
# consoleLevel, fileLevel: set the logging level of the console and
# file logs, if activated.
# <http://mochikit.com/doc/html/MochiKit/Logging.html>
# Path to the test script on the server
use constant TEST_SERVER_HOST => "localhost:8888";
use constant TEST_PATH => "/tests/";
use constant TESTS_URL => "http://" . TEST_SERVER_HOST . TEST_PATH;
# Max time in seconds to wait for server startup before tests will fail -- if
# this seems big, it's mostly for debug machines where cold startup
# (particularly after a build) takes forever.
use constant SERVER_STARTUP_TIMEOUT => 15;
my $profile = "mochitest_testing_profile";
my $profile_dir = "$FindBin::Bin/$profile";
# These are generated in mozilla/testing/mochitest/Makefile.in
#expand my $app = __BROWSER_PATH__;
#expand my $topsrcdir = __TOPSRCDIR__;
#expand my $dist_bin = __XPC_BIN_PATH__;
#ifdef WIN32
#expand my $is_win32 = __WIN32__;
#else
my $is_win32 = 0;
#endif
# Do everything.
main();
#################
# MAIN FUNCTION #
#################
sub main {
my ($close_when_done, $appoverride, $log_path, $autorun,
$console_level, $file_level, $help);
GetOptions("close-when-done!"=> \$close_when_done,
"appname:s"=> \$appoverride,
"log-file:s" => \$log_path,
"autorun!" => \$autorun,
"console-level:s" => \$console_level,
"file-level:s" => \$file_level,
"help!" => \$help);
# if the switches include --help, exit and print directions
if ($help) {
usage_and_exit();
}
# we were passed an explicit path to the app
if ($appoverride) {
$app = $appoverride;
}
initializeProfile();
my $serverPid = startServer($close_when_done);
# If we're lucky, the server has fully started by now, and all paths are
# ready, etc. However, xpcshell cold start times suck, at least for debug
# builds. We'll try to connect to the server for 30 seconds or until we
# succeed, whichever is first. If we succeed, then we continue with
# execution. If we fail, we try to kill the server and exit with an error.
wait_for_server_startup($serverPid, SERVER_STARTUP_TIMEOUT);
my $url = TESTS_URL . "?";
if ($autorun) {
$url .= "&autorun=1";
}
if ($close_when_done) {
$url .= "&closeWhenDone=1";
}
if ($log_path) {
$url .= "&logFile=$log_path";
}
if ($file_level) {
$url .= "&fileLevel=$file_level";
}
if ($console_level) {
$url .= "&consoleLevel=$console_level";
}
my $test_start = runTests($url);
shutdownServer($serverPid);
# print test run times
my $test_finish = localtime();
print " started: $test_start\n";
print "finished: $test_finish\n";
}
#######################
# COMMANDLINE USAGE #
#######################
sub usage_and_exit {
print "\n";
print "Usage instructons for runtests.pl.\n";
print "If --log-file is specified, --file-level must be specified as well.";
print "\n\n";
print "Syntax:\n";
print " runtests.pl \\\n";
print " [--autorun] \\\n";
print " [--close-when-done] \\\n";
print " [--appname=/path/to/app] \\\n";
print " [--log-file=/path/to/logfile] \\\n";
print " [--file-level=DEBUG|INFO|ERROR|FATAL|WARNING] \\\n";
print " [--console-level=DEBUG|INFO|ERROR|FATAL|WARNING] \n\n";
exit(1);
}
#######################
# MAKE A WINDOWS PATH #
#######################
sub winPathFromDir {
my ($path) = abs_path(@_);
# XXXsayrer need to test for cygwin here.
# we can shell out to the cygpath utility to do this for us
# This is a windows mingw32 build, we need to translate the
# given path to the "actual" windows path.
my @m = `mount`;
my $matchlen;
my $bestmatch;
my $mount;
#example mount output:
# C:\DOCUME~1\Temp on /tmp type user (binmode,noumount)
# c:\ActiveState\perl on /perl type user (binmode)
# C:\msys\1.0\bin on /usr/bin type user (binmode,cygexec,noumount)
# C:\msys\1.0\bin on /bin type user (binmode,cygexec,noumount)
foreach $mount (@m) {
if ( $mount =~ /(.*) on ([^ ]*) type /) {
my ($mingw, $real)=($2, $1);
if ($path =~ /^$mingw/) {
# the path starts with the path we
# found on this line in the mount output
my $len = length($mingw);
if ($len > $matchlen) {
# we remember the match that is the longest
$matchlen = $len;
$bestmatch = $real;
}
}
}
}
if (!$matchlen) {
die "Serious error, can't find our \"real\" path!\n";
}
my ($volume,$directories,$file) =
File::Spec->splitpath(substr($path, $matchlen), 1);
my @dirs = File::Spec->splitdir( $directories );
return $bestmatch . join "\\", @dirs;
}
##################
# SERVER STARTUP #
##################
# Start up the server, and let the server script handle shutdown if
# we're closing when done. (We'll kill it later if it goes zombie
# somehow, but that shouldn't be the way it happens except if
# something really breaks.)
sub startServer {
my ($close_when_done) = @_;
my $pid = fork();
if ($pid == 0) {
# Run the server
my $status = 0;
my $command = "";
if ($close_when_done) {
$command .= "CLOSE_WHEN_DONE=1 ";
}
#if (-e "$dist_bin/run-mozilla.sh") {
# $command .= "$dist_bin/run-mozilla.sh ";
#}
$command .= "$dist_bin/xpcshell -v 170 ";
# So we get clean paths passed to the app
my $serverDir = abs_path("${topsrcdir}/netwerk/test/httpserver");
my $mochiDir = abs_path("${topsrcdir}/testing/mochitest");
# this path is passed as a string, so we need to convert it on win32
if ($is_win32) {
$command .= " -f \"" . winPathFromDir($serverDir) . "\\httpd.js\"";
$command .= " -f \"" . winPathFromDir($mochiDir) . "\\server.js\"";
} else {
$command .= " -f \"" . $serverDir . "/httpd.js\"";
$command .= " -f \"" . $mochiDir . "/server.js\"";
}
print "$command\n";
exec("$command") or die("Error running server: $!\n");
}
return ($pid);
}
##############
# TEST SETUP #
##############
sub initializeProfile {
my $pref_content = <<PREFEND;
user_pref("browser.dom.window.dump.enabled", true);
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p1.id", "http://localhost:8888");
user_pref("capability.principal.codebase.p1.subjectName", "");
user_pref("dom.disable_open_during_load", false);
user_pref("signed.applets.codebase_principal_support", true);
user_pref("security.warn_submit_insecure", false);
user_pref("browser.shell.checkDefaultBrowser", false);
PREFEND
my $chrome_content = <<CHROMEEND;
\@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
toolbar,
toolbarpalette {
background-repeat: repeat-x !important;
background-position: top right !important;
background-color: rgb(235, 235, 235) !important;
background-image: url("chrome://browser/skin/bookmark_toolbar_background.gif") !important;
}
toolbar#nav-bar {
background-image: none !important;
}
CHROMEEND
# remove the profile we created last run
rmtree($profile_dir, 0, 0);
my $chrome_dir = "$profile_dir/chrome";
mkdir($profile_dir);
mkdir($chrome_dir);
# first create our profile
my $create_args = "$profile $profile_dir";
if ($is_win32) {
$create_args = "$profile " . winPathFromDir($profile_dir);
}
my @args = ($app, '-CreateProfile', $create_args);
my $rc = 0xffff & system @args;
if ($rc != 0) {
die("FAIL Creating profile failed!\n");
} else {
print "Creating profile succeeded\n";
}
# append magic prefs to user.js
open(PREFOUTFILE, ">>$profile_dir/user.js") ||
die("Could not open user.js file $!\n");
print PREFOUTFILE ($pref_content);
close(PREFOUTFILE) or die("Couldn't close user.js file: $!\n");
# add userChrome.css
open(CHROMEOUTFILE, ">>$chrome_dir/userChrome.css") ||
die("Could not open userChrome.css file $!");
print CHROMEOUTFILE ($chrome_content);
close(CHROMEOUTFILE);
}
###################
# WAIT FOR SERVER #
###################
sub wait_for_server_startup {
my ($pid, $timeout) = @_;
die ("Invalid timeout value passed to wait_for_server_startup()\n")
if ($timeout <= 0);
eval {
my $loop_count = 0;
while ($loop_count++ < $timeout) {
last if (-e "$profile_dir/server_alive.txt");
sleep 1;
}
die "timeout" if ($loop_count >= $timeout);
return "done";
};
my $time_out_message;
if ($@) {
if ($@ =~ /timeout/) {
$time_out_message = "Timed out while waiting for server startup.\n";
} else {
# Died for some other reason.
$time_out_message = "An unknown error occurred ";
$time_out_message .= "while waiting for server startup.\n";
}
}
if ($time_out_message) {
kill_process($pid);
print $time_out_message;
exit(1);
}
}
sub kill_process {
my ($target_pid) = @_;
my $start_time = time();
# Try to kill and wait 10 seconds, then try a kill -9
my $sig;
for $sig ('TERM', 'KILL') {
print "kill $sig $target_pid\n";
kill $sig => $target_pid;
my $interval_start = time;
while (time - $interval_start < 10) {
# the following will work with 'cygwin' perl on win32, but not
# with 'MSWin32' (ActiveState) perl
my $pid = waitpid($target_pid, POSIX::WNOHANG());
if (($pid == $target_pid and POSIX::WIFEXITED($?)) or $pid == -1) {
my $secs = time - $start_time;
$secs = $secs == 1 ? '1 second' : "$secs seconds";
print "Process killed. Took $secs to die.\n";
return;
}
sleep 1;
}
}
die "Unable to kill process: $target_pid";
}
##################
# TEST EXECUTION #
##################
sub runTests {
my ($testUrl) = @_;
# mark the start
my $test_start = localtime();
# set env vars so Firefox doesn't quit weirdly and break the script
$ENV{'MOZ_NO_REMOTE'} = '1';
$ENV{'NO_EM_RESTART'} = '1';
$ENV{'XPCOM_DEBUG_BREAK'} = 'stack';
# now run with the profile we created
my @runargs = ($app, '-P', "$profile", $testUrl);
my $rc = 0xffff & system @runargs;
if ($rc != 0) {
print "FAIL Exited with code $rc during test run\n";
}
return $test_start;
}
##################
# TEST EXECUTION #
##################
sub shutdownServer {
my ($pid) = @_;
kill_process($pid);
}

428
testing/mochitest/server.js Normal file
Просмотреть файл

@ -0,0 +1,428 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is MozJSHTTP code.
*
* The Initial Developer of the Original Code is
* Jeff Walden <jwalden+code@mit.edu>.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Sayre <sayrer@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// Note that the server script itself already defines Cc, Ci, and Cr for us,
// and because they're constants it's not safe to redefine them. Scope leakage
// sucks.
const SERVER_PORT = 8888;
var server; // for use in the shutdown handler, if necessary
//
// HTML GENERATION
//
var tags = ['A', 'ABBR', 'ACRONYM', 'ADDRESS', 'APPLET', 'AREA', 'B', 'BASE',
'BASEFONT', 'BDO', 'BIG', 'BLOCKQUOTE', 'BODY', 'BR', 'BUTTON',
'CAPTION', 'CENTER', 'CITE', 'CODE', 'COL', 'COLGROUP', 'DD',
'DEL', 'DFN', 'DIR', 'DIV', 'DL', 'DT', 'EM', 'FIELDSET', 'FONT',
'FORM', 'FRAME', 'FRAMESET', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6',
'HEAD', 'HR', 'HTML', 'I', 'IFRAME', 'IMG', 'INPUT', 'INS',
'ISINDEX', 'KBD', 'LABEL', 'LEGEND', 'LI', 'LINK', 'MAP', 'MENU',
'META', 'NOFRAMES', 'NOSCRIPT', 'OBJECT', 'OL', 'OPTGROUP',
'OPTION', 'P', 'PARAM', 'PRE', 'Q', 'S', 'SAMP', 'SCRIPT',
'SELECT', 'SMALL', 'SPAN', 'STRIKE', 'STRONG', 'STYLE', 'SUB',
'SUP', 'TABLE', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD',
'TITLE', 'TR', 'TT', 'U', 'UL', 'VAR'];
/**
* Below, we'll use makeTagFunc to create a function for each of the
* strings in 'tags'. This will allow us to use s-expression like syntax
* to create HTML.
*/
function makeTagFunc(tagName)
{
return function (attrs /* rest... */)
{
var startChildren = 0;
var response = "";
// write the start tag and attributes
response += "<" + tagName;
// if attr is an object, write attributes
if (attrs && typeof attrs == 'object') {
startChildren = 1;
for (var [key,value] in attrs) {
var val = "" + value;
response += " " + key + '="' + val.replace('"','&quot;') + '"';
}
}
response += ">";
// iterate through the rest of the args
for (var i = startChildren; i < arguments.length; i++) {
if (typeof arguments[i] == 'function') {
response += arguments[i]();
} else {
response += arguments[i];
}
}
// write the close tag
response += "</" + tagName + ">\n";
return response;
}
}
//
// SCRIPT CODE
//
runServer();
// We can only have gotten here if CLOSE_WHEN_DONE was specified and the
// /server/shutdown path was requested. We can shut down the xpcshell now
// that all testing requests have been served.
quit(0);
//
// SERVER SETUP
//
function runServer()
{
var serverBasePath = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
var procDir = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile);
serverBasePath.initWithPath(procDir.parent.parent.path);
serverBasePath.append("_tests");
serverBasePath.append("testing");
serverBasePath.append("mochitest");
server = new nsHttpServer();
server.registerDirectory("/", serverBasePath);
if (environment["CLOSE_WHEN_DONE"])
server.registerPathHandler("/server/shutdown", serverShutdown);
server.setIndexHandler(defaultDirHandler);
server.start(SERVER_PORT);
// touch a file in the profile directory to indicate we're alive
var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(Ci.nsIFileOutputStream);
var serverAlive = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
serverAlive.initWithFile(serverBasePath);
serverAlive.append("mochitest_testing_profile");
// If we're running outside of the test harness, there might
// not be a test profile directory present
if (serverAlive.exists()) {
serverAlive.append("server_alive.txt");
foStream.init(serverAlive,
0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
data = "It's alive!";
foStream.write(data, data.length);
foStream.close();
}
// map our global HTML generation functions
for each(var tag in tags) {
this[tag] = makeTagFunc(tag);
}
//
// The following is threading magic to spin an event loop -- this has to
// happen manually in xpcshell for the server to actually work.
//
var thread = Cc["@mozilla.org/thread-manager;1"]
.getService()
.currentThread;
while (!server.isStopped())
thread.processNextEvent(true);
// Server stopped by /server/shutdown handler -- go through pending events
// and return.
// get rid of any pending requests
while (thread.hasPendingEvents())
thread.processNextEvent(true);
}
// PATH HANDLERS
// /server/shutdown
function serverShutdown(metadata, response)
{
response.setStatusLine("1.1", 200, "OK");
response.setHeader("Content-type", "text/plain");
var body = "Server shut down.";
response.bodyOutputStream.write(body, body.length);
// Note: this doesn't disrupt the current request.
server.stop();
}
//
// DIRECTORY LISTINGS
//
/**
* Creates a generator that iterates over the contents of
* an nsIFile directory.
*/
function dirIter(dir)
{
var enum = dir.directoryEntries;
while (enum.hasMoreElements()) {
var file = enum.getNext();
yield file.QueryInterface(Ci.nsILocalFile);
}
}
/**
* Builds an optionally nested object containing links to the
* files and directories within dir.
*/
function list(requestPath, directory, recurse)
{
var path = requestPath;
if (path.charAt(path.length - 1) != "/") {
path += "/";
}
var dir = directory.QueryInterface(Ci.nsIFile);
var links = {};
// The SimpleTest directory is hidden
var files = [file for (file in dirIter(dir))
if (file.path.indexOf("SimpleTest") == -1)];
for each (var file in files) {
var key = requestPath + file.leafName;
if (file.isDirectory()) {
key += "/";
}
if (recurse && file.isDirectory()) {
links[key] = list(key, file, recurse);
} else {
links[key] = true;
}
}
return links;
}
/**
* Heuristic function that determines whether a given path
* is a test case to be executed in the harness, or just
* a supporting file.
*/
function isTest(filename)
{
return (filename.indexOf("test_") > -1 &&
filename.indexOf(".js") == -1 &&
filename.indexOf(".css") == -1);
}
/**
* Transform nested hashtables of paths to nested HTML lists.
*/
function linksToListItems(links)
{
var response = "";
for (var [link, value] in links) {
var classVal = (!isTest(link) && !(value instanceof Object))
? "non-test invisible"
: "";
response += LI({class: classVal}, A({href: link}, link));
if (value instanceof Object) {
response += LI({class: "dir"}, UL(linksToListItems(value)));
}
}
return response;
}
/**
* Transform nested hashtables of paths to a flat table rows.
*/
function linksToTableRows(links)
{
var response = "";
for (var [link, value] in links) {
var classVal = (!isTest(link) && !(value instanceof Object))
? "non-test invisible"
: "";
if (value instanceof Object) {
response += TR({class: "dir", id: "tr-" + link },
TD({colspan: "3"},"&nbsp;"));
response += linksToTableRows(value);
} else {
response += TR({class: classVal, id: "tr-" + link},
TD("0"), TD("0"), TD("0"));
}
}
return response;
}
/**
* Produce a flat array of test file paths to be executed in the harness.
*/
function jsonArrayOfTestFiles(links)
{
var testFiles = [];
function arrayOfTestFiles(linkArray) {
for (var [link, value] in linkArray) {
if (value instanceof Object) {
arrayOfTestFiles(value);
} else {
testFiles.push(link)
}
}
}
arrayOfTestFiles(links);
var testFiles = ['"' + file + '"' for each(file in testFiles)
if (isTest(file))];
return "[" + testFiles.join(",\n") + "]";
}
/**
* Produce a normal directory listing.
*/
function regularListing(metadata, response)
{
var links = list(metadata.path,
metadata.getProperty("directory"),
false);
response.write(
HTML(
HEAD(
TITLE("mochitest index ", metadata.path)
),
BODY(
BR(),
A({href: ".."}, "Up a level"),
UL(linksToListItems(links))
)
)
);
}
/**
* Produce a test harness page containing all the test cases
* below it, recursively.
*/
function testListing(metadata, response)
{
var links = list(metadata.path,
metadata.getProperty("directory"),
true);
var tests = jsonArrayOfTestFiles(links);
response.write(
HTML(
HEAD(
TITLE("MochiTest | ", metadata.path),
LINK({rel: "stylesheet",
type: "text/css", href: "/static/harness.css"}
),
SCRIPT({type: "text/javascript", src: "/MochiKit/packed.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/TestRunner.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/MozillaFileLogger.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/quit.js"}),
SCRIPT({type: "text/javascript",
src: "/tests/SimpleTest/setup.js"}),
SCRIPT({type: "text/javascript"},
"gTestList=" + tests + ";"
)
),
BODY(
DIV({class: "container"},
H2("--> ", A({href: "#", id: "runtests"}, "Run Tests"), " <--"),
DIV({class: "status"},
H1({id: "indicator"}, "Status"),
H2({id: "pass"}, "Passed: ", SPAN({id: "pass-count"},"0")),
H2({id: "fail"}, "Failed: ", SPAN({id: "fail-count"},"0")),
H2({id: "fail"}, "Todo: ", SPAN({id: "todo-count"},"0"))
),
DIV({class: "clear"}),
DIV({id: "current-test"},
B("Currently Executing: ",
SPAN({id: "current-test-path"}, "_")
)
),
DIV({class: "clear"}),
DIV({class: "frameholder"},
IFRAME({scrolling: "no", id: "testframe", width: "500"})
),
DIV({class: "clear"}),
DIV({class: "toggle"},
A({href: "#", id: "toggleNonTests"}, "Show Non-Tests"),
BR()
),
UL({class: "top"},
LI(B("Test Files")),
linksToListItems(links)
),
TABLE({cellpadding: 0, cellspacing: 0, id: "test-table"},
TR(TH("Passed"), TH("Failed"), TH("Todo")),
linksToTableRows(links)
),
DIV({class: "clear"}),
P(
SMALL(
"Based on the ",
A({href:"http://www.mochikit.com/"}, "MochiKit"),
" unit tests."
)
)
)
)
)
);
}
/**
* Respond to requests that match a file system directory.
* Under the tests/ directory, return a test harness page.
*/
function defaultDirHandler(metadata, response)
{
response.setStatusLine("1.1", 200, "OK");
response.setHeader("Content-type", "text/html");
try {
if (metadata.path.indexOf("/tests") != 0) {
regularListing(metadata, response);
} else {
testListing(metadata, response);
}
} catch (ex) {
response.write(ex);
}
}

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

@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
_STATIC_FILES = test.template.txt \
xhtml.template.txt \
xul.template.txt \
harness.css \
$(NULL)
libs:: $(_STATIC_FILES)

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

@ -0,0 +1,102 @@
body {
margin: 0;
padding: 0;
font-family: Verdana, Helvetica, Arial, sans-serif;
font-size: 11px;
}
th, td {
font-family: Verdana, Helvetica, Arial, sans-serif;
font-size: 11px;
}
ul {
list-style: none;
padding: 0;
padding-left: 1em;
margin: 0;
background: #f6f6f6;
}
ul.top {
width: 80%;
float: left;
}
li, th, td {
border-bottom: 1px solid white;
height: 14px;
}
th, td {
padding-left: .2em;
padding-right: .2em;
text-align: left;
}
table#test-table {
background: #f6f6f6;
width: 19%;
}
div.container {
margin: 1em;
}
li a {
text-decoration: none;
}
li a:hover {
text-decoration: underline;
}
li.dir a {
color: #000;
}
a {
color: #3333CC;
}
li.non-test a:link, li.non-test a:hover,
li.non-test a:active, li.non-test a:visited {
color: #999999;
}
a#runtests {
color: blue;
}
.clear { clear: both;}
.invisible { display: none;}
div.status {
min-height: 170px;
width: 100%;
border: 1px solid #666;
float: left;
}
div.frameholder {
min-height: 170px;
min-width: 500px;
background-color: #ffffff;
float: left;
}
div#current-test {
margin-top: 1em;
margin-bottom: 1em;
}
#indicator {
color: white;
background-color: green;
padding: .5em;
margin: 0;
}
#pass, #fail {
margin: 0;
padding: .5em;
}

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

@ -39,6 +39,7 @@ DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = testing/mochitest/tests
include $(DEPTH)/config/autoconf.mk
@ -46,3 +47,34 @@ DIRS = SimpleTest \
$(NULL)
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_MochiKit-Async.html \
test_MochiKit-Base.html \
test_MochiKit-DateTime.html \
test_MochiKit-DOM.html \
test_MochiKit-Style.html \
test_MochiKit-Format.html \
test_MochiKit-Iter.html \
test_MochiKit-Logging.html \
test_MochiKit-MochiKit.html \
test_MochiKit-Color.html \
test_MochiKit-Signal.html \
test_Base.js \
test_Color.js \
test_DateTime.js \
test_DragAndDrop.js \
test_Format.js \
test_Iter.js \
test_Logging.js \
test_Signal.js \
cli.js \
FakeJSAN.js \
standalone.js \
test_MochiKit-Async.json \
$(NULL)
# Copy the MochiKit tests into subdirectory, so the top level is all dirs
# in the test screen. We leave them in tests/ in the src tree to mirror
# the upstream MochiKit repository
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/$(relativesrcdir)/MochiKit_Unit_Tests

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

@ -49,6 +49,8 @@ _SIMPLETEST_FILES = MozillaFileLogger.js \
SimpleTest.js \
test.css \
TestRunner.js \
setup.js \
EventUtils.js \
$(NULL)
libs:: $(_SIMPLETEST_FILES)

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

@ -1,37 +1,39 @@
/**
* MozillaFileLogger, a log listener that can write to a local file.
*/
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const Cc = Components.classes;
const Ci = Components.interfaces;
const FOSTREAM_CID = "@mozilla.org/network/file-output-stream;1";
const LF_CID = "@mozilla.org/file/local;1";
// File status flags. It is a bitwise OR of the following bit flags.
// Only one of the first three flags below may be used.
const PR_READ_ONLY = 0x01; // Open for reading only.
const PR_WRITE_ONLY = 0x02; // Open for writing only.
const PR_READ_WRITE = 0x04; // Open for reading and writing.
// If the file does not exist, the file is created.
// If the file exists, this flag has no effect.
const PR_CREATE_FILE = 0x08;
// The file pointer is set to the end of the file prior to each write.
const PR_APPEND = 0x10;
// If the file exists, its length is truncated to 0.
const PR_TRUNCATE = 0x20;
// If set, each write will wait for both the file data
// and file status to be physically updated.
const PR_SYNC = 0x40;
// If the file does not exist, the file is created. If the file already
// exists, no action and NULL is returned.
const PR_EXCL = 0x80;
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const Cc = Components.classes;
const Ci = Components.interfaces;
const FOSTREAM_CID = "@mozilla.org/network/file-output-stream;1";
const LF_CID = "@mozilla.org/file/local;1";
// File status flags. It is a bitwise OR of the following bit flags.
// Only one of the first three flags below may be used.
const PR_READ_ONLY = 0x01; // Open for reading only.
const PR_WRITE_ONLY = 0x02; // Open for writing only.
const PR_READ_WRITE = 0x04; // Open for reading and writing.
// If the file does not exist, the file is created.
// If the file exists, this flag has no effect.
const PR_CREATE_FILE = 0x08;
// The file pointer is set to the end of the file prior to each write.
const PR_APPEND = 0x10;
// If the file exists, its length is truncated to 0.
const PR_TRUNCATE = 0x20;
// If set, each write will wait for both the file data
// and file status to be physically updated.
const PR_SYNC = 0x40;
// If the file does not exist, the file is created. If the file already
// exists, no action and NULL is returned.
const PR_EXCL = 0x80;
} catch (ex) {
// probably not running in the test harness
}
/** Init the file logger with the absolute path to the file.
It will create and append if the file already exists **/
@ -47,20 +49,19 @@ MozillaFileLogger.init = function(path) {
}
MozillaFileLogger.getLogCallback = function() {
var self = MozillaFileLogger;
return function (msg) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
self._foStream.write(data, data.length);
if (data.indexOf("SimpleTest FINISH") >= 0) {
self.close();
}
return function (msg) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
MozillaFileLogger._foStream.write(data, data.length);
if (data.indexOf("SimpleTest FINISH") >= 0) {
MozillaFileLogger.close();
}
}
}
MozillaFileLogger.close = function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
MozillaFileLogger._foStream.close();
MozillaFileLogger._foStream = null;
MozillaFileLogger._file = null;
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
MozillaFileLogger._foStream.close();
MozillaFileLogger._foStream = null;
MozillaFileLogger._file = null;
}

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

@ -8,27 +8,8 @@
**/
var TestRunner = {};
TestRunner.logEnabled = false;
TestRunner._iframes = {};
TestRunner._iframeDocuments = {};
TestRunner._iframeRows = {};
TestRunner._currentTest = 0;
TestRunner._urls = [];
TestRunner._testsDiv = DIV();
TestRunner._progressDiv = DIV();
TestRunner._summaryDiv = DIV({'id': "summaryDiv"},
H1(null, "Tests Summary"),
TABLE(null,
THEAD(null,
TR(null,
TH(null, "Test"),
TH(null, "Passed"),
TH(null, "Failed"),
TH(null, "Todo")
)
),
TBODY()
)
);
/**
* This function is called after generating the summary.
@ -58,14 +39,11 @@ TestRunner._toggle = function(el) {
* Creates the iframe that contains a test
**/
TestRunner._makeIframe = function (url) {
var iframe = document.createElement('iframe');
var iframe = $('testframe');
iframe.src = url;
iframe.name = url;
iframe.width = "500";
var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
var tr = TR(null, TD({'colspan': '4'}, iframe));
iframe._row = tr;
tbody.appendChild(tr);
return iframe;
};
@ -80,14 +58,8 @@ TestRunner.runTests = function (/*url...*/) {
TestRunner.logger.log("SimpleTest START");
var body = document.getElementsByTagName("body")[0];
appendChildNodes(body,
TestRunner._testsDiv,
TestRunner._progressDiv,
TestRunner._summaryDiv
);
for (var i = 0; i < arguments.length; i++) {
TestRunner._urls.push(arguments[i]);
}
TestRunner._urls = flattenArguments(arguments);
$('testframe').src="";
TestRunner.runNextTest();
};
@ -97,17 +69,17 @@ TestRunner.runTests = function (/*url...*/) {
TestRunner.runNextTest = function() {
if (TestRunner._currentTest < TestRunner._urls.length) {
var url = TestRunner._urls[TestRunner._currentTest];
var progress = SPAN(null,
"Running ", A({href:url}, url), "..."
);
$("current-test-path").innerHTML = url;
if (TestRunner.logEnabled)
TestRunner.logger.log(scrapeText(progress));
TestRunner.logger.log("Running " + url + "...");
TestRunner._progressDiv.appendChild(progress);
TestRunner._iframes[url] = TestRunner._makeIframe(url);
TestRunner._makeIframe(url);
} else {
TestRunner.makeSummary();
$("current-test").innerHTML = "<b>Finished</b>";
TestRunner._makeIframe("about:blank");
if (TestRunner.logEnabled)
TestRunner.logger.log("SimpleTest FINISHED");
if (TestRunner.onComplete)
TestRunner.onComplete();
}
@ -116,49 +88,61 @@ TestRunner.runNextTest = function() {
/**
* This stub is called by SimpleTest when a test is finished.
**/
TestRunner.testFinished = function (doc) {
appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR());
TestRunner.testFinished = function(doc) {
var finishedURL = TestRunner._urls[TestRunner._currentTest];
if (TestRunner.logEnabled)
TestRunner.logger.debug("SimpleTest finished " + finishedURL);
TestRunner._iframeDocuments[finishedURL] = doc;
// TestRunner._iframes[finishedURL].style.display = "none";
TestRunner._toggle(TestRunner._iframes[finishedURL]);
TestRunner._updateUI();
TestRunner._currentTest++;
TestRunner.runNextTest();
};
/**
* Display the summary in the browser
**/
TestRunner.makeSummary = function() {
if (TestRunner.logEnabled)
TestRunner.logger.log("SimpleTest FINISHED");
var rows = [];
for (var url in TestRunner._iframeDocuments) {
var doc = TestRunner._iframeDocuments[url];
var nOK = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_ok')
).length;
var nNotOK = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
).length;
var nTodo = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_todo')
).length;
var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
var row = TR(
{'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
TD(null, url),
TD(null, nOK),
TD(null, nNotOK),
TD({'style': {'backgroundColor': nTodo > 0 ? "orange":"transparent"}}, nTodo)
);
row.onclick = toggle;
var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
tbody.insertBefore(row, TestRunner._iframes[url]._row)
}
};
* Get the results.
*/
TestRunner.countResults = function(doc) {
var nOK = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_ok')
).length;
var nNotOK = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
).length;
var nTodo = withDocument(doc,
partial(getElementsByTagAndClassName, 'div', 'test_todo')
).length;
return {"OK": nOK, "notOK": nNotOK, "todo": nTodo};
}
TestRunner._updateUI = function() {
var results = TestRunner.countResults($('testframe').contentDocument);
var passCount = parseInt($("pass-count").innerHTML) + results.OK;
var failCount = parseInt($("fail-count").innerHTML) + results.notOK;
var todoCount = parseInt($("todo-count").innerHTML) + results.todo;
$("pass-count").innerHTML = passCount;
$("fail-count").innerHTML = failCount;
$("todo-count").innerHTML = todoCount;
// Set the top Green/Red bar
var indicator = $("indicator");
if (failCount > 0) {
indicator.innerHTML = "Status: Fail";
indicator.style.backgroundColor = "red";
} else if (passCount > 0) {
indicator.innerHTML = "Status: Pass";
indicator.style.backgroundColor = "green";
}
// Set the table values
var trID = "tr-" + $('current-test-path').innerHTML;
var row = $(trID);
replaceChildNodes(row,
TD({'style':
{'backgroundColor': results.notOK > 0 ? "#f00":"#0d0"}}, results.OK),
TD({'style':
{'backgroundColor': results.notOK > 0 ? "#f00":"#0d0"}}, results.notOK),
TD({'style': {'backgroundColor':
results.todo > 0 ? "orange":"#0d0"}}, results.todo)
);
}

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

@ -12,14 +12,16 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is The Original Code is Mozilla Automated Testing Code
* The Original Code is Mozilla Automated Testing Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Bob Clary <bob@bclary.com>
* Contributor(s):
* Bob Clary <bob@bclary.com>
* Jeff Walden <jwalden+code@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -40,6 +42,18 @@
These files did not have a license
*/
function quitHook()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://" + location.host + "/server/shutdown", true);
xhr.onreadystatechange = function (event)
{
if (xhr.readyState == 4)
goQuitApplication();
};
xhr.send(null);
}
function canQuitApplication()
{
var os = Components.classes["@mozilla.org/observer-service;1"]

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

@ -0,0 +1,130 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Sayre <sayrer@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
TestRunner.logEnabled = true;
TestRunner.logger = new Logger();
// Check the query string for arguments
var params = parseQueryString(location.search.substring(1), true);
// log levels for console and logfile
var fileLevel = params.fileLevel || null;
var consoleLevel = params.consoleLevel || null;
// closeWhenDone tells us to call quit.js when complete
if (params.closeWhenDone) {
TestRunner.onComplete = goQuitApplication;
}
// logFile to write our results
if (params.logFile) {
MozillaFileLogger.init(params.logFile);
TestRunner.logger.addListener("mozLogger", fileLevel + "", MozillaFileLogger.getLogCallback());
}
// if we get a quiet param, don't log to the console
if (!params.quiet) {
function dumpListener(msg) {
dump("*** " + msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n");
}
TestRunner.logger.addListener("dumpListener", consoleLevel + "", dumpListener);
}
var gTestList = [];
var RunSet = {}
RunSet.runall = function(e) {
TestRunner.runTests(gTestList);
}
RunSet.reloadAndRunAll = function(e) {
e.preventDefault();
//window.location.hash = "";
var addParam = "";
if (params.autorun) {
window.location.search += "";
window.location.href = window.location.href;
} else if (window.location.search) {
window.location.href += "&autorun=1";
} else {
window.location.href += "?autorun=1";
}
};
// UI Stuff
function toggleVisible(elem) {
toggleElementClass("invisible", elem);
}
function makeVisible(elem) {
removeElementClass(elem, "invisible");
}
function makeInvisible(elem) {
addElementClass(elem, "invisible");
}
function isVisible(elem) {
// you may also want to check for
// getElement(elem).style.display == "none"
return !hasElementClass(elem, "invisible");
};
function toggleNonTests (e) {
e.preventDefault();
var elems = getElementsByTagAndClassName("*", "non-test");
for (var i="0"; i<elems.length; i++) {
toggleVisible(elems[i]);
}
if (isVisible(elems[0])) {
$("toggleNonTests").innerHTML = "Hide Non-Tests";
} else {
$("toggleNonTests").innerHTML = "Show Non-Tests";
}
}
// hook up our buttons
function hookup() {
connect("runtests", "onclick", RunSet, "reloadAndRunAll");
connect("toggleNonTests", "onclick", toggleNonTests);
// run automatically if
if (params.autorun) {
connect(window, 'onload', RunSet, "runall");
RunSet.runall();
}
}
connect(window, 'onload', hookup);

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

@ -1,17 +1,18 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Async.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Async.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script type="text/javascript">
try {
var increment = function (res) {
@ -385,7 +386,6 @@ try {
SimpleTest.finish();
});
} catch (err) {
var s = "test suite failure!\n";

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

@ -1,11 +1,11 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>
@ -14,7 +14,7 @@
<script type="text/javascript">
try {
tests.test_Base({ok:ok,is:is});
ok( true, "test suite finished!");
ok(true, "test suite finished!");
} catch (err) {
var s = "test suite failure!\n";
var o = {};

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

@ -1,13 +1,13 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Logging.js"></script>
<script type="text/javascript" src="/MochiKit/Color.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
<style type="text/css">.redtext {color: red}</style>
</head>
<body>

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

@ -1,12 +1,12 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,12 +1,12 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/DateTime.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/DateTime.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,16 +1,16 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<script type="text/javascript" src="../MochiKit/New.js"></script>
<script type="text/javascript" src="../MochiKit/Visual.js"></script>
<script type="text/javascript" src="../MochiKit/DragAndDrop.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Color.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/MochiKit/New.js"></script>
<script type="text/javascript" src="/MochiKit/Visual.js"></script>
<script type="text/javascript" src="/MochiKit/DragAndDrop.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
<style type="text/css">
.drop-hover {
}

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

@ -1,12 +1,12 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Format.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Format.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,11 +1,11 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,12 +1,12 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Logging.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,8 +1,8 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,13 +1,13 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/MochiKit/Logging.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body>

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

@ -1,14 +1,14 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Logging.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<script type="text/javascript" src="/MochiKit/MockDOM.js"></script>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Color.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Logging.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
</head>
<body style="border: 0; margin: 0; padding: 0;">

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

@ -1,17 +1,17 @@
<html>
<head>
<script type="text/javascript" src="../MochiKit/Base.js"></script>
<script type="text/javascript" src="../MochiKit/Iter.js"></script>
<script type="text/javascript" src="../MochiKit/DOM.js"></script>
<script type="text/javascript" src="../MochiKit/Async.js"></script>
<script type="text/javascript" src="../MochiKit/Style.js"></script>
<script type="text/javascript" src="../MochiKit/Color.js"></script>
<script type="text/javascript" src="../MochiKit/Signal.js"></script>
<script type="text/javascript" src="../MochiKit/New.js"></script>
<script type="text/javascript" src="../MochiKit/Visual.js"></script>
<script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/MochiKit/Base.js"></script>
<script type="text/javascript" src="/MochiKit/Iter.js"></script>
<script type="text/javascript" src="/MochiKit/DOM.js"></script>
<script type="text/javascript" src="/MochiKit/Async.js"></script>
<script type="text/javascript" src="/MochiKit/Style.js"></script>
<script type="text/javascript" src="/MochiKit/Color.js"></script>
<script type="text/javascript" src="/MochiKit/Signal.js"></script>
<script type="text/javascript" src="/MochiKit/New.js"></script>
<script type="text/javascript" src="/MochiKit/Visual.js"></script>
<script type="text/javascript" src="../SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
<link rel="stylesheet" type="text/css" href="../SimpleTest/test.css">
<style type="text/css">
#elt1, #elt2, #ctn1 {
visibility: hidden;