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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

import com.scytl.slogger.policy.LogFileNamePolicies;

import org.apache.log4j.Layout;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.Before;
import org.junit.Test;

import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * Tests of {@link DeferredSecureAppender}.
 * 
 * @author aakimov
 */
public class DeferredSecureAppenderTest {
  private SecureAppenderSpy delegate;
  private DeferredSecureAppender appender;

  @Before
  public void setUp() {
    delegate = new SecureAppenderSpy();
    appender = new DeferredSecureAppender(delegate);
  }

  @Test
  public void testActivateOptions() {
    PrivateKey signaturePrivateKey = mock(PrivateKey.class);
    PrivateKey cipherPrivateKey = mock(PrivateKey.class);
    PublicKey cipherPublicKey = mock(PublicKey.class);
    appender.activateOptions(signaturePrivateKey, cipherPrivateKey, cipherPublicKey);
    assertEquals(signaturePrivateKey, delegate.signaturePrivateKey);
    assertEquals(cipherPrivateKey, delegate.cipherPrivateKey);
    assertEquals(cipherPublicKey, delegate.cipherPublicKey);
    assertTrue(delegate.isActivated());
  }

  @Test
  public void testAddFilter() {
    Filter filter = mock(Filter.class);
    appender.addFilter(filter);
    assertEquals(filter, delegate.getFilter());
  }

  @Test
  public void testClearFilters() {
    Filter filter = mock(Filter.class);
    appender.addFilter(filter);
    appender.clearFilters();
    assertNull(delegate.getFilter());
  }

  @Test
  public void testClose() {
    appender.close();
    assertTrue(delegate.isClosed());
  }

  @Test
  public void testDoAppend() {
    LoggingEvent event = mock(LoggingEvent.class);
    appender.doAppend(event);
    assertEquals(event, delegate.getEvent());
  }

  public void testGetFilter() {
    Filter filter = mock(Filter.class);
    appender.addFilter(filter);
    assertEquals(filter, appender.getFilter());
  }

  @Test
  public void testGetLayout() {
    assertNull(appender.getLayout());
  }

  @Test
  public void testGetLogFileNamePolicyName() {
    appender.setLogFileNamePolicyName(LogFileNamePolicies.SINGLE_FILENAME.name());
    assertEquals(LogFileNamePolicies.SINGLE_FILENAME.name(), appender.getLogFileNamePolicyName());
  }

  @Test
  public void testGetName() {
    appender.setName("name");
    assertEquals("name", appender.getName());
  }

  @Test
  public void testGetNumberLogLines() {
    appender.setNumberLogLines(1);
    assertEquals(1, appender.getNumberLogLines());
  }

  @Test
  public void testGetPattern() {
    appender.setPattern("pattern");
    assertEquals("pattern", appender.getPattern());
  }

  @Test
  public void testGetTimerLogMilliseconds() {
    appender.setTimerLogMilliseconds(2);
    assertEquals(2, appender.getTimerLogMilliseconds());
  }

  @Test
  public void testGetTriggeringTime() {
    appender.setTriggeringTime(3);
    assertEquals(3, appender.getTriggeringTime());
  }

  @Test
  public void testGetVerifyPattern() {
    appender.setVerifyPattern("verifyPattern");
    assertEquals("verifyPattern", appender.getVerifyPattern());
  }

  @Test
  public void testRequiresLayout() {
    assertEquals(delegate.requiresLayout(), appender.requiresLayout());
  }

  @Test
  public void testSetAppend() {
    appender.setAppend(true);
    assertTrue(delegate.getAppend());
  }

  @Test
  public void testSetBufferedIO() {
    appender.setBufferedIO(true);
    assertTrue(delegate.getBufferedIO());
  }

  @Test
  public void testSetBufferSize() {
    appender.setBufferSize(4);
    assertEquals(4, delegate.getBufferSize());
  }

  @Test
  public void testSetCryptographyProviderClass() {
    appender.setCryptographyProviderClass("cryptographyProviderClass");
    assertEquals("cryptographyProviderClass", delegate.getCryptographyProviderClass());
  }

  @Test
  public void testSetEncoding() {
    appender.setEncoding("encoding");
    assertEquals("encoding", delegate.getEncoding());
  }

  @Test
  public void testSetErrorHandler() {
    ErrorHandler handler = mock(ErrorHandler.class);
    appender.setErrorHandler(handler);
    assertEquals(handler, delegate.getErrorHandler());
  }

  @Test
  public void testSetFile() {
    appender.setFile("file");
    assertEquals("file", delegate.getFile());
  }

  @Test
  public void testSetLayout() {
    appender.setLayout(mock(Layout.class));
    assertNull(appender.getLayout());
  }

  @Test
  public void testSetLogFileNamePolicyName() {
    appender.setLogFileNamePolicyName(LogFileNamePolicies.SINGLE_FILENAME.name());
    assertEquals(LogFileNamePolicies.SINGLE_FILENAME.name(), delegate.getLogFileNamePolicyName());
  }

  @Test
  public void testSetName() {
    appender.setName("name");
    assertEquals("name", delegate.getName());
  }

  @Test
  public void testSetNumberLogLines() {
    appender.setNumberLogLines(5);
    assertEquals(5, delegate.getNumberLogLines());
  }

  @Test
  public void testSetPattern() {
    appender.setPattern("pattern");
    assertEquals("pattern", delegate.getPattern());
  }

  @Test
  public void testSetTimerLogMilliseconds() {
    appender.setTimerLogMilliseconds(6);
    assertEquals(6, delegate.getTimerLogMilliseconds());
  }

  @Test
  public void testSetTriggeringTime() {
    appender.setTriggeringTime(7);
    assertEquals(7, delegate.getTriggeringTime());
  }

  @Test
  public void testSetVerifyPattern() {
    appender.setPattern("verifyPattern");
    assertEquals("verifyPattern", delegate.getPattern());
  }

  private static class SecureAppenderSpy extends SecureAppender {
    private boolean activated;
    private LoggingEvent event;

    @Override
    public void activateOptions() {
      activated = true;
    }

    public boolean isActivated() {
      return activated;
    }

    public boolean isClosed() {
      return closed;
    }

    @Override
    public void doAppend(LoggingEvent event) {
      this.event = event;
    }

    public LoggingEvent getEvent() {
      return event;
    }
  }
}
