use anyhow::Result;
use tempfile::TempDir;
use xchecker::fixup::{FixupMode, FixupParser};
#[test]
fn test_review_detects_fixup_plan_with_unified_diffs() -> Result<()> {
let sandbox = TempDir::new()?;
let parser = FixupParser::new(FixupMode::Preview, sandbox.path().to_path_buf())?;
let review_content_with_fixups = r#"
# Review Document
The requirements and design look good overall, but there are some issues that need to be addressed.
**FIXUP PLAN:**
The following changes are needed to address the identified issues:
```diff
--- artifacts/00-requirements.md
+++ artifacts/00-requirements.md
@@ -15,6 +15,10 @@
#### Acceptance Criteria
+1. WHEN user submits valid data THEN system SHALL process request within 200ms
+2. WHEN user submits invalid data THEN system SHALL return error with details
+3. WHEN system is under load THEN response time SHALL not exceed 500ms
+
### Requirement 2
**User Story:** As a developer, I want comprehensive API documentation
```
```diff
--- artifacts/10-design.md
+++ artifacts/10-design.md
@@ -45,6 +45,15 @@
## API Endpoints
+### POST /api/users
+- Creates a new user account
+- Request body: `{"name": "string", "email": "string"}`
+- Response: `{"id": "string", "status": "created"}`
+
+### GET /api/users/{id}
+- Retrieves user information
+- Response: `{"id": "string", "name": "string", "email": "string"}`
+
### Authentication
All endpoints require valid JWT token in Authorization header.
```
These changes will ensure the specification is complete and implementable.
"#;
assert!(
parser.has_fixup_markers(review_content_with_fixups),
"Should detect FIXUP PLAN: marker"
);
let fixup_content = parser
.detect_fixup_markers(review_content_with_fixups)
.expect("Should extract fixup content");
assert!(
fixup_content.contains("The following changes are needed"),
"Should extract content after FIXUP PLAN: marker"
);
let diffs = parser.parse_diffs(review_content_with_fixups)?;
assert_eq!(diffs.len(), 2, "Should parse 2 unified diff blocks");
let req_diff = &diffs[0];
assert_eq!(
req_diff.target_file, "artifacts/00-requirements.md",
"First diff should target requirements.md"
);
assert!(!req_diff.hunks.is_empty(), "Should have at least one hunk");
assert!(
req_diff
.diff_content
.contains("--- artifacts/00-requirements.md"),
"Should have proper diff header"
);
assert!(
req_diff
.diff_content
.contains("+1. WHEN user submits valid data"),
"Should contain added acceptance criteria"
);
let design_diff = &diffs[1];
assert_eq!(
design_diff.target_file, "artifacts/10-design.md",
"Second diff should target design.md"
);
assert!(
!design_diff.hunks.is_empty(),
"Should have at least one hunk"
);
assert!(
design_diff
.diff_content
.contains("--- artifacts/10-design.md"),
"Should have proper diff header"
);
assert!(
design_diff.diff_content.contains("+### POST /api/users"),
"Should contain added API endpoint"
);
println!("✓ Review FIXUP PLAN: detection and unified diff parsing test passed");
println!(" Detected {} unified diff blocks", diffs.len());
println!(
" Target files: {:?}",
diffs.iter().map(|d| &d.target_file).collect::<Vec<_>>()
);
Ok(())
}
#[test]
fn test_review_detects_needs_fixups_marker() -> Result<()> {
let sandbox = TempDir::new()?;
let parser = FixupParser::new(FixupMode::Preview, sandbox.path().to_path_buf())?;
let review_content_needs_fixups = r#"
# Review Analysis
After reviewing the current artifacts, this specification needs fixups to address several issues:
1. Missing error handling specifications
2. Incomplete API documentation
3. Unclear acceptance criteria
The requirements document needs fixups in the following areas:
```diff
--- artifacts/00-requirements.md
+++ artifacts/00-requirements.md
@@ -20,6 +20,8 @@
#### Acceptance Criteria
1. WHEN system receives request THEN it SHALL validate input
+2. WHEN validation fails THEN system SHALL return HTTP 400 with error details
+3. WHEN system error occurs THEN system SHALL return HTTP 500 with generic message
### Requirement 2
```
These changes are essential for a complete specification.
"#;
assert!(
parser.has_fixup_markers(review_content_needs_fixups),
"Should detect 'needs fixups' marker"
);
let fixup_content = parser
.detect_fixup_markers(review_content_needs_fixups)
.expect("Should extract fixup content");
assert!(
fixup_content.contains("needs fixups in the following areas"),
"Should extract content after 'needs fixups' marker"
);
let diffs = parser.parse_diffs(review_content_needs_fixups)?;
assert_eq!(diffs.len(), 1, "Should parse 1 unified diff block");
let diff = &diffs[0];
assert_eq!(
diff.target_file, "artifacts/00-requirements.md",
"Should target requirements.md"
);
assert!(
diff.diff_content.contains("+2. WHEN validation fails"),
"Should contain added error handling criteria"
);
println!("✓ Review 'needs fixups' marker detection test passed");
Ok(())
}
#[test]
fn test_fixup_parser_handles_various_diff_formats() -> Result<()> {
let sandbox = TempDir::new()?;
let parser = FixupParser::new(FixupMode::Preview, sandbox.path().to_path_buf())?;
let complex_diff_content = r#"
**FIXUP PLAN:**
Multiple files need updates:
```diff
--- src/main.rs
+++ src/main.rs
@@ -1,5 +1,8 @@
fn main() {
println!("Hello, world!");
+
+ // Initialize logging
+ env_logger::init();
}
```
```diff
--- Cargo.toml
+++ Cargo.toml
@@ -8,3 +8,4 @@
[dependencies]
serde = "1.0"
tokio = "1.0"
+env_logger = "0.10"
```
```diff
--- README.md
+++ README.md
@@ -1,3 +1,6 @@
# Project Title
This is a sample project.
+
+## Usage
+Run with `cargo run` to start the application.
```
"#;
let diffs = parser.parse_diffs(complex_diff_content)?;
assert_eq!(diffs.len(), 3, "Should parse 3 unified diff blocks");
let expected_files = vec!["src/main.rs", "Cargo.toml", "README.md"];
for (i, diff) in diffs.iter().enumerate() {
assert_eq!(
diff.target_file, expected_files[i],
"Diff {} should target {}",
i, expected_files[i]
);
assert!(!diff.hunks.is_empty(), "Diff {} should have hunks", i);
}
println!("✓ Complex diff parsing test passed");
println!(" Parsed {} files: {:?}", diffs.len(), expected_files);
Ok(())
}
#[test]
fn test_fixup_parser_error_handling() -> Result<()> {
let sandbox = TempDir::new()?;
let parser = FixupParser::new(FixupMode::Preview, sandbox.path().to_path_buf())?;
let malformed_diff = r#"
**FIXUP PLAN:**
```diff
@@ -1,3 +1,4 @@
line 1
line 2
+new line
line 3
```
"#;
let result = parser.parse_diffs(malformed_diff);
match result {
Ok(diffs) => {
println!("ℹ Malformed diff parsed with {} results", diffs.len());
}
Err(e) => {
println!("ℹ Malformed diff properly rejected: {}", e);
}
}
let no_diffs = r#"
**FIXUP PLAN:**
No specific diffs needed, just general improvements.
"#;
let result = parser.parse_diffs(no_diffs);
assert!(
result.is_err(),
"Should return error when no valid diff blocks are present"
);
println!("✓ Error handling test passed");
Ok(())
}
#[test]
fn test_case_insensitive_marker_detection() -> Result<()> {
let sandbox = TempDir::new()?;
let parser = FixupParser::new(FixupMode::Preview, sandbox.path().to_path_buf())?;
let test_cases = vec![
"FIXUP PLAN:",
"fixup plan:",
"Fixup Plan:",
"NEEDS FIXUPS",
"needs fixups",
"Needs Fixups",
];
for marker in &test_cases {
let content = format!("Review content\n\n{}\n\nSome fixup details here.", marker);
assert!(
parser.has_fixup_markers(&content),
"Should detect marker: {}",
marker
);
let extracted = parser
.detect_fixup_markers(&content)
.unwrap_or_else(|| panic!("Should extract content for marker: {}", marker));
assert!(
extracted.contains("Some fixup details"),
"Should extract content after marker: {}",
marker
);
}
println!("✓ Case-insensitive marker detection test passed");
println!(" Tested {} different marker variations", test_cases.len());
Ok(())
}
#[test]
fn test_m4_gate_simple_validation() -> Result<()> {
println!("🚀 Starting M4 Gate simple validation...");
test_review_detects_fixup_plan_with_unified_diffs()?;
test_review_detects_needs_fixups_marker()?;
test_fixup_parser_handles_various_diff_formats()?;
test_fixup_parser_error_handling()?;
test_case_insensitive_marker_detection()?;
println!("✅ M4 Gate simple validation passed!");
println!();
println!("M4 Gate Core Requirements Validated:");
println!(" ✓ R5.1: Review detects FIXUP PLAN: and surfaces validated unified diff blocks");
println!(" ✓ Fixup marker detection works with both 'FIXUP PLAN:' and 'needs fixups'");
println!(" ✓ Unified diff parsing handles multiple files and complex changes");
println!(" ✓ Error handling for malformed diffs works gracefully");
println!(" ✓ Case-insensitive marker detection supports various formats");
println!();
println!("Key Features Verified:");
println!(" ✓ FIXUP PLAN: marker detection in review output");
println!(" ✓ Alternative 'needs fixups' marker detection");
println!(" ✓ Unified diff block parsing and validation");
println!(" ✓ Multi-file diff support");
println!(" ✓ Graceful error handling for malformed input");
println!(" ✓ Case-insensitive marker matching");
Ok(())
}