public static <FnT extends DoFn<?, ?>> DoFnSignature getSignature(Class<FnT> fn) {
    return signatureCache.computeIfAbsent(fn, DoFnSignatures::parseSignature);
  }
@Test
  public void testTimerParameterDuplicate() throws Exception {
    thrown.expect(IllegalArgumentException.class);
    thrown.expectMessage("duplicate");
    thrown.expectMessage("my-id");
    thrown.expectMessage("myProcessElement");
    thrown.expectMessage("index 2");
    thrown.expectMessage(not(mentionsState()));
    DoFnSignatures.getSignature(
        new DoFn<KV<String, Integer>, Long>() {

          @TimerId("my-id")
          private final TimerSpec myfield = TimerSpecs.timer(TimeDomain.PROCESSING_TIME);

          @ProcessElement
          public void myProcessElement(
              ProcessContext context, @TimerId("my-id") Timer one, @TimerId("my-id") Timer two) {}

          @OnTimer("my-id")
          public void onWhatever() {}
        }.getClass());
  }