package io.dropwizard.jetty;

import io.dropwizard.jackson.DiscoverableSubtypeResolver;

import java.security.KeyStore;
import java.security.KeyStoreException;
import java.util.Collection;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.apache.commons.lang3.SystemUtils;
import org.junit.Test;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;

public class HttpsConnectorFactoryTest {
    private static final String WINDOWS_MY_KEYSTORE_NAME = "Windows-MY";
    private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    @Test
    public void isDiscoverable() throws Exception {
        assertThat(new DiscoverableSubtypeResolver().getDiscoveredSubtypes())
                .contains(HttpsConnectorFactory.class);
    }

    @Test
    public void nonWindowsKeyStoreValidation() throws Exception {
        HttpsConnectorFactory factory = new HttpsConnectorFactory();
        Collection<String> properties = getViolationProperties(validator.validate(factory));
        assertThat(properties.contains("validKeyStorePassword")).isEqualTo(true);
        assertThat(properties.contains("validKeyStorePath")).isEqualTo(true);
    }

    @Test
    public void windowsKeyStoreValidation() throws Exception {
        HttpsConnectorFactory factory = new HttpsConnectorFactory();
        factory.setKeyStoreType(WINDOWS_MY_KEYSTORE_NAME);
        Collection<String> properties = getViolationProperties(validator.validate(factory));
        assertThat(properties.contains("validKeyStorePassword")).isEqualTo(false);
        assertThat(properties.contains("validKeyStorePath")).isEqualTo(false);
    }

    @Test
    public void windowsKeyStore() throws Exception {
        HttpsConnectorFactory factory = new HttpsConnectorFactory();
        factory.setKeyStoreType(WINDOWS_MY_KEYSTORE_NAME);
        if (canAccessWindowsKeyStore()) {
            factory.buildSslContextFactory();
            return;
        } else {
            try {
                factory.buildSslContextFactory();
                fail("Windows key store should not be supported here");
            } catch (IllegalStateException ex) {
                assertThat(ex.getMessage()).containsIgnoringCase("not supported");
            }
        }
    }

    private boolean canAccessWindowsKeyStore() {
        if (SystemUtils.IS_OS_WINDOWS) {
            try {
                KeyStore.getInstance(WINDOWS_MY_KEYSTORE_NAME);
                return true;
            } catch (KeyStoreException e) {
                return false;
            }
        }
        return false;
    }

    private <T> Collection<String> getViolationProperties(Set<ConstraintViolation<T>> violations) {
        return Collections2.transform(violations, new Function<ConstraintViolation<T>, String>() {
            @Override
            public String apply(ConstraintViolation<T> input) {
                return input.getPropertyPath().toString();
            }
        });
    }
}

@@ -568,20 +568,116 @@
 .Assert.
-fail
+assertNotNull;%0Aimport static org.junit.Assume.assumeFalse;%0Aimport static org.junit.Assume.assumeTrue
 ;%0A%0Apubli
@@ -1973,33 +1973,59 @@
     public void 
-w
+canBuildContextFactoryWhenW
 indowsKeyStore()
@@ -2022,16 +2022,25 @@
 KeyStore
+Available
 () throw
@@ -2053,32 +2053,144 @@
 ption %7B%0A        
+// ignore test when Windows Keystore unavailable%0A        assumeTrue(canAccessWindowsKeyStore());%0A%0A        final 
 HttpsConnectorFa
@@ -2293,24 +2293,25 @@
 _NAME);%0A
+%0A
         
 if (canA
@@ -2306,54 +2306,22 @@
     
-if (canAccessWindowsKeyStore()) %7B%0A            
+assertNotNull(
 fact
@@ -2352,342 +2352,372 @@
 ry()
+)
 ;%0A    
+%7D%0A%0A
     
-    return;%0A        %7D else %7B%0A            try %7B%0A                factory.buildSslContextFactory();%0A                fail(%22Windows key store should not be supported here%22);%0A            %7D catch (IllegalStateException ex) %7B%0A                assertThat(ex.getMessage()).containsIgnoringCase(%22not supported%22);%0A            %7D%0A        %7D
+@Test(expected = IllegalStateException.class)%0A    public void windowsKeyStoreUnavailableThrowsException() throws Exception %7B%0A        assumeFalse(canAccessWindowsKeyStore());%0A%0A        final HttpsConnectorFactory factory = new HttpsConnectorFactory();%0A        factory.setKeyStoreType(WINDOWS_MY_KEYSTORE_NAME);%0A        factory.buildSslContextFactory();
 %0A   

Split multi-purposed test and clarified names.