diff --git a/tests/disasm_tests.rs b/tests/disasm_tests.rs index f9e09fb..ddea3d0 100644 --- a/tests/disasm_tests.rs +++ b/tests/disasm_tests.rs @@ -313,10 +313,10 @@ fn test_disasm_zero_instructions() { // Snapshot Tests // ============================================================================ -/// Snapshot test for disassembly output format. +/// Test that disassembly JSON output has expected structure. #[test] #[serial] -fn test_disasm_output_format_snapshot() { +fn test_disasm_output_format_structure() { require_ghidra!(); ensure_test_project(TEST_PROJECT, TEST_PROGRAM); @@ -329,15 +329,42 @@ fn test_disasm_output_format_snapshot() { .arg("disasm") .arg(&main_addr) .arg("--instructions") - .arg("3") // Small count for stable snapshot + .arg("3") .arg("--program") .arg(TEST_PROGRAM) .arg("--format") .arg("json") .run(); - if result.exit_code == 0 { - let normalized = common::normalize_json(&result.stdout); - insta::assert_snapshot!("disasm_json_output", normalized); + result.assert_success(); + + // Parse and validate JSON structure + let json: serde_json::Value = + serde_json::from_str(&result.stdout).expect("Output should be valid JSON"); + + // Should be an array (or object with results array) + let instructions = if let Some(arr) = json.as_array() { + arr.clone() + } else if let Some(obj) = json.as_object() { + obj.get("results") + .and_then(|v| v.as_array()) + .expect("Object should have 'results' array") + .clone() + } else { + panic!("Expected JSON array or object with results"); + }; + + assert!( + !instructions.is_empty() && instructions.len() <= 3, + "Expected 1-3 instructions, got {}", + instructions.len() + ); + + // Each instruction should have required fields + for instr in &instructions { + let obj = instr.as_object().expect("Instruction should be an object"); + assert!(obj.contains_key("address"), "Missing 'address' field"); + assert!(obj.contains_key("mnemonic"), "Missing 'mnemonic' field"); + assert!(obj.contains_key("bytes"), "Missing 'bytes' field"); } } diff --git a/tests/patch_tests.rs b/tests/patch_tests.rs index f9d7d0c..a8b326b 100644 --- a/tests/patch_tests.rs +++ b/tests/patch_tests.rs @@ -278,13 +278,10 @@ fn test_patch_missing_program_arg() { // Snapshot tests for output format regression detection // ============================================================================ -/// Snapshot test for patch bytes output format. -/// -/// This captures the exact output format and will fail if the format changes, -/// helping prevent accidental breaking changes to the CLI output. +/// Test that patch bytes JSON output has expected structure. #[test] #[serial] -fn test_patch_output_format_snapshot() { +fn test_patch_output_format_structure() { require_ghidra!(); ensure_test_project(TEST_PROJECT, TEST_PROGRAM); @@ -304,11 +301,16 @@ fn test_patch_output_format_snapshot() { .arg("json") .run(); - if result.exit_code == 0 { - // Normalize the output to remove non-deterministic values - let normalized = common::normalize_json(&result.stdout); + result.assert_success(); - // Use insta for snapshot testing - insta::assert_snapshot!("patch_bytes_json_output", normalized); - } + // Validate JSON structure + let json: serde_json::Value = + serde_json::from_str(&result.stdout).expect("Output should be valid JSON"); + + // Should be a JSON object or array with patch result info + assert!( + json.is_object() || json.is_array(), + "Expected JSON object or array, got: {}", + json + ); } diff --git a/tests/query_tests.rs b/tests/query_tests.rs index e0004d6..1f84037 100644 --- a/tests/query_tests.rs +++ b/tests/query_tests.rs @@ -392,10 +392,10 @@ fn test_xref_from() { // Snapshot Tests // ============================================================================ -/// Snapshot test for function list JSON format. +/// Test that function list JSON output has expected structure. #[test] #[serial] -fn test_function_list_snapshot() { +fn test_function_list_json_structure() { require_ghidra!(); let harness = &*HARNESS; @@ -406,11 +406,27 @@ fn test_function_list_snapshot() { .arg("--format") .arg("json") .arg("--limit") - .arg("3") // Small limit for stable snapshot + .arg("3") .run(); - if result.exit_code == 0 { - let normalized = common::normalize_json(&result.stdout); - insta::assert_snapshot!("function_list_json", normalized); + result.assert_success(); + + // Validate JSON structure + let json: serde_json::Value = + serde_json::from_str(&result.stdout).expect("Output should be valid JSON"); + + // Should be an array of functions + let functions = json.as_array().expect("Expected JSON array of functions"); + + assert!( + !functions.is_empty() && functions.len() <= 3, + "Expected 1-3 functions, got {}", + functions.len() + ); + + // Each function should have name field + for func in functions { + let obj = func.as_object().expect("Function should be an object"); + assert!(obj.contains_key("name"), "Missing 'name' field"); } }