use clap::Parser;
use mdq::run::Error;
use std::io::ErrorKind;
use std::{env, io};
#[derive(Debug)]
struct Case<const N: usize> {
cli_args: [&'static str; N],
expect_output: &'static str,
expect_error: &'static str,
expect_output_json: bool,
md: &'static str,
files: &'static [(&'static str, &'static str)],
expect_success: bool,
}
#[derive(Debug)]
struct CaseRunner<'a, const N: usize> {
case: &'a Case<N>,
stdout: Vec<u8>,
stderr: String,
}
impl<const N: usize> mdq::run::OsFacade for CaseRunner<'_, N> {
fn read_stdin(&self) -> io::Result<String> {
Ok(self.case.md.to_string())
}
fn read_file(&self, path: &str) -> io::Result<String> {
for (name, content) in self.case.files {
if path == *name {
return Ok(content.to_string());
}
}
Err(io::Error::new(ErrorKind::NotFound, format!("File not found: {path}")))
}
fn stdout(&mut self) -> impl io::Write {
&mut self.stdout
}
fn write_error(&mut self, err: Error) {
self.stderr.push_str(&err.to_string())
}
}
impl<const N: usize> Case<N> {
fn check(&mut self) {
let (actual_success, actual_out, actual_err) = self.run();
let (actual_out, expect_out) = if self.expect_output_json {
let actual_obj = serde_json::from_str::<serde_json::Value>(&actual_out).unwrap();
let expect_obj = serde_json::from_str::<serde_json::Value>(self.expect_output).unwrap();
(
serde_json::to_string_pretty(&actual_obj).unwrap(),
serde_json::to_string_pretty(&expect_obj).unwrap(),
)
} else {
(actual_out, self.expect_output.to_string())
};
assert_eq!(actual_out, expect_out);
assert_eq!(actual_err, self.expect_error);
assert_eq!(actual_success, self.expect_success);
}
fn run(&self) -> (bool, String, String) {
let all_cli_args = ["cmd"].iter().chain(&self.cli_args);
let cli = mdq::run::CliOptions::try_parse_from(all_cli_args).unwrap();
let mut runner = CaseRunner {
case: self,
stdout: vec![],
stderr: "".to_string(),
};
let result = mdq::run::run(&cli.into(), &mut runner);
let out_str =
String::from_utf8(runner.stdout).unwrap_or_else(|err| String::from_utf8_lossy(err.as_bytes()).into_owned());
(result, out_str, runner.stderr)
}
}
include!(concat!(env!("OUT_DIR"), "/tests/integ_test_cases.rs"));