mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 03:07:13 +00:00
seriesof: the series a book belongs to, and which volume this is
This commit is contained in:
@@ -24,6 +24,7 @@ mdscrub.workspace = true
|
||||
mdsplit.workspace = true
|
||||
avplan.workspace = true
|
||||
pdfgutter.workspace = true
|
||||
seriesof.workspace = true
|
||||
pdftriage.workspace = true
|
||||
rrf.workspace = true
|
||||
corpus-core.workspace = true
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
{"name": "number-9-0", "kind": "number", "text": "9"}
|
||||
{"name": "number-IX-1", "kind": "number", "text": "IX"}
|
||||
{"name": "number-ix-2", "kind": "number", "text": "ix"}
|
||||
{"name": "number-ix-3", "kind": "number", "text": " ix "}
|
||||
{"name": "number-XX-4", "kind": "number", "text": "XX"}
|
||||
{"name": "number-0-5", "kind": "number", "text": "0"}
|
||||
{"name": "number-201-6", "kind": "number", "text": "201"}
|
||||
{"name": "number-200-7", "kind": "number", "text": "200"}
|
||||
{"name": "number-1-8", "kind": "number", "text": "1"}
|
||||
{"name": "number-xxi-9", "kind": "number", "text": "xxi"}
|
||||
{"name": "number-nine-10", "kind": "number", "text": "nine"}
|
||||
{"name": "number-blank-11", "kind": "number", "text": ""}
|
||||
{"name": "number-blank-12", "kind": "number", "text": " "}
|
||||
{"name": "number-i-13", "kind": "number", "text": "i"}
|
||||
{"name": "number-III-14", "kind": "number", "text": "III"}
|
||||
{"name": "number-c-15", "kind": "number", "text": "c"}
|
||||
{"name": "number-l-16", "kind": "number", "text": "l"}
|
||||
{"name": "number-12.5-17", "kind": "number", "text": "12.5"}
|
||||
{"name": "number-07-18", "kind": "number", "text": "07"}
|
||||
{"name": "number-\u0663-19", "kind": "number", "text": "\u0663"}
|
||||
{"name": "volume-20", "kind": "volume", "title": "The Philokalia Vol 3"}
|
||||
{"name": "volume-21", "kind": "volume", "title": "Collected Works of C.G. Jung, Volume 9"}
|
||||
{"name": "volume-22", "kind": "volume", "title": "The Art of Computer Programming, Volume 3: Sorting and Searching"}
|
||||
{"name": "volume-23", "kind": "volume", "title": "The Song of the Sirin (Raven Son Book 1)"}
|
||||
{"name": "volume-24", "kind": "volume", "title": "Vol. 2. PLATO, EPICTETUS, MARCUS AURELIUS"}
|
||||
{"name": "volume-25", "kind": "volume", "title": "Book 1"}
|
||||
{"name": "volume-26", "kind": "volume", "title": "Being and Time 1927"}
|
||||
{"name": "volume-27", "kind": "volume", "title": "Ethics 2"}
|
||||
{"name": "volume-28", "kind": "volume", "title": "A History of Philosophy, Vol. IV"}
|
||||
{"name": "volume-29", "kind": "volume", "title": "A History of Philosophy Volume IV: Modern Philosophy"}
|
||||
{"name": "volume-30", "kind": "volume", "title": "The Lord of the Rings Part 2"}
|
||||
{"name": "volume-31", "kind": "volume", "title": "Summa Theologica, Tome II"}
|
||||
{"name": "volume-32", "kind": "volume", "title": "Institutes Bk 4"}
|
||||
{"name": "volume-33", "kind": "volume", "title": "Harry Potter (Book 7)"}
|
||||
{"name": "volume-34", "kind": "volume", "title": "The Decline and Fall vol. xx"}
|
||||
{"name": "volume-35", "kind": "volume", "title": "The Decline and Fall vol. xxi"}
|
||||
{"name": "volume-36", "kind": "volume", "title": "Works pt 3"}
|
||||
{"name": "volume-37", "kind": "volume", "title": "Volume 1"}
|
||||
{"name": "volume-38", "kind": "volume", "title": ""}
|
||||
{"name": "volume-39", "kind": "volume", "title": " "}
|
||||
{"name": "volume-40", "kind": "volume", "title": "The Republic"}
|
||||
{"name": "volume-41", "kind": "volume", "title": "Selected Works Vol 201"}
|
||||
{"name": "volume-42", "kind": "volume", "title": "Selected Works Vol 0"}
|
||||
{"name": "volume-43", "kind": "volume", "title": "abc Vol 1"}
|
||||
{"name": "volume-44", "kind": "volume", "title": "abcd Vol 1"}
|
||||
{"name": "volume-45", "kind": "volume", "title": "(Raven Son Book 12)"}
|
||||
{"name": "volume-46", "kind": "volume", "title": "Sirin [Raven Son Book 3]"}
|
||||
{"name": "volume-47", "kind": "volume", "title": "Title (Series Book 2) extra"}
|
||||
{"name": "volume-48", "kind": "volume", "title": "Jung \u2014 Volume 9"}
|
||||
{"name": "volume-49", "kind": "volume", "title": "Jung \u2013 Volume 9"}
|
||||
{"name": "volume-50", "kind": "volume", "title": "Nicomachean Ethics, Books VIII and IX"}
|
||||
{"name": "volume-51", "kind": "volume", "title": "The Cambridge History, Volume II: The Middle Ages"}
|
||||
{"name": "publisher-52", "kind": "publisher", "title": "Aquinas (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-53", "kind": "publisher", "title": "Nietzsche (Companion)", "author": "Blackwell"}
|
||||
{"name": "publisher-54", "kind": "publisher", "title": "Logic (Very Short Introduction)", "author": "Oxford"}
|
||||
{"name": "publisher-55", "kind": "publisher", "title": "Ethics (Handbook)", "author": "Oxford"}
|
||||
{"name": "publisher-56", "kind": "publisher", "title": "Ethics (Companion)", "author": "Routledge"}
|
||||
{"name": "publisher-57", "kind": "publisher", "title": "Christian Ethics (2004) (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-58", "kind": "publisher", "title": "Christian Ethics.2009 (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-59", "kind": "publisher", "title": "Christian Ethics [2006] (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-60", "kind": "publisher", "title": "British Drama [Contemporary] (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-61", "kind": "publisher", "title": "Aquinas (Second Edition)", "author": "Cambridge"}
|
||||
{"name": "publisher-62", "kind": "publisher", "title": "Aquinas", "author": "Cambridge"}
|
||||
{"name": "publisher-63", "kind": "publisher", "title": "Aquinas (Companion)", "author": "Fergus Kerr"}
|
||||
{"name": "publisher-64", "kind": "publisher", "title": "Aquinas (Companion)", "author": null}
|
||||
{"name": "publisher-65", "kind": "publisher", "title": "(Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-66", "kind": "publisher", "title": "Ethics (Companion)", "author": " WILEY BLACKWELL "}
|
||||
{"name": "publisher-67", "kind": "publisher", "title": "Ethics (Companions)", "author": "Cambridge"}
|
||||
{"name": "publisher-68", "kind": "publisher", "title": "Kant (Guidebook)", "author": "Routledge"}
|
||||
{"name": "publisher-69", "kind": "publisher", "title": "Mind (Contemporary Debates)", "author": "Blackwell"}
|
||||
{"name": "publisher-70", "kind": "publisher", "title": "Philosophy (Anthology)", "author": "Blackwell"}
|
||||
{"name": "publisher-71", "kind": "publisher", "title": "Theology (Studies)", "author": "SUNY"}
|
||||
{"name": "publisher-72", "kind": "publisher", "title": "Hegel (Concise)", "author": "Blackwell"}
|
||||
{"name": "publisher-73", "kind": "publisher", "title": "Ethics (Contemporary Introductions)", "author": "Routledge"}
|
||||
{"name": "publisher-74", "kind": "publisher", "title": "X (Companion)", "author": "Cambridge"}
|
||||
{"name": "publisher-75", "kind": "publisher", "title": "Ethics (companion)", "author": "cambridge"}
|
||||
{"name": "publisher-76", "kind": "publisher", "title": "Ethics ( Companion )", "author": "Cambridge"}
|
||||
{"name": "publisher-77", "kind": "publisher", "title": "Ethics (Handbook)", "author": "Palgrave"}
|
||||
{"name": "publisher-78", "kind": "publisher", "title": "Ethics (Handbook)", "author": "Springer"}
|
||||
{"name": "publisher-79", "kind": "publisher", "title": "", "author": "Cambridge"}
|
||||
@@ -0,0 +1,80 @@
|
||||
{"kind": "number", "name": "number-9-0", "number": 9}
|
||||
{"kind": "number", "name": "number-IX-1", "number": 9}
|
||||
{"kind": "number", "name": "number-ix-2", "number": 9}
|
||||
{"kind": "number", "name": "number-ix-3", "number": 9}
|
||||
{"kind": "number", "name": "number-XX-4", "number": 20}
|
||||
{"kind": "number", "name": "number-0-5", "number": null}
|
||||
{"kind": "number", "name": "number-201-6", "number": null}
|
||||
{"kind": "number", "name": "number-200-7", "number": 200}
|
||||
{"kind": "number", "name": "number-1-8", "number": 1}
|
||||
{"kind": "number", "name": "number-xxi-9", "number": null}
|
||||
{"kind": "number", "name": "number-nine-10", "number": null}
|
||||
{"kind": "number", "name": "number-blank-11", "number": null}
|
||||
{"kind": "number", "name": "number-blank-12", "number": null}
|
||||
{"kind": "number", "name": "number-i-13", "number": 1}
|
||||
{"kind": "number", "name": "number-III-14", "number": 3}
|
||||
{"kind": "number", "name": "number-c-15", "number": null}
|
||||
{"kind": "number", "name": "number-l-16", "number": null}
|
||||
{"kind": "number", "name": "number-12.5-17", "number": null}
|
||||
{"kind": "number", "name": "number-07-18", "number": 7}
|
||||
{"kind": "number", "name": "number-\u0663-19", "number": 3}
|
||||
{"kind": "volume", "name": "volume-20", "series": "The Philokalia", "volume": 3}
|
||||
{"kind": "volume", "name": "volume-21", "series": "Collected Works of C.G. Jung", "volume": 9}
|
||||
{"kind": "volume", "name": "volume-22", "series": "The Art of Computer Programming", "volume": 3}
|
||||
{"kind": "volume", "name": "volume-23", "series": "Raven Son", "volume": 1}
|
||||
{"kind": "volume", "name": "volume-24", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-25", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-26", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-27", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-28", "series": "A History of Philosophy", "volume": 4}
|
||||
{"kind": "volume", "name": "volume-29", "series": "A History of Philosophy", "volume": 4}
|
||||
{"kind": "volume", "name": "volume-30", "series": "The Lord of the Rings", "volume": 2}
|
||||
{"kind": "volume", "name": "volume-31", "series": "Summa Theologica", "volume": 2}
|
||||
{"kind": "volume", "name": "volume-32", "series": "Institutes", "volume": 4}
|
||||
{"kind": "volume", "name": "volume-33", "series": "Harry Potter", "volume": 7}
|
||||
{"kind": "volume", "name": "volume-34", "series": "The Decline and Fall", "volume": 20}
|
||||
{"kind": "volume", "name": "volume-35", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-36", "series": "Works", "volume": 3}
|
||||
{"kind": "volume", "name": "volume-37", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-38", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-39", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-40", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-41", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-42", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-43", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-44", "series": "abcd", "volume": 1}
|
||||
{"kind": "volume", "name": "volume-45", "series": "Raven Son", "volume": 12}
|
||||
{"kind": "volume", "name": "volume-46", "series": "Raven Son", "volume": 3}
|
||||
{"kind": "volume", "name": "volume-47", "series": "Series", "volume": 2}
|
||||
{"kind": "volume", "name": "volume-48", "series": "Jung", "volume": 9}
|
||||
{"kind": "volume", "name": "volume-49", "series": "Jung", "volume": 9}
|
||||
{"kind": "volume", "name": "volume-50", "series": null, "volume": null}
|
||||
{"kind": "volume", "name": "volume-51", "series": "The Cambridge History", "volume": 2}
|
||||
{"kind": "publisher", "name": "publisher-52", "proposed_title": "The Cambridge Companion to Aquinas", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-53", "proposed_title": null, "series": "Blackwell Companions"}
|
||||
{"kind": "publisher", "name": "publisher-54", "proposed_title": "Logic: A Very Short Introduction", "series": "Very Short Introductions"}
|
||||
{"kind": "publisher", "name": "publisher-55", "proposed_title": "The Oxford Handbook of Ethics", "series": "Oxford Handbooks"}
|
||||
{"kind": "publisher", "name": "publisher-56", "proposed_title": "The Routledge Companion to Ethics", "series": "Routledge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-57", "proposed_title": "The Cambridge Companion to Christian Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-58", "proposed_title": "The Cambridge Companion to Christian Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-59", "proposed_title": "The Cambridge Companion to Christian Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-60", "proposed_title": "The Cambridge Companion to British Drama", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-61", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-62", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-63", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-64", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-65", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-66", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-67", "proposed_title": "The Cambridge Companion to Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-68", "proposed_title": "Routledge Philosophy Guidebook to Kant", "series": "Routledge Philosophy Guidebooks"}
|
||||
{"kind": "publisher", "name": "publisher-69", "proposed_title": "Contemporary Debates in Mind", "series": "Contemporary Debates"}
|
||||
{"kind": "publisher", "name": "publisher-70", "proposed_title": null, "series": "Blackwell Anthologies"}
|
||||
{"kind": "publisher", "name": "publisher-71", "proposed_title": null, "series": "SUNY Studies"}
|
||||
{"kind": "publisher", "name": "publisher-72", "proposed_title": null, "series": "Blackwell Concise Companions"}
|
||||
{"kind": "publisher", "name": "publisher-73", "proposed_title": null, "series": "Routledge Contemporary Introductions"}
|
||||
{"kind": "publisher", "name": "publisher-74", "proposed_title": null, "series": null}
|
||||
{"kind": "publisher", "name": "publisher-75", "proposed_title": "The Cambridge Companion to Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-76", "proposed_title": "The Cambridge Companion to Ethics", "series": "Cambridge Companions"}
|
||||
{"kind": "publisher", "name": "publisher-77", "proposed_title": null, "series": "Palgrave Handbooks"}
|
||||
{"kind": "publisher", "name": "publisher-78", "proposed_title": null, "series": "Springer Handbooks"}
|
||||
{"kind": "publisher", "name": "publisher-79", "proposed_title": null, "series": null}
|
||||
@@ -0,0 +1,44 @@
|
||||
"""Read a series and a volume off a title the way the book pipeline did.
|
||||
|
||||
The functions the module exports are imported rather than copied — it has no
|
||||
import-time side effects, unlike the modules the other oracles copy from.
|
||||
|
||||
python3 oracle/series.py < cases.ndjson
|
||||
|
||||
One case per line: {name, title, author}. Writes one JSON answer per line.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
from book_pipeline.series import ( # noqa: E402
|
||||
parse_publisher_series,
|
||||
parse_volume,
|
||||
roman_or_int,
|
||||
)
|
||||
|
||||
|
||||
def answer(case: dict) -> dict:
|
||||
kind = case["kind"]
|
||||
if kind == "number":
|
||||
return {"number": roman_or_int(case["text"])}
|
||||
if kind == "volume":
|
||||
found = parse_volume(case["title"])
|
||||
return {"series": found[0] if found else None,
|
||||
"volume": found[1] if found else None}
|
||||
if kind == "publisher":
|
||||
found = parse_publisher_series(case["title"], case.get("author"))
|
||||
return {"proposed_title": found[0] if found else None,
|
||||
"series": found[1] if found else None}
|
||||
raise SystemExit(f"no such case: {kind}")
|
||||
|
||||
|
||||
for line in sys.stdin:
|
||||
if not line.strip():
|
||||
continue
|
||||
case = json.loads(line)
|
||||
out = {"name": case["name"], "kind": case["kind"]}
|
||||
out.update(answer(case))
|
||||
sys.stdout.write(json.dumps(out, sort_keys=True) + "\n")
|
||||
+14
-1
@@ -19,7 +19,7 @@ type Written = Result<Vec<String>, String>;
|
||||
type Job = (&'static str, fn() -> Written);
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let jobs: [Job; 17] = [
|
||||
let jobs: [Job; 18] = [
|
||||
("tokens", tokens),
|
||||
("unescape", unescape),
|
||||
("chunkmd", chunkmd),
|
||||
@@ -37,6 +37,7 @@ fn main() -> ExitCode {
|
||||
("mdsplit", mdsplit),
|
||||
("avplan", avplan),
|
||||
("pdfgutter", pdfgutter),
|
||||
("seriesof", seriesof),
|
||||
];
|
||||
|
||||
for (name, job) in jobs {
|
||||
@@ -219,6 +220,18 @@ fn cueseg() -> Written {
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn seriesof() -> Written {
|
||||
let dir = parity::golden("seriesof");
|
||||
std::fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
|
||||
|
||||
let cases = parity::dir().join("cases/seriesof/cases.ndjson");
|
||||
let text = std::fs::read_to_string(&cases).map_err(|e| e.to_string())?;
|
||||
let answers = parity::run_oracle("series.py", &text)?;
|
||||
let path = dir.join("cases.ndjson");
|
||||
std::fs::write(&path, answers).map_err(|e| e.to_string())?;
|
||||
Ok(vec![path.display().to_string()])
|
||||
}
|
||||
|
||||
fn pdfgutter() -> Written {
|
||||
let dir = parity::golden("pdfgutter");
|
||||
std::fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
//! Every series and volume read off a title must match the Python exactly.
|
||||
//!
|
||||
//! The cost of getting it wrong is a shelf that looks right and is not: a
|
||||
//! volume filed under the wrong series disappears from the work it belongs
|
||||
//! to, and a title reconstructed from the wrong template renames a book to
|
||||
//! something nobody published.
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
fn records(text: &str) -> Vec<Value> {
|
||||
text.lines()
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| serde_json::from_str(line).expect("valid JSON"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn cases() -> Vec<Value> {
|
||||
let text = std::fs::read_to_string(parity::dir().join("cases/seriesof/cases.ndjson"))
|
||||
.expect("a readable case file");
|
||||
records(&text)
|
||||
}
|
||||
|
||||
/// A string field, where `null` and absent mean the same thing.
|
||||
fn text(value: &Value) -> Option<&str> {
|
||||
value.as_str()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_series_matches_python() {
|
||||
let golden = records(&parity::read_golden_text("seriesof/cases.ndjson"));
|
||||
let cases = cases();
|
||||
assert_eq!(cases.len(), golden.len(), "case count moved — regenerate");
|
||||
|
||||
let mut wrong: Vec<String> = Vec::new();
|
||||
for (case, theirs) in cases.iter().zip(&golden) {
|
||||
let name = case["name"].as_str().expect("a name");
|
||||
let kind = case["kind"].as_str().expect("a kind");
|
||||
assert_eq!(theirs["name"].as_str(), Some(name), "cases out of order");
|
||||
|
||||
let mut note = |field: &str, ours: String, theirs: &Value| {
|
||||
wrong.push(format!("{name}.{field}: python {theirs}, rust {ours}"));
|
||||
};
|
||||
|
||||
match kind {
|
||||
"number" => {
|
||||
let ours = seriesof::roman_or_int(case["text"].as_str().expect("text"));
|
||||
let theirs_number = theirs["number"].as_u64().map(|n| n as u32);
|
||||
if ours != theirs_number {
|
||||
note("number", format!("{ours:?}"), &theirs["number"]);
|
||||
}
|
||||
}
|
||||
"volume" => {
|
||||
let found = seriesof::parse_volume(case["title"].as_str().expect("a title"));
|
||||
let (series, volume) = match &found {
|
||||
Some((series, volume)) => (Some(series.as_str()), Some(*volume)),
|
||||
None => (None, None),
|
||||
};
|
||||
if series != text(&theirs["series"]) {
|
||||
note("series", format!("{series:?}"), &theirs["series"]);
|
||||
}
|
||||
let theirs_volume = theirs["volume"].as_u64().map(|n| n as u32);
|
||||
if volume != theirs_volume {
|
||||
note("volume", format!("{volume:?}"), &theirs["volume"]);
|
||||
}
|
||||
}
|
||||
"publisher" => {
|
||||
let author = case["author"].as_str();
|
||||
let found = author.and_then(|author| {
|
||||
seriesof::publisher_series(case["title"].as_str().expect("a title"), author)
|
||||
});
|
||||
let (proposed, series) = match &found {
|
||||
Some((proposed, series)) => (proposed.as_deref(), Some(series.as_str())),
|
||||
None => (None, None),
|
||||
};
|
||||
if proposed != text(&theirs["proposed_title"]) {
|
||||
note(
|
||||
"proposed_title",
|
||||
format!("{proposed:?}"),
|
||||
&theirs["proposed_title"],
|
||||
);
|
||||
}
|
||||
if series != text(&theirs["series"]) {
|
||||
note("series", format!("{series:?}"), &theirs["series"]);
|
||||
}
|
||||
}
|
||||
other => panic!("nothing answers a {other} case"),
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
wrong.is_empty(),
|
||||
"{} answers differ:\n{}",
|
||||
wrong.len(),
|
||||
wrong
|
||||
.iter()
|
||||
.take(20)
|
||||
.map(|line| line.chars().take(200).collect::<String>())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
/// All three questions have to be asked, or the file proves less than it
|
||||
/// looks like it does.
|
||||
#[test]
|
||||
fn every_kind_of_case_is_present() {
|
||||
let cases = cases();
|
||||
for kind in ["number", "volume", "publisher"] {
|
||||
assert!(
|
||||
cases.iter().any(|case| case["kind"] == kind),
|
||||
"no {kind} case"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Catches a golden file drifting away from a Python that has moved on.
|
||||
#[test]
|
||||
#[cfg(feature = "python")]
|
||||
fn the_golden_file_still_matches_live_python() {
|
||||
let cases = std::fs::read_to_string(parity::dir().join("cases/seriesof/cases.ndjson"))
|
||||
.expect("a readable case file");
|
||||
let live = parity::run_oracle("series.py", &cases).expect("the oracle runs");
|
||||
assert_eq!(live, parity::read_golden_text("seriesof/cases.ndjson"));
|
||||
}
|
||||
Reference in New Issue
Block a user