package com.github.cseppento.gradle.evosuite;

import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.internal.plugins.PluginApplicationException;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.github.cseppento.gradle.evosuite.testhelper.ExceptionMessageMatcher.messageContainsString;
import static org.hamcrest.CoreMatchers.isA;
import static org.junit.Assert.assertEquals;

public class EvoSuitePluginIntegTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    private Project project;
    private Path projectDir;

    @Before
    public void setUp() {
        project = ProjectBuilder.builder().withName("test-project").build();
        projectDir = project.getProjectDir().toPath();
    }

    @Test
    public void testSourceSets() {
        project.getPluginManager().apply(JavaPlugin.class);
        project.getPluginManager().apply(EvoSuitePlugin.class);

        SourceSetContainer sourceSets = (SourceSetContainer) project.property("sourceSets");
        SourceSet sourceSet = sourceSets.getByName("evosuiteTest");

        assertEquals(1, sourceSet.getJava().getSrcDirs().size());
        assertEquals(1, sourceSet.getResources().getSrcDirs().size());

        Set<Path> compileCp = toRelPaths(sourceSet.getCompileClasspath().getFiles());
        Set<Path> runtimeCp = toRelPaths(sourceSet.getRuntimeClasspath().getFiles());

        assertEquals(pathSet("build/classes/java/main", "build/resources/main"), compileCp);
        assertEquals(pathSet(
                "build/classes/java/main", "build/resources/main",
                "build/classes/java/evosuiteTest", "build/resources/evosuiteTest"), runtimeCp);
    }

    @Test
    public void testApplyFailsIfJavaPluginIsNotApplied() {
        thrown.expect(PluginApplicationException.class);
        thrown.expectMessage("Failed to apply plugin");
        thrown.expectCause(isA(GradleException.class));
        thrown.expectCause(messageContainsString("Please apply the java plugin first in order to use the EvoSuite plugin"));

        project.getPluginManager().apply(EvoSuitePlugin.class);
    }

    private Set<Path> toRelPaths(Set<File> files) {
        return files.stream().map(File::toPath).map(projectDir::relativize).collect(Collectors.toSet());
    }

    private Set<Path> pathSet(String... paths) {
        return Stream.of(paths).map(Paths::get).collect(Collectors.toSet());
    }
}

@@ -40,16 +40,55 @@
 suite;%0A%0A
+import com.google.common.collect.Sets;%0A
 import o
@@ -582,16 +582,43 @@
 .Paths;%0A
+import java.util.Optional;%0A
 import j
@@ -854,16 +854,62 @@
 rs.isA;%0A
+import static org.hamcrest.Matchers.hasItems;%0A
 import s
@@ -931,28 +931,17 @@
 .Assert.
-assertEquals
+*
 ;%0A%0Apubli
@@ -1219,24 +1219,74 @@
 %22).build();%0A
+        project.getRepositories().mavenCentral();%0A
         proj
@@ -1801,24 +1801,189 @@
 ).size());%0A%0A
+        Set%3CPath%3E srcDirs = toRelPaths(sourceSet.getAllSource().getSrcDirs());%0A        assertEquals(pathSet(%22src/evoTest/java%22, %22src/evoTest/resources%22), srcDirs);%0A%0A
         Set%3C
@@ -2157,30 +2157,50 @@
   assert
-Equal
+That(compileCp, hasItem
 s(path
-Set
+Array
 (%22build/
@@ -2246,19 +2246,9 @@
 in%22)
-, compileCp
+)
 );%0A 
@@ -2260,30 +2260,50 @@
   assert
-Equal
+That(runtimeCp, hasItem
 s(path
-Set
+Array
 (%0A      
@@ -2449,19 +2449,406 @@
 st%22)
-, runtimeCp
+));%0A%0A        Optional%3CPath%3E evoSuiteDep = compileCp.stream()%0A                .filter(p -%3E p.getFileName().endsWith(%22evosuite-client-1.0.5.jar%22))%0A                .findAny();%0A        assertTrue(%22Missing EvoSuite dependency: %22 + compileCp, evoSuiteDep.isPresent());%0A%0A        assertEquals(pathSet(%22build/classes/java/evosuiteTest%22, %22build/resources/evosuiteTest%22), Sets.difference(runtimeCp, compileCp)
 );%0A 
@@ -3369,16 +3369,33 @@
 stream()
+%0A                
 .map(Fil
@@ -3404,16 +3404,33 @@
 :toPath)
+%0A                
 .map(pro
@@ -3449,16 +3449,33 @@
 ativize)
+%0A                
 .collect
@@ -3634,11 +3634,136 @@
 );%0A    %7D
+%0A%0A    private Path%5B%5D pathArray(String... paths) %7B%0A        return Stream.of(paths).map(Paths::get).toArray(Path%5B%5D::new);%0A    %7D
 %0A%7D%0A

Update integration test