]> git.proxmox.com Git - rustc.git/blob - src/librustc_data_structures/obligation_forest/test.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_data_structures / obligation_forest / test.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use super::{ObligationForest, Outcome, Error};
12
13 #[test]
14 fn push_pop() {
15 let mut forest = ObligationForest::new();
16 forest.push_tree("A", "A");
17 forest.push_tree("B", "B");
18 forest.push_tree("C", "C");
19
20 // first round, B errors out, A has subtasks, and C completes, creating this:
21 // A |-> A.1
22 // |-> A.2
23 // |-> A.3
24 let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
25 tree,
26 _| {
27 assert_eq!(obligation.chars().next(), tree.chars().next());
28 match *obligation {
29 "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
30 "B" => Err("B is for broken"),
31 "C" => Ok(Some(vec![])),
32 _ => unreachable!(),
33 }
34 });
35 assert_eq!(ok, vec!["C"]);
36 assert_eq!(err,
37 vec![Error {
38 error: "B is for broken",
39 backtrace: vec!["B"],
40 }]);
41
42 // second round: two delays, one success, creating an uneven set of subtasks:
43 // A |-> A.1
44 // |-> A.2
45 // |-> A.3 |-> A.3.i
46 // D |-> D.1
47 // |-> D.2
48 forest.push_tree("D", "D");
49 let Outcome { completed: ok, errors: err, .. }: Outcome<&'static str, ()> =
50 forest.process_obligations(|obligation, tree, _| {
51 assert_eq!(obligation.chars().next(), tree.chars().next());
52 match *obligation {
53 "A.1" => Ok(None),
54 "A.2" => Ok(None),
55 "A.3" => Ok(Some(vec!["A.3.i"])),
56 "D" => Ok(Some(vec!["D.1", "D.2"])),
57 _ => unreachable!(),
58 }
59 });
60 assert_eq!(ok, Vec::<&'static str>::new());
61 assert_eq!(err, Vec::new());
62
63
64 // third round: ok in A.1 but trigger an error in A.2. Check that it
65 // propagates to A.3.i, but not D.1 or D.2.
66 // D |-> D.1 |-> D.1.i
67 // |-> D.2 |-> D.2.i
68 let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
69 tree,
70 _| {
71 assert_eq!(obligation.chars().next(), tree.chars().next());
72 match *obligation {
73 "A.1" => Ok(Some(vec![])),
74 "A.2" => Err("A is for apple"),
75 "D.1" => Ok(Some(vec!["D.1.i"])),
76 "D.2" => Ok(Some(vec!["D.2.i"])),
77 _ => unreachable!(),
78 }
79 });
80 assert_eq!(ok, vec!["A.1"]);
81 assert_eq!(err,
82 vec![Error {
83 error: "A is for apple",
84 backtrace: vec!["A.2", "A"],
85 }]);
86
87 // fourth round: error in D.1.i that should propagate to D.2.i
88 let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(|obligation,
89 tree,
90 _| {
91 assert_eq!(obligation.chars().next(), tree.chars().next());
92 match *obligation {
93 "D.1.i" => Err("D is for dumb"),
94 _ => panic!("unexpected obligation {:?}", obligation),
95 }
96 });
97 assert_eq!(ok, Vec::<&'static str>::new());
98 assert_eq!(err,
99 vec![Error {
100 error: "D is for dumb",
101 backtrace: vec!["D.1.i", "D.1", "D"],
102 }]);
103 }
104
105 // Test that if a tree with grandchildren succeeds, everything is
106 // reported as expected:
107 // A
108 // A.1
109 // A.2
110 // A.2.i
111 // A.2.ii
112 // A.3
113 #[test]
114 fn success_in_grandchildren() {
115 let mut forest = ObligationForest::new();
116 forest.push_tree("A", "A");
117
118 let Outcome { completed: ok, errors: err, .. } =
119 forest.process_obligations::<(), _>(|obligation, tree, _| {
120 assert_eq!(obligation.chars().next(), tree.chars().next());
121 match *obligation {
122 "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
123 _ => unreachable!(),
124 }
125 });
126 assert!(ok.is_empty());
127 assert!(err.is_empty());
128
129 let Outcome { completed: ok, errors: err, .. } =
130 forest.process_obligations::<(), _>(|obligation, tree, _| {
131 assert_eq!(obligation.chars().next(), tree.chars().next());
132 match *obligation {
133 "A.1" => Ok(Some(vec![])),
134 "A.2" => Ok(Some(vec!["A.2.i", "A.2.ii"])),
135 "A.3" => Ok(Some(vec![])),
136 _ => unreachable!(),
137 }
138 });
139 assert_eq!(ok, vec!["A.3", "A.1"]);
140 assert!(err.is_empty());
141
142 let Outcome { completed: ok, errors: err, .. } =
143 forest.process_obligations::<(), _>(|obligation, tree, _| {
144 assert_eq!(obligation.chars().next(), tree.chars().next());
145 match *obligation {
146 "A.2.i" => Ok(Some(vec!["A.2.i.a"])),
147 "A.2.ii" => Ok(Some(vec![])),
148 _ => unreachable!(),
149 }
150 });
151 assert_eq!(ok, vec!["A.2.ii"]);
152 assert!(err.is_empty());
153
154 let Outcome { completed: ok, errors: err, .. } =
155 forest.process_obligations::<(), _>(|obligation, tree, _| {
156 assert_eq!(obligation.chars().next(), tree.chars().next());
157 match *obligation {
158 "A.2.i.a" => Ok(Some(vec![])),
159 _ => unreachable!(),
160 }
161 });
162 assert_eq!(ok, vec!["A.2.i.a", "A.2.i", "A.2", "A"]);
163 assert!(err.is_empty());
164
165 let Outcome { completed: ok, errors: err, .. } = forest.process_obligations::<(), _>(|_,
166 _,
167 _| {
168 unreachable!()
169 });
170 assert!(ok.is_empty());
171 assert!(err.is_empty());
172 }
173
174 #[test]
175 fn to_errors_no_throw() {
176 // check that converting multiple children with common parent (A)
177 // only yields one of them (and does not panic, in particular).
178 let mut forest = ObligationForest::new();
179 forest.push_tree("A", "A");
180 let Outcome { completed: ok, errors: err, .. } =
181 forest.process_obligations::<(), _>(|obligation, tree, _| {
182 assert_eq!(obligation.chars().next(), tree.chars().next());
183 match *obligation {
184 "A" => Ok(Some(vec!["A.1", "A.2", "A.3"])),
185 _ => unreachable!(),
186 }
187 });
188 assert_eq!(ok.len(), 0);
189 assert_eq!(err.len(), 0);
190 let errors = forest.to_errors(());
191 assert_eq!(errors.len(), 1);
192 }
193
194 #[test]
195 fn backtrace() {
196 // check that converting multiple children with common parent (A)
197 // only yields one of them (and does not panic, in particular).
198 let mut forest = ObligationForest::new();
199 forest.push_tree("A", "A");
200 let Outcome { completed: ok, errors: err, .. } =
201 forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
202 assert_eq!(obligation.chars().next(), tree.chars().next());
203 assert!(backtrace.next().is_none());
204 match *obligation {
205 "A" => Ok(Some(vec!["A.1"])),
206 _ => unreachable!(),
207 }
208 });
209 assert!(ok.is_empty());
210 assert!(err.is_empty());
211 let Outcome { completed: ok, errors: err, .. } =
212 forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
213 assert_eq!(obligation.chars().next(), tree.chars().next());
214 assert!(backtrace.next().unwrap() == &"A");
215 assert!(backtrace.next().is_none());
216 match *obligation {
217 "A.1" => Ok(Some(vec!["A.1.i"])),
218 _ => unreachable!(),
219 }
220 });
221 assert!(ok.is_empty());
222 assert!(err.is_empty());
223 let Outcome { completed: ok, errors: err, .. } =
224 forest.process_obligations::<(), _>(|obligation, tree, mut backtrace| {
225 assert_eq!(obligation.chars().next(), tree.chars().next());
226 assert!(backtrace.next().unwrap() == &"A.1");
227 assert!(backtrace.next().unwrap() == &"A");
228 assert!(backtrace.next().is_none());
229 match *obligation {
230 "A.1.i" => Ok(None),
231 _ => unreachable!(),
232 }
233 });
234 assert_eq!(ok.len(), 0);
235 assert!(err.is_empty());
236 }