static boolean compareSignatures(Map<String, JavaClassSignature> expected,
      Map<String, JavaClassSignature> actual, Log log) {
    return SetMatcher.compare(expected.keySet(), actual.keySet(),
        item -> matchingClasses(item, expected.get(item), actual.get(item), log),
        item -> log.error(String.format("Missing class: %s", item)),
        item -> log.error(String.format("Extra class: %s", item)));
  }
@Test
  public void testCompareSignatures() {
    Log log = mock(Log.class);

    JavaClassSignature signatureA = new JavaClassSignature(
        "java.lang.Object",
        Set.of(),
        List.of("public"),
        Set.of("public void foo()"),
        Set.of("public int bar"));
    JavaClassSignature signatureB = new JavaClassSignature(
        "java.lang.Exception",
        Set.of("java.lang.Runnable"),
        List.of("protected"),
        Set.of("public void foo(int)"),
        Set.of("public boolean bar"));

    Map<String, JavaClassSignature> expected = ImmutableMap.<String, JavaClassSignature>builder()
        .put("test.Missing", signatureA)
        .put("test.A", signatureA)
        .put("test.B", signatureB)
        .build();

    Map<String, JavaClassSignature> actual = ImmutableMap.<String, JavaClassSignature>builder()
        .put("test.A", signatureA)
        .put("test.Extra", signatureA)
        .put("test.B", signatureA)
        .build();

    assertThat(AbiCheck.compareSignatures(expected, actual, log), equalTo(false));

    verify(log).error("Missing class: test.Missing");
    verify(log).error("Extra class: test.Extra");
    verify(log)
        .error("Class test.B: Expected superclass java.lang.Exception, found java.lang.Object");
    verify(log).error("Class test.B: Missing interface java.lang.Runnable");
    verify(log).error("Class test.B: Missing attribute protected");
    verify(log).error("Class test.B: Extra attribute public");
    verify(log).error("Class test.B: Missing method public void foo(int)");
    verify(log).error("Class test.B: Extra method public void foo()");
    verify(log).error("Class test.B: Missing field public boolean bar");
    verify(log).error("Class test.B: Extra field public int bar");
  }