mod common;
use common::*;
use std::fs;
use std::path::Path;
#[test]
fn gen_project_info_has_artifact_path() {
let dir = unique_sandbox_dir("gen_pi");
let out = run_dcr(&["new", "app", "--vcs", "none"], &dir);
assert!(out.status.success());
let project = dir.join("app");
let out = run_dcr(&["gen", "project-info", "-q"], &project);
assert!(
out.status.success(),
"project-info failed: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("\"artifact_path\""),
"missing artifact_path: {stdout}"
);
assert!(stdout.contains("\"target_dir\""), "missing target_dir");
assert!(
stdout.contains("\"artifact_kind\""),
"missing artifact_kind"
);
assert!(stdout.contains("\"source_roots\""), "missing source_roots");
let root_canon = fs::canonicalize(&project).unwrap();
assert!(
stdout.contains(&root_canon.to_string_lossy().to_string()) || stdout.contains("app"),
"root should be absolute-ish: {stdout}"
);
assert!(project.join(".dcr").join("build-info.json").is_file());
assert!(project.join(".dcr").join("toolchain.json").is_file());
assert!(project.join(".clangd").is_file());
let clangd = fs::read_to_string(project.join(".clangd")).unwrap();
assert!(clangd.contains("CompilationDatabase: .dcr"));
}
#[test]
fn gen_compile_commands_in_dcr_dir() {
let dir = unique_sandbox_dir("gen_cc");
let out = run_dcr(&["new", "app", "--vcs", "none"], &dir);
assert!(out.status.success());
let project = dir.join("app");
let out = run_dcr(&["gen", "compile-commands", "-q"], &project);
assert!(
out.status.success(),
"compile-commands failed: {}",
String::from_utf8_lossy(&out.stderr)
);
assert!(
!project.join("compile_commands.json").exists(),
"compile_commands.json must not be in project root"
);
let cc = project.join(".dcr").join("compile_commands.json");
assert!(cc.is_file(), "expected .dcr/compile_commands.json");
let content = fs::read_to_string(&cc).unwrap();
assert!(content.contains("\"directory\""), "missing directory field");
assert!(content.contains("\"file\""), "missing file field");
assert!(content.starts_with('['));
assert!(project.join(".clangd").is_file());
assert!(project.join(".dcr").join("ide").is_dir());
}
#[test]
fn gen_clangd_not_overwritten_if_custom() {
let dir = unique_sandbox_dir("gen_clangd");
let out = run_dcr(&["new", "app", "--vcs", "none"], &dir);
assert!(out.status.success());
let project = dir.join("app");
let custom = "CompileFlags:\n Add: [-Wall]\n";
fs::write(project.join(".clangd"), custom).unwrap();
let out = run_dcr(&["gen", "compile-commands", "-q"], &project);
assert!(out.status.success());
let after = fs::read_to_string(project.join(".clangd")).unwrap();
assert_eq!(after, custom, "custom .clangd must not be overwritten");
}
#[test]
fn gen_vscode_launch_uses_resolver() {
let dir = unique_sandbox_dir("gen_vscode");
let out = run_dcr(&["new", "app", "--vcs", "none"], &dir);
assert!(out.status.success());
let project = dir.join("app");
let out = run_dcr(&["gen", "vscode"], &project);
assert!(
out.status.success(),
"gen vscode failed: {}",
String::from_utf8_lossy(&out.stderr)
);
let launch = fs::read_to_string(project.join(".vscode").join("launch.json")).unwrap();
assert!(launch.contains("\"program\""), "launch missing program");
let normalized = launch.replace("\\\\", "/").replace('\\', "/");
let expected_rel = host_profile_dir(&project, "debug")
.join(bin_name("app"))
.strip_prefix(&project)
.unwrap_or_else(|_| Path::new("target"))
.to_string_lossy()
.replace('\\', "/");
assert!(
normalized.contains(&expected_rel),
"program should use host profile layout ({expected_rel}): {launch}"
);
let settings = fs::read_to_string(project.join(".vscode").join("settings.json")).unwrap();
assert!(
settings.contains(".dcr") || settings.contains("compile-commands-dir"),
"settings should point at .dcr: {settings}"
);
}
#[test]
fn build_print_artifact_path() {
if available_compiler().is_none() {
return;
}
let dir = unique_sandbox_dir("build_print");
let out = run_dcr(&["new", "app", "--vcs", "none"], &dir);
assert!(out.status.success());
let project = dir.join("app");
let out = run_dcr(&["build", "--print-artifact-path"], &project);
assert!(
out.status.success(),
"build failed: {}",
String::from_utf8_lossy(&out.stderr)
);
let stdout = String::from_utf8_lossy(&out.stdout);
let path_line = stdout
.lines()
.map(str::trim)
.rfind(|l| !l.is_empty())
.unwrap_or("");
assert!(
Path::new(path_line).is_absolute() || path_line.contains("app"),
"expected artifact path on stdout, got: {stdout}"
);
assert!(
project.join(".dcr").join("build-info.json").is_file(),
"build-info.json should be written after build"
);
}