/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.cryptolib.asymmetric.keypair.openssl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.KeyPair;
import java.security.KeyPairGeneratorSpi;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;

import org.junit.Before;
import org.junit.Test;

import mockit.Expectations;
import mockit.Injectable;
import mockit.Verifications;

/**
 * Tests of {@link OpenSSLKeyPairGenerator}.
 */
public class OpenSSLKeyPairGeneratorTest {
    @Injectable
    private KeyPairGeneratorSpi spi;

    @Injectable
    private OpenSSLFactory factory;

    @Injectable
    private OpenSSL openSSL;

    private OpenSSLKeyPairGenerator generator;

    @Before
    public void setUp() {
        generator = new OpenSSLKeyPairGenerator("RSA", spi);
    }

    @Test
    public void testGenerateKeyPair() {
        final KeyPair pair = new KeyPair(null, null);
        new Expectations() {
            {
                spi.generateKeyPair();
                result = pair;
            }
        };
        assertEquals(pair, generator.generateKeyPair());
    }

    @Test
    public void testGetInstanceOpenSSLFactoryStringRSA()
            throws OpenSSLException, NoSuchAlgorithmException {
        new Expectations() {
            {
                factory.getOpenSSL();
                result = openSSL;
            }
        };
        assertNotNull(OpenSSLKeyPairGenerator.getInstance(factory, "RSA"));
    }

    @Test(expected = NoSuchAlgorithmException.class)
    public void testGetInstanceOpenSSLStringOpenSSLNotAvailable()
            throws OpenSSLException, NoSuchAlgorithmException {
        new Expectations() {
            {
                factory.getOpenSSL();
                result = new OpenSSLException("test");
            }
        };
        OpenSSLKeyPairGenerator.getInstance(factory, "RSA");
    }

    @Test(expected = NoSuchAlgorithmException.class)
    public void testGetInstanceOpenSSLStringUnsupportedAlgorithm()
            throws OpenSSLException, NoSuchAlgorithmException {
        new Expectations() {
            {
                factory.getOpenSSL();
                result = openSSL;
            }
        };
        OpenSSLKeyPairGenerator.getInstance(factory, "Unsupported");
    }

    @Test
    public void testInitializeAlgorithmParameterSpecSecureRandom()
            throws InvalidAlgorithmParameterException {
        final AlgorithmParameterSpec spec =
            new RSAKeyGenParameterSpec(1, BigInteger.TEN);
        final SecureRandom random = new SecureRandom();
        generator.initialize(spec, random);
        new Verifications() {
            {
                spi.initialize(spec, random);
            }
        };
    }

    @Test(expected = InvalidAlgorithmParameterException.class)
    public void testInitializeAlgorithmParameterSpecSecureRandomInvalid()
            throws InvalidAlgorithmParameterException {
        final AlgorithmParameterSpec spec =
            new RSAKeyGenParameterSpec(1, BigInteger.TEN);
        final SecureRandom random = new SecureRandom();
        new Expectations() {
            {
                spi.initialize(spec, random);
                result = new InvalidAlgorithmParameterException("test");
            }
        };
        generator.initialize(spec, random);
    }

    @Test
    public void testInitializeIntSecureRandom() {
        final int keysize = 1;
        final SecureRandom random = new SecureRandom();
        generator.initialize(keysize, random);
        new Verifications() {
            {
                spi.initialize(keysize, random);
            }
        };
    }

    @Test(expected = InvalidParameterException.class)
    public void testInitializeIntSecureRandomInvalid() {
        final int keysize = 1;
        final SecureRandom random = new SecureRandom();
        new Expectations() {
            {
                spi.initialize(keysize, random);
                result = new InvalidParameterException("test");
            }
        };
        generator.initialize(keysize, random);
    }
}
