Lines
100 %
Functions
95.12 %
Branches
#![cfg(test)]
use std::assert_matches::assert_matches;
use proptest::prelude::*;
use crate::source_map::{BytePos, Pos, SourceFile, Span, Spanned};
use crate::tests::*;
proptest! {
#[test]
fn convert_byte_pos_to_and_from_usize(value: usize) {
let byte_pos = <BytePos as Pos>::from_usize(value);
assert_eq!(<BytePos as Pos>::to_usize(byte_pos), value);
}
fn add_two_byte_poses(a: usize, b: usize) {
prop_assume!(a.checked_add(b).is_some());
let p1 = BytePos::from_usize(a);
let p2 = BytePos::from_usize(b);
assert_eq!(p1 + p2, BytePos::from_usize(a + b));
fn add_assign_two_byte_poses(a: usize, b: usize) {
let mut p1 = BytePos::from_usize(a);
p1 += p2;
assert_eq!(p1, BytePos::from_usize(a + b));
fn span_from_usizes_should_create_a_span_of_byte_poses(start: usize, end: usize) {
prop_assume!(start <= end);
let span = Span::from_usizes(start, end);
assert_eq!(
span,
Span {
start: BytePos::from_usize(start),
end: BytePos::from_usize(end),
);
fn span_from_usizes_should_not_allow_start_greater_than_end(start: usize, end: usize) {
prop_assume!(start > end);
let result = std::panic::catch_unwind(|| Span::from_usizes(start, end));
assert_matches!(result, Err(_));
fn valid_span() -> impl Strategy<Value = Span> {
any::<usize>()
.prop_flat_map(|end| (0..end, Just(end)))
.prop_map(|(start, end)| Span {
start: start.into(),
end: end.into(),
})
fn span_from_spanned(span in valid_span()) {
struct S;
let spanned = Spanned::new(S, span);
assert_eq!(Span::from(spanned), span);
fn spanned_new_should_create_a_spanned_with_a_value_and_a_span(span in valid_span()) {
#[derive(PartialEq, Debug)]
assert_eq!(spanned.value, S);
assert_eq!(spanned.span, span);
fn spanned_new_should_accept_a_dummy_span() {
let spanned = Spanned::new(S, Span::dummy());
assert_eq!(spanned.span, Span::dummy());
fn spanned_with_dummy_span_should_create_a_spanned_with_a_value_and_dummy_span() {
let spanned = Spanned::with_dummy_span(S);
fn spanned_should_deref_to_its_internal_value(span in valid_span()) {
struct S {
i: i32,
let spanned = Spanned::new(S { i: 42 }, span);
assert_eq!(*spanned, S { i: 42 });
assert_eq!(spanned.i, 42);
fn usize_should_be_convertible_to_byte_pos(value: usize) {
let bp = <usize as Into<BytePos>>::into(value);
assert_eq!(bp, BytePos::from_usize(value));
fn get_text_snippet_should_return_empty_string_for_dummy_span(text in ".*") {
let sf = SourceFile::new(&text);
assert_eq!(sf.get_text_snippet(Span::dummy()), "");
fn text_and_inbounds_byte_pos() -> impl Strategy<Value = (String, BytePos)> {
source_chars()
.prop_flat_map(|text| (0..text.len(), Just(text)))
.prop_map(|(index, text)| (text, index.into()))
fn get_text_snippet_should_return_empty_string_for_empty_span_and_non_empty_text(
(text, byte_pos) in text_and_inbounds_byte_pos()
) {
let empty_span = Span {
start: byte_pos,
end: byte_pos
};
assert_eq!(sf.get_text_snippet(empty_span), "");
fn get_text_snippet_should_panic_if_span_is_non_dummy_and_text_is_empty(
span in valid_span().prop_filter("no dummy", |&span| span != Span::dummy())
let sf = SourceFile::new("");
let result = std::panic::catch_unwind(|| sf.get_text_snippet(span));
fn get_text_snippet_should_panic_on_fully_out_of_bounds_span(
text in source_chars(),
span in valid_span()
prop_assume!(span.start.to_usize() > text.len());
fn text_and_partially_out_of_bounds_span() -> impl Strategy<Value = (String, Span)> {
.prop_flat_map(|text| (0..text.len(), text.len().., Just(text)))
.prop_map(|(inbounds_index, outbounds_index, text)| {
(text, Span::from_usizes(inbounds_index, outbounds_index))
fn get_text_snippet_should_panic_on_partially_out_of_bounds_span(
(text, span) in text_and_partially_out_of_bounds_span()
fn get_text_snippet_should_return_substring_for_the_exclusive_range_of_a_non_dummy_span(
prefix in ".*",
infix in ".*",
suffix in ".*",
let start = prefix.len();
let end = start + infix.len();
let expected_snippet = infix.clone();
let text = [prefix, infix, suffix].concat();
assert_eq!(sf.get_text_snippet(span), &expected_snippet);
fn get_text_snippet_should_return_whole_text_if_span_covers_it(
text in ".*",
let span = Span::from_usizes(0, text.len());
assert_eq!(sf.get_text_snippet(span), &text);
fn get_text_snippet_should_work_with_utf8_text() {
let sf = SourceFile::new("🗻∈🌏");
assert_eq!(sf.get_text_snippet(Span::from_usizes(0, 4)), "🗻");
assert_eq!(sf.get_text_snippet(Span::from_usizes(4, 7)), "∈");
assert_eq!(sf.get_text_snippet(Span::from_usizes(7, 11)), "🌏");
fn get_text_snippet_should_panic_if_span_is_broken_utf8() {
let sf = SourceFile::new("\u{0800}");
let span = Span::from_usizes(0, 1);
fn get_text_snippet_should_panic_if_empty_span_start_is_not_a_utf_8_char_boundary() {
let span = Span::from_usizes(1, 1);