#[cfg_attr(not(test), expect(dead_code, reason = "the corpus is a test fixture"))]
pub(crate) fn document(name: &str) -> &'static str {
match name {
"numbers.json" => include_str!("../../fixtures/documents/numbers.json"),
"numbers.yaml" => include_str!("../../fixtures/documents/numbers.yaml"),
"numbers.toml" => include_str!("../../fixtures/documents/numbers.toml"),
"mixed-array.toml" => include_str!("../../fixtures/documents/mixed-array.toml"),
"numbers.ini" => include_str!("../../fixtures/documents/numbers.ini"),
"numbers.env" => include_str!("../../fixtures/documents/numbers.env"),
"numbers.csv" => include_str!("../../fixtures/documents/numbers.csv"),
"numbers.txt" => include_str!("../../fixtures/documents/numbers.txt"),
other => panic!("the corpus has no document named {other}"),
}
}
#[cfg(test)]
mod tests {
use serde::Deserialize;
use crate::extract::render::js_number;
const CORPUS: &str = include_str!("../../fixtures/extraction.json");
#[derive(Debug, Deserialize)]
struct Corpus {
rendering: Vec<RenderCase>,
}
#[derive(Debug, Deserialize)]
struct RenderCase {
input: String,
expected: String,
}
#[test]
fn every_pinned_rendering_matches_javascript() {
let corpus: Corpus = serde_json::from_str(CORPUS).expect("the corpus is valid JSON");
assert!(!corpus.rendering.is_empty(), "the corpus pins no rendering");
for case in corpus.rendering {
let value: f64 = case.input.parse().expect(&case.input);
assert_eq!(js_number(value), case.expected, "rendering {}", case.input);
}
}
#[test]
fn serde_json_still_rounds_a_large_integer_differently() {
let token = "123456789012345680000";
let via_serde: f64 = serde_json::from_str(token).expect("a number");
let via_std: f64 = token.parse().expect("a number");
assert_ne!(
via_serde.to_bits(),
via_std.to_bits(),
"serde_json now parses this correctly — json.rs can stop working around it"
);
assert_eq!(
js_number(via_std),
token,
"str::parse is the one that agrees"
);
}
#[test]
fn the_corpus_pins_both_notation_boundaries() {
let corpus: Corpus = serde_json::from_str(CORPUS).expect("the corpus is valid JSON");
let pinned: Vec<&str> = corpus
.rendering
.iter()
.map(|case| case.expected.as_str())
.collect();
for boundary in ["100000000000000000000", "1e+21", "0.000001", "1e-7"] {
assert!(
pinned.contains(&boundary),
"the corpus no longer pins {boundary}"
);
}
}
}
#[cfg(test)]
mod document_tests {
use serde::Deserialize;
use super::document;
use crate::extract::{Options, extract};
const CORPUS: &str = include_str!("../../fixtures/extraction.json");
#[derive(Debug, Deserialize)]
struct Corpus {
documents: Vec<Case>,
}
#[derive(Debug, Deserialize)]
struct Case {
name: String,
file: String,
#[serde(rename = "fileType")]
file_type: String,
expected: Vec<String>,
errors: Vec<String>,
}
#[test]
fn every_corpus_document_reproduces() {
let corpus: Corpus = serde_json::from_str(CORPUS).expect("the corpus is valid JSON");
assert!(!corpus.documents.is_empty(), "the corpus is empty");
for case in corpus.documents {
if case.file == "mixed-array.toml" {
assert!(
!case.errors.is_empty(),
"the divergence has stopped being one"
);
continue;
}
assert_eq!(
extract(document(&case.file), &case.file_type, Options),
case.expected,
"{}",
case.name
);
}
}
#[test]
fn the_corpus_covers_every_extractor() {
let corpus: Corpus = serde_json::from_str(CORPUS).expect("the corpus is valid JSON");
for format in ["json", "yaml", "toml", "ini", "env", "csv", "unknown"] {
assert!(
corpus.documents.iter().any(|case| case.file_type == format),
"no corpus case reads {format}"
);
}
}
}