@@ -347,3 +347,153 @@ fn check_llvm_and_get_config() -> Result<String> {
347347
348348 Ok ( llvm_config)
349349}
350+
351+ #[ cfg( test) ]
352+ mod tests {
353+ use super :: { copy_aflplusplus_submodule, remove_aflplusplus_dir, update_to_stable_or_tag} ;
354+ use crate :: { common, config:: is_repo} ;
355+ use anyhow:: Result ;
356+ use assert_cmd:: cargo:: CommandCargoExt ;
357+ use std:: { path:: Path , process:: Command } ;
358+ use tempfile:: tempdir;
359+
360+ #[ derive( Clone , Copy , Debug ) ]
361+ enum State {
362+ Nonexistent ,
363+ Submodule ,
364+ Tag ( & ' static str ) ,
365+ Stable ,
366+ }
367+
368+ const TESTCASES : & [ ( State , State , & [ & str ] ) ] = & [
369+ // smoelius: There is currently no way to update to the submodule.
370+ // (State::Nonexistent, State::Submodule, &[]),
371+ (
372+ State :: Nonexistent ,
373+ State :: Tag ( "v4.33c" ) ,
374+ & [
375+ if cfg ! ( target_os = "macos" ) {
376+ "Previous HEAD position was"
377+ } else {
378+ "Note: switching to 'v4.33c'."
379+ } ,
380+ "HEAD is now at" ,
381+ ] ,
382+ ) ,
383+ (
384+ State :: Nonexistent ,
385+ State :: Stable ,
386+ & [
387+ if cfg ! ( target_os = "macos" ) {
388+ "Previous HEAD position was"
389+ } else {
390+ "Note: switching to 'origin/stable'."
391+ } ,
392+ "HEAD is now at" ,
393+ ] ,
394+ ) ,
395+ (
396+ State :: Submodule ,
397+ State :: Tag ( "v4.33c" ) ,
398+ & [
399+ if cfg ! ( target_os = "macos" ) {
400+ "Previous HEAD position was"
401+ } else {
402+ "Note: switching to 'v4.33c'."
403+ } ,
404+ "HEAD is now at" ,
405+ ] ,
406+ ) ,
407+ (
408+ State :: Submodule ,
409+ State :: Stable ,
410+ & [
411+ if cfg ! ( target_os = "macos" ) {
412+ "Previous HEAD position was"
413+ } else {
414+ "Note: switching to 'origin/stable'."
415+ } ,
416+ "HEAD is now at" ,
417+ ] ,
418+ ) ,
419+ // smoelius: It should be possible to go from a tag to the stable version.
420+ (
421+ State :: Tag ( "v4.33c" ) ,
422+ State :: Stable ,
423+ & [ "Previous HEAD position was" , "HEAD is now at" ] ,
424+ ) ,
425+ // smoelius: It should be possible to go from the stable version to a tag.
426+ (
427+ State :: Stable ,
428+ State :: Tag ( "v4.33c" ) ,
429+ & [ "Previous HEAD position was" , "HEAD is now at" ] ,
430+ ) ,
431+ ] ;
432+
433+ #[ test]
434+ fn update ( ) {
435+ let mut base_dir = common:: xdg_base_dir ( ) ;
436+
437+ for & ( before, after, line_prefixes) in TESTCASES {
438+ eprintln ! ( "{before:?} -> {after:?}" ) ;
439+
440+ let tempdir = tempdir ( ) . unwrap ( ) ;
441+
442+ // smoelius: Based on https://github.com/whitequark/rust-xdg/issues/44, the recommended
443+ // way of testing with a fake value of `XDG_DATA_HOME` seems to be manually overwriting
444+ // the `data_home` field in `xdg::BaseDirectories`.
445+ base_dir. data_home = Some ( tempdir. path ( ) . to_path_buf ( ) ) ;
446+
447+ let aflplusplus_dir = common:: aflplusplus_dir_from_base_dir ( & base_dir) . unwrap ( ) ;
448+
449+ assert ! ( aflplusplus_dir. starts_with( tempdir. path( ) ) ) ;
450+
451+ set_aflplusplus_dir_contents ( before, & aflplusplus_dir) . unwrap ( ) ;
452+
453+ let mut command = Command :: cargo_bin ( "cargo-afl" ) . unwrap ( ) ;
454+ command. args ( [ "afl" , "config" , "--update" ] ) ;
455+ command. env ( "XDG_DATA_HOME" , tempdir. path ( ) ) ;
456+ match after {
457+ State :: Nonexistent | State :: Submodule => unreachable ! ( ) ,
458+ State :: Tag ( tag) => {
459+ command. args ( [ "--tag" , tag] ) ;
460+ }
461+ State :: Stable => { }
462+ }
463+ let output = command. output ( ) . unwrap ( ) ;
464+ assert ! ( output. status. success( ) ) ;
465+ let stderr = String :: from_utf8 ( output. stderr ) . unwrap ( ) ;
466+ contains_expected_line_prefixes ( & stderr, line_prefixes) ;
467+ }
468+ }
469+
470+ fn set_aflplusplus_dir_contents ( state : State , aflplusplus_dir : & Path ) -> Result < ( ) > {
471+ let result = match state {
472+ State :: Nonexistent => remove_aflplusplus_dir ( aflplusplus_dir) ,
473+ State :: Submodule => copy_aflplusplus_submodule ( aflplusplus_dir) ,
474+ State :: Tag ( tag) => update_to_stable_or_tag ( aflplusplus_dir, Some ( tag) ) ,
475+ State :: Stable => update_to_stable_or_tag ( aflplusplus_dir, None ) ,
476+ } ;
477+ // smoelius: Sanity.
478+ assert ! (
479+ is_repo( aflplusplus_dir)
480+ . is_ok_and( |value| value == matches!( state, State :: Tag ( _) | State :: Stable ) )
481+ ) ;
482+ result
483+ }
484+
485+ fn contains_expected_line_prefixes ( stderr : & str , mut line_prefixes : & [ & str ] ) {
486+ for line in stderr. lines ( ) {
487+ if line_prefixes
488+ . first ( )
489+ . is_some_and ( |prefix| line. starts_with ( prefix) )
490+ {
491+ line_prefixes = & line_prefixes[ 1 ..] ;
492+ }
493+ }
494+ assert ! (
495+ line_prefixes. is_empty( ) ,
496+ "Could not find line prefix {line_prefixes:?}:\n ```\n {stderr}```"
497+ ) ;
498+ }
499+ }
0 commit comments