1use super::*;
2
3#[derive(Debug, PartialEq, Eq, Clone)]
7pub struct ArbitraryUri(pub http::Uri);
8#[derive(Debug, Clone, Copy)]
9pub struct UriStrategy;
10#[derive(Debug, Clone)]
11pub struct UriValueTree {
12 pub with_schema_and_host: BoolValueTree,
13 pub schema: IndexValueTree,
14 pub authority: IndexValueTree,
15 pub host: IndexValueTree,
16 pub path: IndexValueTree,
17 pub query: IndexValueTree,
18
19 pub whose_turn: usize,
20}
21
22const SCHEMAS: [&str; 2] = ["http://", "https://"];
23
24const AUTHS : [&str;16] = [
25 "",
26 "a@",
27 "a:a@",
28 "a:@",
29 ":a@",
30 ":@",
31 "%C3%BC:a@",
32 "%20:%20@",
33 "0:4@",
34 "1:%20@",
35 "2:%C5%81@",
36 "3:%F3%A0%80%A0@",
37 "4:%20a%20@",
38 "5:%20%09%F3%A0%80%A0%D1%89%F3%A0%80%A0%09%20@",
39 "6:%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20@",
40 "7:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@",
41];
42
43const HOSTS: [&str; 10] = [
44 "localhost",
45 "127.0.0.1",
46 "localhost:8080",
47 "127.0.0.1:8080",
48 "example.com",
49 "example.com:8080",
50 "[::1]",
51 "[::1]:8080",
52 "[0000:0000:0000:0000:0000:0000:0000:0001]:8080",
53 "longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong.example:8080",
54];
55
56const PATHS : [&str;9] = [
57 "/",
58 "/foo",
59 "/foo/",
60 "/foo/bar/",
61 "/%20",
62 "/%D0%B9%D1%86%D1%83%D0%BA%D0%B5%D0%BD%D0%B3%D1%88%D1%89",
63 "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z",
64 "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/",
65 "/%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20?%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20#%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20",
66];
67
68const QUERIES : [&str; 9] = [
69 "",
70 "?",
71 "?q",
72 "?q=w",
73 "?q=%20bar%20",
74 "?q=w&",
75 "?q=%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20?%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20#%5B%5D%3F%2F%3C%7E%23%6D%21%40%24%25%5E%26%2A%28%29%2B%3D%7D%7C%3A%22%3B%27%2C%3E%7B%20&",
76 "?q=http%3A%2F%2F%5B%3A%3A1%5D%3A123%2F%3Fqw%3D3%26q%3D1%231v&",
77 "?q=http%253A%252F%252F%255B%253A%253A1%255D%253A123%252F%253Fqw%253D3%2526q%253D1%25231v&",
78];
79
80impl Arbitrary for ArbitraryUri {
81 type Parameters = ();
82 type Strategy = UriStrategy;
83
84 fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
85 UriStrategy
86 }
87}
88
89impl Strategy for UriStrategy {
90 type Value = ArbitraryUri;
91 type Tree = UriValueTree;
92
93 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
94 Ok(UriValueTree {
95 with_schema_and_host: weighted(0.95).new_tree(runner)?,
96 schema: Index::arbitrary().new_tree(runner)?,
97 authority: Index::arbitrary().new_tree(runner)?,
98 host: Index::arbitrary().new_tree(runner)?,
99 path: Index::arbitrary().new_tree(runner)?,
100 query: Index::arbitrary().new_tree(runner)?,
101 whose_turn: 1,
102 })
103 }
104}
105
106impl ValueTree for UriValueTree {
107 type Value = ArbitraryUri;
108
109 fn current(&self) -> Self::Value {
110 let mut s = String::with_capacity(50);
112
113 if self.with_schema_and_host.current() {
114 s += *self.schema.current().get(&SCHEMAS[..]);
115 s += *self.authority.current().get(&AUTHS[..]);
116 s += *self.host.current().get(&HOSTS[..]);
117 }
118 s += *self.path.current().get(&PATHS[..]);
119 s += *self.query.current().get(&QUERIES[..]);
120
121 let uri: http::uri::Uri = s.parse().unwrap();
123 ArbitraryUri(uri)
124 }
125
126 fn simplify(&mut self) -> bool {
127 let mut ctr = 0;
128 loop {
129 if self.simplify1() {
130 self.advance_turn();
131 return true;
132 } else {
133 self.advance_turn();
134 ctr += 1;
135 }
136 if ctr == 5 {
137 return false;
138 }
139 }
140 }
141
142 fn complicate(&mut self) -> bool {
143 self.unadvance_turn();
144 let ret = self.complicate1();
145 self.advance_turn(); ret
147 }
148}
149
150impl UriValueTree {
151 fn simplify1(&mut self) -> bool {
152 match self.whose_turn {
153 0 => self.with_schema_and_host.simplify(),
154 1 => self.schema.simplify(),
155 2 => self.authority.simplify(),
156 3 => self.path.simplify(),
157 4 => self.query.simplify(),
158 _ => unreachable!(),
159 }
160 }
161 fn complicate1(&mut self) -> bool {
162 match self.whose_turn {
163 0 => self.with_schema_and_host.complicate(),
164 1 => self.schema.complicate(),
165 2 => self.authority.complicate(),
166 3 => self.path.complicate(),
167 4 => self.query.complicate(),
168 _ => unreachable!(),
169 }
170 }
171
172 fn advance_turn(&mut self) {
173 self.whose_turn += 1;
174 if self.whose_turn > 4 {
175 self.whose_turn = 0;
176 }
177 }
178
179 fn unadvance_turn(&mut self) {
180 if self.whose_turn == 0 {
181 self.whose_turn = 5;
182 }
183 self.whose_turn -= 1;
184 }
185}