package sg.ncl.service.data.logic;

import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.springframework.test.context.TestPropertySource;
import sg.ncl.common.AvScannerProperties;
import sg.ncl.service.data.domain.AvScannerService;
import sg.ncl.service.transmission.DirectoryProperties;
import xyz.capybara.clamav.ClamavClient;
import xyz.capybara.clamav.commands.scan.result.ScanResult;
import xyz.capybara.clamav.exceptions.ClamavException;

import java.nio.file.Path;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mockingDetails;
import static org.mockito.Mockito.when;

/**
 * Created by dcsyeoty on 05-Jun-17.
 */
@TestPropertySource(properties = "flyway.enabled=false")
public class AvScannerImplTest {

    @Rule
    public MockitoRule mockito = MockitoJUnit.rule();
    @Rule
    public final ExpectedException exception = ExpectedException.none();

    @Mock
    private AvScannerProperties avScannerProperties;
    @Mock
    private DirectoryProperties directoryProperties;
    @Mock
    private AvScannerImpl.ClamavFactory clamavFactory;
    @Mock
    private ClamavClient clamavClient;
    @Mock
    private ScanResult scanResult;

    private AvScannerService avScannerService;

    @Before
    public void before() {
        assertThat(mockingDetails(avScannerProperties).isMock()).isTrue();
        assertThat(mockingDetails(clamavClient).isMock()).isTrue();
        assertThat(mockingDetails(clamavFactory).isMock()).isTrue();
        assertThat(mockingDetails(directoryProperties).isMock()).isTrue();
        assertThat(mockingDetails(scanResult).isMock()).isTrue();

        when(clamavFactory.createClamavClient(anyString(), anyInt())).thenReturn(clamavClient);

        // invoke the factory design pattern constructor when unit testing instead of the ordinary one
        avScannerService = new AvScannerImpl(avScannerProperties, directoryProperties, clamavFactory);
    }

    @Test
    public void testScanCleanFile() throws ClamavException {
        when(clamavClient.scan(any(Path.class), eq(false))).thenReturn(scanResult);
        when(scanResult.getStatus()).thenReturn(ScanResult.Status.OK);
        assertThat(avScannerService.scan("data", "dataset", "fileName")).isFalse();
    }

    @Test
    public void testScanMaliciousFile() throws ClamavException {
        when(clamavClient.scan(any(Path.class), eq(false))).thenReturn(scanResult);
        when(scanResult.getStatus()).thenReturn(ScanResult.Status.VIRUS_FOUND);
        assertThat(avScannerService.scan("data", "dataset", "fileName")).isTrue();
    }

    @Test
    public void testScanFileNullResult() throws ClamavException {
        when(clamavClient.scan(any(Path.class), eq(false))).thenReturn(scanResult);
        when(scanResult.getStatus()).thenReturn(null);
        assertThat(avScannerService.scan("data", "dataset", "fileName")).isFalse();
    }

    @Test
    public void testScanFileClamAvException() throws ClamavException {
        when(clamavClient.version()).thenReturn(RandomStringUtils.randomAlphanumeric(20));
        doThrow(new ClamavException(new Throwable("error_message"))).when(clamavClient).scan(any(Path.class), eq(false));
        when(scanResult.getStatus()).thenReturn(ScanResult.Status.VIRUS_FOUND);

        assertThat(avScannerService.scan("data", "dataset", "fileName")).isFalse();
    }
}

@@ -644,31 +644,17 @@
 eptions.
-ClamavException
+*
 ;%0A%0Aimpor
@@ -3550,24 +3550,1471 @@
 US_FOUND);%0A%0A
+        assertThat(avScannerService.scan(%22data%22, %22dataset%22, %22fileName%22)).isFalse();%0A    %7D%0A%0A    @Test%0A    public void testScanCommunicationException() throws Exception %7B%0A        doThrow(new CommunicationException(new Throwable(%22error_message%22))).when(clamavClient).scan(any(Path.class), eq(false));%0A%0A        assertThat(avScannerService.scan(%22data%22, %22dataset%22, %22fileName%22)).isFalse();%0A    %7D%0A%0A    @Test%0A    public void testScanInvalidResponseException() throws Exception %7B%0A        doThrow(new InvalidResponseException(%22error_message%22)).when(clamavClient).scan(any(Path.class), eq(false));%0A%0A        assertThat(avScannerService.scan(%22data%22, %22dataset%22, %22fileName%22)).isFalse();%0A    %7D%0A%0A    @Test%0A    public void testScanScanFailureException() throws Exception %7B%0A        doThrow(new ScanFailureException(%22error_message%22)).when(clamavClient).scan(any(Path.class), eq(false));%0A%0A        assertThat(avScannerService.scan(%22data%22, %22dataset%22, %22fileName%22)).isFalse();%0A    %7D%0A%0A    @Test%0A    public void testScanUnknownCommandException() throws Exception %7B%0A        doThrow(new UnknownCommandException(%22error_message%22)).when(clamavClient).scan(any(Path.class), eq(false));%0A%0A        assertThat(avScannerService.scan(%22data%22, %22dataset%22, %22fileName%22)).isFalse();%0A    %7D%0A%0A    @Test%0A    public void testScanUnsupportedCommandException() throws Exception %7B%0A        doThrow(new UnsupportedCommandException(%22error_message%22)).when(clamavClient).scan(any(Path.class), eq(false));%0A%0A
         asse

add tests for additional capture clamav related exceptions