@@ -196,173 +196,6 @@ Respond with ONLY JSON:
196196 }
197197}
198198
199- #[ cfg( test) ]
200- mod tests {
201- use super :: * ;
202- use crate :: config:: { LlmConfig , LlmPhaseConfig , LlmPhasesConfig , ScannerConfig } ;
203- use crate :: findings:: { Severity , VulnerabilityFinding } ;
204- use crate :: scanner:: Scanner ;
205- use tempfile:: TempDir ;
206-
207- fn create_test_scanner ( ) -> ( Scanner , TempDir ) {
208- let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
209- let config = ScannerConfig :: default ( ) ;
210- let scanner = Scanner :: new ( config, temp_dir. path ( ) . to_path_buf ( ) , false ) ;
211- ( scanner, temp_dir)
212- }
213-
214- fn create_test_scanner_with_llm ( ) -> ( Scanner , TempDir ) {
215- let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
216- let mut config = ScannerConfig :: default ( ) ;
217- config. llm = LlmConfig {
218- timeout_secs : 30 ,
219- max_retries : 3 ,
220- retry_backoff_ms : 2000 ,
221- max_concurrent : 4 ,
222- phases : LlmPhasesConfig {
223- discovery : LlmPhaseConfig {
224- base_url : "http://test.local" . to_string ( ) ,
225- api_key : Some ( "test-key" . to_string ( ) ) ,
226- model : "test-model" . to_string ( ) ,
227- models : vec ! [ ] ,
228- timeout_secs : None ,
229- } ,
230- ..Default :: default ( )
231- } ,
232- tgi : Default :: default ( ) ,
233- } ;
234- let scanner = Scanner :: new ( config, temp_dir. path ( ) . to_path_buf ( ) , false ) ;
235- ( scanner, temp_dir)
236- }
237-
238- #[ test]
239- fn test_llm_discovery_phase_creation ( ) {
240- let phase = LlmDiscoveryPhase ;
241- assert_eq ! ( phase. name( ) , "LlmDiscovery" ) ;
242- assert_eq ! ( phase. order( ) , 4 ) ;
243- }
244-
245- #[ test]
246- fn test_is_enabled_with_api_key ( ) {
247- let ( scanner, _temp) = create_test_scanner_with_llm ( ) ;
248- let analyzed_files = Vec :: new ( ) ;
249- let ctx = PhaseContext {
250- scanner : Box :: leak ( Box :: new ( scanner) ) ,
251- analyzed_files : Box :: leak ( Box :: new ( analyzed_files) ) ,
252- } ;
253- let phase = LlmDiscoveryPhase ;
254- assert ! ( phase. is_enabled( & ctx) ) ;
255- }
256-
257- #[ test]
258- fn test_is_disabled_without_api_key ( ) {
259- let ( scanner, _temp) = create_test_scanner ( ) ;
260- let analyzed_files = Vec :: new ( ) ;
261- let ctx = PhaseContext {
262- scanner : Box :: leak ( Box :: new ( scanner) ) ,
263- analyzed_files : Box :: leak ( Box :: new ( analyzed_files) ) ,
264- } ;
265- let phase = LlmDiscoveryPhase ;
266- assert ! ( !phase. is_enabled( & ctx) ) ;
267- }
268-
269- #[ tokio:: test]
270- async fn test_execute_with_empty_findings ( ) {
271- let ( scanner, _temp) = create_test_scanner_with_llm ( ) ;
272- let analyzed_files = Vec :: new ( ) ;
273- let mut ctx = PhaseContext {
274- scanner : Box :: leak ( Box :: new ( scanner) ) ,
275- analyzed_files : Box :: leak ( Box :: new ( analyzed_files) ) ,
276- } ;
277- let phase = LlmDiscoveryPhase ;
278- let result = phase. execute ( & mut ctx) . await ;
279- assert ! ( result. is_ok( ) ) ;
280- let findings = result. unwrap ( ) ;
281- assert ! ( findings. is_empty( ) ) ;
282- }
283-
284- #[ tokio:: test]
285- async fn test_execute_without_api_key_returns_original ( ) {
286- let ( scanner, _temp) = create_test_scanner ( ) ;
287- scanner. state . send_modify ( |s| {
288- s. findings . push ( VulnerabilityFinding {
289- id : "test-1" . to_string ( ) ,
290- title : "Test vulnerability" . to_string ( ) ,
291- description : "Test description" . to_string ( ) ,
292- severity : Severity :: High ,
293- confidence_score : 0.5 ,
294- cwe_id : Some ( "CWE-79" . to_string ( ) ) ,
295- file_path : "test.c" . to_string ( ) ,
296- line_number : Some ( 10 ) ,
297- code_snippet : None ,
298- diff_hunk : None ,
299- recommendation : None ,
300- code_location : None ,
301- already_reported : false ,
302- sources : vec ! [ "test" . to_string( ) ] ,
303- commit_reference : None ,
304- ticket_reference : None ,
305- priority_score : None ,
306- cross_file_references : None ,
307- verification_status : None ,
308- verification_notes : None ,
309- verification_error : None ,
310- agent_evidence_path : None ,
311- security_issue : None ,
312- poc_code : None ,
313- mitigation_code : None ,
314- poc_format : None ,
315- llm_model : None ,
316- agent_mode : false ,
317- statement_range : None ,
318- triage_verdict : None ,
319- } ) ;
320- } ) ;
321- let analyzed_files = Vec :: new ( ) ;
322- let mut ctx = PhaseContext {
323- scanner : Box :: leak ( Box :: new ( scanner) ) ,
324- analyzed_files : Box :: leak ( Box :: new ( analyzed_files) ) ,
325- } ;
326- let phase = LlmDiscoveryPhase ;
327- let result = phase. execute ( & mut ctx) . await ;
328- assert ! ( result. is_ok( ) ) ;
329- let findings = result. unwrap ( ) ;
330- assert_eq ! ( findings. len( ) , 1 ) ;
331- }
332-
333- #[ test]
334- fn test_parse_llm_response_valid_json ( ) {
335- let content = r#"{"description": "Test desc", "fix_code": "test fix"}"# ;
336- let mut descriptions = Vec :: new ( ) ;
337- let mut fixes = Vec :: new ( ) ;
338- parse_llm_response ( content, & mut descriptions, & mut fixes, "test-model" ) ;
339- assert_eq ! ( descriptions. len( ) , 1 ) ;
340- assert_eq ! ( descriptions[ 0 ] , "Test desc" ) ;
341- assert_eq ! ( fixes. len( ) , 1 ) ;
342- assert_eq ! ( fixes[ 0 ] , "test fix" ) ;
343- }
344-
345- #[ test]
346- fn test_parse_llm_response_invalid_json ( ) {
347- let content = "not valid json" ;
348- let mut descriptions = Vec :: new ( ) ;
349- let mut fixes = Vec :: new ( ) ;
350- parse_llm_response ( content, & mut descriptions, & mut fixes, "test-model" ) ;
351- assert ! ( descriptions. is_empty( ) ) ;
352- assert ! ( fixes. is_empty( ) ) ;
353- }
354-
355- #[ test]
356- fn test_parse_llm_response_partial_json ( ) {
357- let content = r#"{"description": "Only desc"}"# ;
358- let mut descriptions = Vec :: new ( ) ;
359- let mut fixes = Vec :: new ( ) ;
360- parse_llm_response ( content, & mut descriptions, & mut fixes, "test-model" ) ;
361- assert_eq ! ( descriptions. len( ) , 1 ) ;
362- assert ! ( fixes. is_empty( ) ) ;
363- }
364- }
365-
366199/// Helper to parse LLM JSON response and extract description/fix
367200fn parse_llm_response (
368201 content : & str ,
0 commit comments