mod common;
use std::sync::Arc;
use common::*;
use ikigai_conformance::{Fixture, Suite};
use ikigai_core::Verb;
use ikigai_script::ScriptSpace;
const SPACE_LABEL: &str = "ikigai_script::space(config)";
fn seeded() -> (Host, String) {
let host = host();
let version = publish(&host.kernel, "walk", "(+ 1 2)", &[]);
publish(&host.kernel, "retiree", "1", &[]);
ok(&host.kernel, Verb::Sink, "urn:script:walk:runs", &[]);
let digest = version
.rsplit(":version:")
.next()
.expect("a version IRI")
.to_string();
(host, digest)
}
const BASE_INHERITED: [(&str, &str); 4] = [
(
"eval",
"ikigai-lisp's own conformance suite covers it; it is bound here only because every \
run composes over it",
),
("whoami", "a test probe, not part of this crate"),
("vault", "a test probe, not part of this crate"),
("fallback", "a test probe, not part of this crate"),
];
fn assert_inherited(report: &ikigai_conformance::Report, expected: &[(&str, String)]) {
for (id, why) in expected {
println!("inherited because: {id}: {why}");
}
let mut inherited: Vec<&str> = report
.declared
.inherited
.iter()
.map(String::as_str)
.collect();
inherited.sort_unstable();
let mut expected: Vec<&str> = expected.iter().map(|(id, _)| *id).collect();
expected.sort_unstable();
assert_eq!(inherited, expected, "{report}");
}
fn base_inherited() -> Vec<(&'static str, String)> {
BASE_INHERITED
.iter()
.map(|(id, why)| (*id, why.to_string()))
.collect()
}
fn suite(digest: &str, space: &Arc<ScriptSpace>) -> Suite {
Suite::new()
.own("script*")
.required_on_mutating()
.host_named_space(SPACE_LABEL, Arc::clone(space))
.fixture(Fixture::new("script", Verb::Source).binding("name", "walk"))
.fixture(Fixture::new("script", Verb::Exists).binding("name", "walk"))
.fixture(
Fixture::new("script", Verb::Sink)
.binding("name", "published")
.arg("content", "(+ 2 2)"),
)
.fixture(Fixture::new("script", Verb::Delete).binding("name", "retiree"))
.fixture(
Fixture::new("script-version", Verb::Source)
.binding("name", "walk")
.binding("digest", digest),
)
.fixture(
Fixture::new("script-version", Verb::Exists)
.binding("name", "walk")
.binding("digest", digest),
)
.fixture(Fixture::new("script-compiled", Verb::Source).binding("name", "walk"))
.fixture(Fixture::new("script-result", Verb::Source).binding("name", "walk"))
.fixture(Fixture::new("script-runs", Verb::Sink).binding("name", "walk"))
.fixture(
Fixture::new("script-run", Verb::Source)
.binding("name", "walk")
.binding("id", "1"),
)
.fixture(
Fixture::new("script-run", Verb::Exists)
.binding("name", "walk")
.binding("id", "1"),
)
.fixture(Fixture::new("script-eval", Verb::Sink).arg("content", "(+ 1 2)"))
.cacheable("script")
.cacheable("script-compiled")
.pure("script-version")
.pure("script-run")
.live("script-catalog")
}
#[test]
fn conforms() {
let (host, digest) = seeded();
let report = suite(&digest, &host.space).run_blocking(&host.kernel);
println!("{report}");
assert!(report.is_clean(), "{report}");
assert!(
report
.to_string()
.contains(&format!("space: {SPACE_LABEL} host-named\n")),
"{report}"
);
}
#[test]
fn the_walk_reaches_every_resource_this_crate_binds() {
let (host, digest) = seeded();
let report = suite(&digest, &host.space).run_blocking(&host.kernel);
let mut walked: Vec<&str> = report
.walked
.iter()
.map(String::as_str)
.filter(|id| id.starts_with("script"))
.collect();
walked.sort_unstable();
assert_inherited(&report, &base_inherited());
assert_eq!(
walked,
vec![
"script",
"script-catalog",
"script-compiled",
"script-eval",
"script-result",
"script-run",
"script-runs",
"script-version",
],
"{report}"
);
}
const STORE_IDS: [&str; 13] = [
"store-select",
"store-graph-select",
"store-ask",
"store-graph-ask",
"store-construct",
"store-graph-construct",
"store-describe",
"store-graph-describe",
"store-info",
"store-graphs",
"store-update",
"store-graph-update",
"store-load",
];
fn sparql_seeded() -> (SparqlHost, String) {
let host = sparql_host();
seed(
&host.kernel,
"INSERT DATA { GRAPH <urn:test:g> { <urn:item:1> <urn:p:age> 10 } }",
);
let version = publish(&host.kernel, "walk", "(+ 1 2)", &[]);
publish(&host.kernel, "retiree", "1", &[]);
ok(&host.kernel, Verb::Sink, "urn:script:walk:runs", &[]);
publish(
&host.kernel,
"walkq",
"# The walk's query.\n# @param days xsd:integer -- older than this\n\
SELECT ?item WHERE { GRAPH <urn:test:g> { ?item <urn:p:age> ?age FILTER(?age > ?days) } }",
&[("language", "sparql")],
);
publish(
&host.kernel,
"walku",
"# @param age xsd:integer\n\
INSERT { GRAPH <urn:test:g> { ?item <urn:p:age> ?age } } WHERE { GRAPH <urn:test:g> { ?item <urn:p:age> ?old } }",
&[("language", "sparql")],
);
let digest = version
.rsplit(":version:")
.next()
.expect("a version IRI")
.to_string();
(host, digest)
}
fn sparql_suite(digest: &str, space: &Arc<ScriptSpace>) -> Suite {
suite(digest, space)
.fixture(Fixture::new("script-walkq-result", Verb::Source).arg("days", "1"))
.fixture(
Fixture::new("script-walkq-runs", Verb::Sink)
.arg("days", "1")
.arg("content", "{}"),
)
.fixture(
Fixture::new("script-walku-runs", Verb::Sink)
.arg("age", "11")
.arg("content", "{}"),
)
}
#[test]
fn a_host_with_sparql_scripts_conforms() {
let (host, digest) = sparql_seeded();
let report = sparql_suite(&digest, &host.space).run_blocking(&host.kernel);
println!("{report}");
assert!(report.is_clean(), "{report}");
let store = STORE_IDS.iter().map(|id| {
(
*id,
"ikigai-store's own conformance suite covers it; it is bound here because every \
SPARQL run composes over it"
.to_string(),
)
});
assert_inherited(
&report,
&base_inherited()
.into_iter()
.chain(store)
.collect::<Vec<_>>(),
);
let mut walked: Vec<&str> = report
.walked
.iter()
.map(String::as_str)
.filter(|id| id.starts_with("script-walk"))
.collect();
walked.sort_unstable();
assert_eq!(
walked,
vec![
"script-walkq-result",
"script-walkq-runs",
"script-walku-runs"
],
"{report}"
);
}
const PLAN_READ: &str = r#"# The walk's read plan.
@prefix ik: <https://ikigai-rs.dev/ns#> .
<urn:plan:walkp> a ik:Process ;
ik:input <urn:plan:walkp:input:who> ;
ik:step <urn:plan:walkp:step:1> ;
ik:result <urn:plan:walkp:step:1> .
<urn:plan:walkp:input:who> ik:inputName "who" ; ik:required false ; ik:default "walk" .
<urn:plan:walkp:step:1> a ik:Step ; ik:verb "Source" ; ik:resolves <urn:test:greet> ;
ik:argument <urn:plan:walkp:step:1:arg:who> .
<urn:plan:walkp:step:1:arg:who> a ik:Argument ; ik:inputName "who" ;
ik:ref <urn:plan:walkp:var:who> .
"#;
const PLAN_WRITE: &str = r#"@prefix ik: <https://ikigai-rs.dev/ns#> .
<urn:plan:walkw> a ik:Process ;
ik:step <urn:plan:walkw:step:1> ;
ik:result <urn:plan:walkw:step:1> .
<urn:plan:walkw:step:1> a ik:Step ; ik:verb "Sink" ; ik:resolves <urn:test:vault> .
"#;
fn plan_seeded(doors: Doors) -> (PlanHost, String) {
let host = plan_host_of(doors);
let version = publish(&host.kernel, "walk", "(+ 1 2)", &[]);
publish(&host.kernel, "retiree", "1", &[]);
ok(&host.kernel, Verb::Sink, "urn:script:walk:runs", &[]);
publish(&host.kernel, "walkp", PLAN_READ, &[("language", "plan")]);
publish(&host.kernel, "walkw", PLAN_WRITE, &[("language", "plan")]);
let digest = version
.rsplit(":version:")
.next()
.expect("a version IRI")
.to_string();
(host, digest)
}
fn plan_inherited(doors: Doors) -> Vec<(&'static str, String)> {
let which = match doors {
Doors::Double => "here a test double of its contract",
Doors::Engine => "here ikigai-engine's, conformance-tested in ikigai-cli",
};
let mut doors_and_probes = vec![
("plan-eval", format!("the host's plan evaluator ({which})")),
(
"plan-validate",
format!("the host's plan validator ({which})"),
),
("plan-requires", format!("the host's derivation ({which})")),
("greet", "a test probe, not part of this crate".to_string()),
("host", "a test probe, not part of this crate".to_string()),
("held", "a test probe, not part of this crate".to_string()),
];
if doors == Doors::Engine {
doors_and_probes.push((
"shacl-validate",
"ikigai-shacl's validator, which the engine's plan doors compose; conformance-tested \
in ikigai-shacl"
.to_string(),
));
}
doors_and_probes
}
fn plan_suite(digest: &str, space: &Arc<ScriptSpace>) -> Suite {
suite(digest, space)
.fixture(Fixture::new("script-walkp-result", Verb::Source).arg("who", "conformance"))
.fixture(Fixture::new("script-walkp-runs", Verb::Sink).arg("content", "{}"))
.fixture(Fixture::new("script-walkw-runs", Verb::Sink).arg("content", "{}"))
}
#[test]
fn a_host_with_plan_scripts_conforms() {
both(|doors| {
let (host, digest) = plan_seeded(doors);
let report = plan_suite(&digest, &host.space).run_blocking(&host.kernel);
println!("{report}");
assert!(report.is_clean(), "{report}");
assert_inherited(&report, &[base_inherited(), plan_inherited(doors)].concat());
let mut walked: Vec<&str> = report
.walked
.iter()
.map(String::as_str)
.filter(|id| id.starts_with("script-walk"))
.collect();
walked.sort_unstable();
assert_eq!(
walked,
vec![
"script-walkp-result",
"script-walkp-runs",
"script-walkw-runs"
],
"{report}"
);
});
}