@Test
  public void testBlobTtlUpdateErrors() throws Exception {
    try {
      String updateServiceId = "update-service";
      MockServerLayout layout = new MockServerLayout(mockClusterMap);
      setRouter(getNonBlockingRouterProperties(localDcName), layout, new LoggingNotificationSystem());
      setOperationParams();
      String blobId =
          router.putBlob(putBlobProperties, putUserMetadata, putChannel, new PutBlobOptionsBuilder().build())
              .get(AWAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
      Map<ServerErrorCode, RouterErrorCode> testsAndExpected = new HashMap<>();
      testsAndExpected.put(ServerErrorCode.BlobNotFound, RouterErrorCode.BlobDoesNotExist);
      testsAndExpected.put(ServerErrorCode.BlobDeleted, RouterErrorCode.BlobDeleted);
      testsAndExpected.put(ServerErrorCode.BlobExpired, RouterErrorCode.BlobExpired);
      testsAndExpected.put(ServerErrorCode.DiskUnavailable, RouterErrorCode.AmbryUnavailable);
      testsAndExpected.put(ServerErrorCode.ReplicaUnavailable, RouterErrorCode.AmbryUnavailable);
      testsAndExpected.put(ServerErrorCode.UnknownError, RouterErrorCode.UnexpectedInternalError);
      // note that this test makes all nodes return same server error code.
      for (Map.Entry<ServerErrorCode, RouterErrorCode> testAndExpected : testsAndExpected.entrySet()) {
        layout.getMockServers()
            .forEach(mockServer -> mockServer.setServerErrorForAllRequests(testAndExpected.getKey()));
        TestCallback<Void> testCallback = new TestCallback<>();
        Future<Void> future =
            router.updateBlobTtl(null, blobId, updateServiceId, Utils.Infinite_Time, testCallback, null);
        assertFailureAndCheckErrorCode(future, testCallback, testAndExpected.getValue());

        // Since we are using same blob ID for all tests, clear cache which stores blobs that are not found in router.
        router.getNotFoundCache().invalidateAll();
      }
      layout.getMockServers().forEach(mockServer -> mockServer.setServerErrorForAllRequests(null));
      // bad blob id
      TestCallback<Void> testCallback = new TestCallback<>();
      Future<Void> future =
          router.updateBlobTtl(null, "bad-blob-id", updateServiceId, Utils.Infinite_Time, testCallback, null);
      assertFailureAndCheckErrorCode(future, testCallback, RouterErrorCode.InvalidBlobId);
    } finally {
      if (router != null) {
        router.close();
      }
    }
  }
Test for most error cases involving TTL updates
@throws Exception
ambry-router/src/test/java/com/github/ambry/router/NonBlockingRouterTest.java