1
Fork 0

use find not echo; this also brings fuzzer under the iron fist of tidy.py!

This commit is contained in:
Niko Matsakis 2012-04-13 11:59:17 -07:00
parent 27f1c2b742
commit d2482fd763
7 changed files with 94 additions and 76 deletions

View file

@ -2,11 +2,6 @@
# Testing variables # Testing variables
###################################################################### ######################################################################
SOME_TEST_INPUTS = $(wildcard $(S)src/test/*/*.rs)
SOME_MOAR_TEST_INPUTS = $(wildcard $(S)src/test/*/*/*.rs \
$(S)src/test/*/*.rc)
RPASS_RC := $(wildcard $(S)src/test/run-pass/*.rc) RPASS_RC := $(wildcard $(S)src/test/run-pass/*.rc)
RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs) RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
RFAIL_RC := $(wildcard $(S)src/test/run-fail/*.rc) RFAIL_RC := $(wildcard $(S)src/test/run-fail/*.rc)
@ -124,34 +119,13 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \
tidy: tidy:
@$(call E, check: formatting) @$(call E, check: formatting)
$(Q)echo \ $(Q)find $(S)src -name '*.r[sc]' \
$(wildcard $(S)src/etc/*.py) \
$(COMPILER_CRATE) \
$(COMPILER_INPUTS) \
$(LIBRUSTSYNTAX_CRATE) \
$(LIBRUSTSYNTAX_INPUTS) \
$(CORELIB_CRATE) \
$(CORELIB_INPUTS) \
| xargs -n 10 python $(S)src/etc/tidy.py | xargs -n 10 python $(S)src/etc/tidy.py
$(Q)echo \ $(Q)find $(S)src/etc -name '*.py' \
$(STDLIB_CRATE) \
$(STDLIB_INPUTS) \
$(COMPILETEST_CRATE) \
$(COMPILETEST_INPUTS) \
$(CARGO_CRATE) \
$(CARGO_INPUTS) \
$(RUSTDOC_CRATE) \
$(RUSTDOC_INPUTS) \
| xargs -n 10 python $(S)src/etc/tidy.py | xargs -n 10 python $(S)src/etc/tidy.py
$(Q)echo \ $(Q)echo $(ALL_CS) \
$(SOME_TEST_INPUTS) \
| xargs -n 10 python $(S)src/etc/tidy.py | xargs -n 10 python $(S)src/etc/tidy.py
$(Q)echo \ $(Q)echo $(ALL_HS) \
$(SOME_MOAR_TEST_INPUTS) \
| xargs -n 10 python $(S)src/etc/tidy.py
$(Q)echo \
$(ALL_CS) \
$(ALL_HS) \
| xargs -n 10 python $(S)src/etc/tidy.py | xargs -n 10 python $(S)src/etc/tidy.py
endif endif

View file

@ -1,7 +1,8 @@
use std; use std;
import vec; import vec;
fn vec_equal<T>(v: [T], u: [T], element_equality_test: fn@(&&T, &&T) -> bool) -> fn vec_equal<T>(v: [T], u: [T],
element_equality_test: fn@(&&T, &&T) -> bool) ->
bool { bool {
let Lv = vec::len(v); let Lv = vec::len(v);
if Lv != vec::len(u) { ret false; } if Lv != vec::len(u) { ret false; }

View file

@ -3,10 +3,14 @@ import std::rand;
import uint::range; import uint::range;
// random uint less than n // random uint less than n
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n } fn under(r : rand::rng, n : uint) -> uint {
assert n != 0u; r.next() as uint % n
}
// random choice from a vec // random choice from a vec
fn choice<T: copy>(r : rand::rng, v : [const T]) -> T { assert vec::len(v) != 0u; v[under(r, vec::len(v))] } fn choice<T: copy>(r : rand::rng, v : [const T]) -> T {
assert vec::len(v) != 0u; v[under(r, vec::len(v))]
}
// k in n chance of being true // k in n chance of being true
fn likelihood(r : rand::rng, k : uint, n : uint) -> bool { under(r, n) < k } fn likelihood(r : rand::rng, k : uint, n : uint) -> bool { under(r, n) < k }
@ -68,7 +72,8 @@ fn test_cycles(r : rand::rng, k: uint, n: uint)
if (likelihood(r, k, n)) { v[i].c = @p(choice(r, v)); } if (likelihood(r, k, n)) { v[i].c = @p(choice(r, v)); }
if (likelihood(r, k, n)) { v[i].f = bind nopP(choice(r, v)); } if (likelihood(r, k, n)) { v[i].f = bind nopP(choice(r, v)); }
//if (false) { v[i].g = bind (fn~(_x: @pointy) { })(choice(r, v)); } //if (false) { v[i].g = bind (fn~(_x: @pointy) { })(
// choice(r, v)); }
// https://github.com/mozilla/rust/issues/1899 // https://github.com/mozilla/rust/issues/1899
if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; } if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; }

View file

@ -44,7 +44,8 @@ fn common_exprs() -> [ast::expr] {
[dse(ast::expr_break), [dse(ast::expr_break),
dse(ast::expr_cont), dse(ast::expr_cont),
dse(ast::expr_fail(option::none)), dse(ast::expr_fail(option::none)),
dse(ast::expr_fail(option::some(@dse(ast::expr_lit(@dsl(ast::lit_str("boo"))))))), dse(ast::expr_fail(option::some(
@dse(ast::expr_lit(@dsl(ast::lit_str("boo"))))))),
dse(ast::expr_ret(option::none)), dse(ast::expr_ret(option::none)),
dse(ast::expr_lit(@dsl(ast::lit_nil))), dse(ast::expr_lit(@dsl(ast::lit_nil))),
dse(ast::expr_lit(@dsl(ast::lit_bool(false)))), dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
@ -64,9 +65,9 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
alt tm { alt tm {
tm_converge { tm_converge {
alt e.node { alt e.node {
// If the fuzzer moves a block-ending-in-semicolon into callee position, // If the fuzzer moves a block-ending-in-semicolon into callee
// the pretty-printer can't preserve this even by parenthesizing!! // position, the pretty-printer can't preserve this even by
// See email to marijn. // parenthesizing!! See email to marijn.
ast::expr_if(_, _, _) { false } ast::expr_if(_, _, _) { false }
ast::expr_if_check(_, _, _) { false } ast::expr_if_check(_, _, _) { false }
ast::expr_block(_) { false } ast::expr_block(_) { false }
@ -166,18 +167,21 @@ fn safe_to_replace_expr(e: ast::expr_, _tm: test_mode) -> bool {
fn safe_to_replace_ty(t: ast::ty_, _tm: test_mode) -> bool { fn safe_to_replace_ty(t: ast::ty_, _tm: test_mode) -> bool {
alt t { alt t {
ast::ty_infer { false } // always implicit, always top level ast::ty_infer { false } // always implicit, always top level
ast::ty_bot { false } // in source, can only appear as the out type of a function ast::ty_bot { false } // in source, can only appear
// as the out type of a function
ast::ty_mac(_) { false } ast::ty_mac(_) { false }
_ { true } _ { true }
} }
} }
// Replace the |i|th expr (in fold order) of |crate| with |newexpr|. // Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: test_mode) -> fn replace_expr_in_crate(crate: ast::crate, i: uint,
newexpr: ast::expr, tm: test_mode) ->
ast::crate { ast::crate {
let j: @mut uint = @mut 0u; let j: @mut uint = @mut 0u;
fn fold_expr_rep(j_: @mut uint, i_: uint, newexpr_: ast::expr_, fn fold_expr_rep(j_: @mut uint, i_: uint, newexpr_: ast::expr_,
original: ast::expr_, fld: fold::ast_fold, tm_: test_mode) -> original: ast::expr_, fld: fold::ast_fold,
tm_: test_mode) ->
ast::expr_ { ast::expr_ {
*j_ += 1u; *j_ += 1u;
if i_ + 1u == *j_ && safe_to_replace_expr(original, tm_) { if i_ + 1u == *j_ && safe_to_replace_expr(original, tm_) {
@ -187,8 +191,9 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: tes
} }
} }
let afp = let afp =
{fold_expr: fold::wrap(bind fold_expr_rep(j, i, newexpr.node, _, _, tm)) {fold_expr: fold::wrap(bind fold_expr_rep(j, i,
with *fold::default_ast_fold()}; newexpr.node, _, _, tm))
with *fold::default_ast_fold()};
let af = fold::make_fold(afp); let af = fold::make_fold(afp);
let crate2: @ast::crate = @af.fold_crate(crate); let crate2: @ast::crate = @af.fold_crate(crate);
*crate2 *crate2
@ -196,11 +201,12 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, newexpr: ast::expr, tm: tes
// Replace the |i|th ty (in fold order) of |crate| with |newty|. // Replace the |i|th ty (in fold order) of |crate| with |newty|.
fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty, tm: test_mode) -> fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::ty,
ast::crate { tm: test_mode) -> ast::crate {
let j: @mut uint = @mut 0u; let j: @mut uint = @mut 0u;
fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_, fn fold_ty_rep(j_: @mut uint, i_: uint, newty_: ast::ty_,
original: ast::ty_, fld: fold::ast_fold, tm_: test_mode) -> original: ast::ty_, fld: fold::ast_fold,
tm_: test_mode) ->
ast::ty_ { ast::ty_ {
*j_ += 1u; *j_ += 1u;
if i_ + 1u == *j_ && safe_to_replace_ty(original, tm_) { if i_ + 1u == *j_ && safe_to_replace_ty(original, tm_) {
@ -233,8 +239,11 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
let stolen = steal(crate, cx.mode); let stolen = steal(crate, cx.mode);
let extra_exprs = vec::filter(common_exprs(), let extra_exprs = vec::filter(common_exprs(),
bind safe_to_use_expr(_, cx.mode)); bind safe_to_use_expr(_, cx.mode));
check_variants_T(crate, codemap, filename, "expr", extra_exprs + stolen.exprs, pprust::expr_to_str, replace_expr_in_crate, cx); check_variants_T(crate, codemap, filename, "expr",
check_variants_T(crate, codemap, filename, "ty", stolen.tys, pprust::ty_to_str, replace_ty_in_crate, cx); extra_exprs + stolen.exprs, pprust::expr_to_str,
replace_expr_in_crate, cx);
check_variants_T(crate, codemap, filename, "ty", stolen.tys,
pprust::ty_to_str, replace_ty_in_crate, cx);
} }
fn check_variants_T<T: copy>( fn check_variants_T<T: copy>(
@ -247,7 +256,8 @@ fn check_variants_T<T: copy>(
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate, replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
cx: context cx: context
) { ) {
#error("%s contains %u %s objects", filename, vec::len(things), thing_label); #error("%s contains %u %s objects", filename,
vec::len(things), thing_label);
let L = vec::len(things); let L = vec::len(things);
@ -257,8 +267,8 @@ fn check_variants_T<T: copy>(
under(uint::min(L, 30u)) {|j| under(uint::min(L, 30u)) {|j|
log(error, "With... " + stringifier(@things[j])); log(error, "With... " + stringifier(@things[j]));
let crate2 = @replacer(crate, i, things[j], cx.mode); let crate2 = @replacer(crate, i, things[j], cx.mode);
// It would be best to test the *crate* for stability, but testing the // It would be best to test the *crate* for stability, but
// string for stability is easier and ok for now. // testing the string for stability is easier and ok for now.
let handler = diagnostic::mk_handler(none); let handler = diagnostic::mk_handler(none);
let str3 = let str3 =
@as_str(bind pprust::print_crate( @as_str(bind pprust::print_crate(
@ -273,8 +283,11 @@ fn check_variants_T<T: copy>(
check_roundtrip_convergence(str3, 1u); check_roundtrip_convergence(str3, 1u);
} }
tm_run { tm_run {
let file_label = #fmt("rusttmp/%s_%s_%u_%u", last_part(filename), thing_label, i, j); let file_label = #fmt("rusttmp/%s_%s_%u_%u",
let safe_to_run = !(content_is_dangerous_to_run(*str3) || has_raw_pointers(*crate2)); last_part(filename),
thing_label, i, j);
let safe_to_run = !(content_is_dangerous_to_run(*str3)
|| has_raw_pointers(*crate2));
check_whole_compiler(*str3, file_label, safe_to_run); check_whole_compiler(*str3, file_label, safe_to_run);
} }
} }
@ -292,9 +305,11 @@ enum happiness { passed, cleanly_rejected(str), known_bug(str), failed(str), }
// We'd find more bugs if we could take an AST here, but // We'd find more bugs if we could take an AST here, but
// - that would find many "false positives" or unimportant bugs // - that would find many "false positives" or unimportant bugs
// - that would be tricky, requiring use of tasks or serialization or randomness. // - that would be tricky, requiring use of tasks or serialization
// or randomness.
// This seems to find plenty of bugs as it is :) // This seems to find plenty of bugs as it is :)
fn check_whole_compiler(code: str, suggested_filename_prefix: str, allow_running: bool) { fn check_whole_compiler(code: str, suggested_filename_prefix: str,
allow_running: bool) {
let filename = suggested_filename_prefix + ".rs"; let filename = suggested_filename_prefix + ".rs";
write_file(filename, code); write_file(filename, code);
@ -331,7 +346,9 @@ fn removeDirIfExists(filename: str) {
} }
fn check_running(exe_filename: str) -> happiness { fn check_running(exe_filename: str) -> happiness {
let p = run::program_output("/Users/jruderman/scripts/timed_run_rust_program.py", [exe_filename]); let p = run::program_output(
"/Users/jruderman/scripts/timed_run_rust_program.py",
[exe_filename]);
let comb = p.out + "\n" + p.err; let comb = p.out + "\n" + p.err;
if str::len(comb) > 1u { if str::len(comb) > 1u {
log(error, "comb comb comb: " + comb); log(error, "comb comb comb: " + comb);
@ -352,17 +369,26 @@ fn check_running(exe_filename: str) -> happiness {
0 { passed } 0 { passed }
100 { cleanly_rejected("running: explicit fail") } 100 { cleanly_rejected("running: explicit fail") }
101 | 247 { cleanly_rejected("running: timed out") } 101 | 247 { cleanly_rejected("running: timed out") }
245 | 246 | 138 | 252 { known_bug("https://github.com/mozilla/rust/issues/1466") } 245 | 246 | 138 | 252 {
136 | 248 { known_bug("SIGFPE - https://github.com/mozilla/rust/issues/944") } known_bug("https://github.com/mozilla/rust/issues/1466")
rc { failed("Rust program ran but exited with status " + int::str(rc)) } }
136 | 248 {
known_bug(
"SIGFPE - https://github.com/mozilla/rust/issues/944")
}
rc {
failed("Rust program ran but exited with status " +
int::str(rc))
}
} }
} }
} }
fn check_compiling(filename: str) -> happiness { fn check_compiling(filename: str) -> happiness {
let p = run::program_output( let p = run::program_output(
"/Users/jruderman/code/rust/build/x86_64-apple-darwin/stage1/bin/rustc", "/Users/jruderman/code/rust/build/x86_64-apple-darwin/\
[filename]); stage1/bin/rustc",
[filename]);
//#error("Status: %d", p.status); //#error("Status: %d", p.status);
if p.status == 0 { if p.status == 0 {
@ -454,10 +480,11 @@ fn content_might_not_converge(code: str) -> bool {
let confusing_patterns = let confusing_patterns =
["xfail-test", ["xfail-test",
"xfail-pretty", "xfail-pretty",
"self", // crazy rules enforced by parser rather than typechecker? "self", // crazy rules enforced by parser not typechecker?
"spawn", // precedence issues? "spawn", // precedence issues?
"bind", // precedence issues? "bind", // precedence issues?
" be ", // don't want to replace its child with a non-call: "Non-call expression in tail call" " be ", // don't want to replace its child with a non-call:
// "Non-call expression in tail call"
"\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850 "\n\n\n\n\n" // https://github.com/mozilla/rust/issues/850
]; ];
@ -467,7 +494,8 @@ fn content_might_not_converge(code: str) -> bool {
fn file_might_not_converge(filename: str) -> bool { fn file_might_not_converge(filename: str) -> bool {
let confusing_files = [ let confusing_files = [
"expr-alt.rs", // pretty-printing "(a = b) = c" vs "a = b = c" and wrapping "expr-alt.rs", // pretty-printing "(a = b) = c"
// vs "a = b = c" and wrapping
"block-arg-in-ternary.rs", // wrapping "block-arg-in-ternary.rs", // wrapping
"move-3-unique.rs", // 0 becomes (0), but both seem reasonable. wtf? "move-3-unique.rs", // 0 becomes (0), but both seem reasonable. wtf?
"move-3.rs" // 0 becomes (0), but both seem reasonable. wtf? "move-3.rs" // 0 becomes (0), but both seem reasonable. wtf?
@ -513,7 +541,8 @@ fn check_convergence(files: [str]) {
let s = @result::get(io::read_whole_file_str(file)); let s = @result::get(io::read_whole_file_str(file));
if !content_might_not_converge(*s) { if !content_might_not_converge(*s) {
#error("pp converge: %s", file); #error("pp converge: %s", file);
// Change from 7u to 2u once https://github.com/mozilla/rust/issues/850 is fixed // Change from 7u to 2u once
// https://github.com/mozilla/rust/issues/850 is fixed
check_roundtrip_convergence(s, 7u); check_roundtrip_convergence(s, 7u);
} }
} }
@ -523,7 +552,8 @@ fn check_convergence(files: [str]) {
fn check_variants(files: [str], cx: context) { fn check_variants(files: [str], cx: context) {
for files.each {|file| for files.each {|file|
if cx.mode == tm_converge && file_might_not_converge(file) { if cx.mode == tm_converge && file_might_not_converge(file) {
#error("Skipping convergence test based on file_might_not_converge"); #error("Skipping convergence test based on\
file_might_not_converge");
cont; cont;
} }

View file

@ -2,14 +2,16 @@
Idea: provide functions for 'exhaustive' and 'random' modification of vecs. Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
two functions, "return all edits" and "return a random edit" <-- leaning toward this model two functions, "return all edits" and "return a random edit" <--
or leaning toward this model or two functions, "return the number of
two functions, "return the number of possible edits" and "return edit #n" possible edits" and "return edit #n"
It would be nice if this could be data-driven, so the two functions could share information: It would be nice if this could be data-driven, so the two functions
could share information:
type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di); type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di);
const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...]; const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal". But that gives me "error: internal compiler error unimplemented consts
that's not a plain literal".
https://github.com/graydon/rust/issues/570 https://github.com/graydon/rust/issues/570
vec_edits is not an iter because iters might go away. vec_edits is not an iter because iters might go away.
@ -47,7 +49,8 @@ fn ix(skip_low: uint, skip_high: uint, length: uint, it: block(uint)) {
while i + skip_high <= length { it(i); i += 1u; } while i + skip_high <= length { it(i); i += 1u; }
} }
// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs). // Returns a bunch of modified versions of v, some of which introduce
// new elements (borrowed from xs).
fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] { fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] {
let edits: [[T]] = []; let edits: [[T]] = [];
let Lv: uint = len(v); let Lv: uint = len(v);
@ -78,7 +81,8 @@ fn vec_edits<T: copy>(v: [T], xs: [T]) -> [[T]] {
edits edits
} }
// Would be nice if this were built in: https://github.com/graydon/rust/issues/424 // Would be nice if this were built in:
// https://github.com/graydon/rust/issues/424
fn vec_to_str(v: [int]) -> str { fn vec_to_str(v: [int]) -> str {
let i = 0u; let i = 0u;
let s = "["; let s = "[";

View file

@ -3,10 +3,14 @@ import std::rand;
import vec; import vec;
// random uint less than n // random uint less than n
fn under(r : rand::rng, n : uint) -> uint { assert n != 0u; r.next() as uint % n } fn under(r : rand::rng, n : uint) -> uint {
assert n != 0u; r.next() as uint % n
}
// random choice from a vec // random choice from a vec
fn choice<T: copy>(r : rand::rng, v : [T]) -> T { assert vec::len(v) != 0u; v[under(r, vec::len(v))] } fn choice<T: copy>(r : rand::rng, v : [T]) -> T {
assert vec::len(v) != 0u; v[under(r, vec::len(v))]
}
// 1 in n chance of being true // 1 in n chance of being true
fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u } fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u }

View file

@ -48,7 +48,7 @@ Options:
--out-dir <dir> Write output to compiler-chosen filename in <dir> --out-dir <dir> Write output to compiler-chosen filename in <dir>
--parse-only Parse only; do not compile, assemble, or link --parse-only Parse only; do not compile, assemble, or link
--pretty [type] Pretty-print the input instead of compiling; --pretty [type] Pretty-print the input instead of compiling;
valid types are: normal (un-annotated source), valid types are: normal (un-annotated source),
expanded (crates expanded), typed (crates expanded, expanded (crates expanded), typed (crates expanded,
with type annotations), or identified (fully with type annotations), or identified (fully
parenthesized, AST nodes and blocks with IDs) parenthesized, AST nodes and blocks with IDs)