Add basic content test framework.

This commit is contained in:
Josh Matthews 2012-09-29 17:49:43 -04:00
parent 006f5be58f
commit 27ccaa80be
10 changed files with 137 additions and 5 deletions

View file

@ -20,7 +20,10 @@ $(eval $(call DEF_SUBMODULE_TEST_RULES,$(submodule))))
servo-test: $(DEPS_servo) servo-test: $(DEPS_servo)
$(CFG_RUSTC) $(RFLAGS_servo) --test -o $@ $< $(CFG_RUSTC) $(RFLAGS_servo) --test -o $@ $<
reftest: src/reftest/reftest.rs servo reftest: $(S)src/reftest/reftest.rs servo
$(CFG_RUSTC) $(RFLAGS_servo) -o $@ $< -L .
contenttest: $(S)src/contenttest/contenttest.rs servo
$(CFG_RUSTC) $(RFLAGS_servo) -o $@ $< -L . $(CFG_RUSTC) $(RFLAGS_servo) -o $@ $< -L .
.PHONY: check $(DEPS_CHECK) .PHONY: check $(DEPS_CHECK)
@ -31,5 +34,7 @@ check-servo: servo-test
./servo-test $(TESTNAME) ./servo-test $(TESTNAME)
check-ref: reftest check-ref: reftest
./reftest --source-dir=$(VPATH)/src/test/ref --work-dir=src/test/ref $(TESTNAME) ./reftest --source-dir=$(VPATH)/test/ref --work-dir=src/test/ref $(TESTNAME)
check-content: contenttest
./contenttest --source-dir=$(VPATH)/test/content $(TESTNAME)

View file

@ -0,0 +1,73 @@
extern mod std;
use std::test::{TestOpts, run_tests_console, TestDesc};
use std::getopts::{getopts, reqopt, opt_str, fail_str};
use os::list_dir_path;
struct Config {
source_dir: ~str,
filter: Option<~str>
}
fn main(args: ~[~str]) {
let config = parse_config(args);
let opts = test_options(config);
let tests = find_tests(config);
run_tests_console(&opts, tests);
}
fn parse_config(args: ~[~str]) -> Config {
let args = args.tail();
let opts = ~[reqopt(~"source-dir")];
let matches = match getopts(args, opts) {
Ok(m) => m,
Err(f) => fail fail_str(f)
};
Config {
source_dir: opt_str(matches, ~"source-dir"),
filter: if matches.free.is_empty() {
None
} else {
Some(matches.free.head())
}
}
}
fn test_options(config: Config) -> TestOpts {
{
filter: config.filter,
run_ignored: false,
logfile: None
}
}
fn find_tests(config: Config) -> ~[TestDesc] {
let all_files = list_dir_path(&Path(config.source_dir));
let html_files = all_files.filter( |file| file.to_str().ends_with(".html") );
return html_files.map(|file| make_test(config, (*file).to_str()) );
}
fn make_test(config: Config, file: ~str) -> TestDesc {
{
name: file,
testfn: fn~() { run_test(config, file) },
ignore: false,
should_fail: false
}
}
fn run_test(config: Config, file: ~str) {
let infile = ~"file://" + os::make_absolute(&Path(file)).to_str();
let res = run::program_output("./servo", ~[infile]);
io::print(res.out);
do str::split_char_each(res.out, '\n') |line| {
if line.contains("TEST-UNEXPECTED-FAIL") {
fail str::from_slice(line);
}
true
}
}
fn render_servo(config: Config, file: ~str) {
}

View file

@ -51,7 +51,7 @@ use ptr::null;
enum ControlMsg { enum ControlMsg {
ParseMsg(Url), ParseMsg(Url),
ExecuteMsg(Url), ExecuteMsg(Url),
Timer(~dom::base::TimerData), Timer(~dom::window::TimerData),
ExitMsg ExitMsg
} }

View file

@ -45,6 +45,12 @@ extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool unsafe
return 1; return 1;
} }
extern fn close(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool unsafe {
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.close();
JS_SET_RVAL(cx, vp, JSVAL_NULL);
return 1;
}
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> { unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
let val = JS_GetReservedSlot(obj, 0); let val = JS_GetReservedSlot(obj, 0);
cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val)) cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val))
@ -76,6 +82,11 @@ fn init(compartment: bare_compartment, win: @Window) {
call: {op: setTimeout, info: null()}, call: {op: setTimeout, info: null()},
nargs: 2, nargs: 2,
flags: 0, flags: 0,
selfHostedName: null()},
{name: compartment.add_name(~"close"),
call: {op: close, info: null()},
nargs: 2,
flags: 0,
selfHostedName: null()}]; selfHostedName: null()}];
vec::as_imm_buf(methods, |fns, _len| { vec::as_imm_buf(methods, |fns, _len| {

View file

@ -1,9 +1,12 @@
use comm::{Port, Chan}; use comm::{Port, Chan};
use content::content_task::{ControlMsg, Timer}; use content::content_task::{ControlMsg, Timer, ExitMsg};
use js::jsapi::jsval;
use dvec::DVec;
enum TimerControlMsg { enum TimerControlMsg {
TimerMessage_Fire(~TimerData), TimerMessage_Fire(~TimerData),
TimerMessage_Close TimerMessage_Close,
TimerMessage_TriggerExit //XXXjdm this is just a quick hack to talk to the content task
} }
struct Window { struct Window {
@ -43,6 +46,10 @@ impl Window {
io::println(#fmt("ALERT: %s", s)); io::println(#fmt("ALERT: %s", s));
} }
fn close() {
self.timer_chan.send(TimerMessage_TriggerExit);
}
fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *jsval) { fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *jsval) {
let timeout = int::max(0, timeout) as uint; let timeout = int::max(0, timeout) as uint;
@ -65,6 +72,7 @@ fn Window(content_port: Port<ControlMsg>) -> Window {
TimerMessage_Fire(td) => { TimerMessage_Fire(td) => {
content_chan.send(Timer(copy td)); content_chan.send(Timer(copy td));
} }
TimerMessage_TriggerExit => content_chan.send(ExitMsg)
} }
} }
} }

View file

@ -0,0 +1,16 @@
function _fail(s) {
window.alert("TEST-UNEXPECTED-FAIL | " + s);
}
function _pass(s) {
window.alert("TEST-PASS | " + s);
}
function is(a, b) {
let f = a != b ? _fail : _pass;
f(a + " == " + b);
}
function finish() {
window.close();
}

View file

@ -0,0 +1,8 @@
<html>
<head>
<script src="harness.js"></script>
</head>
<body>
<script src="test_prototypes.js"></script>
</body>
</html>

View file

@ -0,0 +1,7 @@
is(HTMLImageElement instanceof HTMLElement, true);
is(HTMLElement instanceof Element, true);
is(Element instanceof Node, true);
is(document instanceof Document, true);
is(document.documentElement instanceof HTMLElement, true);
is(document.documentElement instanceof Element, true);
finish();

3
src/test/test_close.html Normal file
View file

@ -0,0 +1,3 @@
<html>
<script src="test_close.js"></script>
</html>

1
src/test/test_close.js Normal file
View file

@ -0,0 +1 @@
window.setTimeout(function() { window.close(); }, 3000);