Add test for programatic queries

This commit is contained in:
Nicolas Luck
2023-07-12 11:57:53 +02:00
parent f65675836c
commit c0dd94c8a3
5 changed files with 92 additions and 9 deletions

7
Cargo.lock generated
View File

@@ -1004,6 +1004,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "markup5ever"
version = "0.8.1"
@@ -1833,6 +1839,7 @@ dependencies = [
"lazy_static",
"lexical",
"libc",
"maplit",
"modular-bitfield",
"native-tls",
"ordered-float",

View File

@@ -68,6 +68,7 @@ futures = "0.3"
assert_cmd = "1.0.3"
predicates-core = "1.0.2"
serial_test = "0.5.1"
maplit = "1.0.2"
[patch.crates-io]
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }

View File

@@ -2,6 +2,8 @@
#[macro_use]
extern crate static_assertions;
#[cfg(test)]
#[macro_use] extern crate maplit;
#[macro_use]
pub mod macros;

View File

@@ -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
);
}
}

View File

@@ -8,7 +8,12 @@ use crate::atom_table::*;
pub enum QueryResult {
True,
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)]
@@ -30,6 +35,24 @@ pub enum Value {
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 {
fn from(query_result_lines: Vec<QueryResultLine>) -> Self {
// 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 query_result_lines.iter().any(|l| {
if let &QueryResultLine::Match(_) = l { true } else { false }
}) {
let all_matches = query_result_lines.into_iter()
.filter(|l| {
if let &QueryResultLine::Match(_) = l { true } else { false }
})
.collect::<Vec<_>>();
let all_matches = query_result_lines.into_iter()
.filter(|l| {
if let &QueryResultLine::Match(_) = l { true } else { false }
})
.map(|l| {
match l {
QueryResultLine::Match(m) => {
QueryMatch::from(m)
},
_ => unreachable!()
}
})
.collect::<Vec<_>>();
if !all_matches.is_empty() {
return QueryResult::Matches(all_matches);
}
@@ -145,4 +175,10 @@ impl TryFrom<String> for Value {
Err(())
}
}
}
impl From<&str> for Value {
fn from(str: &str) -> Self {
Value::String(str.to_string())
}
}