1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/// g-code emitter with a few basic commands and argument-checking
pub mod emit;
/// g-code parser written with [peg]
pub mod parse;

#[cfg(test)]
mod test {
    use crate::{emit::FormatOptions, parse::into_diagnostic};
    use pretty_assertions::assert_eq;

    #[test]
    #[cfg(feature = "codespan_helpers")]
    fn parsing_gcode_then_emitting_then_parsing_again_returns_functionally_identical_gcode() {
        use codespan_reporting::diagnostic::{Diagnostic, Label};
        use codespan_reporting::term::{
            emit,
            termcolor::{ColorChoice, StandardStream},
        };

        let mut writer = StandardStream::stderr(ColorChoice::Auto);
        let config = codespan_reporting::term::Config::default();

        for str in [
            include_str!("../tests/square.gcode"),
            include_str!("../tests/edge_cases.gcode"),
            include_str!("../tests/vandy_commodores_logo.gcode"),
            include_str!("../tests/ncviewer_sample.gcode"),
        ] {
            let parsed_file = crate::parse::file_parser(str).unwrap();
            let emission_tokens = parsed_file.iter_emit_tokens().collect::<Vec<_>>();

            for format_options in [true, false]
                .iter()
                .copied()
                .map(|a| [[a, true], [a, false]])
                .flatten()
                .map(|[a, b]| [[a, b, true], [a, b, false]])
                .flatten()
                .map(
                    |[checksums, line_numbers, delimit_with_percent]| FormatOptions {
                        checksums,
                        line_numbers,
                        delimit_with_percent,
                    },
                )
            {
                let mut emitted_gcode = String::new();
                crate::emit::format_gcode_fmt(&emission_tokens, format_options, &mut emitted_gcode)
                    .unwrap();

                let reparsed_file = match super::parse::file_parser(&emitted_gcode) {
                    Ok(reparsed) => reparsed,
                    Err(err) => {
                        emit(
                            &mut writer,
                            &config,
                            &codespan_reporting::files::SimpleFile::new(
                                "test_input.gcode",
                                emitted_gcode,
                            ),
                            &into_diagnostic(&err),
                        )
                        .unwrap();
                        panic!("{}", err);
                    }
                };

                for line in reparsed_file.iter() {
                    let validated_checksum = line.validate_checksum();
                    assert!(
                        validated_checksum.clone().transpose().is_ok(),
                        "got {:?} for {:#?}",
                        validated_checksum,
                        line
                    );
                }

                parsed_file
                    .iter_fields()
                    .filter(|field| field.letters != "N")
                    .zip(
                        reparsed_file
                            .iter_fields()
                            .filter(|field| field.letters != "N"),
                    )
                    .for_each(|(expected, actual)| {
                        if expected.value != actual.value || expected.letters != actual.letters {
                            emit(
                                &mut writer,
                                &config,
                                &codespan_reporting::files::SimpleFile::new(
                                    "test_input.gcode",
                                    str,
                                ),
                                &Diagnostic::error()
                                    .with_message("fields do not match")
                                    .with_labels(vec![Label::primary((), expected.span)
                                        .with_message("this one here officer")]),
                            )
                            .unwrap();
                        }
                        assert_eq!(
                            expected.letters, actual.letters,
                            "{:?} vs {:?}",
                            expected, actual
                        );
                        assert_eq!(
                            expected.value, actual.value,
                            "{:?} vs {:?}",
                            expected, actual
                        );
                    })
            }
        }
    }
}