mod common;
use common::sqry_bin;
use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;
#[test]
fn cli_zig_exports_functions_and_types() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const std = @import("std");
pub fn add(a: i32, b: i32) i32 {
return a + b;
}
fn privateHelper() i32 {
return 42;
}
pub const Point = struct {
x: f32,
y: f32,
pub fn distance(self: Point) f32 {
return @sqrt(self.x * self.x + self.y * self.y);
}
};
const PrivateType = struct {
value: i32,
};
pub const API_VERSION = "1.0.0";
"#;
std::fs::write(project.path().join("module.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("exports:add")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("module.zig"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:Point")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("module.zig"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:API_VERSION")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("module.zig"));
}
#[test]
fn cli_zig_exports_hide_private() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const std = @import("std");
pub fn publicFunction() i32 {
return privateHelper();
}
fn privateHelper() i32 {
return 42;
}
pub const PublicType = struct {
value: i32,
};
const PrivateType = struct {
value: i32,
};
"#;
std::fs::write(project.path().join("visibility.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("exports:publicFunction")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("publicFunction"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:PublicType")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("PublicType"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:privateHelper")
.arg(project.path())
.assert()
.success()
.stderr(predicate::str::contains("No matches found"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:PrivateType")
.arg(project.path())
.assert()
.success()
.stderr(predicate::str::contains("No matches found"));
}
#[test]
fn cli_zig_exports_nested_pub_members() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const PrivateContainer = struct {
pub fn publicMethod() i32 {
return 42;
}
pub const PUBLIC_CONST: i32 = 100;
};
pub const PublicContainer = struct {
fn privateMethod() i32 {
return 42;
}
};
"#;
std::fs::write(project.path().join("nested.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("exports:PrivateContainer")
.arg(project.path())
.assert()
.success()
.stderr(predicate::str::contains("No matches found"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:PublicContainer")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("PublicContainer"));
}
#[test]
fn cli_zig_imports() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const std = @import("std");
const builtin = @import("builtin");
pub fn main() void {
std.debug.print("Hello, Zig!\n", .{});
}
"#;
std::fs::write(project.path().join("main.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("imports:std")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("main.zig"));
Command::new(sqry_bin())
.arg("query")
.arg("imports:builtin")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("main.zig"));
}
#[test]
fn cli_zig_callers_function_calls() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const std = @import("std");
fn validate(x: i32) bool {
return x > 0;
}
fn process(value: i32) i32 {
if (validate(value)) {
return value * 2;
}
return 0;
}
fn analyze(num: i32) bool {
return validate(num);
}
"#;
std::fs::write(project.path().join("functions.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:validate")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("process"))
.stdout(predicate::str::contains("analyze"));
}
#[test]
fn cli_zig_callers_method_calls() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const Point = struct {
x: f32,
y: f32,
fn distance(self: Point) f32 {
return @sqrt(self.x * self.x + self.y * self.y);
}
fn normalize(self: *Point) void {
const d = self.distance();
if (d > 0) {
self.x /= d;
self.y /= d;
}
}
};
"#;
std::fs::write(project.path().join("methods.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:distance")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("normalize"));
}
#[test]
fn cli_zig_callees_function() {
let project = TempDir::new().unwrap();
let zig_code = r#"
const std = @import("std");
fn log(message: []const u8) void {
std.debug.print("{s}\n", .{message});
}
fn warn(message: []const u8) void {
std.debug.print("WARNING: {s}\n", .{message});
}
fn handleError(error_msg: []const u8) void {
log("Error occurred");
warn(error_msg);
}
"#;
std::fs::write(project.path().join("logger.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callees:handleError")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("log"))
.stdout(predicate::str::contains("warn"));
}
#[test]
fn cli_zig_multi_file_calls() {
let project = TempDir::new().unwrap();
let utils_code = r#"
const std = @import("std");
pub fn log(message: []const u8) void {
std.debug.print("[LOG] {s}\n", .{message});
}
pub fn validate(input: i32) bool {
return input > 0;
}
"#;
std::fs::write(project.path().join("utils.zig"), utils_code).unwrap();
let main_code = r#"
const utils = @import("utils.zig");
pub fn process(data: i32) void {
utils.log("processing");
_ = utils.validate(data);
}
"#;
std::fs::write(project.path().join("main.zig"), main_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:log")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("process"));
}
#[test]
fn cli_zig_callers_no_results() {
let project = TempDir::new().unwrap();
let zig_code = r#"
fn unusedFunction() i32 {
return 42;
}
pub fn main() void {
const value: i32 = 10;
_ = value;
}
"#;
std::fs::write(project.path().join("unused.zig"), zig_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:unusedFunction")
.arg(project.path())
.assert()
.success()
.stderr(predicate::str::contains("No matches found"));
}