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

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;

/**
 * Tests of {@link SignatureInputStream}.
 */
public class SignatureInputStreamTest {
    private static final byte[] DATA = {0, 1, 2 };

    private AsymmetricServiceAPI service;

    private KeyPair pair;

    private Signature signature;

    private SignatureInputStream stream;

    @BeforeClass
    public static void init() {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Before
    public void setUp() throws GeneralCryptoLibException {
        service = new AsymmetricService();
        pair = service.getKeyPairForSigning();
        signature = SignatureFactoryImpl.newInstance().newSignature();
        stream = new SignatureInputStream(new ByteArrayInputStream(DATA), signature);
    }

    @Test
    public void testRead() throws IOException, SignatureException, InvalidKeyException, GeneralCryptoLibException {
        signature.initSign(pair.getPrivate());

        assertEquals(0, stream.read());
        assertEquals(1, stream.read());
        assertEquals(2, stream.read());
        assertEquals(-1, stream.read());

        assertTrue(service.verifySignature(signature.sign(), pair.getPublic(), DATA));
    }

    @Test(expected = IOException.class)
    public void testReadArrayIntIntSignatureException()
            throws IOException, SignatureException, InvalidKeyException, GeneralCryptoLibException {
        stream.read(new byte[3], 0, 3);
    }

    @Test
    public void testReadByteArrayIntInt()
            throws InvalidKeyException, IOException, SignatureException, GeneralCryptoLibException {
        signature.initSign(pair.getPrivate());

        byte[] buffer = new byte[3];
        assertEquals(2, stream.read(buffer, 0, 2));
        assertEquals(1, stream.read(buffer, 2, 1));
        assertEquals(-1, stream.read());
        assertArrayEquals(DATA, buffer);

        assertTrue(service.verifySignature(signature.sign(), pair.getPublic(), DATA));
    }

    @Test(expected = IOException.class)
    public void testReadSignatureException()
            throws IOException, SignatureException, InvalidKeyException, GeneralCryptoLibException {
        stream.read();
    }
}
