Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_text/tests/diag.rs

6.1 KiB, 1 run

created by r1870400018:12054, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use oxedyne_fe2o3_text::fmt::{format_rust, spec::FormatSpec};
2
3use std::fs;
4use std::path::PathBuf;
5
6fn diag_file(path: &str) {
7 let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
8 .parent().unwrap().to_path_buf();
9 let full = root.join(path);
10 let source = fs::read_to_string(&full).expect("read failed");
11 let spec = FormatSpec::fe2o3();
12
13 let first = format_rust(&source, &spec).expect("format failed");
14 let second = format_rust(&first, &spec).expect("second format failed");
15
16 if first == second {
17 println!("=== {} === OK", path);
18 return;
19 }
20
21 let fl: Vec<&str> = first.lines().collect();
22 let sl: Vec<&str> = second.lines().collect();
23
24 println!("=== {} ===", path);
25 println!(" first: {} lines, second: {} lines", fl.len(), sl.len());
26 let mut diffs = 0;
27 for (i, (a, b)) in fl.iter().zip(sl.iter()).enumerate() {
28 if a != b {
29 if diffs < 30 {
30 println!(" L{}: F={:?}", i+1, a);
31 println!(" L{}: S={:?}", i+1, b);
32 }
33 diffs += 1;
34 }
35 }
36 if fl.len() > sl.len() {
37 for i in sl.len()..fl.len() {
38 if diffs < 30 { println!(" L{}: F={:?} (extra)", i+1, fl[i]); }
39 diffs += 1;
40 }
41 } else if sl.len() > fl.len() {
42 for i in fl.len()..sl.len() {
43 if diffs < 30 { println!(" L{}: S={:?} (extra)", i+1, sl[i]); }
44 diffs += 1;
45 }
46 }
47 println!(" Total differing lines: {}", diffs);
48}
49
50/// Files that historically triggered idempotency failures.
51#[test]
52fn test_real_files() {
53 diag_file("fe2o3_jdat/tests/daticle.rs");
54 diag_file("fe2o3_jdat/tests/map.rs");
55 diag_file("fe2o3_jdat/dat_map/src/lib.rs");
56}
57
58fn check_idempotent(label: &str, source: &str) {
59 let spec = FormatSpec::fe2o3();
60 let first = format_rust(source, &spec).expect("format failed");
61 let second = format_rust(&first, &spec).expect("second format failed");
62 if first == second {
63 println!("{}: OK", label);
64 } else {
65 println!("{}: DRIFT", label);
66 let fl: Vec<&str> = first.lines().collect();
67 let sl: Vec<&str> = second.lines().collect();
68 for (i, (a, b)) in fl.iter().zip(sl.iter()).enumerate() {
69 if a != b {
70 let st = if i > 2 { i - 2 } else { 0 };
71 let en = (i + 3).min(fl.len()).min(sl.len());
72 for j in st..en {
73 let m = if j == i { ">>>" } else { " " };
74 println!(" {} {:3} F: {:?}", m, j+1, fl[j]);
75 println!(" {} {:3} S: {:?}", m, j+1, sl[j]);
76 }
77 break;
78 }
79 }
80 if fl.len() != sl.len() {
81 println!(" (line count: first={}, second={})", fl.len(), sl.len());
82 }
83 }
84}
85
86/// Synthetic repros for edge cases fixed during development.
87#[test]
88fn minimal_repro() {
89 check_idempotent("simple_impl", r#"
90impl Foo {
91 pub fn bar() -> Outcome<()> {
92 let x = 1;
93 Ok(())
94 }
95}
96"#);
97
98 check_idempotent("two_fn_match", r#"
99impl Foo {
100 pub fn first(&self) -> String {
101 let name = match self.x {
102 Some(s) => s.to_string(),
103 None => String::new(),
104 };
105 name
106 }
107
108 pub fn second(&self) -> Outcome<()> {
109 // body
110 let x = 1;
111 Ok(())
112 }
113}
114"#);
115
116 check_idempotent("match_align", r#"
117impl Foo {
118 pub fn bar(&self) -> Outcome<()> {
119 match self.state {
120 State::Active => {
121 // do stuff
122 let x = 1;
123 }
124 State::Inactive => {
125 let y = 2;
126 }
127 }
128 Ok(())
129 }
130}
131"#);
132
133 check_idempotent("match_arm_braced", r#"
134impl Foo {
135 pub fn bar(&self) -> Outcome<()> {
136 for shard in shards {
137 for (fnum, fstate) in shard.map_mut() {
138 match fstate.present() {
139 Present::Pair => {
140 // Comment line one.
141 let x = fstate.get_data();
142 let y = fstate.get_index();
143 },
144 Present::Solo(FileType::Data) => {
145 // Another comment.
146 let x = fstate.get_data();
147 },
148 }
149 }
150 }
151 Ok(())
152 }
153}
154"#);
155
156 check_idempotent("match_arm_ifelse", r#"
157impl Foo {
158 pub fn bar(&self) -> Outcome<()> {
159 for shard in shards {
160 for (fnum, fstate) in shard.map_mut() {
161 match fstate.present() {
162 Present::Pair => {
163 // Comment.
164 let dat = fstate.get_data();
165 let ind = fstate.get_index();
166 if let Err(e) = bot.send(Msg::Cache { fnum: *fnum, dat, ind }) {
167 return Err(err!(e, "Cannot send request to bot {}", j; Channel, Write));
168 } else {
169 requests += 1;
170 }
171 },
172 Present::Solo(FileType::Data) => {
173 // Another comment.
174 let dat = fstate.get_data();
175 if let Err(e) = bot.send(Msg::CacheData { fnum: *fnum, dat }) {
176 return Err(err!(e, "Cannot send request to bot {}", j; Channel, Write));
177 } else {
178 requests += 1;
179 }
180 },
181 Present::Solo(FileType::Index) => {
182 // Yet another comment.
183 match missing { None => missing = Some(vec![*fnum]), Some(ref mut m) => m.push(*fnum), }
184 },
185 }
186 }
187 }
188 Ok(())
189 }
190}
191"#);
192
193 // Truncated file: unclosed braces should not gain synthetic closing braces.
194 check_idempotent("truncated_match", r#"
195pub fn foo() -> Outcome<()> {
196 match x {
197"#);
198
199 // Colon-path adjacency: `map: ::std` must not compress to `map:::std`.
200 check_idempotent("colon_path", r#"
201fn bar(mut map: ::std::collections::BTreeMap<u32, u32>) {}
202"#);
203}