package org.netbeans.gradle.model.java;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.GradleProject;
import org.gradle.tooling.model.eclipse.EclipseProject;
import org.gradle.tooling.model.idea.IdeaModule;
import org.gradle.tooling.model.idea.IdeaProject;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.netbeans.gradle.model.BuildInfoBuilder;
import org.netbeans.gradle.model.BuilderIssue;
import org.netbeans.gradle.model.BuilderResult;
import org.netbeans.gradle.model.FetchedModels;
import org.netbeans.gradle.model.FetchedModelsOrError;
import org.netbeans.gradle.model.GenericModelFetcher;
import org.netbeans.gradle.model.GenericProjectProperties;
import org.netbeans.gradle.model.GradleBuildInfoQuery;
import org.netbeans.gradle.model.GradleMultiProjectDef;
import org.netbeans.gradle.model.GradleProjectTree;
import org.netbeans.gradle.model.GradleTaskID;
import org.netbeans.gradle.model.ProjectId;
import org.netbeans.gradle.model.api.GradleProjectInfoQuery2;
import org.netbeans.gradle.model.api.ProjectInfoBuilder2;
import org.netbeans.gradle.model.internal.ConstBuilders;
import org.netbeans.gradle.model.util.CollectionUtils;
import org.netbeans.gradle.model.util.Exceptions;
import org.netbeans.gradle.model.util.ProjectConnectionTask;
import org.netbeans.gradle.model.util.SourceSetVerification;
import org.netbeans.gradle.model.util.TestUtils;
import org.netbeans.gradle.model.util.ZipUtils;
import static org.junit.Assert.*;
import static org.netbeans.gradle.model.java.InfoQueries.*;
import static org.netbeans.gradle.model.util.TestUtils.*;
public class MultiLevelJavaProjectTest {
private static final String ROOT_NAME = "gradle-multi-level";
private static File tempFolder = null;
private static File testedProjectDir = null;
@BeforeClass
public static void setUpClass() throws IOException {
tempFolder = ZipUtils.unzipResourceToTemp(MultiLevelJavaProjectTest.class, "gradle-multi-level.zip");
testedProjectDir = new File(tempFolder, ROOT_NAME);
}
@AfterClass
public static void tearDownClass() throws IOException {
if (tempFolder != null) {
ZipUtils.recursiveDelete(tempFolder);
}
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
private static File getProjectDir(String... subprojectNames) throws IOException {
return getSubPath(testedProjectDir, subprojectNames);
}
private void runTestForSubProject(String projectName, ProjectConnectionTask task) {
TestUtils.runTestForSubProject(testedProjectDir, projectName, task);
}
private static Set<String> toTaskNames(Collection<GradleTaskID> tasks) {
Set<String> result = new LinkedHashSet<String>(2 * tasks.size());
for (GradleTaskID task: tasks) {
result.add(task.getName());
}
return result;
}
private static Set<String> mustHaveTasks(
String relativeProjectPath,
Collection<GradleTaskID> tasks,
String... expectedNames) {
String taskPrefix = relativeProjectPath.length() > 0
? ":" + relativeProjectPath + ":"
: ":";
Set<String> otherTasks = new LinkedHashSet<String>();
Set<String> expectedSet = new LinkedHashSet<String>(Arrays.asList(expectedNames));
for (GradleTaskID task: tasks) {
String name = task.getName();
assertEquals(taskPrefix + name, task.getFullName());
if (!expectedSet.remove(name)) {
otherTasks.add(name);
}
}
if (!expectedSet.isEmpty()) {
fail("The following tasks were not found but were expected: " + expectedSet
+ ". The project has the following tasks: " + toTaskNames(tasks));
}
return otherTasks;
}
private static void testBasicInfoForProject(
String relativeProjectName,
GradleMultiProjectDef projectDef) throws IOException {
assertNotNull("Must have a GradleMultiProjectDef.", projectDef);
String[] projectPathParts = relativeProjectName.length() > 0
? relativeProjectName.split(Pattern.quote(":"))
: new String[0];
String projectPath = ":" + relativeProjectName;
String projectName = projectPathParts.length > 0
? projectPathParts[projectPathParts.length - 1]
: ROOT_NAME;
GradleProjectTree projectTree = projectDef.getMainProject();
GenericProjectProperties genericProperties = projectTree.getGenericProperties();
String fullName = genericProperties.getProjectFullName();
assertEquals(projectPath, fullName);
String simpleName = genericProperties.getProjectName();
assertEquals(projectName, simpleName);
ProjectId projectId = genericProperties.getProjectId();
assertEquals("group", "my-group", projectId.getGroup());
assertEquals("name", simpleName, projectId.getName());
assertEquals("version", getProjectVersion(simpleName), projectId.getVersion());
File projectDir = genericProperties.getProjectDir();
assertEquals(getProjectDir(projectPathParts), projectDir.getCanonicalFile());
}
private void testBasicInfoForProjectWithTasks(
final String relativeProjectName,
final String[] expectedTasks,
final String[] unexpectedTasks) {
runTestForSubProject(relativeProjectName, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
GradleMultiProjectDef projectDef = fetchProjectDef(connection);
testBasicInfoForProject(relativeProjectName, projectDef);
GradleProjectTree mainProject = projectDef.getMainProject();
GenericProjectProperties genericProperties = mainProject.getGenericProperties();
assertEquals("Build script for the project must be build.gradle.",
new File(genericProperties.getProjectDir(), "build.gradle"),
genericProperties.getBuildScript());
Collection<GradleTaskID> tasks = mainProject.getTasks();
Set<String> remainingTasks = mustHaveTasks(relativeProjectName, tasks, expectedTasks);
for (String task: unexpectedTasks) {
if (remainingTasks.contains(task)) {
fail("The project must not have the following task: " + task);
}
}
}
});
}
private static String[] groovyProjects() {
return new String[] {
"apps:app1",
};
}
private static String[] javaProjects() {
return new String[] {
"libs:lib3:lib1",
"apps:app2",
"libs:lib1",
"libs:lib2",
"libs:lib3",
"libs:lib3:lib2",
};
}
private static String[] concatArrays(String[]... arrays) {
int length = 0;
for (String[] array: arrays) {
length += array.length;
}
String[] result = new String[length];
int offset = 0;
for (String[] array: arrays) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
private static String[] subprojects() {
return concatArrays(groovyProjects(), javaProjects());
}
private static String[] allProjects() {
return concatArrays(new String[]{""}, subprojects());
}
@Test
public void testBasicInfoForJavaProjects() {
String[] expectedTasks = {"clean", "build", "compileJava"};
String[] unexpectedTasks = {"wrapper"};
for (String relativeProjectName: javaProjects()) {
testBasicInfoForProjectWithTasks(relativeProjectName, expectedTasks, unexpectedTasks);
}
}
@Test
public void testBasicInfoForGroovyProjects() {
String[] expectedTasks = {"clean", "build", "compileJava", "compileGroovy"};
String[] unexpectedTasks = {"wrapper"};
for (String relativeProjectName: groovyProjects()) {
testBasicInfoForProjectWithTasks(relativeProjectName, expectedTasks, unexpectedTasks);
}
}
@Test
public void testBasicInfoForRootProject() {
String[] expectedTasks = {};
String[] unexpectedTasks = {"compileJava"};
testBasicInfoForProjectWithTasks("", expectedTasks, unexpectedTasks);
}
private static void assertNoProblem(Throwable issue) {
if (issue != null) {
throw Exceptions.throwUnchecked(issue);
}
}
private static JavaClassPaths classPathsOfSourceSet(JavaSourcesModel model, String sourceSetName) {
for (JavaSourceSet sourceSet: model.getSourceSets()) {
if (sourceSetName.equals(sourceSet.getName())) {
assertNoProblem(sourceSet.getCompileClassPathProblem());
assertNoProblem(sourceSet.getRuntimeClassPathProblem());
return sourceSet.getClasspaths();
}
}
throw new AssertionError("Missing source set: " + sourceSetName);
}
private static File getLibraryPath(File projectDir) throws IOException {
return getSubPath(projectDir, "build", "libs");
}
private static File getFileInLibs(File projectDir, String... subPaths) throws IOException {
return getSubPath(getLibraryPath(projectDir), subPaths);
}
private Map<File, String> parseProjectDependencies(String... projectDependencies) throws IOException {
Map<File, String> result = CollectionUtils.newHashMap(projectDependencies.length);
for (String dep: projectDependencies) {
String[] nameParts = dep.split(Pattern.quote(":"));
String name = nameParts[nameParts.length - 1];
File projectDir = getProjectDir(nameParts);
result.put(getFileInLibs(projectDir, name + "-" + getProjectVersion(name) + ".jar"), dep);
}
return result;
}
private void verifyProjectDependencies(Set<File> files, String... projectDependencies) throws IOException {
Map<File, String> expected = parseProjectDependencies(projectDependencies);
for (Map.Entry<File, String> entry: expected.entrySet()) {
if (!files.contains(entry.getKey())) {
fail("Expected project dependency " + entry.getValue());
}
}
}
private void verifyArtifact(Set<File> files, String artifactName, String version) {
for (File file: files) {
String name = file.getName();
if (name.contains(artifactName) && name.contains(version)) {
return;
}
}
fail("Missing required artifact: " + artifactName + ":" + version);
}
private void verifyTestClassPath(Set<File> files) {
verifyArtifact(files, "junit", "4.11");
verifyArtifact(files, "mockito-core", "1.9.5");
}
private void testJavaSourcesModelForJavaProject(
String relativeProjectName,
final JavaSourcesModel expected,
final String... projectDependencies) {
runTestForSubProject(relativeProjectName, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaSourcesModel sourcesModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_SOURCES_BUILDER_COMPLETE);
assertNotNull("Must have a JavaSourcesModel.", sourcesModel);
SourceSetVerification.verifySourcesModelWithoutDependencies(expected, sourcesModel);
JavaClassPaths mainClassPaths = classPathsOfSourceSet(sourcesModel, "main");
verifyProjectDependencies(mainClassPaths.getCompileClasspaths(), projectDependencies);
verifyProjectDependencies(mainClassPaths.getRuntimeClasspaths(), projectDependencies);
JavaClassPaths testClassPaths = classPathsOfSourceSet(sourcesModel, "test");
verifyTestClassPath(testClassPaths.getCompileClasspaths());
verifyTestClassPath(testClassPaths.getRuntimeClasspaths());
JavaModelTests.checkNoDependencyResolultionError(sourcesModel);
}
});
}
@Test
public void testJavaSourcesModel() throws IOException {
testJavaSourcesModelForJavaProject("apps:app1", sourcesOfApp1(), "libs:lib1", "libs:lib2");
testJavaSourcesModelForJavaProject("apps:app2", sourcesOfApp2(), "libs:lib1", "libs:lib2");
testJavaSourcesModelForJavaProject("libs:lib1", sourcesOfLib1(), "libs:lib2");
testJavaSourcesModelForJavaProject("libs:lib2", sourcesOfLib2());
testJavaSourcesModelForJavaProject("libs:lib3", sourcesOfLib3());
testJavaSourcesModelForJavaProject("libs:lib3:lib1", sourcesOfLib3Lib1());
testJavaSourcesModelForJavaProject("libs:lib3:lib2", sourcesOfLib3Lib2());
}
private static JavaSourceGroup findSourceGroup(JavaSourceSet sourceSet, JavaSourceGroupName name) {
for (JavaSourceGroup group: sourceSet.getSourceGroups()) {
if (name.equals(group.getGroupName())) {
return group;
}
}
return null;
}
private static JavaSourceSet findSourceSet(JavaSourcesModel sourcesModel, String name) {
for (JavaSourceSet sourceSet: sourcesModel.getSourceSets()) {
if (name.equals(sourceSet.getName())) {
return sourceSet;
}
}
return null;
}
private static JavaSourceGroup findSourceGroup(
JavaSourcesModel sourcesModel,
String setName,
JavaSourceGroupName groupName) {
JavaSourceSet sourceSet = findSourceSet(sourcesModel, setName);
if (sourceSet == null) {
return null;
}
return findSourceGroup(sourceSet, groupName);
}
@Test
public void testExcludeIncludePatterns() throws IOException {
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaSourcesModel sourcesModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_SOURCES_BUILDER_ONLY_COMPILE);
assertNotNull("apps:app1 must have a JavaSourcesModel.", sourcesModel);
JavaSourceGroup group = findSourceGroup(sourcesModel, JavaSourceSet.NAME_MAIN, JavaSourceGroupName.JAVA);
assertNotNull("apps:app1 must not have a main/java source group.", group);
SourceIncludePatterns patterns = group.getExcludePatterns();
assertEquals("includes", Collections.singleton("**"), patterns.getIncludePatterns());
assertEquals("excludes", Collections.singleton("**/excluded/"), patterns.getExcludePatterns());
}
});
}
@Test
public void testJavaSourcesModelForRoot() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaSourcesModel sourcesModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_SOURCES_BUILDER_ONLY_COMPILE);
assertNull("Root must not have a JavaSourcesModel.", sourcesModel);
}
});
}
private void testJavaCompatibilityModel(String relativeProjectName) throws IOException {
runTestForSubProject(relativeProjectName, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaCompatibilityModel compatibilityModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_COMPATIBILITY_BUILDER);
assertNotNull("Must have a JavaCompatibilityModel.", compatibilityModel);
assertEquals("1.5", compatibilityModel.getSourceCompatibility());
assertEquals("1.7", compatibilityModel.getTargetCompatibility());
}
});
}
@Test
public void testJavaCompatibilityModel() throws IOException {
for (String project: subprojects()) {
testJavaCompatibilityModel(project);
}
}
@Test
public void testJavaCompatibilityModelForRoot() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaCompatibilityModel compatibilityModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_COMPATIBILITY_BUILDER);
assertNull("Root must not have a JavaCompatibilityModel.", compatibilityModel);
}
});
}
@Test
public void testMissingJacocoPluginIsNotAProblem() throws IOException {
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JacocoModel jacocoModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JACOCO_BUILDER);
assertNull("apps:app1 must not have a JacocoModel.", jacocoModel);
}
});
}
private static String getProjectVersion(String name) {
return "app1".equals(name) ? "5.95.3-beta" : "3.5.78-alpha";
}
private void testJarOutputsModel(String relativeProjectPath) throws IOException {
String[] projectPathParts = relativeProjectPath.split(Pattern.quote(":"));
String name = projectPathParts[projectPathParts.length - 1];
File projectDir = getProjectDir(projectPathParts);
final File expectedJarPath = getFileInLibs(projectDir, name + "-" + getProjectVersion(name) + ".jar");
runTestForSubProject(relativeProjectPath, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JarOutputsModel jarOutputs
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAR_OUTPUTS_BUILDER);
assertNotNull("Must have a JarOutputsModel.", jarOutputs);
JarOutput mainJar = null;
for (JarOutput jar: jarOutputs.getJars()) {
if (jar.getTaskName().equals("jar")) {
mainJar = jar;
break;
}
}
assertNotNull("Project must contain a main jar.", mainJar);
assertEquals("Output jar must be at the expected location",
expectedJarPath, mainJar.getJar().getCanonicalFile());
assertNull("mainJar.tryGetSourceSetNames", mainJar.tryGetSourceSetNames());
}
});
}
@Test
public void testJarOutputsModel() throws IOException {
for (String project: subprojects()) {
testJarOutputsModel(project);
}
}
private static JarOutput getJarOutput(JarOutputsModel jarOutputs, String taskName) {
for (JarOutput jar: jarOutputs.getJars()) {
if (jar.getTaskName().equals(taskName)) {
return jar;
}
}
throw new AssertionError("Missing jar task: " + taskName);
}
@Test
public void testCustomJarOutputsModel() throws IOException {
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JarOutputsModel jarOutputs
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAR_OUTPUTS_BUILDER);
assertNotNull("Must have a JarOutputsModel.", jarOutputs);
File projectDir = getProjectDir("apps", "app1");
String version = getProjectVersion("app1");
JarOutput testJar = getJarOutput(jarOutputs, "testJar");
assertEquals("Output jar must be at the expected location",
getFileInLibs(projectDir, "test-app1-" + version + ".jar"),
testJar.getJar().getCanonicalFile());
assertEquals("testJar.name", "testJar", testJar.getTaskName());
assertEquals("testJar.sourceSets",
Collections.singleton("test"),
testJar.tryGetSourceSetNames());
JarOutput customJar = getJarOutput(jarOutputs, "customJar");
assertEquals("Output jar must be at the expected location",
getFileInLibs(projectDir, "custom-app1-" + version + ".jar"),
customJar.getJar().getCanonicalFile());
assertEquals("customJar.name", "customJar", customJar.getTaskName());
assertEquals("customJar.sourceSets",
Collections.singleton("main"),
customJar.tryGetSourceSetNames());
}
});
}
private Map<String, JavaTestTask> nameToTestTask(JavaTestModel testModel) {
Collection<JavaTestTask> testTasks = testModel.getTestTasks();
Map<String, JavaTestTask> result = CollectionUtils.newHashMap(testTasks.size());
for (JavaTestTask testTask: testTasks) {
if (result.put(testTask.getName(), testTask) != null) {
fail("Test task has been retrieved multiple times: " + testTask.getName());
}
}
return result;
}
private void verifyTestTask(Map<String, JavaTestTask> testTasks, String name, File expectedOutputDir) {
JavaTestTask testTask = testTasks.get(name);
assertNotNull("Expected test task with name " + name, testTask);
assertEquals(name, testTask.getName());
assertEquals(expectedOutputDir, testTask.getXmlOutputDir());
}
private void testJavaTestModel(String relativeProjectPath) throws IOException {
String[] projectPathParts = relativeProjectPath.split(Pattern.quote(":"));
File projectDir = getProjectDir(projectPathParts);
final File expectedXmlPathTest = getSubPath(projectDir, "build", "test-results");
final File expectedXmlPathMyTest = getSubPath(projectDir, "build", "my-test-custom-results");
runTestForSubProject(relativeProjectPath, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaTestModel testModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_TEST_BUILDER);
assertNotNull("Must have a JavaTestModel.", testModel);
Map<String, JavaTestTask> testTasks = nameToTestTask(testModel);
assertEquals("Must have a 2 test tasks.", 2, testTasks.size());
verifyTestTask(testTasks, "test", expectedXmlPathTest);
verifyTestTask(testTasks, "myTest", expectedXmlPathMyTest);
}
});
}
@Test
public void testJavaTestModel() throws IOException {
for (String project: subprojects()) {
testJavaTestModel(project);
}
}
@Test
public void testJavaTestModelForRoot() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JavaTestModel testModel
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAVA_TEST_BUILDER);
assertNull("Root project must not have a JavaTestModel.", testModel);
}
});
}
@Test
public void testJarOutputsModelForRoot() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
JarOutputsModel jarOutputs
= fetchSingleProjectInfo(connection, JavaModelBuilders.JAR_OUTPUTS_BUILDER);
assertNull("Root project must not have a JarOutputsModel.", jarOutputs);
}
});
}
@Test
public void testWarFoldersModel() throws IOException {
for (String project: allProjects()) {
runTestForSubProject(project, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
WarFoldersModel warFolders
= fetchSingleProjectInfo(connection, JavaModelBuilders.WAR_FOLDERS_BUILDER);
assertNull("Must not have a WarFoldersModel.", warFolders);
}
});
}
}
@Test
public void testCustomQuery() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
String prefix = "testCustomQuery-";
String result = fetchSingleBuildInfo(connection, TestBuilders.testBuildInfoBuilder(prefix));
assertEquals(prefix + ROOT_NAME, result);
}
});
}
@Test
public void testFailingProjectQuery() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
String message = "testFailingProjectQuery-message";
ProjectInfoBuilder2<?> builder = TestBuilders.failingProjectInfoBuilder(message);
BuilderResult result = fetchSingleProjectInfoWithError(connection, builder);
assertNotNull("Required result for FailingProjectInfoBuilder.", result);
BuilderIssue issue = result.getIssue();
assertNotNull("Required issue for FailingProjectInfoBuilder", issue);
assertEquals("Expected approriate builder name.", builder.getName(), issue.getName());
String issueMessage = issue.getException().getMessage();
if (!issueMessage.contains(message)) {
fail("Issue message is invalid: " + issueMessage);
}
}
});
}
@Test
public void testFailingBuildQuery() throws IOException {
runTestForSubProject("", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
String message = "testFailingBuildQuery-message";
BuildInfoBuilder<?> builder = TestBuilders.failingBuildInfoBuilder(message);
BuilderResult result = fetchSingleBuildInfoWithError(connection, builder);
assertNotNull("Required result for FailingBuildInfoBuilder.", result);
BuilderIssue issue = result.getIssue();
assertNotNull("Required issue for FailingBuildInfoBuilder", issue);
assertEquals("Expected approriate builder name.", builder.getName(), issue.getName());
String issueMessage = issue.getException().getMessage();
if (!issueMessage.contains(message)) {
fail("Issue message is invalid: " + issueMessage);
}
}
});
}
private static Object getSingleBuildResult(List<BuilderResult> list) {
BuilderResult result = CollectionUtils.getSingleElement(list);
return result != null ? result.getResultIfNoIssue() : null;
}
private static FetchedModels verifyNoError(FetchedModelsOrError modelsOrError) {
return InfoQueries.verifyNoError(modelsOrError);
}
@Test
public void testManyQueries() throws IOException {
Map<Object, List<GradleBuildInfoQuery<?>>> buildInfos
= new HashMap<Object, List<GradleBuildInfoQuery<?>>>();
Map<Object, List<GradleProjectInfoQuery2<?>>> projectInfos
= new HashMap<Object, List<GradleProjectInfoQuery2<?>>>();
Set<Class<?>> toolingModels = new HashSet<Class<?>>();
projectInfos.put(0, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(JavaModelBuilders.JAR_OUTPUTS_BUILDER)));
projectInfos.put(1, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(JavaModelBuilders.JAVA_COMPATIBILITY_BUILDER)));
projectInfos.put(2, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(JavaModelBuilders.JAVA_SOURCES_BUILDER_COMPLETE)));
projectInfos.put(3, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(JavaModelBuilders.WAR_FOLDERS_BUILDER)));
final String prefix = "testCustomQuery-";
buildInfos.put(0, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.testBuildInfoBuilder(prefix))));
toolingModels.add(IdeaProject.class);
final GenericModelFetcher fetcher = new GenericModelFetcher(buildInfos, projectInfos, toolingModels);
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
FetchedModels models = verifyNoError(fetcher.getModels(connection, TestUtils.defaultInit()));
String buildInfo = (String)getSingleBuildResult(
models.getBuildInfoResults().get(0));
assertEquals(prefix + ROOT_NAME, buildInfo);
Map<Object, List<BuilderResult>> projectInfos
= models.getDefaultProjectModels().getProjectInfoResults();
JarOutputsModel model1 = (JarOutputsModel)getSingleBuildResult(projectInfos.get(0));
JavaCompatibilityModel model2 = (JavaCompatibilityModel)getSingleBuildResult(projectInfos.get(1));
JavaSourcesModel model3 = (JavaSourcesModel)getSingleBuildResult(projectInfos.get(2));
WarFoldersModel model4 = (WarFoldersModel)getSingleBuildResult(projectInfos.get(3));
assertNotNull(model1);
assertNotNull(model2);
assertNotNull(model3);
assertNull(model4);
}
});
}
private static <T> T findResultOfType(Class<T> type, Collection<BuilderResult> builders) {
for (BuilderResult builder: builders) {
Object result = builder.getResultObject();
if (type.isInstance(result)) {
return type.cast(result);
}
}
return null;
}
@Test
public void testManyQueriesSingleKey() throws IOException {
Map<Object, List<GradleBuildInfoQuery<?>>> buildInfos
= new HashMap<Object, List<GradleBuildInfoQuery<?>>>();
Map<Object, List<GradleProjectInfoQuery2<?>>> projectInfos
= new HashMap<Object, List<GradleProjectInfoQuery2<?>>>();
Set<Class<?>> toolingModels = new HashSet<Class<?>>();
projectInfos.put(0, Arrays.<GradleProjectInfoQuery2<?>>asList(
InfoQueries.toCustomQuery(JavaModelBuilders.JAR_OUTPUTS_BUILDER),
InfoQueries.toCustomQuery(JavaModelBuilders.JAVA_COMPATIBILITY_BUILDER),
InfoQueries.toCustomQuery(JavaModelBuilders.JAVA_SOURCES_BUILDER_COMPLETE),
InfoQueries.toCustomQuery(JavaModelBuilders.WAR_FOLDERS_BUILDER)));
final String prefix = "testCustomQuery-";
buildInfos.put(0, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.testBuildInfoBuilder(prefix))));
toolingModels.add(IdeaProject.class);
final GenericModelFetcher fetcher = new GenericModelFetcher(buildInfos, projectInfos, toolingModels);
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
FetchedModels models = verifyNoError(fetcher.getModels(connection, TestUtils.defaultInit()));
String buildInfo = (String)getSingleBuildResult(
models.getBuildInfoResults().get(0));
assertEquals(prefix + ROOT_NAME, buildInfo);
Map<Object, List<BuilderResult>> projectInfos
= models.getDefaultProjectModels().getProjectInfoResults();
List<BuilderResult> results = projectInfos.get(0);
assertNotNull("Must have results of query", results);
assertEquals("Must have 3/4 queries.", 3, results.size());
JarOutputsModel model1 = findResultOfType(JarOutputsModel.class, results);
JavaCompatibilityModel model2 = findResultOfType(JavaCompatibilityModel.class, results);
JavaSourcesModel model3 = findResultOfType(JavaSourcesModel.class, results);
WarFoldersModel model4 = findResultOfType(WarFoldersModel.class, results);
assertNotNull(model1);
assertNotNull(model2);
assertNotNull(model3);
assertNull(model4);
}
});
}
private static void verifySerializationError(BuilderResult result) {
assertNotNull("Must have a result with a serialization issue.", result);
BuilderIssue issue = result.getIssue();
assertNotNull("Must have a serialization issue.", issue);
assertTrue("Cause must be a serialization error.",
issue.getException().getMessage().contains("NotSerializableException"));
}
private static void verifyDeserializationError(BuilderResult result) {
assertNotNull("Must have a result with a deserialization issue.", result);
BuilderIssue issue = result.getIssue();
assertNotNull("Must have a deserialization issue.", issue);
assertTrue("Cause must be a ClassNotFoundException error.",
issue.getException().getMessage().contains("ClassNotFoundException"));
}
@Test
public void testEvenBuilderNameFails() throws IOException {
Map<Object, List<GradleBuildInfoQuery<?>>> buildInfos = Collections.emptyMap();
Map<Object, List<GradleProjectInfoQuery2<?>>> projectInfos
= new HashMap<Object, List<GradleProjectInfoQuery2<?>>>();
final String infoMessage = "TEST-INFO-1270748702750";
final String nameMessage = "TEST-NAME-5478210972357";
projectInfos.put(1, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.failingNameProjectInfoBuilder(infoMessage, nameMessage))));
Set<Class<?>> toolingModels = Collections.emptySet();
final GenericModelFetcher fetcher = new GenericModelFetcher(buildInfos, projectInfos, toolingModels);
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
FetchedModels models = verifyNoError(fetcher.getModels(connection, TestUtils.defaultInit()));
BuilderResult result = CollectionUtils.getSingleElement(
models.getDefaultProjectModels().getProjectInfoResults().get(1));
assertNotNull("Required result for FailingProjectInfoBuilder.", result);
BuilderIssue issue = result.getIssue();
assertNotNull("Required issue for FailingProjectInfoBuilder", issue);
//assertEquals("Expected approriate builder name.", builder.getName(), issue.getName());
String issueMessage = issue.getException().getMessage();
if (!issueMessage.contains(infoMessage)) {
fail("Issue message is invalid: " + issueMessage);
}
}
});
}
@Test
public void testSerializationFailures() throws IOException {
Map<Object, List<GradleBuildInfoQuery<?>>> buildInfos
= new HashMap<Object, List<GradleBuildInfoQuery<?>>>();
Map<Object, List<GradleProjectInfoQuery2<?>>> projectInfos
= new HashMap<Object, List<GradleProjectInfoQuery2<?>>>();
Set<Class<?>> toolingModels = new HashSet<Class<?>>();
final String projectInfoPrefix = "testSerializationFailures-project-";
final String buildInfoPrefix = "testSerializationFailures-build-";
projectInfos.put(0, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.testProjectInfoBuilder(projectInfoPrefix))));
projectInfos.put(1, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.notSerializableProjectInfoBuilder())));
projectInfos.put(2, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.notSerializableResultProjectInfoBuilder())));
projectInfos.put(3, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toQueryWithKnownClassPath(TestBuilders.testProjectInfoBuilder(""))));
projectInfos.put(4, Collections.<GradleProjectInfoQuery2<?>>singletonList(
InfoQueries.toQueryWithKnownClassPath(ConstBuilders.constProjectInfoBuilder(new SerializableObject()))));
buildInfos.put(0, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.testBuildInfoBuilder(buildInfoPrefix))));
buildInfos.put(1, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.notSerializableBuildInfoBuilder())));
buildInfos.put(2, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toCustomQuery(TestBuilders.notSerializableResultBuildInfoBuilder())));
buildInfos.put(3, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toQueryWithKnownClassPath(TestBuilders.testBuildInfoBuilder(""))));
buildInfos.put(4, Collections.<GradleBuildInfoQuery<?>>singletonList(
InfoQueries.toQueryWithKnownClassPath(ConstBuilders.constBuildInfoBuilder(new SerializableObject()))));
toolingModels.add(IdeaProject.class);
final GenericModelFetcher fetcher = new GenericModelFetcher(buildInfos, projectInfos, toolingModels);
runTestForSubProject("apps:app1", new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
FetchedModels models = verifyNoError(fetcher.getModels(connection, TestUtils.defaultInit()));
BuilderResult buildInfo1 = CollectionUtils
.getSingleElement(models.getBuildInfoResults().get(1));
BuilderResult buildInfo2 = CollectionUtils
.getSingleElement(models.getBuildInfoResults().get(2));
BuilderResult buildInfo3 = CollectionUtils
.getSingleElement(models.getBuildInfoResults().get(3));
BuilderResult buildInfo4 = CollectionUtils
.getSingleElement(models.getBuildInfoResults().get(4));
verifySerializationError(buildInfo1);
verifySerializationError(buildInfo2);
verifyDeserializationError(buildInfo3);
verifyDeserializationError(buildInfo4);
BuilderResult projectInfo1 = CollectionUtils.getSingleElement(
models.getDefaultProjectModels().getProjectInfoResults().get(1));
BuilderResult projectInfo2 = CollectionUtils.getSingleElement(
models.getDefaultProjectModels().getProjectInfoResults().get(2));
BuilderResult projectInfo3 = CollectionUtils.getSingleElement(
models.getDefaultProjectModels().getProjectInfoResults().get(3));
BuilderResult projectInfo4 = CollectionUtils.getSingleElement(
models.getDefaultProjectModels().getProjectInfoResults().get(4));
verifySerializationError(projectInfo1);
verifySerializationError(projectInfo2);
verifyDeserializationError(projectInfo3);
verifyDeserializationError(projectInfo4);
Object buildInfoOk = getSingleBuildResult(
models.getBuildInfoResults().get(0));
assertTrue("The valid builder must succeed",
buildInfoOk.toString().startsWith(buildInfoPrefix));
Object projectInfoOk = getSingleBuildResult(
models.getDefaultProjectModels().getProjectInfoResults().get(0));
assertTrue("The valid builder must succeed",
projectInfoOk.toString().startsWith(projectInfoPrefix));
}
});
}
private static Map<Class<?>, Object> fetchBuiltInModels(
ProjectConnection connection,
Class<?>... modelClasses) throws IOException {
Map<Object, List<GradleBuildInfoQuery<?>>> buildInfos = Collections.emptyMap();
Map<Object, List<GradleProjectInfoQuery2<?>>> projectInfos = Collections.emptyMap();
Set<Class<?>> toolingModels = new HashSet<Class<?>>(Arrays.asList(modelClasses));
GenericModelFetcher modelFetcher = new GenericModelFetcher(buildInfos, projectInfos, toolingModels);
FetchedModels models = verifyNoError(modelFetcher.getModels(connection, defaultInit()));
return models.getDefaultProjectModels().getToolingModels();
}
private void testBuiltInModels(String relativeProjectPath) throws IOException {
final String projectPath = ":" + relativeProjectPath;
runTestForSubProject(relativeProjectPath, new ProjectConnectionTask() {
public void doTask(ProjectConnection connection) throws Exception {
Class<?>[] models = new Class<?>[]{
EclipseProject.class,
IdeaProject.class,
GradleProject.class
};
Map<Class<?>, Object> fetched = fetchBuiltInModels(connection, models);
HashSet<Class<?>> expected = new HashSet<Class<?>>(Arrays.asList(models));
expected.removeAll(fetched.keySet());
if (!expected.isEmpty()) {
fail("The following models are unavailable: "
+ expected.toString().replace(",", ",\n"));
}
// FIXME: We don't test the GradleProject instance because
// Gradle returns the root project for each project. Is this a bug?
EclipseProject eclipseProject = (EclipseProject)fetched.get(EclipseProject.class);
assertEquals("EclipseProject must match the requested one",
projectPath, eclipseProject.getGradleProject().getPath());
IdeaProject ideaProject = (IdeaProject)fetched.get(IdeaProject.class);
GradleProject gradleProjectOfIdea = null;
for (IdeaModule ideaModule: ideaProject.getModules()) {
if (projectPath.equals(ideaModule.getGradleProject().getPath())) {
gradleProjectOfIdea = ideaModule.getGradleProject();
break;
}
}
assertNotNull("IdeaProject must contain the requested module.", gradleProjectOfIdea);
}
});
}
@Test
public void testBuiltInModels() throws IOException {
for (String project: allProjects()) {
testBuiltInModels(project);
}
}
private static JavaOutputDirs defaultOutputOfSourceSet(
File projectDir,
String name) throws IOException {
File classesDir = getSubPath(projectDir, "build", "classes", name);
File resourcesDir = getSubPath(projectDir, "build", "resources", name);
return new JavaOutputDirs(classesDir, resourcesDir, Collections.<File>emptySet());
}
private static JavaSourceGroup sourceGroupOfSourceSet(
File projectDir,
String name,
JavaSourceGroupName sourceGroupName) throws IOException {
File sourceRoot = getSubPath(projectDir, name, sourceGroupName.name().toLowerCase(Locale.US));
return new JavaSourceGroup(sourceGroupName, Collections.singleton(sourceRoot));
}
private static JavaSourceSet.Builder defaultSourceSetBuilder(
File projectDir,
String name) throws IOException {
JavaSourceSet.Builder sourceSet = new JavaSourceSet.Builder(
name,
defaultOutputOfSourceSet(projectDir, name));
sourceSet.addSourceGroup(sourceGroupOfSourceSet(projectDir, name, JavaSourceGroupName.JAVA));
sourceSet.addSourceGroup(sourceGroupOfSourceSet(projectDir, name, JavaSourceGroupName.RESOURCES));
return sourceSet;
}
private static File projectDirByRelativeName(String relativeProjectName) throws IOException {
return getSubProjectDir(testedProjectDir, relativeProjectName);
}
private static JavaSourceSet defaultJavaSourceSet(
File projectDir,
String name) throws IOException {
JavaSourceSet.Builder builder = defaultSourceSetBuilder(projectDir, name);
return builder.create();
}
private static JavaSourceSet defaultGroovySourceSet(
File projectDir,
String name) throws IOException {
JavaSourceSet.Builder builder = defaultSourceSetBuilder(projectDir, name);
builder.addSourceGroup(sourceGroupOfSourceSet(projectDir, name, JavaSourceGroupName.GROOVY));
return builder.create();
}
private static JavaSourcesModel sourcesOfJavaProject(String relativeProjectName) throws IOException {
File projectDir = projectDirByRelativeName(relativeProjectName);
Collection<JavaSourceSet> sourceSets = new LinkedList<JavaSourceSet>();
sourceSets.add(defaultJavaSourceSet(projectDir, "main"));
sourceSets.add(defaultJavaSourceSet(projectDir, "test"));
return new JavaSourcesModel(sourceSets);
}
private static JavaSourcesModel sourcesOfApp1() throws IOException {
String relativeProjectName = "apps:app1";
File projectDir = projectDirByRelativeName(relativeProjectName);
Collection<JavaSourceSet> sourceSets = new LinkedList<JavaSourceSet>();
sourceSets.add(defaultGroovySourceSet(projectDir, "main"));
sourceSets.add(defaultGroovySourceSet(projectDir, "test"));
return new JavaSourcesModel(sourceSets);
}
private static JavaSourcesModel sourcesOfApp2() throws IOException {
return sourcesOfJavaProject("apps:app2");
}
private static JavaSourcesModel sourcesOfLib1() throws IOException {
return sourcesOfJavaProject("libs:lib1");
}
private static JavaSourcesModel sourcesOfLib2() throws IOException {
return sourcesOfJavaProject("libs:lib2");
}
private static JavaSourcesModel sourcesOfLib3() throws IOException {
return sourcesOfJavaProject("libs:lib3");
}
private static JavaSourcesModel sourcesOfLib3Lib1() throws IOException {
return sourcesOfJavaProject("libs:lib3:lib1");
}
private static JavaSourcesModel sourcesOfLib3Lib2() throws IOException {
return sourcesOfJavaProject("libs:lib3:lib2");
}
}