зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
646ef36184
Коммит
23ba5ce55d
|
@ -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);
|
||||
}
|
|
@ -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('"','"') + '"';
|
||||
}
|
||||
}
|
||||
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"}," "));
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче