/*
 * 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.certificates.bean;

import static org.junit.Assert.assertEquals;

import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.constants.X509CertificateConstants;
import com.scytl.cryptolib.commons.constants.Constants;
import com.scytl.cryptolib.primitives.securerandom.configuration.SecureRandomPolicyFromProperties;
import com.scytl.cryptolib.primitives.securerandom.constants.SecureRandomConstants;
import com.scytl.cryptolib.primitives.securerandom.factory.CryptoRandomString;
import com.scytl.cryptolib.primitives.securerandom.factory.SecureRandomFactory;

/**
 * Tests of X509DistinguishedName.
 */
public class X509DistinguishedNameTest {

    /**
     * A set 64 of characters.
     * <P>
     * Contains:
     * <ul>
     * <li>The 52 English letter characters (lowercase and uppercase).</li>
     * <li>The number characters 0 - 9 (inclusive).</li>
     * <li>The 'plus' and 'forward slash' characters.</li>
     * </ul>
     */

    private static String ILLEGAL_CHARACTER = "ç";

    private static String _commonName;

    private static String _country;

    private static String _organizationalUnit;

    private static String _organization;

    private static String _locality;

    private static String _maxSizeAttribute;

    private static String _tooLargeAttribute;

    private static String _illegalAttribute;

    private static String _illegalCountryAttribute;

    private static X509DistinguishedName _x509DistinguishedName;

    @BeforeClass
    public static void setUp() throws GeneralCryptoLibException {

        CryptoRandomString randomAttributeGenerator =
            new SecureRandomFactory(new SecureRandomPolicyFromProperties(
                Constants.CRYPTOLIB_POLICY_PROPERTIES_FILE_PATH))
                .createStringRandom(SecureRandomConstants.ALPHABET_BASE64);

        _commonName = randomAttributeGenerator.nextRandom(10);
        _country = randomAttributeGenerator.nextRandom(2);
        _organizationalUnit = randomAttributeGenerator.nextRandom(10);
        _organization = randomAttributeGenerator.nextRandom(10);
        _locality = randomAttributeGenerator.nextRandom(10);

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country);
        builder.addOrganization(_organization);
        builder.addOrganizationalUnit(_organizationalUnit);
        builder.addLocality(_locality);

        _x509DistinguishedName = builder.build();

        _maxSizeAttribute =
            randomAttributeGenerator
                .nextRandom(X509CertificateConstants.X509_DISTINGUISHED_NAME_ATTRIBUTE_MAX_SIZE);
        _tooLargeAttribute =
            randomAttributeGenerator
                .nextRandom(X509CertificateConstants.X509_DISTINGUISHED_NAME_ATTRIBUTE_MAX_SIZE + 1);
        _illegalAttribute =
            randomAttributeGenerator.nextRandom(10) + ILLEGAL_CHARACTER;
        _illegalCountryAttribute =
            randomAttributeGenerator.nextRandom(1) + ILLEGAL_CHARACTER;
    }

    @Test
    public void whenGetCommonNameAttributeThenOK() {

        String errorMsg =
            "The returned common name was not what was expected";
        assertEquals(errorMsg, _commonName,
            _x509DistinguishedName.getCommonName());
    }

    @Test
    public void whenGetOrganizationalUnitAttributeThenOK() {

        String errorMsg =
            "The returned organizational unit was not what was expected";
        assertEquals(errorMsg, _organizationalUnit,
            _x509DistinguishedName.getOrganizationalUnit());
    }

    @Test
    public void whenGetOrganizationAttributeThenOK() {

        String errorMsg =
            "The returned organization was not what was expected";
        assertEquals(errorMsg, _organization,
            _x509DistinguishedName.getOrganization());
    }

    @Test
    public void whenGetLocalityAttributeThenOK() {

        String errorMsg =
            "The returned locality was not what was expected";
        assertEquals(errorMsg, _locality,
            _x509DistinguishedName.getLocality());
    }

    @Test
    public void whenGetCountryAttributeThenOK() {

        String errorMsg = "The returned country was not what was expected";
        assertEquals(errorMsg, _country,
            _x509DistinguishedName.getCountry());
    }

    @Test
    public void givenMaxSizeCommonNameAttributeThenOk()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_maxSizeAttribute, _country);
    }

    @Test
    public void givenMaxSizeOrganizationalUnitAttributeThenOk()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganizationalUnit(_maxSizeAttribute);

        builder.build();
    }

    @Test
    public void givenMaxSizeOrganizationAttributeThenOk()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganization(_maxSizeAttribute);

        builder.build();
    }

    @Test
    public void givenMaxSizeLocalityAttributeThenOk()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addLocality(_maxSizeAttribute);

        builder.build();
    }

    @Test
    public void givenSameDistinguishedNamesThenEquality()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country);
        builder.addOrganization(_organization);
        builder.addOrganizationalUnit(_organizationalUnit);
        builder.addLocality(_locality);

        X509DistinguishedName x509DistinguishedName1 = builder.build();
        X509DistinguishedName x509DistinguishedName2 = builder.build();

        assert (x509DistinguishedName1.equals(x509DistinguishedName2));
    }

    @Test
    public void givenDifferentDistinguishedNamesThenInEquality()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country);
        builder.addOrganization(_organization);
        builder.addOrganizationalUnit(_organizationalUnit);
        builder.addLocality(_locality);

        X509DistinguishedName x509DistinguishedName1 = builder.build();

        builder = new X509DistinguishedName.Builder(_commonName, _country);
        builder.addOrganization(_organization);
        builder.addOrganizationalUnit(_organizationalUnit);
        builder.addLocality(_locality + "x");

        X509DistinguishedName x509DistinguishedName2 = builder.build();

        assert (!x509DistinguishedName1.equals(x509DistinguishedName2));
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenNullCommonNameAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(null, _country);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenNullCountryAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_commonName, null);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenNullOrganizationalUnitAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganizationalUnit(null);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenNullOrganizationAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganization(null);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenNullLocalityAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addLocality(null);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenEmptyCommonNameAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder("", _country);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenEmptyCountryAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_commonName, "");
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenTooLargeCommonNameAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_tooLargeAttribute, _country);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenTooLargeCountryAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_commonName, _tooLargeAttribute);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenTooLargeOrganizationalUnitAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganizationalUnit(_tooLargeAttribute);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenTooLargeOrganizationAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganization(_tooLargeAttribute);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenTooLargeLocalityAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addLocality(_tooLargeAttribute);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenIllegalCommonNameAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_illegalAttribute, _country);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenIllegalCountryAttributeThenException()
            throws GeneralCryptoLibException {

        new X509DistinguishedName.Builder(_commonName,
            _illegalCountryAttribute);
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenIllegalOrganizationalUnitAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganizationalUnit(_illegalAttribute);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenIllegalOrganizationAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addOrganization(_illegalAttribute);

        builder.build();
    }

    @Test(expected = GeneralCryptoLibException.class)
    public void givenIllegalLocalityAttributeThenException()
            throws GeneralCryptoLibException {

        X509DistinguishedName.Builder builder =
            new X509DistinguishedName.Builder(_commonName, _country)
                .addLocality(_illegalAttribute);

        builder.build();
    }

}
