// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/hash/BCryptProvider.java
// public class BCryptProvider implements HashProvider {
//     @Override
//     public boolean validateHash(String password, PrincipalDetail principalDetail) {
//         return BCrypt.checkpw(password, principalDetail.getPasswordHash());
//     }
// 
//     @Override
//     public boolean canHandle(String hashConfig) {
//         return hashConfig.equals("bcrypt");
//     }
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/hash/PBESpecHashProvider.java
// public class PBESpecHashProvider implements HashProvider {
//     public final String pluginId = Constants.PLUGIN_ID;
//     private static final Logger LOGGER = Logger.getLoggerFor(PBESpecHashProvider.class);
// 
//     private static final Pattern HASH_CONFIG_PATTERN = Pattern.compile("^(\\w+)\\((\\d+), (\\d+)\\)$");
// 
//     @Override
//     public boolean validateHash(final String password, final PrincipalDetail principalDetail) {
//         Optional<HashConfig> maybeHashConfig = parseHashConfig(principalDetail.getHashConfiguration());
//         return maybeHashConfig.transform(new Function<HashConfig, Boolean>() {
//             @Override
//             public Boolean apply(HashConfig hashConfig) {
//                 PBEKeySpec spec = new PBEKeySpec(
//                         password.toCharArray(),
//                         Base64.decodeBase64(principalDetail.getSalt()),
//                         hashConfig.getIterations(),
//                         hashConfig.getKeySize());
//                 try {
//                     String encoded = Hex.encodeHexString(SecretKeyFactory.getInstance(hashConfig.getAlgorithm()).generateSecret(spec).getEncoded());
//                     return encoded.equals(principalDetail.getPasswordHash());
//                 } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
//                     LOGGER.warn("build hash", e);
//                     return false;
//                 }
//             }
//         }).or(false);
//     }
// 
//     @Override
//     public boolean canHandle(String hashConfig) {
//         return parseHashConfig(hashConfig).isPresent();
//     }
// 
//     private static Optional<HashConfig> parseHashConfig(String configString) {
//         final Matcher matcher = HASH_CONFIG_PATTERN.matcher(configString);
//         if (matcher.find()) {
//             return Optional.of(new HashConfig(
//                     matcher.group(1),
//                     parseInt(matcher.group(2)),
//                     parseInt(matcher.group(3)))
//             );
//         } else {
//             return Optional.absent();
//         }
//     }
// 
//     @Value
//     private static class HashConfig {
//         private final String algorithm;
//         private final int iterations;
//         private final int keySize;
//     }
// }


import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.thoughtworks.go.strongauth.authentication.hash.BCryptProvider;
import com.thoughtworks.go.strongauth.authentication.hash.PBESpecHashProvider;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
                )));


        when(principalDetailSource.byUsername("usingBCrypt")).thenReturn(
                Optional.of(new PrincipalDetail(
                        "usingBCrypt",
                        "$2a$10$xannybUjnYmLhbfwHsd3deJXBRaBG7.U.t/Jl6gMEHMkod7U/XTs6",
                        "",
                        "bcrypt"
                )));
    }

    @Test
    public void testAuthenticateUserSuccessBCrypt() {
        String username = "usingBCrypt";
        String password = "pazzword123";

        Optional<Principal> maybePrincipal = authenticator.authenticate(username, password);
        assertThat(maybePrincipal, is(Optional.of(new Principal("usingBCrypt"))));
    }

    @Test
    public void testAuthenticateUserFailureBCrypt() {
        String username = "usingBCrypt";
        String password = "pazzword1234";

        Optional<Principal> maybePrincipal = authenticator.authenticate(username, password);
        assertThat(maybePrincipal, is(Optional.<Principal>absent()));
    }

// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/hash/BCryptProvider.java
// public class BCryptProvider implements HashProvider {
//     @Override
//     public boolean validateHash(String password, PrincipalDetail principalDetail) {
//         return BCrypt.checkpw(password, principalDetail.getPasswordHash());
//     }
// 
//     @Override
//     public boolean canHandle(String hashConfig) {
//         return hashConfig.equals("bcrypt");
//     }
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/hash/PBESpecHashProvider.java
// public class PBESpecHashProvider implements HashProvider {
//     public final String pluginId = Constants.PLUGIN_ID;
//     private static final Logger LOGGER = Logger.getLoggerFor(PBESpecHashProvider.class);
// 
//     private static final Pattern HASH_CONFIG_PATTERN = Pattern.compile("^(\\w+)\\((\\d+), (\\d+)\\)$");
// 
//     @Override
//     public boolean validateHash(final String password, final PrincipalDetail principalDetail) {
//         Optional<HashConfig> maybeHashConfig = parseHashConfig(principalDetail.getHashConfiguration());
//         return maybeHashConfig.transform(new Function<HashConfig, Boolean>() {
//             @Override
//             public Boolean apply(HashConfig hashConfig) {
//                 PBEKeySpec spec = new PBEKeySpec(
//                         password.toCharArray(),
//                         Base64.decodeBase64(principalDetail.getSalt()),
//                         hashConfig.getIterations(),
//                         hashConfig.getKeySize());
//                 try {
//                     String encoded = Hex.encodeHexString(SecretKeyFactory.getInstance(hashConfig.getAlgorithm()).generateSecret(spec).getEncoded());
//                     return encoded.equals(principalDetail.getPasswordHash());
//                 } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
//                     LOGGER.warn("build hash", e);
//                     return false;
//                 }
//             }
//         }).or(false);
//     }
// 
//     @Override
//     public boolean canHandle(String hashConfig) {
//         return parseHashConfig(hashConfig).isPresent();
//     }
// 
//     private static Optional<HashConfig> parseHashConfig(String configString) {
//         final Matcher matcher = HASH_CONFIG_PATTERN.matcher(configString);
//         if (matcher.find()) {
//             return Optional.of(new HashConfig(
//                     matcher.group(1),
//                     parseInt(matcher.group(2)),
//                     parseInt(matcher.group(3)))
//             );
//         } else {
//             return Optional.absent();
//         }
//     }
// 
//     @Value
//     private static class HashConfig {
//         private final String algorithm;
//         private final int iterations;
//         private final int keySize;
//     }
// }


// Path: src/test/java/com/thoughtworks/go/strongauth/authentication/AuthenticatorIntegrationTest.java
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.thoughtworks.go.strongauth.authentication.hash.BCryptProvider;
import com.thoughtworks.go.strongauth.authentication.hash.PBESpecHashProvider;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

                )));


        when(principalDetailSource.byUsername("usingBCrypt")).thenReturn(
                Optional.of(new PrincipalDetail(
                        "usingBCrypt",
                        "$2a$10$xannybUjnYmLhbfwHsd3deJXBRaBG7.U.t/Jl6gMEHMkod7U/XTs6",
                        "",
                        "bcrypt"
                )));
    }

    @Test
    public void testAuthenticateUserSuccessBCrypt() {
        String username = "usingBCrypt";
        String password = "pazzword123";

        Optional<Principal> maybePrincipal = authenticator.authenticate(username, password);
        assertThat(maybePrincipal, is(Optional.of(new Principal("usingBCrypt"))));
    }

    @Test
    public void testAuthenticateUserFailureBCrypt() {
        String username = "usingBCrypt";
        String password = "pazzword1234";

        Optional<Principal> maybePrincipal = authenticator.authenticate(username, password);
        assertThat(maybePrincipal, is(Optional.<Principal>absent()));
    }

    @Test