@@ -418,6 +418,127 @@ public void remoteCacheEvictBlobs_whenPrefetchingInput_succeedsWithActionRewindi
418
418
assertValidOutputFile ("a/bar.out" , "foo" + lineSeparator () + "updated bar" + lineSeparator ());
419
419
}
420
420
421
+ @ Test
422
+ public void remoteCacheEvictBlobs_whenPrefetchingSymlinkedInput_exitWithCode39 ()
423
+ throws Exception {
424
+ // Arrange: Prepare workspace and populate remote cache
425
+ writeSymlinkRule ();
426
+ write (
427
+ "a/BUILD" ,
428
+ """
429
+ load("//:symlink.bzl", "symlink")
430
+
431
+ genrule(
432
+ name = "foo",
433
+ srcs = ["foo.in"],
434
+ outs = ["foo.out"],
435
+ cmd = "cat $(SRCS) > $@",
436
+ )
437
+
438
+ symlink(
439
+ name = "symlinked_foo",
440
+ target_artifact = ":foo.out",
441
+ )
442
+
443
+ genrule(
444
+ name = "bar",
445
+ srcs = [
446
+ ":symlinked_foo",
447
+ "bar.in",
448
+ ],
449
+ outs = ["bar.out"],
450
+ cmd = "cat $(SRCS) > $@",
451
+ tags = ["no-remote-exec"],
452
+ )
453
+ """ );
454
+ write ("a/foo.in" , "foo" );
455
+ write ("a/bar.in" , "bar" );
456
+
457
+ // Populate remote cache
458
+ buildTarget ("//a:bar" );
459
+ var bytes = readContent (getOutputPath ("a/foo.out" ));
460
+ var hashCode = getDigestHashFunction ().getHashFunction ().hashBytes (bytes );
461
+ getOnlyElement (getArtifacts ("//a:symlinked_foo" )).getPath ().delete ();
462
+ getOutputPath ("a/foo.out" ).delete ();
463
+ getOutputPath ("a/bar.out" ).delete ();
464
+ getOutputBase ().getRelative ("action_cache" ).deleteTreesBelow ();
465
+ restartServer ();
466
+
467
+ // Clean build, foo.out isn't downloaded
468
+ buildTarget ("//a:bar" );
469
+ assertOutputDoesNotExist ("a/foo.out" );
470
+ assertOutputsDoNotExist ("//a:symlinked_foo" );
471
+
472
+ // Act: Evict blobs from remote cache and do an incremental build
473
+ evictAllBlobs ();
474
+ write ("a/bar.in" , "updated bar" );
475
+ var error = assertThrows (BuildFailedException .class , () -> buildTarget ("//a:bar" ));
476
+
477
+ // Assert: Exit code is 39
478
+ assertThat (error ).hasMessageThat ().contains ("Lost inputs no longer available remotely" );
479
+ assertThat (error ).hasMessageThat ().contains ("a/symlinked_foo" );
480
+ assertThat (error ).hasMessageThat ().contains (String .format ("%s/%s" , hashCode , bytes .length ));
481
+ assertThat (error .getDetailedExitCode ().getExitCode ().getNumericExitCode ()).isEqualTo (39 );
482
+ }
483
+
484
+ @ Test
485
+ public void remoteCacheEvictBlobs_whenPrefetchingSymlinkedInput_succeedsWithActionRewinding ()
486
+ throws Exception {
487
+ writeSymlinkRule ();
488
+ write (
489
+ "a/BUILD" ,
490
+ """
491
+ load("//:symlink.bzl", "symlink")
492
+
493
+ genrule(
494
+ name = "foo",
495
+ srcs = ["foo.in"],
496
+ outs = ["foo.out"],
497
+ cmd = "cat $(SRCS) > $@",
498
+ )
499
+
500
+ symlink(
501
+ name = "symlinked_foo",
502
+ target_artifact = ":foo.out",
503
+ )
504
+
505
+ genrule(
506
+ name = "bar",
507
+ srcs = [
508
+ ":symlinked_foo",
509
+ "bar.in",
510
+ ],
511
+ outs = ["bar.out"],
512
+ cmd = "cat $(SRCS) > $@",
513
+ tags = ["no-remote-exec"],
514
+ )
515
+ """ );
516
+ write ("a/foo.in" , "foo" );
517
+ write ("a/bar.in" , "bar" );
518
+
519
+ // Populate remote cache
520
+ buildTarget ("//a:bar" );
521
+ getOnlyElement (getArtifacts ("//a:symlinked_foo" )).getPath ().delete ();
522
+ getOutputPath ("a/foo.out" ).delete ();
523
+ getOutputPath ("a/bar.out" ).delete ();
524
+ getOutputBase ().getRelative ("action_cache" ).deleteTreesBelow ();
525
+ restartServer ();
526
+
527
+ // Clean build, foo.out isn't downloaded
528
+ buildTarget ("//a:bar" );
529
+ assertOutputDoesNotExist ("a/foo.out" );
530
+ assertOutputsDoNotExist ("//a:symlinked_foo" );
531
+
532
+ // Act: Evict blobs from remote cache and do an incremental build
533
+ evictAllBlobs ();
534
+ write ("a/bar.in" , "updated bar" );
535
+ enableActionRewinding ();
536
+ buildTarget ("//a:bar" );
537
+
538
+ // Assert: target was successfully built
539
+ assertValidOutputFile ("a/bar.out" , "foo" + lineSeparator () + "updated bar" + lineSeparator ());
540
+ }
541
+
421
542
@ Test
422
543
public void remoteCacheEvictBlobs_whenUploadingInput_exitWithCode39 () throws Exception {
423
544
// Arrange: Prepare workspace and populate remote cache
0 commit comments