use std::process::Command;
use protobuf::Message;
use scip::types::{Document, Index, Occurrence};
fn sinter(repo: &std::path::Path, args: &[&str]) -> (bool, String) {
let out = Command::new(env!("CARGO_BIN_EXE_sinter"))
.args(args)
.env("HOME", repo)
.env("USERPROFILE", repo)
.current_dir(repo)
.output()
.expect("run sinter");
let text = format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
(out.status.success(), text)
}
fn write_index(repo: &std::path::Path, version: &str) {
let index = Index {
documents: vec![Document {
relative_path: "src/main.rs".to_string(),
occurrences: vec![
Occurrence {
range: vec![0, 27, 32],
symbol: format!("rust-analyzer cargo tokio {version} task/spawn()."),
symbol_roles: 0,
..Default::default()
},
Occurrence {
range: vec![0, 14, 19],
symbol: format!("rust-analyzer cargo tokio {version} task/"),
symbol_roles: 0,
..Default::default()
},
],
..Default::default()
}],
..Default::default()
};
std::fs::write(repo.join("index.scip"), index.write_to_bytes().unwrap()).unwrap();
}
#[test]
fn dependency_surface_binds_survives_noop_and_refreshes() {
let dir = tempfile::tempdir().unwrap();
let repo = dir.path();
std::fs::create_dir_all(repo.join("src")).unwrap();
std::fs::write(
repo.join("src/main.rs"),
"fn caller() { tokio::task::spawn(); }\nfn main() { caller(); }\n",
)
.unwrap();
write_index(repo, "1.0.0");
let (ok, out) = sinter(repo, &["build"]);
assert!(ok, "{out}");
assert!(
out.contains("dependency surface: 1 refs bound to 1 external symbols across 1 packages"),
"{out}"
);
let (ok, out) = sinter(repo, &["query", "spawn"]);
assert!(ok, "{out}");
assert!(out.contains("dep:tokio@1.0.0"), "{out}");
assert!(out.contains("tokio::task::spawn"), "{out}");
let (ok, out) = sinter(repo, &["affected", "tokio::task::spawn"]);
assert!(ok, "{out}");
assert!(out.contains("dep:tokio@1.0.0"), "{out}");
assert!(out.contains("caller"), "{out}");
assert!(out.contains("scip"), "{out}");
assert!(!out.contains("note:"), "{out}");
let (ok, out) = sinter(repo, &["build"]);
assert!(ok, "{out}");
assert!(out.contains("0 changed, 0 removed"), "{out}");
let (ok, out) = sinter(repo, &["affected", "spawn"]);
assert!(ok, "{out}");
assert!(out.contains("caller"), "{out}");
write_index(repo, "2.0.0");
let (ok, out) = sinter(repo, &["build"]);
assert!(ok, "{out}");
assert!(out.contains("dependency surface: 1 refs"), "{out}");
let (ok, out) = sinter(repo, &["query", "spawn"]);
assert!(ok, "{out}");
assert!(out.contains("dep:tokio@2.0.0"), "{out}");
assert!(!out.contains("dep:tokio@1.0.0"), "{out}");
}