7a2e28d9cb9a444a8f143ee19ac091e77a827d3f
[idea/community.git] / plugins / gradle / tooling-extension-impl / testSources / org / jetbrains / plugins / gradle / tooling / builder / AbstractModelBuilderTest.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.gradle.tooling.builder;
17
18 import com.intellij.openapi.externalSystem.model.ExternalProject;
19 import com.intellij.openapi.util.Pair;
20 import com.intellij.openapi.util.io.FileUtil;
21 import com.intellij.testFramework.UsefulTestCase;
22 import com.intellij.util.Function;
23 import com.intellij.util.containers.ContainerUtil;
24 import org.gradle.tooling.BuildActionExecuter;
25 import org.gradle.tooling.GradleConnector;
26 import org.gradle.tooling.ProjectConnection;
27 import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
28 import org.gradle.tooling.model.DomainObjectSet;
29 import org.gradle.tooling.model.idea.IdeaModule;
30 import org.gradle.util.GradleVersion;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
33 import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
34 import org.jetbrains.plugins.gradle.model.ProjectImportAction;
35 import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper;
36 import org.jetbrains.plugins.gradle.util.GradleConstants;
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Rule;
40 import org.junit.rules.TestName;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.Parameterized;
43
44 import java.io.File;
45 import java.io.IOException;
46 import java.net.URI;
47 import java.net.URISyntaxException;
48 import java.util.*;
49 import java.util.concurrent.TimeUnit;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
52
53 import static org.junit.Assert.assertEquals;
54 import static org.junit.Assert.assertNotNull;
55
56 /**
57  * @author Vladislav.Soroka
58  * @since 11/29/13
59  */
60 @RunWith(value = Parameterized.class)
61 public abstract class AbstractModelBuilderTest {
62
63   public static final Object[][] SUPPORTED_GRADLE_VERSIONS = {
64     {"1.9"}, {"1.10"}, {"1.11"}, {"1.12"},
65     {"2.0"}, {"2.1"}, {"2.2"}
66   };
67
68   public static final Pattern TEST_METHOD_NAME_PATTERN = Pattern.compile("(.*)\\[(\\d*: with Gradle-.*)\\]");
69
70   private static File ourTempDir;
71
72   @NotNull
73   private final String gradleVersion;
74   protected File testDir;
75   protected ProjectImportAction.AllModels allModels;
76
77   @Rule public TestName name = new TestName();
78
79   public AbstractModelBuilderTest(@NotNull String gradleVersion) {
80     this.gradleVersion = gradleVersion;
81   }
82
83   @Parameterized.Parameters(name = "{index}: with Gradle-{0}")
84   public static Collection<Object[]> data() {
85     return Arrays.asList(SUPPORTED_GRADLE_VERSIONS);
86   }
87
88
89   @Before
90   public void setUp() throws Exception {
91     ensureTempDirCreated();
92
93     String methodName = name.getMethodName();
94     Matcher m = TEST_METHOD_NAME_PATTERN.matcher(methodName);
95     if (m.matches()) {
96       methodName = m.group(1);
97     }
98
99     testDir = new File(ourTempDir, methodName);
100     FileUtil.ensureExists(testDir);
101
102     FileUtil.writeToFile(
103       new File(testDir, GradleConstants.DEFAULT_SCRIPT_NAME),
104       FileUtil.loadTextAndClose(getClass().getResourceAsStream("/" + methodName + "/" + GradleConstants.DEFAULT_SCRIPT_NAME))
105     );
106
107     FileUtil.writeToFile(
108       new File(testDir, GradleConstants.SETTINGS_FILE_NAME),
109       FileUtil.loadTextAndClose(getClass().getResourceAsStream("/" + methodName + "/" + GradleConstants.SETTINGS_FILE_NAME))
110     );
111
112     GradleConnector connector = GradleConnector.newConnector();
113
114     final URI distributionUri = new DistributionLocator().getDistributionFor(GradleVersion.version(gradleVersion));
115     connector.useDistribution(distributionUri);
116     connector.forProjectDirectory(testDir);
117     int daemonMaxIdleTime = 10;
118     try {
119       daemonMaxIdleTime = Integer.parseInt(System.getProperty("gradleDaemonMaxIdleTime", "10"));
120     }
121     catch (NumberFormatException ignore) {}
122
123     ((DefaultGradleConnector)connector).daemonMaxIdleTime(daemonMaxIdleTime, TimeUnit.SECONDS);
124     ProjectConnection connection = connector.connect();
125
126     try {
127       final ProjectImportAction projectImportAction = new ProjectImportAction(false);
128       projectImportAction.addExtraProjectModelClasses(getModels());
129       BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
130       File initScript = GradleExecutionHelper.generateInitScript(false, getToolingExtensionClasses());
131       assertNotNull(initScript);
132       buildActionExecutor.setJvmArguments("-Xmx64m", "-XX:MaxPermSize=64m");
133       buildActionExecutor.withArguments("--info", "--recompile-scripts", GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
134       allModels = buildActionExecutor.run();
135       assertNotNull(allModels);
136     } finally {
137       connection.close();
138     }
139   }
140
141   @NotNull
142   private Set<Class> getToolingExtensionClasses() {
143     final Set<Class> classes = ContainerUtil.<Class>set(
144       ExternalProject.class,
145       // gradle-tooling-extension-api jar
146       ProjectImportAction.class,
147       // gradle-tooling-extension-impl jar
148       ModelBuildScriptClasspathBuilderImpl.class
149     );
150
151     ContainerUtil.addAllNotNull(classes, doGetToolingExtensionClasses());
152     return classes;
153   }
154
155   @NotNull
156   protected Set<Class> doGetToolingExtensionClasses() {
157     return Collections.emptySet();
158   }
159
160   @After
161   public void tearDown() throws Exception {
162     if (testDir != null) {
163       FileUtil.delete(testDir);
164     }
165   }
166
167   protected abstract Set<Class> getModels();
168
169
170   protected <T> Map<String, T> getModulesMap(final Class<T> aClass) {
171     final DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
172
173     final String filterKey = "to_filter";
174     final Map<String, T> map = ContainerUtil.map2Map(ideaModules, new Function<IdeaModule, Pair<String, T>>() {
175       @Override
176       public Pair<String, T> fun(IdeaModule module) {
177         final T value = allModels.getExtraProject(module, aClass);
178         final String key = value != null ? module.getGradleProject().getPath() : filterKey;
179         return Pair.create(key, value);
180       }
181     });
182
183     map.remove(filterKey);
184     return map;
185   }
186
187   protected void assertBuildClasspath(String projectPath, String... classpath) {
188     final Map<String, BuildScriptClasspathModel> classpathModelMap = getModulesMap(BuildScriptClasspathModel.class);
189     final BuildScriptClasspathModel classpathModel = classpathModelMap.get(projectPath);
190
191     assertNotNull(classpathModel);
192
193     final List<? extends ClasspathEntryModel> classpathEntryModels = classpathModel.getClasspath().getAll();
194     assertEquals(classpath.length, classpathEntryModels.size());
195
196     for (int i = 0, length = classpath.length; i < length; i++) {
197       String classpathEntry = classpath[i];
198       final ClasspathEntryModel classpathEntryModel = classpathEntryModels.get(i);
199       assertNotNull(classpathEntryModel);
200       assertEquals(1, classpathEntryModel.getClasses().size());
201       final String path = classpathEntryModel.getClasses().iterator().next();
202       assertEquals(classpathEntry, new File(path).getName());
203     }
204   }
205
206   private static void ensureTempDirCreated() throws IOException {
207     if (ourTempDir != null) return;
208
209     ourTempDir = new File(FileUtil.getTempDirectory(), "gradleTests");
210     FileUtil.delete(ourTempDir);
211     FileUtil.ensureExists(ourTempDir);
212   }
213
214   public static class DistributionLocator {
215     private static final String RELEASE_REPOSITORY_ENV = "GRADLE_RELEASE_REPOSITORY";
216     private static final String SNAPSHOT_REPOSITORY_ENV = "GRADLE_SNAPSHOT_REPOSITORY";
217     private static final String INTELLIJ_LABS_GRADLE_RELEASE_MIRROR =
218       "http://services.gradle.org-mirror.labs.intellij.net/distributions";
219     private static final String INTELLIJ_LABS_GRADLE_SNAPSHOT_MIRROR =
220       "http://services.gradle.org-mirror.labs.intellij.net/distributions-snapshots";
221     private static final String GRADLE_RELEASE_REPO = "http://services.gradle.org/distributions";
222     private static final String GRADLE_SNAPSHOT_REPO = "http://services.gradle.org/distributions-snapshots";
223
224     @NotNull private final String myReleaseRepoUrl;
225     @NotNull private final String mySnapshotRepoUrl;
226
227     public DistributionLocator() {
228       this(DistributionLocator.getRepoUrl(false), DistributionLocator.getRepoUrl(true));
229     }
230
231     public DistributionLocator(@NotNull String releaseRepoUrl, @NotNull String snapshotRepoUrl) {
232       myReleaseRepoUrl = releaseRepoUrl;
233       mySnapshotRepoUrl = snapshotRepoUrl;
234     }
235
236     @NotNull
237     public URI getDistributionFor(@NotNull GradleVersion version) throws URISyntaxException {
238       return getDistribution(getDistributionRepository(version), version, "gradle", "bin");
239     }
240
241     @NotNull
242     private String getDistributionRepository(@NotNull GradleVersion version) {
243       return version.isSnapshot() ? mySnapshotRepoUrl : myReleaseRepoUrl;
244     }
245
246     private static URI getDistribution(@NotNull String repositoryUrl,
247                                        @NotNull GradleVersion version,
248                                        @NotNull String archiveName,
249                                        @NotNull String archiveClassifier) throws URISyntaxException {
250       return new URI(String.format("%s/%s-%s-%s.zip", repositoryUrl, archiveName, version.getVersion(), archiveClassifier));
251     }
252
253     @NotNull
254     public static String getRepoUrl(boolean isSnapshotUrl) {
255       final String envRepoUrl = System.getenv(isSnapshotUrl ? SNAPSHOT_REPOSITORY_ENV : RELEASE_REPOSITORY_ENV);
256       if (envRepoUrl != null) return envRepoUrl;
257
258       if (UsefulTestCase.IS_UNDER_TEAMCITY) {
259         return isSnapshotUrl ? INTELLIJ_LABS_GRADLE_SNAPSHOT_MIRROR : INTELLIJ_LABS_GRADLE_RELEASE_MIRROR;
260       }
261
262       return isSnapshotUrl ? GRADLE_SNAPSHOT_REPO : GRADLE_RELEASE_REPO;
263     }
264   }
265 }