/*
 * 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.products.ov.commons.verify;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.commons.beans.domain.model.messaging.Payload;
import com.scytl.products.ov.commons.beans.domain.model.messaging.PayloadSignature;
import com.scytl.products.ov.commons.beans.domain.model.messaging.PayloadVerificationException;
import com.scytl.products.ov.commons.beans.validation.CertificateValidationResult;
import com.scytl.products.ov.commons.beans.validation.CryptographicOperationException;

import java.io.InputStream;
import java.security.cert.X509Certificate;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * Test for CryptolibPayloadVerifier
 */
public class CryptolibPayloadVerifierTest {

    private X509Certificate platformCACertificate;

    private X509Certificate verificationCertificate;

    private CertificateValidationResult certificateValidationResult;

    private AsymmetricServiceAPI asymmetricService;

    private Payload payload;

    private PayloadSignature payloadSignature;

    private PayloadSigningCertificateValidator certificateChainValidator;

    @Before
    public void setUp() {
        asymmetricService = mock(AsymmetricServiceAPI.class);
        certificateChainValidator = mock(PayloadSigningCertificateValidator.class);

        platformCACertificate = mock(X509Certificate.class);
        verificationCertificate = mock(X509Certificate.class);
        X509Certificate[] certificateChain = new X509Certificate[] {platformCACertificate, verificationCertificate };

        payloadSignature = mock(PayloadSignature.class);
        when(payloadSignature.getCertificateChain()).thenReturn(certificateChain);

        payload = mock(Payload.class);
        when(payload.getSignature()).thenReturn(payloadSignature);
    }

    /**
     * @throws PayloadVerificationException
     * @throws GeneralCryptoLibException
     * @throws CryptographicOperationException
     * @throws CertificateChainValidationException 
     */
    @Test
    public void validateWithCorrectCertificateChainAndSignature()
            throws PayloadVerificationException, GeneralCryptoLibException, CryptographicOperationException, CertificateChainValidationException {
        // Set up the verifier.
        when(certificateChainValidator.isValid(any(), any())).thenReturn(true);
        when(asymmetricService.verifySignature(any(), any(), any(InputStream.class))).thenReturn(true);

        CryptolibPayloadVerifier sut = new CryptolibPayloadVerifier(asymmetricService, certificateChainValidator);

        assertTrue(sut.isValid(payload, platformCACertificate));
    }

    /**
     * @throws PayloadVerificationException
     * @throws GeneralCryptoLibException
     * @throws CryptographicOperationException
     * @throws CertificateChainValidationException 
     */
    @Test
    public void notValidateWithWrongCertificateChainAndSignature()
            throws PayloadVerificationException, GeneralCryptoLibException, CryptographicOperationException, CertificateChainValidationException {
        // Set up the verifier.
        when(certificateChainValidator.isValid(any(), any())).thenReturn(false);

        CryptolibPayloadVerifier sut = new CryptolibPayloadVerifier(asymmetricService, certificateChainValidator);

        assertFalse(sut.isValid(payload, platformCACertificate));
    }

    /**
     * @throws PayloadVerificationException
     * @throws GeneralCryptoLibException
     * @throws CryptographicOperationException
     * @throws CertificateChainValidationException 
     */
    @Test
    public void notValidateWithCorrectCertificateChainAndWrongSignature()
            throws PayloadVerificationException, GeneralCryptoLibException, CryptographicOperationException, CertificateChainValidationException {
        // Set up the verifier.
        when(certificateChainValidator.isValid(any(), any())).thenReturn(true);
        when(asymmetricService.verifySignature(any(), any(), any(InputStream.class))).thenReturn(false);

        CryptolibPayloadVerifier sut = new CryptolibPayloadVerifier(asymmetricService,certificateChainValidator);

        assertFalse(sut.isValid(payload, platformCACertificate));
    }
}
