blob: c82f6f2baca17989c41347a716092937161d69bc [file] [log] [blame] [edit]
extern crate fwdansi;
extern crate proptest;
extern crate termcolor;
use fwdansi::write_ansi;
use proptest::prelude::*;
use std::io;
use termcolor::{Ansi, Color, ColorSpec, WriteColor};
proptest! {
#[test]
fn check_no_crash(ref ansi_string in any::<Vec<u8>>()) {
let mut ansi = Ansi::new(Vec::with_capacity(ansi_string.len()));
prop_assert!(write_ansi(&mut ansi, &ansi_string).is_ok());
}
#[test]
fn ansi_idempotent(ref elements in prop::collection::vec(Element::any(), 0..100)) {
// first, write the test string into an ANSI buffer.
let mut original = Ansi::new(Vec::new());
for e in elements {
e.write(&mut original).unwrap();
}
// recover the original string, and forward it using `write_ansi`.
let original = original.into_inner();
let mut forwarded = Ansi::new(Vec::with_capacity(original.len()));
prop_assert!(write_ansi(&mut forwarded, &original).is_ok());
prop_assert_eq!(original, forwarded.into_inner());
}
}
#[derive(Debug, Clone)]
enum Element {
ColorSpec(ColorSpec),
Reset,
Text(Vec<u8>),
}
fn any_opt_color() -> impl Strategy<Value = Option<Color>> {
let color = prop_oneof![
Just(Color::Black),
Just(Color::Red),
Just(Color::Green),
Just(Color::Yellow),
Just(Color::Blue),
Just(Color::Magenta),
Just(Color::Cyan),
Just(Color::White),
any::<u8>().prop_map(Color::Ansi256),
any::<[u8; 3]>().prop_map(|[r, g, b]| Color::Rgb(r, g, b)),
];
prop::option::weighted(0.9, color)
}
prop_compose! {
fn any_color_spec()(
bold in any::<bool>(),
underline in any::<bool>(),
intense in any::<bool>(),
fg_color in any_opt_color(),
bg_color in any_opt_color(),
) -> ColorSpec {
let mut spec = ColorSpec::new();
spec.set_bold(bold)
.set_underline(underline)
.set_intense(intense)
.set_fg(fg_color)
.set_bg(bg_color);
spec
}
}
impl Element {
fn any() -> impl Strategy<Value = Self> {
prop_oneof![
Just(Element::Reset),
any_color_spec().prop_map(Element::ColorSpec),
any::<Vec<u8>>().prop_filter_map("ignored empty SGR", |v| {
if v.windows(3).find(|w| w == b"\x1b[m").is_some() {
None
} else {
Some(Element::Text(v))
}
}),
]
}
fn write<W: WriteColor>(&self, mut w: W) -> io::Result<()> {
w.write_all(b"~")?;
match self {
Element::ColorSpec(cs) => w.set_color(cs),
Element::Reset => w.reset(),
Element::Text(text) => w.write_all(text),
}
}
}