]> git.lizzy.rs Git - rust.git/blob - src/fuzzer/ivec_fuzz.rs
Type-parameterize ivec_fuzz
[rust.git] / src / fuzzer / ivec_fuzz.rs
1 /*
2
3 Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
4
5   two functions, "return all edits" and "return a random edit" <-- leaning toward this model
6     or
7   two functions, "return the number of possible edits" and "return edit #n"
8
9 It would be nice if this could be data-driven, so the two functions could share information:
10   type vec_modifier = rec(fn (&T[] v, uint i) -> T[] fun, uint lo, uint di);
11   const vec_modifier[] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
12 But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
13 https://github.com/graydon/rust/issues/570
14
15 vec_edits is not an iter because iters might go away and:
16 https://github.com/graydon/rust/issues/639
17
18 vec_omit and friends are not type-parameterized because:
19 https://github.com/graydon/rust/issues/640
20
21 */
22
23 use std;
24 import std::ivec;
25 import std::ivec::slice;
26 import std::ivec::len;
27 import std::int;
28
29 //fn vec_reverse(&T[] v) -> T[] { ... }
30
31 fn vec_omit   [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) +                      slice(v, i+1u, len(v)) }
32 fn vec_dup    [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) + ~[v.(i)]           + slice(v, i,    len(v)) }
33 fn vec_swadj  [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) + ~[v.(i+1u), v.(i)] + slice(v, i+2u, len(v)) }
34 fn vec_prefix [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) }
35 fn vec_suffix [T] (&T[] v, uint i) -> T[] { slice(v, i, len(v)) }
36
37 fn vec_poke   [T] (&T[] v, uint i, &T x) -> T[] { slice(v, 0u, i) + ~[x] + slice(v, i+1u, len(v)) }
38 fn vec_insert [T] (&T[] v, uint i, &T x) -> T[] { slice(v, 0u, i) + ~[x] + slice(v, i, len(v)) }
39
40 // Iterates over 0...length, skipping the specified number on each side.
41 iter ix(uint skip_low, uint skip_high, uint length) -> uint { let uint i = skip_low; while (i + skip_high <= length) { put i; i += 1u; } }
42
43 // Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
44 fn vec_edits[T](&T[] v, &T[] xs) -> T[][] {
45     let T[][] edits = ~[];
46     let uint Lv = len(v);
47
48     if (Lv != 1u) { edits += ~[~[]]; } // When Lv == 1u, this is redundant with omit
49     //if (Lv >= 3u) { edits += ~[vec_reverse(v)]; }
50
51     for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_omit  (v, i)]; }
52     for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_dup   (v, i)]; }
53     for each (uint i in ix(0u, 2u, Lv)) { edits += ~[vec_swadj (v, i)]; }
54     for each (uint i in ix(1u, 2u, Lv)) { edits += ~[vec_prefix(v, i)]; }
55     for each (uint i in ix(2u, 1u, Lv)) { edits += ~[vec_suffix(v, i)]; }
56
57     for each (uint j in ix(0u, 1u, len(xs))) {
58         for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_poke  (v, i, xs.(j))]; }
59         for each (uint i in ix(0u, 0u, Lv)) { edits += ~[vec_insert(v, i, xs.(j))]; }
60     }
61
62     edits
63 }
64
65 // Would be nice if this were built in: https://github.com/graydon/rust/issues/424
66 fn vec_to_str(&int[] v) -> str {
67     auto i = 0u;
68     auto s = "[";
69     while (i < len(v)) {
70         s += int::str(v.(i));
71         if (i + 1u < len(v)) {
72             s += ", "
73         }
74         i += 1u;
75     }
76     ret s + "]";
77 }
78
79 fn show_edits(&int[] a, &int[] xs) {
80     log_err "=== Edits of " + vec_to_str(a) + " ===";
81     auto b = vec_edits(a, xs);
82     for each (uint i in ix(0u, 1u, len(b))) {
83         log_err vec_to_str(b.(i));
84     }
85 }
86
87 fn demo_edits() {
88     auto xs = ~[7, 8];
89     show_edits(~[], xs);
90     show_edits(~[1], xs);
91     show_edits(~[1,2], xs);
92     show_edits(~[1,2,3], xs);
93     show_edits(~[1,2,3,4], xs);
94 }
95
96 fn main() {
97     demo_edits();
98 }