#![allow(clippy::items_after_test_module)]
use std::io;
use std::str::from_utf8;
use rstest::rstest;
use xt::Format;
macro_rules! xt_assert_translation {
(
input_source = $input_source:path;
translator = $translator:path;
translation = $from:expr => $to:expr;
source_format = $source_format:expr;
) => {
let input = $input_source($from);
let expected = $input_source($to);
let mut output = Vec::with_capacity(expected.len());
$translator(input, $source_format, $to, &mut output).unwrap();
if let (Ok(expected), Ok(output)) = (from_utf8(expected), from_utf8(&output)) {
similar_asserts::assert_eq!(expected, output);
} else {
similar_asserts::assert_eq!(expected, output);
}
};
}
#[rstest]
fn translate_single_slice_detected(
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_single_document_input;
translator = xt::translate_slice;
translation = from => to;
source_format = None;
}
}
#[rstest]
fn translate_single_slice_explicit(
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_single_document_input;
translator = xt::translate_slice;
translation = from => to;
source_format = Some(from);
}
}
#[rstest]
fn translate_single_reader_detected(
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_single_document_input;
translator = xt::translate_reader;
translation = from => to;
source_format = None;
}
}
#[rstest]
fn translate_single_reader_explicit(
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Toml, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_single_document_input;
translator = xt::translate_reader;
translation = from => to;
source_format = Some(from);
}
}
#[rstest]
fn translate_multi_slice_detected(
#[values(Format::Json, Format::Msgpack, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_multi_document_input;
translator = xt::translate_slice;
translation = from => to;
source_format = None;
}
}
#[rstest]
fn translate_multi_slice_explicit(
#[values(Format::Json, Format::Msgpack, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_multi_document_input;
translator = xt::translate_slice;
translation = from => to;
source_format = Some(from);
}
}
#[rstest]
fn translate_multi_reader_detected(
#[values(Format::Json, Format::Msgpack, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_multi_document_input;
translator = xt::translate_reader;
translation = from => to;
source_format = None;
}
}
#[rstest]
fn translate_multi_reader_explicit(
#[values(Format::Json, Format::Msgpack, Format::Yaml)] from: Format,
#[values(Format::Json, Format::Msgpack, Format::Yaml)] to: Format,
) {
xt_assert_translation! {
input_source = get_multi_document_input;
translator = xt::translate_reader;
translation = from => to;
source_format = Some(from);
}
}
fn get_single_document_input(fmt: Format) -> &'static [u8] {
match fmt {
Format::Json => include_bytes!("single.json"),
Format::Msgpack => include_bytes!("single.msgpack"),
Format::Toml => include_bytes!("single.toml"),
Format::Yaml => include_bytes!("single.yaml"),
fmt => panic!("{fmt} does not have a single-document test case"),
}
}
fn get_multi_document_input(fmt: Format) -> &'static [u8] {
match fmt {
Format::Json => include_bytes!("multi.json"),
Format::Msgpack => include_bytes!("multi.msgpack"),
Format::Yaml => include_bytes!("multi.yaml"),
fmt => panic!("{fmt} does not have a multi-document test case"),
}
}
#[rstest]
fn yaml_encoding(
#[values("utf16be", "utf16le", "utf32be", "utf32le", "utf16bebom", "utf32lebom")] name: &str,
) {
let input = get_yaml_encoding_input(name);
let mut output = Vec::with_capacity(YAML_ENCODING_RESULT.len());
xt::translate_slice(input, Some(Format::Yaml), Format::Json, &mut output).unwrap();
assert_eq!(std::str::from_utf8(&output), Ok(YAML_ENCODING_RESULT));
}
const YAML_ENCODING_RESULT: &str = concat!(r#"{"xt":"🧑💻"}"#, "\n");
fn get_yaml_encoding_input(name: &str) -> &'static [u8] {
match name {
"utf16be" => include_bytes!("utf16be.yaml"),
"utf16le" => include_bytes!("utf16le.yaml"),
"utf32be" => include_bytes!("utf32be.yaml"),
"utf32le" => include_bytes!("utf32le.yaml"),
"utf16bebom" => include_bytes!("utf16bebom.yaml"),
"utf32lebom" => include_bytes!("utf32lebom.yaml"),
name => panic!("{name} is not a known YAML encoding input"),
}
}
#[test]
fn toml_reordering() {
const INPUT: &[u8] = include_bytes!("single_reordered.json");
const EXPECTED: &str = include_str!("single.toml");
let mut output = Vec::with_capacity(EXPECTED.len());
xt::translate_slice(INPUT, Some(Format::Json), Format::Toml, &mut output).unwrap();
assert_eq!(std::str::from_utf8(&output), Ok(EXPECTED));
}
#[test]
fn toml_initial_table_detection() {
const INPUT: &[u8] = include_bytes!("initial_table.toml");
xt::translate_reader(INPUT, None, Format::Json, io::sink()).unwrap();
}
#[test]
fn yaml_halting_without_panic() {
const INPUT: &[u8] = include_bytes!("nullkey.yaml");
let _ = xt::translate_slice(INPUT, Some(Format::Yaml), Format::Json, std::io::sink());
}