use predicates::prelude::*;
use tempfile::tempdir;
mod common;
use common::{fixtures_dir, generate_compare_receipt, perfgate_cmd};
#[test]
fn test_github_annotations_fail_scenario() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_fail.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
assert!(
compare_receipt_path.exists(),
"compare receipt should exist"
);
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path);
cmd.assert()
.success()
.stdout(predicate::str::contains("::error::"))
.stdout(predicate::str::contains("test-benchmark"))
.stdout(predicate::str::contains("wall_ms"))
.stdout(predicate::str::contains("%"));
}
#[test]
fn test_github_annotations_warn_scenario() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_warn.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
assert!(
compare_receipt_path.exists(),
"compare receipt should exist"
);
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path);
cmd.assert()
.success()
.stdout(predicate::str::contains("::warning::"))
.stdout(predicate::str::contains("test-benchmark"))
.stdout(predicate::str::contains("wall_ms"));
}
#[test]
fn test_github_annotations_pass_scenario_empty_output() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_pass.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
assert!(
compare_receipt_path.exists(),
"compare receipt should exist"
);
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path);
cmd.assert()
.success()
.stdout(predicate::str::contains("::error::").not())
.stdout(predicate::str::contains("::warning::").not());
}
#[test]
fn test_github_annotations_contains_baseline_current_values() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_fail.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path);
cmd.assert()
.success()
.stdout(predicate::str::contains("baseline"))
.stdout(predicate::str::contains("current"));
}
#[test]
fn test_github_annotations_missing_compare_file() {
let temp_dir = tempdir().expect("failed to create temp dir");
let nonexistent_path = temp_dir.path().join("nonexistent.json");
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&nonexistent_path);
cmd.assert()
.failure()
.stderr(predicate::str::contains("read"));
}
#[test]
fn test_github_annotations_missing_compare_argument() {
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations");
cmd.assert()
.failure()
.stderr(predicate::str::contains("--compare"));
}
#[test]
fn test_github_annotations_one_per_metric() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_fail.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
let mut cmd = perfgate_cmd();
cmd.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path);
let output = cmd.output().expect("failed to execute command");
let stdout = String::from_utf8_lossy(&output.stdout);
let annotation_lines: Vec<&str> = stdout.lines().filter(|line| !line.is_empty()).collect();
assert!(
!annotation_lines.is_empty(),
"fail scenario should produce at least one annotation"
);
for line in &annotation_lines {
assert!(
line.starts_with("::"),
"annotation line should start with '::': {}",
line
);
}
}
#[test]
fn test_github_annotations_deterministic() {
let temp_dir = tempdir().expect("failed to create temp dir");
let compare_receipt_path = temp_dir.path().join("compare.json");
let baseline = fixtures_dir().join("baseline.json");
let current = fixtures_dir().join("current_fail.json");
generate_compare_receipt(&baseline, ¤t, &compare_receipt_path)
.expect("failed to generate compare receipt");
let output1 = perfgate_cmd()
.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path)
.output()
.expect("first annotations run");
assert!(output1.status.success(), "first run should succeed");
let output2 = perfgate_cmd()
.arg("github-annotations")
.arg("--compare")
.arg(&compare_receipt_path)
.output()
.expect("second annotations run");
assert!(output2.status.success(), "second run should succeed");
assert_eq!(
output1.stdout, output2.stdout,
"annotation output should be byte-for-byte deterministic"
);
}