use quarb::{EnvKind, Environment, QueryResult, Value};
fn doc() -> quarb_json::JsonAdapter {
quarb_json::JsonAdapter::parse(
r#"{"w":["pear","apple","fig"],
"p":[{"n":"a","x":2},{"n":"b","x":1}]}"#,
)
.unwrap()
}
fn run_with(q: &str, envs: Vec<Environment>) -> quarb::Result<Vec<String>> {
let run = quarb::Run {
environments: envs,
..quarb::Run::ambient()
};
let out = quarb::Query::parse(q, &doc())?.run(&doc(), &run)?;
Ok(match out.result {
QueryResult::Values(vs) => vs.iter().map(Value::to_string).collect(),
QueryResult::Nodes(ns) => ns.iter().map(|n| format!("{n:?}")).collect(),
})
}
fn bin() -> Environment {
Environment::parse("u", "exec:/usr/bin").unwrap()
}
fn shell() -> Environment {
Environment::parse("sh", "shell:").unwrap()
}
#[test]
fn the_mount_grammar_names_the_kinds() {
assert_eq!(bin().kind, EnvKind::Exec);
assert_eq!(shell().kind, EnvKind::Shell);
assert!(Environment::parse_mount("ga=events.json").is_none());
assert!(Environment::parse_mount("t=text:book.txt").is_none());
let e = Environment::parse_mount("go=exec:/no/such/dir").unwrap().unwrap_err().to_string();
assert!(e.contains("no such directory or program"), "{e}");
let e = Environment::parse_mount("sh=shell:bash").unwrap().unwrap_err().to_string();
assert!(e.contains("takes no target"), "{e}");
let e = Environment::parse_mount("py=python:./helpers.py").unwrap().unwrap_err().to_string();
assert!(e.contains("plugin round"), "{e}");
let e = Environment::parse_mount("9x=exec:/usr/bin").unwrap().unwrap_err().to_string();
assert!(e.contains("alias is a word"), "{e}");
}
#[test]
fn an_unmounted_alias_refuses_before_the_run() {
let e = run_with("/w/* | :: | sh:tr(a-z; A-Z)", vec![]).unwrap_err().to_string();
assert!(e.contains("environment 'sh' is not mounted"), "{e}");
let e = run_with("/w/* | :: | tr(a-z; A-Z)", vec![shell()]).unwrap_err().to_string();
assert!(e.contains("pipeline command 'tr'"), "{e}");
}
#[test]
fn after_the_plain_pipe_once_per_capsa_on_the_topics_text() {
assert_eq!(
run_with("/w/* | :: | u:tr(a-z; A-Z)", vec![bin()]).unwrap(),
vec!["PEAR", "APPLE", "FIG"]
);
assert_eq!(
run_with("/p/* | ::n | u:printf(\"%s-%s\"; $_; ::x)", vec![bin()]).unwrap(),
vec!["a-2", "b-1"]
);
assert_eq!(
run_with("/w/* | u:tr(a-z; A-Z)", vec![bin()]).unwrap(),
vec!["0", "1", "2"]
);
}
#[test]
fn after_the_aggregation_pipe_once_over_the_context_as_lines() {
let sorted = run_with("/w/* | :: @| u:sort", vec![bin()]).unwrap();
assert_eq!(sorted, vec!["apple", "fig", "pear"]);
assert_eq!(
run_with("/w/* | :: @| u:sort(-r)", vec![bin()]).unwrap(),
vec!["pear", "fig", "apple"]
);
assert_eq!(
run_with("/w/* | :: @| u:wc(-l) | trim", vec![bin()]).unwrap(),
vec!["3"]
);
assert_eq!(
run_with("/p/* | %(n = ::n; x = ::x) @| u:head(-n=1)", vec![bin()]).unwrap(),
vec!["{\"n\": \"a\", \"x\": 2}"]
);
assert_eq!(
run_with("/w/* | :: @| .total(count) @| u:sort @| [1] | %(w = $_; total = $.total)", vec![bin()]).unwrap(),
vec!["%(w = \"apple\"; total = 3)"]
);
}
#[test]
fn the_shell_kind_reaches_the_users_shell() {
assert_eq!(
run_with("/w/* | :: @| [1] | sh:echo(hi; there)", vec![shell()]).unwrap(),
vec!["hi there"]
);
assert_eq!(
run_with("/w/* | :: @| [1] | sh('tr a-z A-Z')", vec![shell()]).unwrap(),
vec!["PEAR"]
);
}
#[test]
fn failures_are_null_per_capsa_and_a_refusal_over_the_context() {
assert_eq!(
run_with("/w/* | :: @| [1] | u:false | default(\"nil\")", vec![bin()]).unwrap(),
vec!["nil"]
);
let e = run_with("/w/* | :: @| u:false", vec![bin()]).unwrap_err().to_string();
assert!(e.contains("'false' failed"), "{e}");
let e = run_with("/w/* | :: | u:no_such_program_here", vec![bin()]).unwrap_err().to_string();
assert!(e.contains("environment 'u' has no command 'no_such_program_here'"), "{e}");
let e = run_with("/w/* | :: @| [1] | sh:no_such_program_here", vec![shell()]).unwrap_err().to_string();
assert!(e.contains("environment 'sh' has no command"), "{e}");
}