Add test for programatic queries
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -1004,6 +1004,12 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markup5ever"
|
name = "markup5ever"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@@ -1833,6 +1839,7 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lexical",
|
"lexical",
|
||||||
"libc",
|
"libc",
|
||||||
|
"maplit",
|
||||||
"modular-bitfield",
|
"modular-bitfield",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ futures = "0.3"
|
|||||||
assert_cmd = "1.0.3"
|
assert_cmd = "1.0.3"
|
||||||
predicates-core = "1.0.2"
|
predicates-core = "1.0.2"
|
||||||
serial_test = "0.5.1"
|
serial_test = "0.5.1"
|
||||||
|
maplit = "1.0.2"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }
|
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate static_assertions;
|
extern crate static_assertions;
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use] extern crate maplit;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|||||||
@@ -936,3 +936,40 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn programatic_query() {
|
||||||
|
let mut machine = Machine::with_test_streams();
|
||||||
|
|
||||||
|
machine.load_module_string("facts", String::from(r#"
|
||||||
|
triple("a", "p1", "b").
|
||||||
|
triple("a", "p2", "b").
|
||||||
|
"#));
|
||||||
|
|
||||||
|
let query = String::from(r#"triple("a",P,"b")."#);
|
||||||
|
let output = machine.run_query(query);
|
||||||
|
assert_eq!(output, QueryResult::Matches(vec![
|
||||||
|
QueryMatch::from(btreemap!{
|
||||||
|
"P" => Value::from("p1"),
|
||||||
|
}),
|
||||||
|
QueryMatch::from(btreemap!{
|
||||||
|
"P" => Value::from("p2"),
|
||||||
|
}),
|
||||||
|
]));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
machine.run_query(String::from(r#"triple("a","p1","b")."#)),
|
||||||
|
QueryResult::True
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
machine.run_query(String::from(r#"triple("x","y","z")."#)),
|
||||||
|
QueryResult::False
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ use crate::atom_table::*;
|
|||||||
pub enum QueryResult {
|
pub enum QueryResult {
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
Matches(Vec<QueryResultLine>),
|
Matches(Vec<QueryMatch>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct QueryMatch {
|
||||||
|
pub bindings: BTreeMap<String, Value>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -30,6 +35,24 @@ pub enum Value {
|
|||||||
Var,
|
Var,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<BTreeMap<&str, Value>> for QueryMatch {
|
||||||
|
fn from(bindings: BTreeMap<&str, Value>) -> Self {
|
||||||
|
QueryMatch {
|
||||||
|
bindings: bindings.into_iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v))
|
||||||
|
.collect::<BTreeMap<_, _>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BTreeMap<String, Value>> for QueryMatch {
|
||||||
|
fn from(bindings: BTreeMap<String, Value>) -> Self {
|
||||||
|
QueryMatch {
|
||||||
|
bindings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<QueryResultLine>> for QueryResult {
|
impl From<Vec<QueryResultLine>> for QueryResult {
|
||||||
fn from(query_result_lines: Vec<QueryResultLine>) -> Self {
|
fn from(query_result_lines: Vec<QueryResultLine>) -> Self {
|
||||||
// If there is only one line, and it is true or false, return that.
|
// If there is only one line, and it is true or false, return that.
|
||||||
@@ -50,14 +73,21 @@ impl From<Vec<QueryResultLine>> for QueryResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there is at least one match, return all matches.
|
// If there is at least one match, return all matches.
|
||||||
if query_result_lines.iter().any(|l| {
|
let all_matches = query_result_lines.into_iter()
|
||||||
if let &QueryResultLine::Match(_) = l { true } else { false }
|
.filter(|l| {
|
||||||
}) {
|
if let &QueryResultLine::Match(_) = l { true } else { false }
|
||||||
let all_matches = query_result_lines.into_iter()
|
})
|
||||||
.filter(|l| {
|
.map(|l| {
|
||||||
if let &QueryResultLine::Match(_) = l { true } else { false }
|
match l {
|
||||||
})
|
QueryResultLine::Match(m) => {
|
||||||
.collect::<Vec<_>>();
|
QueryMatch::from(m)
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !all_matches.is_empty() {
|
||||||
return QueryResult::Matches(all_matches);
|
return QueryResult::Matches(all_matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,4 +175,10 @@ impl TryFrom<String> for Value {
|
|||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Value {
|
||||||
|
fn from(str: &str) -> Self {
|
||||||
|
Value::String(str.to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user