blob: 7d593bbc9c6fd71627a12b4fe2d9937513f9b2b8 (
plain) (
tree)
|
|
open Rnt
module Make (S : Abstract.Storage.STORAGE) (C : Helpers.Storage.CONFIGURATOR) = struct
open Alcotest
module H = Helpers.Storage.Make (S) (C)
module SR = Rnt.Kernel.SubstantialRelation.Make (S)
module SI = Rnt.Kernel.Storage.Make (S)
module Constraint = Rnt.Evaluators.Constraint
let not_a_program () =
Concepts.Condition.condition "not-a-program"
"A handle was expected to carry the program protocol and did not" Concepts.Condition.empty
let named type_ name =
{ Concepts.Tuple.type_;
attributes = BatMap.String.singleton "name" (Concepts.Value.String name) }
let holding conn tuples =
let open Utilities.Result in
let* tx = S.start conn in
let schema = Concepts.Encoding.Bencode.(Dict ["name", String "string"]) in
let* schematics = SI.store_blob tx (Concepts.Encoding.Bencode.to_blob schema) in
let* relation = SR.empty tx ~schematics () in
let* relation =
List.fold_left
(fun acc tuple ->
let* relation = acc in
SR.assert_tuple tx relation tuple)
(Ok relation) tuples
in
let* () = S.commit tx in
SR.wrap conn relation
let membership name binding =
{Constraint.target = Kernel.Path.(name @/ this); binding = BatMap.String.of_list binding}
(* NOT EXISTS (worker w, manager m WHERE w.name = m.name) *)
let no_worker_is_a_manager () =
Constraint.declare ~name:"no-worker-is-a-manager"
(Constraint.Not
(Constraint.Exists
{ Constraint.quantifiers =
[ membership "worker" ["name", Constraint.Var "w"];
membership "manager" ["name", Constraint.Var "m"] ];
body = Constraint.Eq {left = Constraint.Var "w"; right = Constraint.Var "m"} }))
let checking relations =
let open Utilities.Result in
let state =
Kernel.Prototype.mixture
[ Kernel.Prototype.Directory.of_properties
(relations @ ["constraint", Constraint.make ()]) ]
in
let* checker = Kernel.Path.(lookup state ("constraint" @/ this)) in
let* interpreter =
Constraint.Program.from checker |> Option.to_result ~none:(not_a_program ())
in
Ok (interpreter, state)
let a_constraint_across_relations conn =
let apart, together =
begin
let open Utilities.Result in
let* constrains = no_worker_is_a_manager () in
let* worker = holding conn [named "worker" "Alaric"] in
let* elsewhere = holding conn [named "manager" "Brunhilda"] in
let* interpreter, state = checking ["worker", worker; "manager", elsewhere] in
let* apart = Constraint.satisfied interpreter constrains state in
let* promoted = holding conn [named "manager" "Alaric"] in
let* interpreter, state = checking ["worker", worker; "manager", promoted] in
let* together = Constraint.satisfied interpreter constrains state in
Ok (apart, together)
end
|> Helpers.condition_as_failure
in
check bool "no worker is a manager" true apart;
check bool "a worker was made a manager" false together
let suite prefix =
( "constraint/" ^ prefix,
[ test_case "a-constraint-across-relations" `Quick
(H.with_connection a_constraint_across_relations "constraint-test") ] )
end
module LMDB = Make (Rnt.Backend.Storage.LMDB) (Helpers.Storage.LMDB_Configurator)
let suites () = [LMDB.suite "lmdb"]
|