Fixing displayed retry attempts one-off error, when the error is non-retriable.

Adding unit tests.

TESTED=unit tests
RELNOTES: None
PiperOrigin-RevId: 170750220
diff --git a/src/main/java/com/google/devtools/build/lib/remote/Retrier.java b/src/main/java/com/google/devtools/build/lib/remote/Retrier.java
index 8ce9d0a..197f2b5 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/Retrier.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/Retrier.java
@@ -207,13 +207,14 @@
         throw e;  // Nested retries are always pass-through.
       } catch (StatusException | StatusRuntimeException e) {
         Status st = Status.fromThrowable(e);
+        int attempts = backoff.getRetryAttempts();
         long delay = backoff.nextDelayMillis();
         if (st.getCode() == Status.Code.CANCELLED && Thread.currentThread().isInterrupted()) {
           Thread.currentThread().interrupt();
           throw new InterruptedException();
         }
         if (delay < 0 || !isRetriable.apply(st)) {
-          throw new RetryException(st.asRuntimeException(), backoff.getRetryAttempts());
+          throw new RetryException(st.asRuntimeException(), attempts);
         }
         sleep(delay);
       } catch (Exception e) {
diff --git a/src/main/java/com/google/devtools/build/lib/remote/Retrier2.java b/src/main/java/com/google/devtools/build/lib/remote/Retrier2.java
index 3f817d0..e9a938b 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/Retrier2.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/Retrier2.java
@@ -233,14 +233,14 @@
           throw new CircuitBreakerException("Call failed in circuit breaker half open state.", 0,
               e);
         }
+        int attempts = backoff.getRetryAttempts();
         if (!shouldRetry.test(e)) {
-          throw new RetryException2("Call failed with not retriable error.",
-              backoff.getRetryAttempts(), e);
+          throw new RetryException2("Call failed with not retriable error.", attempts, e);
         }
         final long delayMillis = backoff.nextDelayMillis();
         if (delayMillis < 0) {
-          throw new RetryException2("Call failed after exhausting retry attempts: "
-              + backoff.getRetryAttempts(), backoff.getRetryAttempts(), e);
+          throw new RetryException2(
+              "Call failed after exhausting retry attempts: " + attempts, attempts, e);
         }
         sleeper.sleep(delayMillis);
       }
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteRetrierTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteRetrierTest.java
index 66de467..058a2df 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteRetrierTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteRetrierTest.java
@@ -103,6 +103,17 @@
   }
 
   @Test
+  public void testNonRetriableError() throws Exception {
+    Supplier<Backoff> s =
+        () -> new ExponentialBackoff(Duration.ofSeconds(1), Duration.ofSeconds(10), 2.0, 0.0, 2);
+    RemoteRetrier retrier = Mockito.spy(new RemoteRetrier(s, (e) -> false,
+        Retrier2.ALLOW_ALL_CALLS, Mockito.mock(Sleeper.class)));
+    when(fooMock.foo()).thenThrow(Status.Code.UNKNOWN.toStatus().asRuntimeException());
+    assertThrows(retrier, 1);
+    Mockito.verify(fooMock, Mockito.times(1)).foo();
+  }
+
+  @Test
   public void testRepeatedRetriesReset() throws Exception {
     Supplier<Backoff> s =
         () -> new ExponentialBackoff(Duration.ofSeconds(1), Duration.ofSeconds(10), 2.0, 0.0, 2);
diff --git a/src/test/java/com/google/devtools/build/lib/remote/Retrier2Test.java b/src/test/java/com/google/devtools/build/lib/remote/Retrier2Test.java
index 8e377f2..220c825 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/Retrier2Test.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/Retrier2Test.java
@@ -47,6 +47,7 @@
   private CircuitBreaker alwaysOpen;
 
   private static final Predicate<Exception> RETRY_ALL = (e) -> true;
+  private static final Predicate<Exception> RETRY_NONE = (e) -> false;
 
   @Before
   public void setup() {
@@ -75,6 +76,26 @@
   }
 
   @Test
+  public void retryShouldWorkNoRetries_failure() throws Exception {
+    // Test that a non-retriable error is not retried.
+    // All calls fail.
+
+    Supplier<Backoff> s  = () -> new ZeroBackoff(/*maxRetries=*/2);
+    Retrier2 r = new Retrier2(s, RETRY_NONE, alwaysOpen);
+    try {
+      r.execute(() -> {
+        throw new Exception("call failed");
+      });
+      fail("exception expected.");
+    } catch (RetryException2 e) {
+      assertThat(e.getAttempts()).isEqualTo(1);
+    }
+
+    verify(alwaysOpen, times(1)).recordFailure();
+    verify(alwaysOpen, never()).recordSuccess();
+  }
+
+  @Test
   public void retryShouldWork_success() throws Exception {
     // Test that a call is retried according to the backoff.
     // The last call succeeds.
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RetrierTest.java b/src/test/java/com/google/devtools/build/lib/remote/RetrierTest.java
index d55e2b6..dfce640 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RetrierTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RetrierTest.java
@@ -95,6 +95,20 @@
   }
 
   @Test
+  public void testNonRetriableError() throws Exception {
+    Retrier retrier =
+        Mockito.spy(
+            new Retrier(
+                Retrier.Backoff.exponential(
+                    Duration.ofSeconds(1), Duration.ofSeconds(10), 2, 0, 2),
+                Retrier.DEFAULT_IS_RETRIABLE));
+    Mockito.doNothing().when(retrier).sleep(Mockito.anyLong());
+    when(fooMock.foo()).thenThrow(Status.Code.NOT_FOUND.toStatus().asRuntimeException());
+    assertThrows(retrier, 1);
+    Mockito.verify(fooMock, Mockito.times(1)).foo();
+  }
+
+  @Test
   public void testRepeatedRetriesReset() throws Exception {
     Retrier retrier =
         Mockito.spy(