use interscript_rs::Error;
use interscript_rs::Runtime;
use std::path::PathBuf;
fn corpus_dir() -> Vec<PathBuf> {
vec![PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/corpus")]
}
fn rt() -> Runtime {
Runtime::new(corpus_dir())
}
#[test]
fn ruleset_expansion_is_recursive_and_in_position() {
let runtime = rt();
assert_eq!(
runtime.transliterate("rs-wf-ruleset", "aeikx").unwrap(),
"AEIKX"
);
}
#[test]
fn ruleset_parallel_block_is_one_pass() {
let runtime = rt();
assert_eq!(runtime.transliterate("rs-wf-ruleset", "kk").unwrap(), "KK");
}
#[test]
fn ruleset_funcall_passes_through() {
let runtime = rt();
assert_eq!(
runtime.transliterate_stage("rs-wf-ruleset", "fun", "sis", None).unwrap(),
"SIS"
);
}
#[test]
fn use_inside_parallel_joins_the_pass() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_stage("rs-wf-ruleset", "flat", "kpk kp kk", None)
.unwrap(),
"KPK KP KK"
);
}
#[test]
fn ruleset_is_not_a_stage() {
let runtime = rt();
let err = runtime
.transliterate_stage("rs-wf-ruleset", "vowels", "a", None)
.err()
.expect("ruleset must not execute as a stage");
assert!(matches!(err, Error::MapLogic(_)), "got {err:?}");
assert!(err.to_string().contains("not found"));
}
#[test]
fn document_carries_expanded_rulesets_and_languages() {
let runtime = rt();
let doc = runtime.load("rs-wf-ruleset").unwrap();
assert_eq!(doc.rulesets.len(), 4);
let plus = &doc.rulesets["vowels_plus"];
assert_eq!(plus.items.len(), 3);
let lang_doc = runtime.load("rs-wf-languages").unwrap();
assert_eq!(lang_doc.languages, vec!["kur".to_string(), "chv".to_string()]);
}
#[test]
fn use_cycle_is_a_load_error() {
let dir = std::env::temp_dir().join(format!("iscrs-use-cycle-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("cycle.isc"),
"system \"T:cycle:1\" {\n ruleset a { use b }\n ruleset b { use a }\n stage main { use a }\n}\n",
)
.unwrap();
let runtime = Runtime::new(vec![dir.clone()]);
let err = runtime
.transliterate("cycle", "x")
.err()
.expect("cycle must not load");
assert!(matches!(err, Error::MapLogic(ref m) if m.contains("use cycle")), "got {err:?}");
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn self_use_cycle_is_a_load_error() {
let dir = std::env::temp_dir().join(format!("iscrs-self-cycle-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("selfcyc.isc"),
"system \"T:selfcyc:1\" {\n ruleset a { use a }\n stage main { use a }\n}\n",
)
.unwrap();
let runtime = Runtime::new(vec![dir.clone()]);
let err = runtime.transliterate("selfcyc", "x").err().expect("cycle");
assert!(matches!(err, Error::MapLogic(ref m) if m.contains("use cycle")), "got {err:?}");
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn unknown_ruleset_is_a_load_error() {
let dir = std::env::temp_dir().join(format!("iscrs-unknown-rs-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("unknown.isc"),
"system \"T:unknown:1\" {\n stage main { use nope }\n}\n",
)
.unwrap();
let runtime = Runtime::new(vec![dir.clone()]);
let err = runtime.transliterate("unknown", "x").err().expect("error");
assert!(
matches!(err, Error::MapLogic(ref m) if m.contains("ruleset \"nope\" not found")),
"got {err:?}"
);
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn unknown_dep_ruleset_is_a_load_error() {
let dir = std::env::temp_dir().join(format!("iscrs-unknown-dep-rs-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join("badalias.isc"),
"system \"T:badalias:1\" {\n stage main { use shared.base }\n}\n",
)
.unwrap();
std::fs::write(
dir.join("badrs.isc"),
"system \"T:badrs:1\" {\n dependency \"rs-wf-override-dep\" as shared\n stage main { use shared.nope }\n}\n",
)
.unwrap();
let dir2 = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/corpus");
let runtime = Runtime::new(vec![dir.clone(), dir2]);
let err = runtime.transliterate("badalias", "x").err().expect("error");
assert!(
matches!(err, Error::MapLogic(ref m) if m.contains("dep alias \"shared\" not found")),
"got {err:?}"
);
let err = runtime.transliterate("badrs", "x").err().expect("error");
assert!(
matches!(err, Error::MapLogic(ref m) if m.contains("ruleset \"nope\" of dep \"shared\" not found")),
"got {err:?}"
);
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn override_child_wins_exact_from() {
let runtime = rt();
assert_eq!(runtime.transliterate("rs-wf-override", "khtk").unwrap(), "xtk");
assert_eq!(runtime.transliterate("rs-wf-override", "kc").unwrap(), "kc");
}
#[test]
fn override_replaces_every_same_from_row() {
let runtime = rt();
let out = runtime
.transliterate_stage("rs-wf-override", "dup", "s", None)
.unwrap();
assert_eq!(out, "S");
}
#[test]
fn override_appends_stage_level_without_trailing_parallel() {
let runtime = rt();
let out = runtime
.transliterate_stage("rs-wf-override", "tailjoin", "qA", None)
.unwrap();
assert_eq!(out, "Qa");
}
#[test]
fn override_keeps_order_then_appends() {
let runtime = rt();
let out = runtime
.transliterate_stage("rs-wf-override", "seq", "ab", None)
.unwrap();
assert_eq!(out, "aY");
}
#[test]
fn override_row_guard_applies_to_that_row_alone() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_stage("rs-wf-override", "lang", "k", Some("kur"))
.unwrap(),
"kk"
);
assert_eq!(
runtime
.transliterate_stage("rs-wf-override", "lang", "k", None)
.unwrap(),
"k"
);
}
#[test]
fn no_selection_all_guards_inert() {
let runtime = rt();
assert_eq!(runtime.transliterate("rs-wf-languages", "қҫ").unwrap(), "ķş");
}
#[test]
fn kur_selection_guard_beats_generic() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_lang("rs-wf-languages", "қҫ", Some("kur"))
.unwrap(),
"k̦ş"
);
}
#[test]
fn chv_selection_guard_beats_generic() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_lang("rs-wf-languages", "қҫ", Some("chv"))
.unwrap(),
"ķș"
);
}
#[test]
fn undeclared_selection_is_like_no_selection() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_lang("rs-wf-languages", "қҫ", Some("rus"))
.unwrap(),
"ķş"
);
}
#[test]
fn sequence_guards_skip_when_inert() {
let runtime = rt();
assert_eq!(
runtime
.transliterate_stage("rs-wf-languages", "seqguards", "k", None)
.unwrap(),
"Q"
);
assert_eq!(
runtime
.transliterate_stage("rs-wf-languages", "seqguards", "k", Some("kur"))
.unwrap(),
"K"
);
assert_eq!(
runtime
.transliterate_stage("rs-wf-languages", "seqguards", "k", Some("chv"))
.unwrap(),
"Q"
);
}