@@ -347,3 +347,141 @@ fn check_llvm_and_get_config() -> Result<String> {
347
347
348
348
Ok ( llvm_config)
349
349
}
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
+ #[ cfg( not( target_os = "macos" ) ) ]
376
+ "Note: switching to 'v4.33c'." ,
377
+ "HEAD is now at" ,
378
+ ] ,
379
+ ) ,
380
+ (
381
+ State :: Nonexistent ,
382
+ State :: Stable ,
383
+ & [
384
+ #[ cfg( not( target_os = "macos" ) ) ]
385
+ "Note: switching to 'origin/stable'." ,
386
+ "HEAD is now at" ,
387
+ ] ,
388
+ ) ,
389
+ (
390
+ State :: Submodule ,
391
+ State :: Tag ( "v4.33c" ) ,
392
+ & [
393
+ #[ cfg( not( target_os = "macos" ) ) ]
394
+ "Note: switching to 'v4.33c'." ,
395
+ "HEAD is now at" ,
396
+ ] ,
397
+ ) ,
398
+ (
399
+ State :: Submodule ,
400
+ State :: Stable ,
401
+ & [
402
+ #[ cfg( not( target_os = "macos" ) ) ]
403
+ "Note: switching to 'origin/stable'." ,
404
+ "HEAD is now at" ,
405
+ ] ,
406
+ ) ,
407
+ // smoelius: It should be possible to go from a tag to the stable version.
408
+ (
409
+ State :: Tag ( "v4.33c" ) ,
410
+ State :: Stable ,
411
+ & [ "Previous HEAD position was" , "HEAD is now at" ] ,
412
+ ) ,
413
+ // smoelius: It should be possible to go from the stable version to a tag.
414
+ (
415
+ State :: Stable ,
416
+ State :: Tag ( "v4.33c" ) ,
417
+ & [ "Previous HEAD position was" , "HEAD is now at" ] ,
418
+ ) ,
419
+ ] ;
420
+
421
+ #[ test]
422
+ fn update ( ) {
423
+ let mut base_dir = common:: xdg_base_dir ( ) ;
424
+
425
+ for & ( before, after, line_prefixes) in TESTCASES {
426
+ eprintln ! ( "{before:?} -> {after:?}" ) ;
427
+
428
+ let tempdir = tempdir ( ) . unwrap ( ) ;
429
+
430
+ // smoelius: Based on https://github.com/whitequark/rust-xdg/issues/44, the recommended
431
+ // way of testing with a fake value of `XDG_DATA_HOME` seems to be manually overwriting
432
+ // the `data_home` field in `xdg::BaseDirectories`.
433
+ base_dir. data_home = Some ( tempdir. path ( ) . to_path_buf ( ) ) ;
434
+
435
+ let aflplusplus_dir = common:: aflplusplus_dir_from_base_dir ( & base_dir) . unwrap ( ) ;
436
+
437
+ assert ! ( aflplusplus_dir. starts_with( tempdir. path( ) ) ) ;
438
+
439
+ set_aflplusplus_dir_contents ( before, & aflplusplus_dir) . unwrap ( ) ;
440
+
441
+ let mut command = Command :: cargo_bin ( "cargo-afl" ) . unwrap ( ) ;
442
+ command. args ( [ "afl" , "config" , "--update" ] ) ;
443
+ command. env ( "XDG_DATA_HOME" , tempdir. path ( ) ) ;
444
+ match after {
445
+ State :: Nonexistent | State :: Submodule => unreachable ! ( ) ,
446
+ State :: Tag ( tag) => {
447
+ command. args ( [ "--tag" , tag] ) ;
448
+ }
449
+ State :: Stable => { }
450
+ }
451
+ let output = command. output ( ) . unwrap ( ) ;
452
+ assert ! ( output. status. success( ) ) ;
453
+ let stderr = String :: from_utf8 ( output. stderr ) . unwrap ( ) ;
454
+ contains_expected_line_prefixes ( & stderr, line_prefixes) ;
455
+ }
456
+ }
457
+
458
+ fn set_aflplusplus_dir_contents ( state : State , aflplusplus_dir : & Path ) -> Result < ( ) > {
459
+ let result = match state {
460
+ State :: Nonexistent => remove_aflplusplus_dir ( aflplusplus_dir) ,
461
+ State :: Submodule => copy_aflplusplus_submodule ( aflplusplus_dir) ,
462
+ State :: Tag ( tag) => update_to_stable_or_tag ( aflplusplus_dir, Some ( tag) ) ,
463
+ State :: Stable => update_to_stable_or_tag ( aflplusplus_dir, None ) ,
464
+ } ;
465
+ // smoelius: Sanity.
466
+ assert ! (
467
+ is_repo( aflplusplus_dir)
468
+ . is_ok_and( |value| value == matches!( state, State :: Tag ( _) | State :: Stable ) )
469
+ ) ;
470
+ result
471
+ }
472
+
473
+ fn contains_expected_line_prefixes ( stderr : & str , mut line_prefixes : & [ & str ] ) {
474
+ for line in stderr. lines ( ) {
475
+ if line_prefixes
476
+ . first ( )
477
+ . is_some_and ( |prefix| line. starts_with ( prefix) )
478
+ {
479
+ line_prefixes = & line_prefixes[ 1 ..] ;
480
+ }
481
+ }
482
+ assert ! (
483
+ line_prefixes. is_empty( ) ,
484
+ "Could not find line prefix {line_prefixes:?}:\n ```\n {stderr}```"
485
+ ) ;
486
+ }
487
+ }
0 commit comments