@Test
  public void testListener() throws Exception {
    time.allowSleepCalls(0);
    DataNodeConfigChangeListener listener = mock(DataNodeConfigChangeListener.class);
    compositeSource.addDataNodeConfigChangeListener(listener);
    DataNodeConfigChangeListener primaryListener = captureRegisteredListener(primarySource);
    DataNodeConfigChangeListener secondaryListener = captureRegisteredListener(secondarySource);
    // create an inconsistency (this should not make the metric fire until 3*5 mock seconds have passed)
    DataNodeConfig configOne = createConfig(1, 1);
    primaryListener.onDataNodeConfigChange(Collections.singleton(configOne));
    verify(listener).onDataNodeConfigChange(Collections.singleton(configOne));
    time.allowSleepCalls(1);
    assertTrue("Expected 0 inconsistencies so far",
        TestUtils.checkAndSleep(0L, metrics.listenerInconsistencyCount::getCount, 500));
    assertTrue("Expected 1 transient inconsistency so far",
        TestUtils.checkAndSleep(1L, metrics.listenerTransientInconsistencyCount::getCount, 500));
    time.allowSleepCalls(2);
    assertTrue("Expected 1 inconsistency so far",
        TestUtils.checkAndSleep(1L, metrics.listenerInconsistencyCount::getCount, 500));
    assertTrue("Expected 2 transient inconsistencies so far",
        TestUtils.checkAndSleep(2L, metrics.listenerTransientInconsistencyCount::getCount, 500));

    // fix the inconsistency
    secondaryListener.onDataNodeConfigChange(Collections.singleton(configOne));
    time.allowSleepCalls(1);
    assertEquals("Expected no more inconsistencies", 1, metrics.listenerInconsistencyCount.getCount());
    assertEquals("Expected no more transient inconsistencies", 2,
        metrics.listenerTransientInconsistencyCount.getCount());

    // add a second listener, this should only be attached to the primary
    DataNodeConfigChangeListener newListener = mock(DataNodeConfigChangeListener.class);
    compositeSource.addDataNodeConfigChangeListener(newListener);
    verify(primarySource).addDataNodeConfigChangeListener(newListener);
    verify(secondarySource, never()).addDataNodeConfigChangeListener(newListener);
  }
Test functionality related to detecting inconsistencies between two listeners
ambry-clustermap/src/test/java/com/github/ambry/clustermap/CompositeDataNodeConfigSourceTest.java