194 lines
5.4 KiB
Rust
194 lines
5.4 KiB
Rust
use super::ast::*;
|
|
use crate::parse_input;
|
|
use crate::{Config, into_spans};
|
|
use proptest::prelude::*;
|
|
use proptest::proptest;
|
|
|
|
proptest! {
|
|
#[test]
|
|
fn proptest_from_segments(original in Segments::arb(Token::arb())) {
|
|
let stringified = original.to_string();
|
|
let parsed = parse_input(&stringified).unwrap();
|
|
let stringified_again = parsed.to_string();
|
|
assert_eq!(stringified, stringified_again, "parsed: `{parsed:#?}`");
|
|
}
|
|
|
|
#[test]
|
|
fn proptest_from_random_text(original in ".*") {
|
|
let parsed = parse_input(&original).unwrap();
|
|
let stringified_again = parsed.to_string();
|
|
assert_eq!(original, stringified_again, "parsed: `{parsed:#?}`");
|
|
}
|
|
|
|
#[test]
|
|
fn proptest_into_spans(original in Segments::arb(Token::arb())) {
|
|
let stringified = original.to_string();
|
|
let spans = into_spans(original, Config {collapse_space: false});
|
|
let spans_concatenated = spans.into_iter().map(|i| i.text).collect::<String>();
|
|
assert_eq!(stringified, spans_concatenated);
|
|
}
|
|
}
|
|
|
|
impl AnyString<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
let prefix = "\\w*";
|
|
let ty = any::<QuoteType>();
|
|
let contents = "\\w*";
|
|
let num_hashtags = 0usize..3;
|
|
let suffix = "\\w*";
|
|
|
|
(prefix, ty, contents, num_hashtags, suffix).prop_map(
|
|
|(prefix, ty, contents, num_hashtags, suffix)| Self {
|
|
prefix: prefix.into(),
|
|
ty,
|
|
contents: contents.into(),
|
|
num_hashtags,
|
|
suffix: suffix.into(),
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
impl PathSegment<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
(any::<PathSep>(), "\\w*").prop_map(|(leading_separator, segment)| Self {
|
|
leading_separator,
|
|
segment: segment.into(),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl FileLocation<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
use proptest::option::*;
|
|
("[0-9]{0,4}", of("[0-9]{0,4}")).prop_map(|(line, offset)| Self {
|
|
line: line.into(),
|
|
offset: offset.map(Into::into),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Space<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
" *".prop_map(|spaces| Self(spaces.into()))
|
|
}
|
|
}
|
|
|
|
impl FileName<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
use proptest::option::*;
|
|
(
|
|
any::<PathSep>(),
|
|
"\\w*",
|
|
of(".{0,3}"),
|
|
of(FileLocation::arb()),
|
|
)
|
|
.prop_map(
|
|
|(leading_separator, segment, ext_excluding_dot, location)| Self {
|
|
leading_separator,
|
|
segment: segment.into(),
|
|
ext_excluding_dot: ext_excluding_dot.map(Into::into),
|
|
location,
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Path<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
use proptest::{char::*, collection::*, option::*};
|
|
(
|
|
of(range('A', 'Z')),
|
|
vec(PathSegment::arb(), 0..3),
|
|
FileName::arb(),
|
|
)
|
|
.prop_map(|(drive_excluding_colon, segments, filename)| Self {
|
|
drive_excluding_colon,
|
|
segments,
|
|
filename,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Number<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
prop_oneof![
|
|
any::<i64>().prop_map(|number| Self(number.to_string().into())),
|
|
any::<f64>().prop_map(|number| Self(number.to_string().into()))
|
|
]
|
|
}
|
|
}
|
|
|
|
impl Atom<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
"[a-zA-Z]+".prop_map(|i| Self::Text(i.into()))
|
|
}
|
|
}
|
|
|
|
impl Token<'static> {
|
|
#[cfg(test)]
|
|
fn arb() -> impl Strategy<Value = Self> {
|
|
let leaf = prop_oneof![
|
|
Just(Self::True),
|
|
Just(Self::False),
|
|
Just(Self::None),
|
|
Path::arb().prop_map(Self::Path),
|
|
AnyString::arb().prop_map(Self::String),
|
|
Number::arb().prop_map(Self::Number),
|
|
Atom::arb().prop_map(Self::Atom),
|
|
];
|
|
|
|
leaf.prop_recursive(4, 64, 16, |token| {
|
|
Delimited::arb(token).prop_map(Self::Delimited).boxed()
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Delimited<'static> {
|
|
#[cfg(test)]
|
|
fn arb(token: impl Strategy<Value = Token<'static>>) -> impl Strategy<Value = Self> {
|
|
use proptest::option::*;
|
|
(
|
|
of((Atom::arb(), Space::arb())),
|
|
any::<Delimiter>(),
|
|
Segments::arb(token),
|
|
)
|
|
.prop_map(|(prefix, delimiter, contents)| Self {
|
|
prefix,
|
|
delimiter,
|
|
contents,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Segment<'static> {
|
|
#[cfg(test)]
|
|
fn arb(token: impl Strategy<Value = Token<'static>>) -> impl Strategy<Value = Self> {
|
|
(Space::arb(), token).prop_map(|(leading_space, token)| Self {
|
|
leading_space,
|
|
token,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Segments<'static> {
|
|
#[cfg(test)]
|
|
fn arb(token: impl Strategy<Value = Token<'static>>) -> impl Strategy<Value = Self> {
|
|
use proptest::collection::*;
|
|
|
|
(vec(Segment::arb(token), 1..10), Space::arb()).prop_map(|(segments, trailing_space)| {
|
|
Self {
|
|
segments,
|
|
trailing_space,
|
|
}
|
|
})
|
|
}
|
|
}
|