mod common;
use common::sqry_bin;
use assert_cmd::Command;
use tempfile::TempDir;
fn write_fixture(dir: &std::path::Path, name: &str, contents: &str) {
std::fs::write(dir.join(name), contents).expect("write fixture file");
}
fn index_dir(dir: &std::path::Path) {
Command::new(sqry_bin())
.arg("index")
.arg(dir)
.assert()
.success();
}
#[test]
fn resolve_prints_outcome_for_indexed_symbol() {
let fixture = TempDir::new().expect("create tempdir");
write_fixture(fixture.path(), "lib.rs", "pub mod foo { pub fn bar() {} }");
index_dir(fixture.path());
let output = Command::new(sqry_bin())
.arg("graph")
.arg("--path")
.arg(fixture.path())
.arg("resolve")
.arg("bar")
.output()
.expect("run sqry graph resolve");
assert!(
output.status.success(),
"sqry graph resolve bar failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("symbol: bar"),
"expected 'symbol: bar' in output, got:\n{stdout}"
);
assert!(
stdout.contains("outcome:"),
"expected 'outcome:' field in output, got:\n{stdout}"
);
}
#[test]
fn resolve_explain_flag_prints_witness_trace() {
let fixture = TempDir::new().expect("create tempdir");
write_fixture(fixture.path(), "lib.rs", "pub fn hello() {}");
index_dir(fixture.path());
let output = Command::new(sqry_bin())
.arg("graph")
.arg("--path")
.arg(fixture.path())
.arg("resolve")
.arg("hello")
.arg("--explain")
.output()
.expect("run sqry graph resolve --explain");
assert!(
output.status.success(),
"sqry graph resolve hello --explain failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("symbol: hello"),
"expected 'symbol: hello', got:\n{stdout}"
);
assert!(
stdout.contains("witness trace:"),
"expected 'witness trace:' section with --explain, got:\n{stdout}"
);
assert!(
stdout.contains(" 1."),
"expected at least one numbered step in witness trace, got:\n{stdout}"
);
}
#[test]
fn resolve_explain_json_emits_stable_shape() {
let fixture = TempDir::new().expect("create tempdir");
write_fixture(fixture.path(), "lib.rs", "pub fn hello() {}");
index_dir(fixture.path());
let output = Command::new(sqry_bin())
.arg("graph")
.arg("--path")
.arg(fixture.path())
.arg("resolve")
.arg("hello")
.arg("--explain")
.arg("--json")
.output()
.expect("run sqry graph resolve --explain --json");
assert!(
output.status.success(),
"sqry graph resolve hello --explain --json failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
let parsed: serde_json::Value =
serde_json::from_str(&stdout).expect("output must be valid JSON");
assert!(
parsed.get("symbol").is_some(),
"JSON must contain 'symbol' field"
);
assert!(
parsed.get("outcome").is_some(),
"JSON must contain 'outcome' field"
);
assert!(
parsed.get("bindings").is_some() && parsed["bindings"].is_array(),
"JSON must contain 'bindings' array"
);
let explain = parsed
.get("explain")
.expect("JSON must contain 'explain' field");
assert!(
!explain.is_null(),
"explain must be non-null when --explain flag is given"
);
assert!(
explain.get("steps").is_some(),
"explain object must contain 'steps' field"
);
assert!(
explain.get("candidate_count").is_some(),
"explain object must contain 'candidate_count' field"
);
assert!(
explain.get("outcome").is_some(),
"explain object must contain 'outcome' field"
);
}
#[test]
fn resolve_json_without_explain_has_null_explain() {
let fixture = TempDir::new().expect("create tempdir");
write_fixture(fixture.path(), "lib.rs", "pub fn hello() {}");
index_dir(fixture.path());
let output = Command::new(sqry_bin())
.arg("graph")
.arg("--path")
.arg(fixture.path())
.arg("resolve")
.arg("hello")
.arg("--json")
.output()
.expect("run sqry graph resolve --json");
assert!(
output.status.success(),
"sqry graph resolve hello --json failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
let parsed: serde_json::Value =
serde_json::from_str(&stdout).expect("output must be valid JSON");
let explain = parsed
.get("explain")
.expect("JSON must contain 'explain' field");
assert!(
explain.is_null(),
"explain must be null when --explain flag is absent, got: {explain}"
);
}
#[test]
fn resolve_not_found_symbol_reports_outcome_not_error() {
let fixture = TempDir::new().expect("create tempdir");
write_fixture(fixture.path(), "lib.rs", "pub fn hello() {}");
index_dir(fixture.path());
let output = Command::new(sqry_bin())
.arg("graph")
.arg("--path")
.arg(fixture.path())
.arg("resolve")
.arg("totally_unknown_symbol_xyz_999")
.output()
.expect("run sqry graph resolve (not found)");
assert!(
output.status.success(),
"sqry graph resolve for unknown symbol must exit 0, got: {:?}",
output.status
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("outcome:"),
"expected 'outcome:' in not-found output, got:\n{stdout}"
);
}