@@ -381,4 +381,137 @@ mod tests {
381381 PathBuf :: from( "/home/user/project/shims" ) . as_path( )
382382 ) ) ;
383383 }
384+
385+ #[ test]
386+ fn test_is_broken_symlink_regular_file ( ) {
387+ // A regular file should not be detected as a broken symlink
388+ let temp_dir = std:: env:: temp_dir ( ) ;
389+ let test_file = temp_dir. join ( "pet_test_regular_file.txt" ) ;
390+ fs:: write ( & test_file, "test" ) . unwrap ( ) ;
391+
392+ assert ! ( !is_broken_symlink( & test_file) ) ;
393+
394+ let _ = fs:: remove_file ( & test_file) ;
395+ }
396+
397+ #[ test]
398+ fn test_is_broken_symlink_nonexistent ( ) {
399+ // A non-existent path should not be detected as a broken symlink
400+ let nonexistent = PathBuf :: from ( "/this/path/does/not/exist/python" ) ;
401+ assert ! ( !is_broken_symlink( & nonexistent) ) ;
402+ }
403+
404+ #[ test]
405+ #[ cfg( unix) ]
406+ fn test_is_broken_symlink_unix ( ) {
407+ use std:: os:: unix:: fs:: symlink;
408+
409+ let temp_dir = std:: env:: temp_dir ( ) ;
410+ let target = temp_dir. join ( "pet_test_symlink_target_nonexistent" ) ;
411+ let link = temp_dir. join ( "pet_test_broken_symlink" ) ;
412+
413+ // Clean up any previous test artifacts
414+ let _ = fs:: remove_file ( & link) ;
415+ let _ = fs:: remove_file ( & target) ;
416+
417+ // Create a symlink to a non-existent target
418+ symlink ( & target, & link) . unwrap ( ) ;
419+
420+ // The symlink should be detected as broken
421+ assert ! ( is_broken_symlink( & link) ) ;
422+
423+ // Clean up
424+ let _ = fs:: remove_file ( & link) ;
425+ }
426+
427+ #[ test]
428+ #[ cfg( unix) ]
429+ fn test_is_broken_symlink_valid_symlink ( ) {
430+ use std:: os:: unix:: fs:: symlink;
431+
432+ let temp_dir = std:: env:: temp_dir ( ) ;
433+ let target = temp_dir. join ( "pet_test_symlink_target_exists" ) ;
434+ let link = temp_dir. join ( "pet_test_valid_symlink" ) ;
435+
436+ // Clean up any previous test artifacts
437+ let _ = fs:: remove_file ( & link) ;
438+ let _ = fs:: remove_file ( & target) ;
439+
440+ // Create the target file
441+ fs:: write ( & target, "test" ) . unwrap ( ) ;
442+
443+ // Create a symlink to the existing target
444+ symlink ( & target, & link) . unwrap ( ) ;
445+
446+ // The symlink should NOT be detected as broken
447+ assert ! ( !is_broken_symlink( & link) ) ;
448+
449+ // Clean up
450+ let _ = fs:: remove_file ( & link) ;
451+ let _ = fs:: remove_file ( & target) ;
452+ }
453+
454+ #[ test]
455+ fn test_find_executable_or_broken_not_found ( ) {
456+ let temp_dir = std:: env:: temp_dir ( ) . join ( "pet_test_empty_env" ) ;
457+ let _ = fs:: create_dir_all ( & temp_dir) ;
458+
459+ match find_executable_or_broken ( & temp_dir) {
460+ ExecutableResult :: NotFound => ( ) ,
461+ other => panic ! ( "Expected NotFound, got {:?}" , other) ,
462+ }
463+
464+ let _ = fs:: remove_dir_all ( & temp_dir) ;
465+ }
466+
467+ #[ test]
468+ fn test_find_executable_or_broken_found ( ) {
469+ let temp_dir = std:: env:: temp_dir ( ) . join ( "pet_test_valid_env" ) ;
470+ #[ cfg( windows) ]
471+ let bin_dir = temp_dir. join ( "Scripts" ) ;
472+ #[ cfg( unix) ]
473+ let bin_dir = temp_dir. join ( "bin" ) ;
474+
475+ let _ = fs:: remove_dir_all ( & temp_dir) ;
476+ fs:: create_dir_all ( & bin_dir) . unwrap ( ) ;
477+
478+ #[ cfg( windows) ]
479+ let python_exe = bin_dir. join ( "python.exe" ) ;
480+ #[ cfg( unix) ]
481+ let python_exe = bin_dir. join ( "python" ) ;
482+
483+ fs:: write ( & python_exe, "fake python" ) . unwrap ( ) ;
484+
485+ match find_executable_or_broken ( & temp_dir) {
486+ ExecutableResult :: Found ( path) => assert_eq ! ( path, python_exe) ,
487+ other => panic ! ( "Expected Found, got {:?}" , other) ,
488+ }
489+
490+ let _ = fs:: remove_dir_all ( & temp_dir) ;
491+ }
492+
493+ #[ test]
494+ #[ cfg( unix) ]
495+ fn test_find_executable_or_broken_broken_symlink ( ) {
496+ use std:: os:: unix:: fs:: symlink;
497+
498+ let temp_dir = std:: env:: temp_dir ( ) . join ( "pet_test_broken_env" ) ;
499+ let bin_dir = temp_dir. join ( "bin" ) ;
500+
501+ let _ = fs:: remove_dir_all ( & temp_dir) ;
502+ fs:: create_dir_all ( & bin_dir) . unwrap ( ) ;
503+
504+ let python_exe = bin_dir. join ( "python" ) ;
505+ let nonexistent_target = PathBuf :: from ( "/nonexistent/python3.10" ) ;
506+
507+ // Create a broken symlink
508+ symlink ( & nonexistent_target, & python_exe) . unwrap ( ) ;
509+
510+ match find_executable_or_broken ( & temp_dir) {
511+ ExecutableResult :: Broken ( path) => assert_eq ! ( path, python_exe) ,
512+ other => panic ! ( "Expected Broken, got {:?}" , other) ,
513+ }
514+
515+ let _ = fs:: remove_dir_all ( & temp_dir) ;
516+ }
384517}
0 commit comments