1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(collections)]
#![feature(exit_status)]
#![feature(path)]
#![feature(rustc_private)]
#![feature(std_misc)]
#![feature(test)]
extern crate getopts;
extern crate test;
use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName};
use test::ShouldPanic;
use getopts::{getopts, reqopt};
use std::{str, env};
use std::ffi::OsStr;
use std::fs::read_dir;
use std::process::{Command, Stdio};
use std::thunk::Thunk;
#[derive(Clone)]
struct Config {
source_dir: String,
filter: Option<String>
}
fn main() {
let args = env::args();
let config = parse_config(args.collect());
let opts = test_options(config.clone());
let tests = find_tests(config);
match run_tests_console(&opts, tests) {
Ok(false) => env::set_exit_status(1), // tests failed
Err(_) => env::set_exit_status(2), // I/O-related failure
_ => (),
}
}
fn parse_config(args: Vec<String>) -> Config {
let args = args.tail();
let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir"));
let matches = match getopts(args, &opts) {
Ok(m) => m,
Err(f) => panic!(f.to_string())
};
Config {
source_dir: matches.opt_str("source-dir").unwrap(),
filter: matches.free.first().map(|s| s.clone())
}
}
fn test_options(config: Config) -> TestOpts {
TestOpts {
filter: config.filter,
run_ignored: false,
run_tests: true,
run_benchmarks: false,
logfile: None,
nocapture: false,
color: AutoColor,
}
}
fn find_tests(config: Config) -> Vec<TestDescAndFn> {
read_dir(&config.source_dir)
.ok()
.expect("Error reading directory.")
.filter_map(Result::ok)
.map(|e| e.path())
.filter(|file| file.extension().map_or(false, |e| e == OsStr::from_str("html")))
.map(|file| make_test(file.display().to_string()))
.collect()
}
fn make_test(file: String) -> TestDescAndFn {
TestDescAndFn {
desc: TestDesc {
name: DynTestName(file.clone()),
ignore: false,
should_panic: ShouldPanic::No,
},
testfn: DynTestFn(Thunk::new(move || { run_test(file) }))
}
}
fn run_test(file: String) {
let path = env::current_dir().unwrap().join(&file);
// FIXME (#1094): not the right way to transform a path
let infile = format!("file://{}", path.display());
let args = ["-z", "-f", &*infile];
let mut prc_arg = env::current_exe().unwrap();
let prc_arg = match prc_arg.pop() {
true => prc_arg.join("servo"),
_ => panic!("could not pop directory"),
};
let output = match Command::new(prc_arg.to_str().unwrap())
.args(&args)
.stdin(Stdio::null())
.stderr(Stdio::inherit())
.output()
{
Ok(p) => p,
_ => panic!("Unable to spawn process."),
};
print!("{}", str::from_utf8(&output.stdout).unwrap());
let out = str::from_utf8(&output.stderr);
let lines: Vec<&str> = out.unwrap().split('\n').collect();
for &line in lines.iter() {
if line.contains("TEST-UNEXPECTED-FAIL") {
panic!(line.to_string());
}
}
if !output.status.success() {
panic!("Servo exited with non-zero status {:?}", output.status);
}
}
|