mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-15 20:05:13 +02:00
added repro subcommand
This commit is contained in:
parent
c1fa6a87cf
commit
8a7d2b8010
9 changed files with 656 additions and 36 deletions
138
tests/repro_cli.rs
Normal file
138
tests/repro_cli.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#![cfg(feature = "dynamic")]
|
||||
|
||||
use assert_cmd::Command;
|
||||
use predicates::prelude::*;
|
||||
use serde_json::json;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn nyx_cmd(home: &Path, repro_base: &Path) -> Command {
|
||||
let mut cmd = Command::cargo_bin("nyx").expect("nyx binary must exist");
|
||||
cmd.env("HOME", home)
|
||||
.env("XDG_CONFIG_HOME", home.join(".config"))
|
||||
.env("XDG_DATA_HOME", home.join(".local/share"))
|
||||
.env("XDG_CACHE_HOME", home.join(".cache"))
|
||||
.env("NYX_REPRO_BASE", repro_base)
|
||||
.env("NO_COLOR", "1");
|
||||
cmd
|
||||
}
|
||||
|
||||
fn write_bundle(base: &Path, spec_hash: &str, finding_id: &str, script: &str) -> PathBuf {
|
||||
let root = base.join(spec_hash);
|
||||
std::fs::create_dir_all(&root).unwrap();
|
||||
std::fs::write(
|
||||
root.join("manifest.json"),
|
||||
serde_json::to_vec_pretty(&json!({
|
||||
"corpus_version": 17,
|
||||
"entry_file": "/fixture/app.js",
|
||||
"entry_name": "handler",
|
||||
"finding_id": finding_id,
|
||||
"lang": "javascript",
|
||||
"sink_file": "/fixture/app.js",
|
||||
"sink_line": 7,
|
||||
"spec_format_version": 2,
|
||||
"spec_hash": spec_hash,
|
||||
"toolchain_id": "node-20"
|
||||
}))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(root.join("reproduce.sh"), script).unwrap();
|
||||
root
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repro_by_finding_replays_matching_bundle() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let repro = tempfile::tempdir().unwrap();
|
||||
write_bundle(
|
||||
repro.path(),
|
||||
"specaaaaaaaaaaaa",
|
||||
"findaaaaaaaaaaaa",
|
||||
"#!/bin/sh\necho replay-ok\nexit 0\n",
|
||||
);
|
||||
|
||||
let mut cmd = nyx_cmd(home.path(), repro.path());
|
||||
cmd.args(["repro", "--finding", "findaaaaaaaaaaaa"]);
|
||||
|
||||
cmd.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("Repro bundle:"))
|
||||
.stdout(predicate::str::contains("Finding: findaaaaaaaaaaaa"))
|
||||
.stdout(predicate::str::contains("replay-ok"))
|
||||
.stdout(predicate::str::contains("Replay result: pass"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repro_print_path_resolves_finding_without_replaying() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let repro = tempfile::tempdir().unwrap();
|
||||
let bundle = write_bundle(
|
||||
repro.path(),
|
||||
"specbbbbbbbbbbbb",
|
||||
"findbbbbbbbbbbbb",
|
||||
"#!/bin/sh\necho should-not-run\nexit 7\n",
|
||||
);
|
||||
|
||||
let mut cmd = nyx_cmd(home.path(), repro.path());
|
||||
cmd.args(["repro", "--finding", "findbbbbbbbbbbbb", "--print-path"]);
|
||||
|
||||
cmd.assert()
|
||||
.success()
|
||||
.stdout(predicate::eq(format!("{}\n", bundle.display())))
|
||||
.stdout(predicate::str::contains("should-not-run").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repro_by_spec_hash_replays_exact_cache_bundle() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let repro = tempfile::tempdir().unwrap();
|
||||
write_bundle(
|
||||
repro.path(),
|
||||
"speccccccccccccc",
|
||||
"findcccccccccccc",
|
||||
"#!/bin/sh\necho spec-replay-ok\nexit 0\n",
|
||||
);
|
||||
|
||||
let mut cmd = nyx_cmd(home.path(), repro.path());
|
||||
cmd.args(["repro", "--spec-hash", "speccccccccccccc"]);
|
||||
|
||||
cmd.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("Spec: speccccccccccccc"))
|
||||
.stdout(predicate::str::contains("spec-replay-ok"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repro_missing_finding_exits_with_actionable_error() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let repro = tempfile::tempdir().unwrap();
|
||||
|
||||
let mut cmd = nyx_cmd(home.path(), repro.path());
|
||||
cmd.args(["repro", "--finding", "missingffffffff", "--print-path"]);
|
||||
|
||||
cmd.assert().failure().stderr(
|
||||
predicate::str::contains("no repro bundle found")
|
||||
.and(predicate::str::contains("missingffffffff"))
|
||||
.and(predicate::str::contains("nyx scan --verify")),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repro_preserves_script_exit_code_for_infra_failures() {
|
||||
let home = tempfile::tempdir().unwrap();
|
||||
let repro = tempfile::tempdir().unwrap();
|
||||
let bundle = write_bundle(
|
||||
repro.path(),
|
||||
"specdddddddddddd",
|
||||
"finddddddddddddd",
|
||||
"#!/bin/sh\necho docker nope >&2\nexit 2\n",
|
||||
);
|
||||
|
||||
let mut cmd = nyx_cmd(home.path(), repro.path());
|
||||
cmd.arg("repro").arg("--bundle").arg(bundle).arg("--docker");
|
||||
|
||||
cmd.assert()
|
||||
.code(2)
|
||||
.stderr(predicate::str::contains("docker nope"))
|
||||
.stderr(predicate::str::contains("docker unavailable"));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue