aboutsummaryrefslogtreecommitdiff
path: root/src/boot
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-09-16 00:26:19 -0700
committerGraydon Hoare <[email protected]>2010-09-16 00:26:19 -0700
commit91b4a0c9f8ba7be56fc098ffc6182a888e3970bf (patch)
tree4e56c4dc3626d03026dd32c2079d9afad8140832 /src/boot
parentAdd Peter Hull's contributed translation of the fasta shootout benchmark (int... (diff)
downloadrust-91b4a0c9f8ba7be56fc098ffc6182a888e3970bf.tar.xz
rust-91b4a0c9f8ba7be56fc098ffc6182a888e3970bf.zip
Add beginnings of a fuzzer to rustboot.
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/driver/main.ml10
-rw-r--r--src/boot/driver/session.ml1
-rw-r--r--src/boot/fe/fuzz.ml166
3 files changed, 177 insertions, 0 deletions
diff --git a/src/boot/driver/main.ml b/src/boot/driver/main.ml
index 8f686522..32c70be6 100644
--- a/src/boot/driver/main.ml
+++ b/src/boot/driver/main.ml
@@ -60,6 +60,7 @@ let (sess:Session.sess) =
Session.sess_report_gc = false;
Session.sess_report_deps = false;
Session.sess_next_crate_id = 0;
+ Session.sess_fuzz_item_count = 5;
Session.sess_timings = Hashtbl.create 0;
Session.sess_lib_dirs = Queue.create ();
Session.sess_crate_meta = Hashtbl.create 0;
@@ -219,6 +220,15 @@ let argspecs =
(flag (fun _ -> sess.Session.sess_use_pexps <- true)
"-pexp" "use pexp portion of AST");
+ ("-zc", Arg.Int (fun i -> sess.Session.sess_fuzz_item_count <- i),
+ "count of items to generate when fuzzing");
+
+ ("-zs", Arg.Int (fun i -> Fuzz.fuzz (Some i) sess),
+ "run fuzzer with given seed");
+
+ (flag (fun _ -> Fuzz.fuzz None sess)
+ "-z" "run fuzzer with random seed")
+
] @ (Glue.alt_argspecs sess)
;;
diff --git a/src/boot/driver/session.ml b/src/boot/driver/session.ml
index f8e79fe2..beb551bb 100644
--- a/src/boot/driver/session.ml
+++ b/src/boot/driver/session.ml
@@ -45,6 +45,7 @@ type sess =
mutable sess_report_gc: bool;
mutable sess_report_deps: bool;
mutable sess_next_crate_id: int;
+ mutable sess_fuzz_item_count: int;
sess_timings: (string, float) Hashtbl.t;
sess_spans: (node_id,span) Hashtbl.t;
sess_lib_dirs: filename Queue.t;
diff --git a/src/boot/fe/fuzz.ml b/src/boot/fe/fuzz.ml
new file mode 100644
index 00000000..47a708dc
--- /dev/null
+++ b/src/boot/fe/fuzz.ml
@@ -0,0 +1,166 @@
+open Common;;
+open Ast;;
+
+let ident_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";;
+let digit_chars = "1234567890";;
+
+type scope =
+ SCOPE_crate of crate
+ | SCOPE_mod_item of (ident * mod_item)
+ | SCOPE_block of block
+ | SCOPE_anon
+;;
+
+type ctxt =
+ {
+ ctxt_scopes: scope Stack.t;
+ ctxt_node_counter: int ref;
+ ctxt_sess: Session.sess;
+ }
+
+let generate_ident _ : ident =
+ let char n =
+ if n = 0
+ then '_'
+ else ident_chars.[Random.int (String.length ident_chars)]
+ in
+ let i = 3 + (Random.int 10) in
+ let s = String.create i in
+ for j = 0 to (i-1)
+ do
+ s.[j] <- char j
+ done;
+ s
+;;
+
+let wrap (n:'a) (cx:ctxt) : 'a identified =
+ incr cx.ctxt_node_counter;
+ { node = n; id = Node (!(cx.ctxt_node_counter)) }
+;;
+
+let generate_in (scope:scope) (fn:(ctxt -> 'a)) (cx:ctxt) : 'a =
+ Stack.push scope cx.ctxt_scopes;
+ let x = fn cx in
+ ignore (Stack.pop cx.ctxt_scopes);
+ x
+;;
+
+let generate_some (fn:(ctxt -> 'a)) (cx:ctxt) : 'a array =
+ let root_count = cx.ctxt_sess.Session.sess_fuzz_item_count in
+ let depth = Stack.length cx.ctxt_scopes in
+ if depth >= root_count
+ then [| |]
+ else
+ Array.init (1 + (Random.int (root_count - depth)))
+ (fun _ -> fn cx)
+;;
+
+let rec generate_ty (cx:ctxt) : ty =
+ let subty _ =
+ generate_in SCOPE_anon
+ generate_ty cx
+ in
+ match Random.int (if Random.bool() then 10 else 17) with
+ 0 -> TY_nil
+ | 1 -> TY_bool
+
+ | 2 -> TY_mach TY_u8
+ | 3 -> TY_mach TY_u32
+
+ | 4 -> TY_mach TY_i8
+ | 5 -> TY_mach TY_i32
+
+ | 6 -> TY_int
+ | 7 -> TY_uint
+ | 8 -> TY_char
+ | 9 -> TY_str
+
+ | 10 -> TY_tup (generate_in SCOPE_anon
+ (generate_some
+ generate_ty) cx)
+ | 11 -> TY_vec (subty())
+ | 12 ->
+ let generate_elt cx =
+ (generate_ident cx, generate_ty cx)
+ in
+ TY_rec (generate_in SCOPE_anon
+ (generate_some generate_elt) cx)
+
+ | 13 -> TY_chan (subty())
+ | 14 -> TY_port (subty())
+
+ | 15 -> TY_task
+
+ | _ -> TY_box (subty())
+;;
+
+
+let rec generate_mod_item (mis:mod_items) (cx:ctxt) : unit =
+ let ident = generate_ident () in
+ let decl i = wrap { decl_item = i;
+ decl_params = [| |] } cx
+ in
+ let item =
+ match Random.int 2 with
+ 0 ->
+ let ty = generate_ty cx in
+ let eff = PURE in
+ decl (MOD_ITEM_type (eff, ty))
+ | _ ->
+ let mis' = Hashtbl.create 0 in
+ let view = { view_imports = Hashtbl.create 0;
+ view_exports = Hashtbl.create 0; }
+ in
+ let item =
+ decl (MOD_ITEM_mod (view, mis'))
+ in
+ let scope =
+ SCOPE_mod_item (ident, item)
+ in
+ ignore
+ (generate_in scope
+ (generate_some (generate_mod_item mis'))
+ cx);
+ item
+ in
+ Hashtbl.add mis ident item
+;;
+
+let fuzz (seed:int option) (sess:Session.sess) : unit =
+ begin
+ match seed with
+ None -> Random.self_init ()
+ | Some s -> Random.init s
+ end;
+ let filename =
+ match sess.Session.sess_out with
+ Some o -> o
+ | None ->
+ match seed with
+ None -> "fuzz.rs"
+ | Some seed -> "fuzz-" ^ (string_of_int seed) ^ ".rs"
+ in
+ let out = open_out_bin filename in
+ let ff = Format.formatter_of_out_channel out in
+ let cx = { ctxt_scopes = Stack.create ();
+ ctxt_node_counter = ref 0;
+ ctxt_sess = sess }
+ in
+ let mis = Hashtbl.create 0 in
+ ignore (generate_some
+ (generate_mod_item mis) cx);
+ fmt_mod_items ff mis;
+ Format.pp_print_flush ff ();
+ close_out out;
+ exit 0
+;;
+
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)