use crate::core::store::db::{self, FtsResult};
fn setup_db() -> rusqlite::Connection {
let conn = db::open_state_db(std::path::Path::new(":memory:")).unwrap();
conn.execute(
"INSERT INTO generations (generation_num, run_id, config_hash, created_at) VALUES (1, 'run-1', 'hash-1', '2026-03-06')",
[],
).unwrap();
conn.execute(
"INSERT INTO machines (name, first_seen, last_seen) VALUES ('test-machine', '2026-03-06', '2026-03-06')",
[],
).unwrap();
conn.execute(
"INSERT INTO resources (resource_id, machine_id, generation_id, resource_type, status, path, duration_secs, reversibility, applied_at) \
VALUES ('nginx-pkg', 1, 1, 'package', 'converged', '/usr/bin/nginx', 1.5, 'reversible', '2026-03-06')",
[],
).unwrap();
conn.execute(
"INSERT INTO resources (resource_id, machine_id, generation_id, resource_type, status, path, duration_secs, reversibility, applied_at) \
VALUES ('app-config', 1, 1, 'file', 'converged', '/etc/app/config.yaml', 0.3, 'reversible', '2026-03-06')",
[],
).unwrap();
conn.execute(
"INSERT INTO resources (resource_id, machine_id, generation_id, resource_type, status, path, duration_secs, reversibility, applied_at) \
VALUES ('svc-nginx', 1, 1, 'service', 'converged', NULL, 2.1, 'irreversible', '2026-03-06')",
[],
).unwrap();
conn.execute(
"INSERT INTO events (resource_id, machine, event_type, run_id, timestamp, duration_ms) \
VALUES ('nginx-pkg', 'test-machine', 'apply', 'run-001', '2026-03-06T10:00:00Z', 1500)",
[],
).unwrap();
conn.execute(
"INSERT INTO events (resource_id, machine, event_type, run_id, timestamp, duration_ms) \
VALUES ('nginx-pkg', 'test-machine', 'drift-check', 'run-002', '2026-03-06T11:00:00Z', 200)",
[],
).unwrap();
conn.execute("INSERT INTO resources_fts(resources_fts) VALUES('rebuild')", []).unwrap();
conn
}
fn sample_results() -> Vec<FtsResult> {
vec![
FtsResult {
resource_id: "nginx-pkg".into(),
resource_type: "package".into(),
status: "converged".into(),
path: Some("/usr/bin/nginx".into()),
rank: -1.5,
},
FtsResult {
resource_id: "app-config".into(),
resource_type: "file".into(),
status: "converged".into(),
path: Some("/etc/app/config.yaml".into()),
rank: -2.0,
},
FtsResult {
resource_id: "svc-nginx".into(),
resource_type: "service".into(),
status: "converged".into(),
path: None,
rank: -3.0,
},
]
}
#[test]
fn timing_stats_with_data() {
let conn = setup_db();
let results = sample_results();
let r = super::query_format::print_timing_stats(&conn, &results);
assert!(r.is_ok());
}
#[test]
fn timing_stats_empty_results() {
let conn = setup_db();
let r = super::query_format::print_timing_stats(&conn, &[]);
assert!(r.is_ok());
}
#[test]
fn timing_stats_single_result() {
let conn = setup_db();
let results = vec![sample_results()[0].clone()];
let r = super::query_format::print_timing_stats(&conn, &results);
assert!(r.is_ok());
}
#[test]
fn history_with_events() {
let conn = setup_db();
let results = sample_results();
let r = super::query_format::print_history(&conn, &results);
assert!(r.is_ok());
}
#[test]
fn history_empty_results() {
let conn = setup_db();
let r = super::query_format::print_history(&conn, &[]);
assert!(r.is_ok());
}
#[test]
fn reversibility_with_data() {
let conn = setup_db();
let results = sample_results();
let r = super::query_format::print_reversibility(&conn, &results);
assert!(r.is_ok());
}
#[test]
fn reversibility_empty_results() {
let conn = setup_db();
let r = super::query_format::print_reversibility(&conn, &[]);
assert!(r.is_ok());
}
#[test]
fn json_output_no_history() {
let conn = setup_db();
let results = sample_results();
super::query_format::print_json(&conn, "nginx", &results, false);
}
#[test]
fn json_output_with_history() {
let conn = setup_db();
let results = sample_results();
super::query_format::print_json(&conn, "nginx", &results, true);
}
#[test]
fn json_output_empty() {
let conn = setup_db();
super::query_format::print_json(&conn, "missing", &[], false);
}
#[test]
fn csv_output() {
let results = sample_results();
super::query_format::print_csv(&results);
}
#[test]
fn csv_output_empty() {
super::query_format::print_csv(&[]);
}
#[test]
fn csv_output_none_path() {
let results = vec![FtsResult {
resource_id: "svc".into(),
resource_type: "service".into(),
status: "converged".into(),
path: None,
rank: -1.0,
}];
super::query_format::print_csv(&results);
}
#[test]
fn git_history_in_repo() {
let results = sample_results();
let r = super::query_format::print_git_history("forjar", &results);
assert!(r.is_ok());
}
#[test]
fn git_history_empty_query() {
let r = super::query_format::print_git_history("zzz_no_match_zzz", &[]);
assert!(r.is_ok());
}
#[test]
fn print_sql_basic() {
super::query_format::print_sql("nginx", None);
}
#[test]
fn print_sql_with_type() {
super::query_format::print_sql("nginx", Some("package"));
}
#[test]
fn git_log_entry_serde() {
let entry = super::query_format::GitLogEntry {
hash: "abc123".into(),
message: "fix thing".into(),
files: vec!["src/main.rs".into()],
};
let json = serde_json::to_string(&entry).unwrap();
assert!(json.contains("abc123"));
assert!(json.contains("fix thing"));
}