#[allow(dead_code)]
#[path = "printers/array/mod.rs"]
mod array;
#[allow(dead_code)]
#[path = "printers/attribute/mod.rs"]
mod attribute;
#[allow(dead_code)]
#[path = "printers/enum/mod.rs"]
mod r#enum;
#[allow(dead_code)]
#[path = "printers/features/mod.rs"]
mod features;
#[allow(dead_code)]
#[path = "printers/formatting/mod.rs"]
mod formatting;
#[allow(dead_code)]
#[path = "printers/map/mod.rs"]
mod map;
#[allow(dead_code)]
#[path = "printers/metas/mod.rs"]
mod metas;
#[allow(dead_code)]
#[path = "printers/optional/mod.rs"]
mod optional;
#[allow(dead_code)]
#[path = "printers/struct/mod.rs"]
mod r#struct;
#[allow(dead_code)]
#[path = "printers/tuple/mod.rs"]
mod tuple;
mod prelude {
#![allow(clippy::single_component_path_imports)]
pub use super::*;
pub use doku::Document;
pub use serde::{Deserialize, Serialize};
macro_rules! printer_test {
(
$(
$file:literal => $assert_fn:ident $assert_args:tt
),+
$(,)?
) => {
#[test]
fn test() {
let mut expectations = Vec::new();
$(
let expected = printer_test!(@assert $assert_fn $assert_args);
expectations.push(($file, expected));
)+
use std::path::{Path, PathBuf};
let dir: PathBuf = Path::new(file!())
.parent()
.unwrap()
.iter()
.skip(1)
.collect();
assert_dir(dir, expectations);
}
};
(@assert to_json($ty:ty)) => {{
doku::to_json::<$ty>()
}};
(@assert to_json_without_comma($ty:ty)) => {{
printer_test!(@assert to_json_without_comma($ty, {}))
}};
(@assert to_json_without_comma($ty:ty, $fmt:tt)) => {{
let fmt = serde_json::json!($fmt);
let mut fmt: doku::json::Formatting = serde_json::from_value(fmt).expect("Given formatting is not valid");
fmt.objects_style.use_comma_as_separator = false;
doku::to_json_fmt::<$ty>(&fmt)
}};
(@assert to_json_without_key_quotes($ty:ty)) => {{
printer_test!(@assert to_json_without_key_quotes($ty, {}))
}};
(@assert to_json_without_key_quotes($ty:ty, $fmt:tt)) => {{
let fmt = serde_json::json!($fmt);
let mut fmt: doku::json::Formatting = serde_json::from_value(fmt).expect("Given formatting is not valid");
fmt.objects_style.surround_keys_with_quotes = false;
doku::to_json_fmt::<$ty>(&fmt)
}};
(@assert to_json_fmt($ty:ty, $fmt:tt)) => {{
let fmt = serde_json::json!($fmt);
let fmt = serde_json::from_value(fmt).expect("Given formatting is not valid");
doku::to_json_fmt::<$ty>(&fmt)
}};
(@assert to_json_fmt_val($ty:ty, $fmt:tt)) => {{
let fmt = serde_json::json!($fmt);
let fmt = serde_json::from_value(fmt).expect("Given formatting is not valid");
doku::to_json_fmt_val(&fmt, &<$ty>::default())
}};
(@assert to_json_val($ty:ty)) => {{
doku::to_json_val(&<$ty>::default())
}};
(@assert to_json_val_without_comma($ty:ty)) => {{
let mut fmt = doku::json::Formatting::default();
fmt.objects_style.use_comma_as_separator = false;
doku::to_json_fmt_val(&fmt, &<$ty>::default())
}};
(@assert to_json_val_without_key_quotes($ty:ty)) => {{
let mut fmt = doku::json::Formatting::default();
fmt.objects_style.surround_keys_with_quotes = false;
doku::to_json_fmt_val(&fmt, &<$ty>::default())
}};
(@assert to_toml($ty:ty)) => {{
doku::to_toml::<$ty>()
}};
(@assert to_toml_fmt($ty:ty, $fmt:tt)) => {{
let fmt = serde_json::json!($fmt);
let fmt = serde_json::from_value(fmt).expect("Given formatting is not valid");
doku::to_toml_fmt::<$ty>(&fmt)
}};
(@assert to_toml_fmt_val($ty:ty, $fmt:tt)) => {{
let fmt = serde_toml::toml!($fmt);
let fmt = serde_toml::from_value(fmt).expect("Given formatting is not valid");
doku::to_toml_fmt_val(&fmt, &<$ty>::default())
}};
(@assert to_toml_val($ty:ty)) => {{
doku::to_toml_val(&<$ty>::default())
}};
}
macro_rules! panic_test {
(
$message:literal => $assert_fn:ident $assert_args:tt
) => {
panic_test!{test: $message => $assert_fn $assert_args}
};
(
$($mod_name:ident: $message:literal => $assert_fn:ident $assert_args:tt),+
$(,)?
) => {
$(mod $mod_name {
use super::*;
#[test]
#[should_panic = $message]
fn panic_test() {
printer_test!(@assert $assert_fn $assert_args);
}
})+
};
}
#[derive(Document)]
#[allow(dead_code)]
pub(crate) struct TomlWrapper<T> {
inner: T,
}
pub(crate) use panic_test;
pub(crate) use printer_test;
}
use difference::Changeset;
use std::fs;
use std::path::Path;
type FileName = &'static str;
type FileBody = String;
type DidAssertSucceed = bool;
pub fn assert_dir(
dir: impl AsRef<Path>,
expectations: Vec<(FileName, FileBody)>,
) {
let dir = dir.as_ref();
let mut all_asserts_succeeded = true;
for (file, expected) in expectations {
all_asserts_succeeded &= assert(dir, file, expected);
}
if !all_asserts_succeeded {
panic!("Some assertions failed");
}
}
fn assert(dir: &Path, file: FileName, expected: FileBody) -> DidAssertSucceed {
let path = dir.join(file);
let path_new = path.with_extension(format!(
"{}.new",
path.extension().unwrap().to_string_lossy()
));
if path_new.exists() {
fs::remove_file(&path_new).unwrap_or_else(|err| {
panic!(
"Couldn't remove new-fixture `{}`: {}",
path_new.display(),
err
)
})
}
let actual = if path.exists() {
fs::read_to_string(&path).unwrap_or_else(|err| {
panic!("Couldn't read fixture `{}`: {}", path.display(), err)
})
} else {
Default::default()
};
if actual == expected {
true
} else {
fs::write(&path_new, &expected).unwrap_or_else(|err| {
panic!("Couldn't write fixture `{}`: {}", path_new.display(), err)
});
eprintln!(
"\nFound differences between `{}` and `{}`:\n{}",
path.display(),
path_new.display(),
Changeset::new(&actual, &expected, "\n"),
);
false
}
}