use std::process::Command;
use assert_cmd::cargo::CommandCargoExt;
const ABANDON_MS1: &str = "ms10entrsqqqqqqqqqqqqqqqqqqqqqqqqqqqqcj9sxraq34v7f";
const ABANDON_HEX: &str = "00000000000000000000000000000000";
const PRIVATE_KEY_LINE: &str = "warning: stdout carries private key material (can spend) \u{2014} redirect or encrypt (e.g. '> file.txt' or '| age -e ...')";
const WATCH_ONLY_LINE: &str = "note: stdout is watch-only \u{2014} public keys only, cannot spend";
#[test]
fn byte_parity_advisory_lines() {
assert_eq!(
PRIVATE_KEY_LINE,
"warning: stdout carries private key material (can spend) \u{2014} redirect or encrypt (e.g. '> file.txt' or '| age -e ...')",
"P advisory must match toolkit literal exactly (em-dash U+2014)"
);
assert_eq!(
WATCH_ONLY_LINE,
"note: stdout is watch-only \u{2014} public keys only, cannot spend",
"W advisory must match toolkit literal exactly"
);
let template_line = "note: stdout is a keyless descriptor template (no keys)";
assert_eq!(
template_line,
"note: stdout is a keyless descriptor template (no keys)",
"T advisory must match toolkit literal exactly"
);
assert!(
PRIVATE_KEY_LINE.contains('\u{2014}'),
"P line must contain U+2014 em-dash, not ASCII hyphen"
);
assert!(
WATCH_ONLY_LINE.contains('\u{2014}'),
"W line must contain U+2014 em-dash, not ASCII hyphen"
);
}
#[test]
fn ms_encode_emits_private_key_material_text_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["encode", "--hex", ABANDON_HEX, "--no-engraving-card"])
.output()
.expect("invoke ms encode");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(PRIVATE_KEY_LINE),
"ms encode (text mode) must emit P advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_encode_emits_private_key_material_json_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["encode", "--hex", ABANDON_HEX, "--json"])
.output()
.expect("invoke ms encode --json");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(PRIVATE_KEY_LINE),
"ms encode (--json mode) must emit P advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_decode_emits_private_key_material_text_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["decode", ABANDON_MS1])
.output()
.expect("invoke ms decode");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(PRIVATE_KEY_LINE),
"ms decode (text mode) must emit P advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_decode_emits_private_key_material_json_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["decode", ABANDON_MS1, "--json"])
.output()
.expect("invoke ms decode --json");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(PRIVATE_KEY_LINE),
"ms decode (--json mode) must emit P advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_derive_emits_watch_only_and_language_note_text_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["derive", ABANDON_MS1])
.output()
.expect("invoke ms derive");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(WATCH_ONLY_LINE),
"ms derive must emit W advisory; got stderr={stderr:?}"
);
assert!(
stderr.contains("note: --language defaulted to english"),
"ms derive with defaulted language must emit language note; got stderr={stderr:?}"
);
}
#[test]
fn ms_derive_emits_watch_only_json_mode() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["derive", ABANDON_MS1, "--language", "english", "--json"])
.output()
.expect("invoke ms derive --json");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(WATCH_ONLY_LINE),
"ms derive (--json mode, explicit language) must emit W advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_derive_emits_watch_only_with_template() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["derive", ABANDON_MS1, "--language", "english", "--template", "bip84"])
.output()
.expect("invoke ms derive --template");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(WATCH_ONLY_LINE),
"ms derive --template must emit W advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_repair_emits_private_key_material() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["repair", "--ms1", ABANDON_MS1])
.output()
.expect("invoke ms repair");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
stderr.contains(PRIVATE_KEY_LINE),
"ms repair must emit P advisory (new canonical line); got stderr={stderr:?}"
);
}
#[test]
fn ms_inspect_is_inert_no_advisory() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["inspect", ABANDON_MS1])
.output()
.expect("invoke ms inspect");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
!stderr.contains("warning:") && !stderr.contains("note: stdout"),
"ms inspect must NOT emit any output-class advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_verify_is_inert_no_advisory() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["verify", ABANDON_MS1])
.output()
.expect("invoke ms verify");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
!stderr.contains("note: stdout"),
"ms verify must NOT emit output-class advisory; got stderr={stderr:?}"
);
}
#[test]
fn ms_vectors_is_inert_no_advisory() {
let out = Command::cargo_bin("ms")
.unwrap()
.args(["vectors"])
.output()
.expect("invoke ms vectors");
assert!(out.status.success(), "expected exit 0; stderr={}", String::from_utf8_lossy(&out.stderr));
let stderr = String::from_utf8(out.stderr).expect("stderr utf-8");
assert!(
!stderr.contains("note: stdout"),
"ms vectors must NOT emit output-class advisory; got stderr={stderr:?}"
);
}