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)
}
fn suite(digest: &str, space: &Arc<ScriptSpace>) -> Suite {
Suite::new()
.host_named_space(SPACE_LABEL, Arc::clone(space))
.opt_out(
"eval",
None,
"ikigai-lisp's own conformance suite covers it; it is bound here only because \
every run composes over it",
)
.opt_out("whoami", None, "a test probe, not part of this crate")
.opt_out("vault", None, "a test probe, not part of this crate")
.opt_out("fallback", None, "a test probe, not part of this crate")
.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_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 {
STORE_IDS
.iter()
.fold(suite(digest, space), |suite, id| {
suite.opt_out(
*id,
None,
"ikigai-store's own conformance suite covers it; it is bound here because \
every SPARQL run composes over it",
)
})
.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 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() -> (PlanHost, String) {
let host = plan_host();
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_suite(digest: &str, space: &Arc<ScriptSpace>) -> Suite {
[
(
"plan-eval",
"the host's plan evaluator (here a test double of its contract)",
),
(
"plan-validate",
"the host's plan validator (here a test double of its contract)",
),
(
"plan-requires",
"the host's derivation (here a test double of its contract)",
),
("greet", "a test probe, not part of this crate"),
("host", "a test probe, not part of this crate"),
]
.into_iter()
.fold(suite(digest, space), |suite, (id, why)| {
suite.opt_out(id, None, why)
})
.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() {
let (host, digest) = plan_seeded();
let report = plan_suite(&digest, &host.space).run_blocking(&host.kernel);
println!("{report}");
assert!(report.is_clean(), "{report}");
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}"
);
}