#![cfg(feature = "mino")]
use mentat::script::Interpreter;
fn seeded() -> Interpreter {
let mut it = Interpreter::new();
it.eval("(def c (mentat.store/open))").unwrap();
it.eval_to_string(
"(mentat.store/transact c \
[{:db/ident :person/name \
:db/valueType :db.type/string \
:db/cardinality :db.cardinality/one}])",
)
.expect("schema transact failed");
it.eval_to_string("(mentat.store/transact c [{:person/name \"Alice\"}])")
.expect("data transact failed");
it
}
#[test]
fn datoms_render_the_attribute_as_a_keyword() {
let mut it = seeded();
let ds = it
.eval_to_string("(mentat.store/datoms (mentat.store/db c))")
.expect("datoms failed");
assert!(ds.starts_with('['), "datoms: {ds}");
assert!(ds.contains(":person/name \"Alice\""), "datoms: {ds}");
}
#[test]
fn q_against_as_of_basis_runs_temporal_datalog() {
let mut it = seeded();
let basis: i64 = it
.eval_to_string("(:mentat.store/basis-tx (mentat.store/db c))")
.unwrap()
.parse()
.unwrap();
it.eval_to_string("(mentat.store/transact c [{:person/name \"Zed\"}])")
.unwrap();
let then = it
.eval_to_string(&format!(
"(mentat.store/q (mentat.store/as-of (mentat.store/db c) {basis}) \
'[:find ?n :where [?e :person/name ?n]])"
))
.expect("q against an as-of basis");
assert!(then.contains("Alice"), "got: {then}");
assert!(!then.contains("Zed"), "as-of must hide later facts: {then}");
}
#[test]
fn inst_and_uuid_representations_round_trip_through_the_reader() {
use mino_rs::printer::print_str;
use mino_rs::reader::read_one;
for lit in [
r#"#inst "2017-01-01T00:00:00Z""#,
r#"#uuid "12345678-1234-5678-1234-567812345678""#,
] {
let (v, _) = read_one(lit).expect("read literal");
let printed = print_str(&v);
let (v2, _) = read_one(&printed).expect("re-read printed form");
assert_eq!(
printed,
print_str(&v2),
"pr-str/read-string round-trip must be stable for {lit}"
);
}
let (inst, _) = read_one(r#"#inst "2017-01-01T00:00:00Z""#).unwrap();
assert_eq!(
print_str(&inst),
"(clojure.instant/read-instant-date \"2017-01-01T00:00:00Z\")"
);
let (uuid, _) = read_one(r#"#uuid "12345678-1234-5678-1234-567812345678""#).unwrap();
assert_eq!(
print_str(&uuid),
"#uuid \"12345678-1234-5678-1234-567812345678\""
);
}
#[test]
fn instant_output_path_emits_tagged_form() {
let mut it = seeded();
let basis: i64 = it
.eval_to_string("(:mentat.store/basis-tx (mentat.store/db c))")
.unwrap()
.parse()
.unwrap();
let ds = it
.eval_to_string(&format!(
"(mentat.store/datoms (mentat.store/as-of (mentat.store/db c) {basis}))"
))
.expect("as-of datoms failed");
assert!(
ds.contains("(clojure.instant/read-instant-date"),
"as-of datoms should carry a tagged instant (:db/txInstant): {ds}"
);
}
#[test]
fn with_default_path_makes_no_arg_open_use_that_file() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("default.db");
let path = path.to_str().unwrap().to_string();
let mut it = Interpreter::with_default_path(&path);
it.eval("(def c (mentat.store/open))").unwrap();
it.eval_to_string(
"(mentat.store/transact c [{:db/ident :person/name \
:db/valueType :db.type/string :db/cardinality :db.cardinality/one}])",
)
.unwrap();
it.eval_to_string("(mentat.store/transact c [{:person/name \"Zed\"}])")
.unwrap();
drop(it);
use mentat::{IntoResult, Queryable};
let store = mentat::Store::open(&path).unwrap();
let name = store
.q_once("[:find ?n . :where [_ :person/name ?n]]", None)
.into_scalar_result()
.unwrap()
.and_then(|b| b.into_string());
assert_eq!(name.as_deref().map(|s| s.as_str()), Some("Zed"));
let mut fresh = Interpreter::new();
fresh.eval("(def c (mentat.store/open))").unwrap();
let r = fresh
.eval_to_string(
"(mentat.store/q (mentat.store/db c) '[:find ?n :where [_ :person/name ?n]])",
)
.unwrap_or_default();
assert!(!r.contains("Zed"), "in-memory store leaked: {r}");
}