// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// abstract class Report implements Serializable {
//     private final File destination;
// 
//     Report(File destination) {
//         this.destination = requireNonNull(destination, "'destination' must not be null for any report.");
//     }
// 
//     File getDestination() {
//         return destination;
//     }
// 
//     public static class Csv extends Report {
//         private final Character separator;
//         private final boolean includeLineCount;
// 
//         public Csv(File destination, Character separator, boolean includeLineCount) {
//             super(destination);
//             this.separator = separator;
//             this.includeLineCount = includeLineCount;
//         }
// 
//         Character getSeparator() {
//             return separator;
//         }
// 
//         boolean isIncludeLineCount() {
//             return includeLineCount;
//         }
//     }
// 
//     public static class Text extends Report {
//         private final String lineSeparator;
//         private final boolean trimLeadingCommonSourceWhitespaces;
// 
//         public Text(File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
//             super(destination);
//             this.lineSeparator = lineSeparator;
//             this.trimLeadingCommonSourceWhitespaces = trimLeadingCommonSourceWhitespaces;
//         }
// 
//         String getLineSeparator() {
//             return lineSeparator;
//         }
// 
//         boolean isTrimLeadingCommonSourceWhitespaces() {
//             return trimLeadingCommonSourceWhitespaces;
//         }
//     }
// 
//     public static class Vs extends Report {
//         public Vs(File destination) {
//             super(destination);
//         }
//     }
// 
//     public static class Xml extends Report {
//         private final String encoding;
// 
//         public Xml(File destination, String encoding) {
//             super(destination);
//             this.encoding = encoding;
//         }
// 
//         String getEncoding() {
//             return encoding;
//         }
//     }
// }
// 
// Path: src/test/java/de/aaschmid/gradle/plugins/cpd/test/TestTag.java
// public interface TestTag {
// 
//     String INTEGRATION_TEST = "integrationTest";
// }


import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import de.aaschmid.gradle.plugins.cpd.test.TestTag;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.Mark;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.SimpleRenderer;
import net.sourceforge.pmd.cpd.SourceCode;
import net.sourceforge.pmd.cpd.SourceCode.StringCodeLoader;
import net.sourceforge.pmd.cpd.TokenEntry;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.contentOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
package de.aaschmid.gradle.plugins.cpd.internal.worker;




@ExtendWith(MockitoExtension.class)
class CpdReporterTest {

    @InjectMocks
    CpdReporter underTest;

    @Test
    void generate_shouldReThrowRendererThrownIoExceptionAsGradleException(@TempDir Path tempDir) throws Exception {
        // Given:
        Report report = mock(Report.class);
        when(report.getDestination()).thenReturn(tempDir.resolve("report.file").toFile());

        CPDRenderer cpdRenderer = mock(CPDRenderer.class);
        doThrow(new IOException("foo")).when(cpdRenderer).render(any(), any());

        CpdReporter underTestSpy = spy(underTest);
        doReturn(cpdRenderer).when(underTestSpy).createRendererFor(report);

        // Expect:
        assertThatThrownBy(() -> underTestSpy.generate(singletonList(report), emptyList()))
                .isInstanceOf(GradleException.class)
                .hasMessage("foo")
                .hasCauseInstanceOf(IOException.class);

    }

