1pub mod emit;
3pub mod parse;
5
6#[cfg(test)]
7mod test {
8 use pretty_assertions::assert_eq;
9
10 use crate::{emit::FormatOptions, parse::into_diagnostic};
11
12 #[test]
13 #[cfg(feature = "codespan_helpers")]
14 fn parsing_gcode_then_emitting_then_parsing_again_returns_functionally_identical_gcode() {
15 use codespan_reporting::{
16 diagnostic::{Diagnostic, Label},
17 term::{
18 emit_to_io_write,
19 termcolor::{ColorChoice, StandardStream},
20 },
21 };
22
23 let mut writer = StandardStream::stderr(ColorChoice::Auto);
24 let config = codespan_reporting::term::Config::default();
25
26 for str in [
27 include_str!("../tests/square.gcode"),
28 include_str!("../tests/edge_cases.gcode"),
29 include_str!("../tests/vandy_commodores_logo.gcode"),
30 include_str!("../tests/ncviewer_sample.gcode"),
31 ] {
32 let parsed_file = crate::parse::file_parser(str).unwrap();
33 let emission_tokens = parsed_file.iter_emit_tokens().collect::<Vec<_>>();
34
35 for format_options in [true, false]
36 .iter()
37 .copied()
38 .flat_map(|a| [[a, true], [a, false]])
39 .flat_map(|[a, b]| [[a, b, true], [a, b, false]])
40 .flat_map(|[a, b, c]| [[a, b, c, true], [a, b, c, false]])
41 .map(
42 |[
43 checksums,
44 line_numbers,
45 delimit_with_percent,
46 newline_before_comment,
47 ]| {
48 FormatOptions {
49 checksums,
50 line_numbers,
51 delimit_with_percent,
52 newline_before_comment,
53 }
54 },
55 )
56 {
57 let mut emitted_gcode = String::new();
58 crate::emit::format_gcode_fmt(
59 emission_tokens.iter(),
60 format_options,
61 &mut emitted_gcode,
62 )
63 .unwrap();
64
65 let reparsed_file = match super::parse::file_parser(&emitted_gcode) {
66 Ok(reparsed) => reparsed,
67 Err(err) => {
68 emit_to_io_write(
69 &mut writer,
70 &config,
71 &codespan_reporting::files::SimpleFile::new(
72 "test_input.gcode",
73 emitted_gcode,
74 ),
75 &into_diagnostic(&err),
76 )
77 .unwrap();
78 panic!("{}", err);
79 }
80 };
81
82 for line in reparsed_file.iter() {
83 let validated_checksum = line.validate_checksum();
84 assert!(
85 validated_checksum.transpose().is_ok(),
86 "got {:?} for {:#?}",
87 validated_checksum,
88 line
89 );
90 }
91
92 parsed_file
93 .iter_fields()
94 .filter(|field| field.letters != "N")
95 .zip(
96 reparsed_file
97 .iter_fields()
98 .filter(|field| field.letters != "N"),
99 )
100 .for_each(|(expected, actual)| {
101 if expected.value != actual.value || expected.letters != actual.letters {
102 emit_to_io_write(
103 &mut writer,
104 &config,
105 &codespan_reporting::files::SimpleFile::new(
106 "test_input.gcode",
107 str,
108 ),
109 &Diagnostic::error()
110 .with_message("fields do not match")
111 .with_labels(vec![
112 Label::primary((), expected.span)
113 .with_message("this one here officer"),
114 ]),
115 )
116 .unwrap();
117 }
118 assert_eq!(
119 expected.letters, actual.letters,
120 "{:?} vs {:?}",
121 expected, actual
122 );
123 assert_eq!(
124 expected.value, actual.value,
125 "{:?} vs {:?}",
126 expected, actual
127 );
128 })
129 }
130 }
131 }
132}