RequestHedgingProxyProvider extends
        ConfiguredFailoverProxyProvider<T> { @Override public synchronized void performFailover(T currentProxy) { toIgnore = successfulProxy.proxyInfo; successfulProxy = null; } RequestHedgingProxyProvider(
          Configuration conf, URI uri, Class<T> xface); @VisibleForTesting  RequestHedgingProxyProvider(Configuration conf, URI uri,
                              Class<T> xface, ProxyFactory<T> factory); @SuppressWarnings("unchecked") @Override synchronized ProxyInfo<T> getProxy(); @Override synchronized void performFailover(T currentProxy);  }
@Test public void testPerformFailover() throws Exception { final AtomicInteger counter = new AtomicInteger(0); final int[] isGood = {1}; final NamenodeProtocols goodMock = Mockito.mock(NamenodeProtocols.class); Mockito.when(goodMock.getStats()).thenAnswer(new Answer<long[]>() { @Override public long[] answer(InvocationOnMock invocation) throws Throwable { counter.incrementAndGet(); if (isGood[0] == 1) { Thread.sleep(1000); return new long[]{1}; } throw new IOException("Was Good mock !!"); } }); final NamenodeProtocols badMock = Mockito.mock(NamenodeProtocols.class); Mockito.when(badMock.getStats()).thenAnswer(new Answer<long[]>() { @Override public long[] answer(InvocationOnMock invocation) throws Throwable { counter.incrementAndGet(); if (isGood[0] == 2) { Thread.sleep(1000); return new long[]{2}; } throw new IOException("Bad mock !!"); } }); RequestHedgingProxyProvider<NamenodeProtocols> provider = new RequestHedgingProxyProvider<>(conf, nnUri, NamenodeProtocols.class, createFactory(goodMock, badMock)); long[] stats = provider.getProxy().proxy.getStats(); Assert.assertTrue(stats.length == 1); Assert.assertEquals(1, stats[0]); Assert.assertEquals(2, counter.get()); Mockito.verify(badMock).getStats(); Mockito.verify(goodMock).getStats(); stats = provider.getProxy().proxy.getStats(); Assert.assertTrue(stats.length == 1); Assert.assertEquals(1, stats[0]); Mockito.verifyNoMoreInteractions(badMock); Assert.assertEquals(3, counter.get()); isGood[0] = 2; try { provider.getProxy().proxy.getStats(); Assert.fail("Should fail since previously successful proxy now fails "); } catch (Exception ex) { Assert.assertTrue(ex instanceof IOException); } Assert.assertEquals(4, counter.get()); provider.performFailover(provider.getProxy().proxy); stats = provider.getProxy().proxy.getStats(); Assert.assertTrue(stats.length == 1); Assert.assertEquals(2, stats[0]); Assert.assertEquals(5, counter.get()); stats = provider.getProxy().proxy.getStats(); Assert.assertTrue(stats.length == 1); Assert.assertEquals(2, stats[0]); Assert.assertEquals(6, counter.get()); isGood[0] = 1; try { provider.getProxy().proxy.getStats(); Assert.fail("Should fail since previously successful proxy now fails "); } catch (Exception ex) { Assert.assertTrue(ex instanceof IOException); } Assert.assertEquals(7, counter.get()); provider.performFailover(provider.getProxy().proxy); stats = provider.getProxy().proxy.getStats(); Assert.assertTrue(stats.length == 1); Assert.assertEquals(1, stats[0]); }