    @Tag(TestTag.INTEGRATION_TEST)
    @Test // ParameterizedTest not possible because Source provider does not allow arguments like @TempDir
    void generate_shouldGenerateReport(@TempDir Path tempDir) {
        // Given:
        File csvReportFile = tempDir.resolve("cpd.csv").toFile();
        Report.Csv csvReport = new Report.Csv(csvReportFile, ',', true);

        File csvReportFileWithoutLines = tempDir.resolve("cpdWithoutLines.csv").toFile();
        Report.Csv csvReportWithoutLines = new Report.Csv(csvReportFileWithoutLines, ';', false);

        File textReportFile = tempDir.resolve("cpd.text").toFile();
        Report.Text textReport = new Report.Text(textReportFile, "#######", false);

        File vsReportFile = tempDir.resolve("cpd.vs").toFile();
// Path: src/main/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdWorkParameters.java
// abstract class Report implements Serializable {
//     private final File destination;
// 
//     Report(File destination) {
//         this.destination = requireNonNull(destination, "'destination' must not be null for any report.");
//     }
// 
//     File getDestination() {
//         return destination;
//     }
// 
//     public static class Csv extends Report {
//         private final Character separator;
//         private final boolean includeLineCount;
// 
//         public Csv(File destination, Character separator, boolean includeLineCount) {
//             super(destination);
//             this.separator = separator;
//             this.includeLineCount = includeLineCount;
//         }
// 
//         Character getSeparator() {
//             return separator;
//         }
// 
//         boolean isIncludeLineCount() {
//             return includeLineCount;
//         }
//     }
// 
//     public static class Text extends Report {
//         private final String lineSeparator;
//         private final boolean trimLeadingCommonSourceWhitespaces;
// 
//         public Text(File destination, String lineSeparator, boolean trimLeadingCommonSourceWhitespaces) {
//             super(destination);
//             this.lineSeparator = lineSeparator;
//             this.trimLeadingCommonSourceWhitespaces = trimLeadingCommonSourceWhitespaces;
//         }
// 
//         String getLineSeparator() {
//             return lineSeparator;
//         }
// 
//         boolean isTrimLeadingCommonSourceWhitespaces() {
//             return trimLeadingCommonSourceWhitespaces;
//         }
//     }
// 
//     public static class Vs extends Report {
//         public Vs(File destination) {
//             super(destination);
//         }
//     }
// 
//     public static class Xml extends Report {
//         private final String encoding;
// 
//         public Xml(File destination, String encoding) {
//             super(destination);
//             this.encoding = encoding;
//         }
// 
//         String getEncoding() {
//             return encoding;
//         }
//     }
// }
// 
// Path: src/test/java/de/aaschmid/gradle/plugins/cpd/test/TestTag.java
// public interface TestTag {
// 
//     String INTEGRATION_TEST = "integrationTest";
// }


// Path: src/test/java/de/aaschmid/gradle/plugins/cpd/internal/worker/CpdReporterTest.java
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import de.aaschmid.gradle.plugins.cpd.internal.worker.CpdWorkParameters.Report;
import de.aaschmid.gradle.plugins.cpd.test.TestTag;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.Mark;
import net.sourceforge.pmd.cpd.Match;
import net.sourceforge.pmd.cpd.SimpleRenderer;
import net.sourceforge.pmd.cpd.SourceCode;
import net.sourceforge.pmd.cpd.SourceCode.StringCodeLoader;
import net.sourceforge.pmd.cpd.TokenEntry;
import net.sourceforge.pmd.cpd.VSRenderer;
import net.sourceforge.pmd.cpd.XMLRenderer;
import net.sourceforge.pmd.cpd.renderer.CPDRenderer;
import org.gradle.api.GradleException;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.contentOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

package de.aaschmid.gradle.plugins.cpd.internal.worker;




@ExtendWith(MockitoExtension.class)
class CpdReporterTest {

    @InjectMocks
    CpdReporter underTest;

    @Test
    void generate_shouldReThrowRendererThrownIoExceptionAsGradleException(@TempDir Path tempDir) throws Exception {
        // Given:
        Report report = mock(Report.class);
        when(report.getDestination()).thenReturn(tempDir.resolve("report.file").toFile());

        CPDRenderer cpdRenderer = mock(CPDRenderer.class);
        doThrow(new IOException("foo")).when(cpdRenderer).render(any(), any());

        CpdReporter underTestSpy = spy(underTest);
        doReturn(cpdRenderer).when(underTestSpy).createRendererFor(report);

        // Expect:
        assertThatThrownBy(() -> underTestSpy.generate(singletonList(report), emptyList()))
                .isInstanceOf(GradleException.class)
                .hasMessage("foo")
                .hasCauseInstanceOf(IOException.class);

    }

    @Tag(TestTag.INTEGRATION_TEST)
    @Test // ParameterizedTest not possible because Source provider does not allow arguments like @TempDir
    void generate_shouldGenerateReport(@TempDir Path tempDir) {
        // Given:
        File csvReportFile = tempDir.resolve("cpd.csv").toFile();
        Report.Csv csvReport = new Report.Csv(csvReportFile, ',', true);

        File csvReportFileWithoutLines = tempDir.resolve("cpdWithoutLines.csv").toFile();
        Report.Csv csvReportWithoutLines = new Report.Csv(csvReportFileWithoutLines, ';', false);

        File textReportFile = tempDir.resolve("cpd.text").toFile();
        Report.Text textReport = new Report.Text(textReportFile, "#######", false);

        File vsReportFile = tempDir.resolve("cpd.vs").toFile();
        Report.Vs vsReport = new Report.Vs(vsReportFile);