@Override
  public KeyVersion createKey(final String name, final byte[] material,
      final Options options) throws IOException {
    return doOp(new ProviderCallable<KeyVersion>() {
      @Override
      public KeyVersion call(KMSClientProvider provider) throws IOException {
        return provider.createKey(name, material, options);
      }
    }, nextIdx(), false);
  }
@Test
  public void testClientRetriesWithSSLHandshakeExceptionSucceedsSecondTime()
      throws Exception {
    Configuration conf = new Configuration();
    conf.setInt(
        CommonConfigurationKeysPublic.KMS_CLIENT_FAILOVER_MAX_RETRIES_KEY, 5);
    final String keyName = "test";
    KMSClientProvider p1 = mock(KMSClientProvider.class);
    when(p1.createKey(Mockito.anyString(), Mockito.any(Options.class)))
        .thenThrow(new SSLHandshakeException("p1"))
        .thenThrow(new SSLException("p1"))
        .thenReturn(new KMSClientProvider.KMSKeyVersion(keyName, "v1",
            new byte[0]));
    KMSClientProvider p2 = mock(KMSClientProvider.class);
    when(p2.createKey(Mockito.anyString(), Mockito.any(Options.class)))
        .thenThrow(new ConnectException("p2"))
        .thenThrow(new SocketException("p1"));

    when(p1.getKMSUrl()).thenReturn("p1");
    when(p2.getKMSUrl()).thenReturn("p2");

    LoadBalancingKMSClientProvider kp = new LoadBalancingKMSClientProvider(
        new KMSClientProvider[] {p1, p2}, 0, conf);

    kp.createKey(keyName, new Options(conf));
    verify(p1, Mockito.times(3)).createKey(Mockito.eq(keyName),
        Mockito.any(Options.class));
    verify(p2, Mockito.times(2)).createKey(Mockito.eq(keyName),
        Mockito.any(Options.class));
  }