]>
Commit | Line | Data |
---|---|---|
83c7162d | 1 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
923072b8 FG |
2 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
3 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your | |
83c7162d XL |
4 | // option. This file may not be copied, modified, or distributed |
5 | // except according to those terms. | |
6 | ||
7 | //! A simple fuzz tester for the library. | |
8 | ||
9 | #![deny(warnings)] | |
10 | ||
11 | extern crate rand; | |
12 | extern crate tendril; | |
13 | ||
14 | use std::borrow::ToOwned; | |
15 | ||
83c7162d | 16 | use rand::distributions::{IndependentSample, Range}; |
923072b8 | 17 | use rand::Rng; |
83c7162d XL |
18 | use tendril::StrTendril; |
19 | ||
20 | fn fuzz() { | |
21 | let mut rng = rand::thread_rng(); | |
22 | let capacity = Range::new(0u32, 1 << 14).ind_sample(&mut rng); | |
23 | let mut buf_string = String::with_capacity(capacity as usize); | |
24 | let mut buf_tendril = StrTendril::with_capacity(capacity); | |
25 | let mut string_slices = vec![]; | |
26 | let mut tendril_slices = vec![]; | |
27 | ||
923072b8 | 28 | for _ in 1..100_000 { |
83c7162d XL |
29 | if buf_string.len() > (1 << 30) { |
30 | buf_string.truncate(0); | |
31 | buf_tendril.clear(); | |
32 | } | |
33 | ||
34 | let dist_action = Range::new(0, 100); | |
35 | match dist_action.ind_sample(&mut rng) { | |
923072b8 | 36 | 0..=15 => { |
83c7162d XL |
37 | let (start, end) = random_slice(&mut rng, TEXT); |
38 | let snip = &TEXT[start..end]; | |
39 | buf_string.push_str(snip); | |
40 | buf_tendril.push_slice(snip); | |
41 | assert_eq!(&*buf_string, &*buf_tendril); | |
42 | } | |
43 | ||
923072b8 | 44 | 16..=31 => { |
83c7162d XL |
45 | let (start, end) = random_slice(&mut rng, &buf_string); |
46 | let snip = &buf_string[start..end].to_owned(); | |
47 | buf_string.push_str(&snip); | |
48 | buf_tendril.push_slice(&snip); | |
49 | assert_eq!(&*buf_string, &*buf_tendril); | |
50 | } | |
51 | ||
923072b8 | 52 | 32..=47 => { |
83c7162d XL |
53 | let lenstr = format!("[length = {}]", buf_tendril.len()); |
54 | buf_string.push_str(&lenstr); | |
55 | buf_tendril.push_slice(&lenstr); | |
56 | assert_eq!(&*buf_string, &*buf_tendril); | |
57 | } | |
58 | ||
923072b8 | 59 | 48..=63 => { |
83c7162d XL |
60 | let n = random_boundary(&mut rng, &buf_string); |
61 | buf_tendril.pop_front(n as u32); | |
62 | buf_string = buf_string[n..].to_owned(); | |
63 | assert_eq!(&*buf_string, &*buf_tendril); | |
64 | } | |
65 | ||
923072b8 | 66 | 64..=79 => { |
83c7162d XL |
67 | let new_len = random_boundary(&mut rng, &buf_string); |
68 | let n = buf_string.len() - new_len; | |
69 | buf_string.truncate(new_len); | |
70 | buf_tendril.pop_back(n as u32); | |
71 | assert_eq!(&*buf_string, &*buf_tendril); | |
72 | } | |
73 | ||
923072b8 | 74 | 80..=90 => { |
83c7162d XL |
75 | let (start, end) = random_slice(&mut rng, &buf_string); |
76 | buf_string = buf_string[start..end].to_owned(); | |
77 | buf_tendril = buf_tendril.subtendril(start as u32, (end - start) as u32); | |
78 | assert_eq!(&*buf_string, &*buf_tendril); | |
79 | } | |
80 | ||
923072b8 | 81 | 91..=96 => { |
83c7162d XL |
82 | let c = rng.gen(); |
83 | buf_string.push(c); | |
84 | assert!(buf_tendril.try_push_char(c).is_ok()); | |
85 | assert_eq!(&*buf_string, &*buf_tendril); | |
86 | } | |
87 | ||
88 | 97 => { | |
89 | buf_string.truncate(0); | |
90 | buf_tendril.clear(); | |
91 | assert_eq!(&*buf_string, &*buf_tendril); | |
92 | } | |
93 | ||
94 | _ => { | |
95 | let (start, end) = random_slice(&mut rng, &buf_string); | |
96 | string_slices.push(buf_string[start..end].to_owned()); | |
97 | tendril_slices.push(buf_tendril.subtendril(start as u32, (end - start) as u32)); | |
98 | assert_eq!(string_slices.len(), tendril_slices.len()); | |
923072b8 FG |
99 | assert!(string_slices |
100 | .iter() | |
101 | .zip(tendril_slices.iter()) | |
102 | .all(|(s, t)| **s == **t)); | |
83c7162d XL |
103 | } |
104 | } | |
105 | } | |
106 | } | |
107 | ||
108 | fn random_boundary<R: Rng>(rng: &mut R, text: &str) -> usize { | |
109 | loop { | |
923072b8 | 110 | let i = Range::new(0, text.len() + 1).ind_sample(rng); |
83c7162d XL |
111 | if text.is_char_boundary(i) { |
112 | return i; | |
113 | } | |
114 | } | |
115 | } | |
116 | ||
117 | fn random_slice<R: Rng>(rng: &mut R, text: &str) -> (usize, usize) { | |
118 | loop { | |
923072b8 FG |
119 | let start = Range::new(0, text.len() + 1).ind_sample(rng); |
120 | let end = Range::new(start, text.len() + 1).ind_sample(rng); | |
83c7162d XL |
121 | if !text.is_char_boundary(start) { |
122 | continue; | |
123 | } | |
124 | if end < text.len() && !text.is_char_boundary(end) { | |
125 | continue; | |
126 | } | |
127 | return (start, end); | |
128 | } | |
129 | } | |
130 | ||
131 | static TEXT: &'static str = | |
132 | "It was from the artists and poets that the pertinent answers came, and I \ | |
133 | know that panic would have broken loose had they been able to compare notes. \ | |
134 | As it was, lacking their original letters, I half suspected the compiler of \ | |
135 | having asked leading questions, or of having edited the correspondence in \ | |
136 | corroboration of what he had latently resolved to see.\ | |
137 | \ | |
138 | ˙ǝǝs oʇ pǝʌʃosǝɹ ʎʃʇuǝʇɐʃ pɐɥ ǝɥ ʇɐɥʍ ɟo uoıʇɐɹoqoɹɹoɔ uı ǝɔuǝpuodsǝɹɹoɔ ǝɥʇ \ | |
139 | pǝʇıpǝ ƃuıʌɐɥ ɟo ɹo 'suoıʇsǝnb ƃuıpɐǝʃ pǝʞsɐ ƃuıʌɐɥ ɟo ɹǝʃıdɯoɔ ǝɥʇ pǝʇɔǝdsns \ | |
140 | ɟʃɐɥ I 'sɹǝʇʇǝʃ ʃɐuıƃıɹo ɹıǝɥʇ ƃuıʞɔɐʃ 'sɐʍ ʇı s∀ ˙sǝʇou ǝɹɐdɯoɔ oʇ ǝʃqɐ uǝǝq \ | |
141 | ʎǝɥʇ pɐɥ ǝsooʃ uǝʞoɹq ǝʌɐɥ pʃnoʍ ɔıuɐd ʇɐɥʇ ʍouʞ I puɐ 'ǝɯɐɔ sɹǝʍsuɐ ʇuǝuıʇɹǝd \ | |
142 | ǝɥʇ ʇɐɥʇ sʇǝod puɐ sʇsıʇɹɐ ǝɥʇ ɯoɹɟ sɐʍ ʇI"; | |
143 | ||
144 | fn main() { | |
145 | fuzz(); | |
146 | } |