Skip to content

Commit 9924a96

Browse files
committedDec 10, 2022
Add test for reparsing
Signed-off-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent c2ff663 commit 9924a96

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed
 

‎sqllogictest/src/parser.rs

+81-2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ pub enum Record {
132132
},
133133
Condition(Condition),
134134
Comment(Vec<String>),
135+
Whitespace(String),
135136
/// Internally injected record which should not occur in the test file.
136137
Injected(Injected),
137138
}
@@ -242,6 +243,9 @@ impl std::fmt::Display for Record {
242243
}
243244
Ok(())
244245
}
246+
Record::Whitespace(w) => {
247+
write!(f, "{}", w)
248+
}
245249
Record::Injected(p) => panic!("unexpected injected record: {:?}", p),
246250
}
247251
}
@@ -397,6 +401,7 @@ fn parse_inner(loc: &Location, script: &str) -> Result<Vec<Record>, ParseError>
397401
}
398402

399403
if line.is_empty() {
404+
records.push(Record::Whitespace(line.to_string()));
400405
continue;
401406
}
402407

@@ -609,11 +614,85 @@ fn parse_file_inner(loc: Location) -> Result<Vec<Record>, ParseError> {
609614

610615
#[cfg(test)]
611616
mod tests {
612-
use crate::parse_file;
617+
use difference::{Changeset, Difference};
618+
619+
use super::*;
613620

614621
#[test]
615622
fn test_include_glob() {
616623
let records = parse_file("../examples/include/include_1.slt").unwrap();
617-
assert_eq!(14, records.len());
624+
assert_eq!(16, records.len());
625+
}
626+
627+
#[test]
628+
fn test_basic() {
629+
parse_roundtrip("../examples/basic/basic.slt")
630+
}
631+
632+
/// Parses the specified file into Records, and ensures the
633+
/// results of unparsing them are the same
634+
///
635+
/// Prints a hopefully useful message on failure
636+
fn parse_roundtrip(filename: impl AsRef<Path>) {
637+
let filename = filename.as_ref();
638+
let input_contents = std::fs::read_to_string(filename).expect("reading file");
639+
640+
let records = parse_file(filename).expect("parsing to complete");
641+
642+
let unparsed = records
643+
.into_iter()
644+
.map(record_to_string)
645+
.collect::<Vec<_>>();
646+
647+
let output_contents = unparsed.join("\n");
648+
649+
let changeset = Changeset::new(&input_contents, &output_contents, "\n");
650+
651+
assert!(
652+
no_diffs(&changeset),
653+
"Mismatch for {:?}\n\
654+
*********\n\
655+
diff:\n\
656+
*********\n\
657+
{}\n\n\
658+
*********\n\
659+
output:\n\
660+
*********\n\
661+
{}\n\n",
662+
filename,
663+
UsefulDiffDisplay(&changeset),
664+
output_contents,
665+
);
666+
}
667+
668+
fn record_to_string(record: Record) -> String {
669+
if matches!(&record, Record::Statement { .. } | Record::Query { .. }) {
670+
// the statement parser includes a newline between the items but the display
671+
// output does not, so add it here
672+
// Not sure about this one
673+
format!("{}\n", record)
674+
} else {
675+
record.to_string()
676+
}
677+
}
678+
679+
/// returns true if there are no differences in the changeset
680+
fn no_diffs(changeset: &Changeset) -> bool {
681+
changeset
682+
.diffs
683+
.iter()
684+
.all(|diff| matches!(diff, Difference::Same(_)))
685+
}
686+
687+
struct UsefulDiffDisplay<'a>(&'a Changeset);
688+
689+
impl<'a> std::fmt::Display for UsefulDiffDisplay<'a> {
690+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
691+
self.0.diffs.iter().try_for_each(|diff| match diff {
692+
Difference::Same(x) => writeln!(f, "{x}"),
693+
Difference::Add(x) => writeln!(f, "+ {x}"),
694+
Difference::Rem(x) => writeln!(f, "- {x}"),
695+
})
696+
}
618697
}
619698
}

‎sqllogictest/src/runner.rs

+1
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ impl<D: AsyncDB> Runner<D> {
546546
}
547547
Record::Include { .. }
548548
| Record::Comment(_)
549+
| Record::Whitespace(_)
549550
| Record::Subtest { .. }
550551
| Record::Halt { .. }
551552
| Record::Injected(_)

0 commit comments

Comments
 (0)