@Test
  public void signAndParseTest() throws Exception {
    AmbryIdSigningService idSigningService = new AmbryIdSigningService();
    String blobId = "unsignedId";
    Map<String, String> metadata = Stream.of("a", "b", "c").collect(Collectors.toMap(s -> "key-" + s, s -> "val-" + s));
    assertFalse("Original blob should not be considered signed", idSigningService.isIdSigned(blobId));
    String signedId = idSigningService.getSignedId(blobId, metadata);
    for (String id : new String[]{signedId, "/" + signedId}) {
      assertTrue("ID should be considered signed", idSigningService.isIdSigned(id));
      Pair<String, Map<String, String>> idAndMetadata = idSigningService.parseSignedId(id);
      assertEquals("Unexpected blob ID from parseSignedId()", blobId, idAndMetadata.getFirst());
      assertEquals("Unexpected metadata from parseSignedId()", metadata, idAndMetadata.getSecond());
    }

    TestUtils.assertException(RestServiceException.class, () -> idSigningService.getSignedId(null, null),
        errorCodeChecker(RestServiceErrorCode.InternalServerError));

    TestUtils.assertException(RestServiceException.class,
        () -> idSigningService.parseSignedId(signedId.substring("signedId/".length())),
        errorCodeChecker(RestServiceErrorCode.InternalServerError));

    TestUtils.assertException(RestServiceException.class, () -> idSigningService.parseSignedId("signedId/abcdefg"),
        errorCodeChecker(RestServiceErrorCode.BadRequest));
  }
Testing signing and parsing IDs use {@link AmbryIdSigningService}.
@throws Exception
ambry-frontend/src/test/java/com/github/ambry/frontend/AmbryIdSigningServiceTest.java