@@ -365,3 +365,98 @@ func TestRunnerAssertionFailure(t *testing.T) {
365365 t .Error ("mock_tool/assertion_test result not found" )
366366 }
367367}
368+
369+ func TestCleanStaleOutputRelativeFile (t * testing.T ) {
370+ dir := t .TempDir ()
371+ staleFile := filepath .Join (dir , "query-results.sarif" )
372+ os .WriteFile (staleFile , []byte ("stale" ), 0o600 )
373+
374+ params := map [string ]any {
375+ "interpretedOutput" : "query-results.sarif" ,
376+ }
377+
378+ cleanStaleOutput ("codeql_query_run" , params , dir )
379+
380+ if fileExists (staleFile ) {
381+ t .Error ("expected stale file to be removed" )
382+ }
383+ }
384+
385+ func TestCleanStaleOutputRelativeDir (t * testing.T ) {
386+ dir := t .TempDir ()
387+ staleDir := filepath .Join (dir , "query-results" )
388+ os .MkdirAll (filepath .Join (staleDir , "subdir" ), 0o755 )
389+ os .WriteFile (filepath .Join (staleDir , "subdir" , "file.txt" ), []byte ("stale" ), 0o600 )
390+
391+ params := map [string ]any {
392+ "interpretedOutput" : "query-results" ,
393+ }
394+
395+ cleanStaleOutput ("codeql_query_run" , params , dir )
396+
397+ if fileExists (staleDir ) {
398+ t .Error ("expected stale directory to be removed" )
399+ }
400+ }
401+
402+ func TestCleanStaleOutputRejectsAbsolutePath (t * testing.T ) {
403+ dir := t .TempDir ()
404+ absFile := filepath .Join (dir , "safe-file" )
405+ os .WriteFile (absFile , []byte ("keep" ), 0o600 )
406+
407+ params := map [string ]any {
408+ "interpretedOutput" : absFile , // absolute path
409+ }
410+
411+ cleanStaleOutput ("codeql_query_run" , params , dir )
412+
413+ if ! fileExists (absFile ) {
414+ t .Error ("absolute path should NOT be removed" )
415+ }
416+ }
417+
418+ func TestCleanStaleOutputRejectsTraversal (t * testing.T ) {
419+ dir := t .TempDir ()
420+ parentFile := filepath .Join (dir , "parent-file" )
421+ os .WriteFile (parentFile , []byte ("keep" ), 0o600 )
422+
423+ childDir := filepath .Join (dir , "child" )
424+ os .MkdirAll (childDir , 0o755 )
425+
426+ params := map [string ]any {
427+ "interpretedOutput" : "../parent-file" ,
428+ }
429+
430+ cleanStaleOutput ("codeql_query_run" , params , childDir )
431+
432+ if ! fileExists (parentFile ) {
433+ t .Error ("traversal path should NOT be removed" )
434+ }
435+ }
436+
437+ func TestCleanStaleOutputSkipsNonQueryRun (t * testing.T ) {
438+ dir := t .TempDir ()
439+ staleFile := filepath .Join (dir , "output.txt" )
440+ os .WriteFile (staleFile , []byte ("keep" ), 0o600 )
441+
442+ params := map [string ]any {
443+ "interpretedOutput" : "output.txt" ,
444+ }
445+
446+ cleanStaleOutput ("codeql_test_run" , params , dir )
447+
448+ if ! fileExists (staleFile ) {
449+ t .Error ("non-codeql_query_run tool should not trigger cleanup" )
450+ }
451+ }
452+
453+ func TestCleanStaleOutputSkipsWhenNoParam (t * testing.T ) {
454+ dir := t .TempDir ()
455+ params := map [string ]any {
456+ "query" : "example.ql" ,
457+ "database" : "/some/db" ,
458+ }
459+
460+ // Should not panic or error — just no-op
461+ cleanStaleOutput ("codeql_query_run" , params , dir )
462+ }
0 commit comments