/**
   * Verify that registering a processing-time timer that is earlier than the existing timers
   * removes the one physical timer and creates one for the earlier timestamp {@link
   * ProcessingTimeService}.
   */
  @Test
  public void testRegisterEarlierProcessingTimerMovesPhysicalProcessingTimer() throws Exception {
    @SuppressWarnings("unchecked")
    Triggerable<Integer, String> mockTriggerable = mock(Triggerable.class);

    TestKeyContext keyContext = new TestKeyContext();

    TestProcessingTimeService processingTimeService = new TestProcessingTimeService();

    HeapInternalTimerService<Integer, String> timerService =
        createTimerService(
            mockTriggerable, keyContext, processingTimeService, testKeyGroupRange, maxParallelism);

    int key = getKeyInKeyGroupRange(testKeyGroupRange, maxParallelism);

    keyContext.setCurrentKey(key);

    timerService.registerProcessingTimeTimer("ciao", 20);

    assertEquals(1, timerService.numProcessingTimeTimers());

    assertEquals(1, processingTimeService.getNumRegisteredTimers());
    assertThat(processingTimeService.getRegisteredTimerTimestamps(), containsInAnyOrder(20L));

    timerService.registerProcessingTimeTimer("ciao", 10);

    assertEquals(2, timerService.numProcessingTimeTimers());

    assertEquals(1, processingTimeService.getNumRegisteredTimers());
    assertThat(processingTimeService.getRegisteredTimerTimestamps(), containsInAnyOrder(10L));
  }
  @Test
  public void testRegisteringProcessingTimeTimerInOnProcessingTimeDoesNotLeakPhysicalTimers()
      throws Exception {
    @SuppressWarnings("unchecked")
    Triggerable<Integer, String> mockTriggerable = mock(Triggerable.class);

    TestKeyContext keyContext = new TestKeyContext();

    TestProcessingTimeService processingTimeService = new TestProcessingTimeService();

    final HeapInternalTimerService<Integer, String> timerService =
        createTimerService(
            mockTriggerable, keyContext, processingTimeService, testKeyGroupRange, maxParallelism);

    int key = getKeyInKeyGroupRange(testKeyGroupRange, maxParallelism);

    keyContext.setCurrentKey(key);

    timerService.registerProcessingTimeTimer("ciao", 10);

    assertEquals(1, timerService.numProcessingTimeTimers());

    assertEquals(1, processingTimeService.getNumRegisteredTimers());
    assertThat(processingTimeService.getRegisteredTimerTimestamps(), containsInAnyOrder(10L));

    doAnswer(
            new Answer<Object>() {
              @Override
              public Object answer(InvocationOnMock invocation) throws Exception {
                timerService.registerProcessingTimeTimer("ciao", 20);
                return null;
              }
            })
        .when(mockTriggerable)
        .onProcessingTime(anyInternalTimer());

    processingTimeService.setCurrentTime(10);

    assertEquals(1, processingTimeService.getNumRegisteredTimers());
    assertThat(processingTimeService.getRegisteredTimerTimestamps(), containsInAnyOrder(20L));

    doAnswer(
            new Answer<Object>() {
              @Override
              public Object answer(InvocationOnMock invocation) throws Exception {
                timerService.registerProcessingTimeTimer("ciao", 30);
                return null;
              }
            })
        .when(mockTriggerable)
        .onProcessingTime(anyInternalTimer());

    processingTimeService.setCurrentTime(20);

    assertEquals(1, timerService.numProcessingTimeTimers());

    assertEquals(1, processingTimeService.getNumRegisteredTimers());
    assertThat(processingTimeService.getRegisteredTimerTimestamps(), containsInAnyOrder(30L));
  }