@@ -357,6 +357,127 @@ public void remoteCacheEvictBlobs_whenPrefetchingInput_exitWithCode39() throws E
357
357
assertThat (error .getDetailedExitCode ().getExitCode ().getNumericExitCode ()).isEqualTo (39 );
358
358
}
359
359
360
+ @ Test
361
+ public void remoteCacheEvictBlobs_whenPrefetchingSymlinkedInput_exitWithCode39 ()
362
+ throws Exception {
363
+ // Arrange: Prepare workspace and populate remote cache
364
+ writeSymlinkRule ();
365
+ write (
366
+ "a/BUILD" ,
367
+ """
368
+ load("//:symlink.bzl", "symlink")
369
+
370
+ genrule(
371
+ name = "foo",
372
+ srcs = ["foo.in"],
373
+ outs = ["foo.out"],
374
+ cmd = "cat $(SRCS) > $@",
375
+ )
376
+
377
+ symlink(
378
+ name = "symlinked_foo",
379
+ target_artifact = ":foo.out",
380
+ )
381
+
382
+ genrule(
383
+ name = "bar",
384
+ srcs = [
385
+ ":symlinked_foo",
386
+ "bar.in",
387
+ ],
388
+ outs = ["bar.out"],
389
+ cmd = "cat $(SRCS) > $@",
390
+ tags = ["no-remote-exec"],
391
+ )
392
+ """ );
393
+ write ("a/foo.in" , "foo" );
394
+ write ("a/bar.in" , "bar" );
395
+
396
+ // Populate remote cache
397
+ buildTarget ("//a:bar" );
398
+ var bytes = readContent (getOutputPath ("a/foo.out" ));
399
+ var hashCode = getDigestHashFunction ().getHashFunction ().hashBytes (bytes );
400
+ getOnlyElement (getArtifacts ("//a:symlinked_foo" )).getPath ().delete ();
401
+ getOutputPath ("a/foo.out" ).delete ();
402
+ getOutputPath ("a/bar.out" ).delete ();
403
+ getOutputBase ().getRelative ("action_cache" ).deleteTreesBelow ();
404
+ restartServer ();
405
+
406
+ // Clean build, foo.out isn't downloaded
407
+ buildTarget ("//a:bar" );
408
+ assertOutputDoesNotExist ("a/foo.out" );
409
+ assertOutputsDoNotExist ("//a:symlinked_foo" );
410
+
411
+ // Act: Evict blobs from remote cache and do an incremental build
412
+ evictAllBlobs ();
413
+ write ("a/bar.in" , "updated bar" );
414
+ var error = assertThrows (BuildFailedException .class , () -> buildTarget ("//a:bar" ));
415
+
416
+ // Assert: Exit code is 39
417
+ assertThat (error ).hasMessageThat ().contains ("Lost inputs no longer available remotely" );
418
+ assertThat (error ).hasMessageThat ().contains ("a/symlinked_foo" );
419
+ assertThat (error ).hasMessageThat ().contains (String .format ("%s/%s" , hashCode , bytes .length ));
420
+ assertThat (error .getDetailedExitCode ().getExitCode ().getNumericExitCode ()).isEqualTo (39 );
421
+ }
422
+
423
+ @ Test
424
+ public void remoteCacheEvictBlobs_whenPrefetchingSymlinkedInput_succeedsWithActionRewinding ()
425
+ throws Exception {
426
+ writeSymlinkRule ();
427
+ write (
428
+ "a/BUILD" ,
429
+ """
430
+ load("//:symlink.bzl", "symlink")
431
+
432
+ genrule(
433
+ name = "foo",
434
+ srcs = ["foo.in"],
435
+ outs = ["foo.out"],
436
+ cmd = "cat $(SRCS) > $@",
437
+ )
438
+
439
+ symlink(
440
+ name = "symlinked_foo",
441
+ target_artifact = ":foo.out",
442
+ )
443
+
444
+ genrule(
445
+ name = "bar",
446
+ srcs = [
447
+ ":symlinked_foo",
448
+ "bar.in",
449
+ ],
450
+ outs = ["bar.out"],
451
+ cmd = "cat $(SRCS) > $@",
452
+ tags = ["no-remote-exec"],
453
+ )
454
+ """ );
455
+ write ("a/foo.in" , "foo" );
456
+ write ("a/bar.in" , "bar" );
457
+
458
+ // Populate remote cache
459
+ buildTarget ("//a:bar" );
460
+ getOnlyElement (getArtifacts ("//a:symlinked_foo" )).getPath ().delete ();
461
+ getOutputPath ("a/foo.out" ).delete ();
462
+ getOutputPath ("a/bar.out" ).delete ();
463
+ getOutputBase ().getRelative ("action_cache" ).deleteTreesBelow ();
464
+ restartServer ();
465
+
466
+ // Clean build, foo.out isn't downloaded
467
+ buildTarget ("//a:bar" );
468
+ assertOutputDoesNotExist ("a/foo.out" );
469
+ assertOutputsDoNotExist ("//a:symlinked_foo" );
470
+
471
+ // Act: Evict blobs from remote cache and do an incremental build
472
+ evictAllBlobs ();
473
+ write ("a/bar.in" , "updated bar" );
474
+ enableActionRewinding ();
475
+ buildTarget ("//a:bar" );
476
+
477
+ // Assert: target was successfully built
478
+ assertValidOutputFile ("a/bar.out" , "foo" + lineSeparator () + "updated bar" + lineSeparator ());
479
+ }
480
+
360
481
@ Test
361
482
public void remoteCacheEvictBlobs_whenUploadingInput_exitWithCode39 () throws Exception {
362
483
// Arrange: Prepare workspace and populate remote cache
0 commit comments