/*
 * 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.channel.cc.commons.slogger;

import static java.util.Arrays.asList;
import static java.util.Collections.enumeration;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Enumeration;

import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.LoggerRepository;
import org.junit.Before;
import org.junit.Test;

import com.scytl.products.ov.channel.cc.commons.keymanagement.KeyManager;
import com.scytl.slogger.DeferredSecureAppender;
import com.scytl.slogger.SecureAppender;
import com.scytl.slogger.SecureLoggerException;

/**
 * Tests of {@link SecureLoggerManagerImpl}.
 */
public class SecureLoggerManagerImplTest {
    private static final String NAME = "SecureLogger";

    private ErrorHandler handler;

    private DeferredSecureAppender appender;

    private Logger logger;

    private LoggerRepository repository;

    private PrivateKey signaturePrivateKey;

    private PrivateKey cipherPrivateKey;

    private PublicKey cipherPublicKey;

    private KeyManager manager;

    private SecureLoggerManagerImpl activator;

    private ErrorTracker tracker;

    @Before
    public void setUp() {
        handler = mock(ErrorHandler.class);

        appender = mock(DeferredSecureAppender.class);
        when(appender.getErrorHandler()).thenReturn(handler);

        Appender appender2 = new FileAppender();
        Appender appender3 = new SecureAppender();

        Enumeration<Object> appenders =
            enumeration(asList(appender, appender2, appender3));

        logger = mock(Logger.class);
        when(logger.getAllAppenders()).thenReturn(appenders);

        repository = mock(LoggerRepository.class);
        when(repository.getLogger(NAME)).thenReturn(logger);

        signaturePrivateKey = mock(PrivateKey.class);
        cipherPrivateKey = mock(PrivateKey.class);
        cipherPublicKey = mock(PublicKey.class);

        manager = mock(KeyManager.class);
        when(manager.hasNodeKeysActivated()).thenReturn(true);
        when(manager.nodeLogSigningPrivateKey())
            .thenReturn(signaturePrivateKey);
        when(manager.nodeLogEncryptionPrivateKey())
            .thenReturn(cipherPrivateKey);
        when(manager.nodeLogEncryptionPublicKey())
            .thenReturn(cipherPublicKey);

        activator = new SecureLoggerManagerImpl(repository, manager);

        tracker = mock(ErrorTracker.class);
    }

    @Test
    public void testCloseSecureLogger() throws SecureLoggerException {
        activator.closeSecureLogger(NAME);
        verify(appender).close();
    }

    @Test(expected = SecureLoggerException.class)
    public void testCloseSecureLoggerAppenderNotFound()
            throws SecureLoggerException {
        Appender appender2 = new FileAppender();
        Appender appender3 = new SecureAppender();
        Enumeration<Object> appenders =
            enumeration(asList(appender2, appender3));
        when(logger.getAllAppenders()).thenReturn(appenders);
        activator.closeSecureLogger(NAME);
    }

    @Test
    public void testOpenSecureLogger() throws SecureLoggerException {
        activator.openSecureLogger(NAME, tracker);
        verify(appender).activateOptions(signaturePrivateKey,
            cipherPrivateKey, cipherPublicKey);
        verify(tracker).setTarget(handler);
        verify(appender).setErrorHandler(tracker);
        verify(tracker).checkNoError();
    }

    @Test(expected = SecureLoggerException.class)
    public void testOpenSecureLoggerAppenderFailed()
            throws SecureLoggerException {
        doThrow(new SecureLoggerException("test")).when(tracker)
            .checkNoError();
        activator.openSecureLogger(NAME, tracker);
    }

    @Test(expected = SecureLoggerException.class)
    public void testOpenSecureLoggerAppenderNotFound()
            throws SecureLoggerException {
        Appender appender2 = new FileAppender();
        Appender appender3 = new SecureAppender();
        Enumeration<Object> appenders =
            enumeration(asList(appender2, appender3));
        when(logger.getAllAppenders()).thenReturn(appenders);
        activator.openSecureLogger(NAME, tracker);
    }

    @Test(expected = SecureLoggerException.class)
    public void testOpenSecureLoggerKeysNotActivated()
            throws SecureLoggerException {
        when(manager.hasNodeKeysActivated()).thenReturn(false);
        activator.openSecureLogger(NAME, tracker);
    }
}
