PageRenderTime 21ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ForkingGradleExecuter.java

https://github.com/cwalker67/gradle
Java | 342 lines | 268 code | 50 blank | 24 comment | 27 complexity | cc249a150f6387dd1ae1fc34319a239a MD5 | raw file
  1. /*
  2. * Copyright 2010 the original author or authors.
  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.gradle.integtests.fixtures;
  17. import org.gradle.api.Action;
  18. import org.gradle.process.internal.ExecHandle;
  19. import org.gradle.process.internal.ExecHandleBuilder;
  20. import org.gradle.util.GUtil;
  21. import org.gradle.util.Jvm;
  22. import org.gradle.util.OperatingSystem;
  23. import org.gradle.util.TestFile;
  24. import org.hamcrest.Matcher;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27. import java.io.*;
  28. import java.util.*;
  29. import java.util.regex.Pattern;
  30. import static org.gradle.util.Matchers.containsLine;
  31. import static org.gradle.util.Matchers.matchesRegexp;
  32. import static org.hamcrest.Matchers.*;
  33. import static org.junit.Assert.assertThat;
  34. import static org.junit.Assert.fail;
  35. public class ForkingGradleExecuter extends AbstractGradleExecuter {
  36. private static final Logger LOG = LoggerFactory.getLogger(ForkingGradleExecuter.class);
  37. private final TestFile gradleHomeDir;
  38. private final List<String> gradleOpts = new ArrayList<String>();
  39. public ForkingGradleExecuter(TestFile gradleHomeDir) {
  40. this.gradleHomeDir = gradleHomeDir;
  41. gradleOpts.add("-ea");
  42. }
  43. public TestFile getGradleHomeDir() {
  44. return gradleHomeDir;
  45. }
  46. @Override
  47. protected ExecutionResult doRun() {
  48. Map result = doRun(false);
  49. return new ForkedExecutionResult(result);
  50. }
  51. @Override
  52. protected ExecutionFailure doRunWithFailure() {
  53. Map result = doRun(true);
  54. return new ForkedExecutionFailure(result);
  55. }
  56. /**
  57. * Adds some options to the GRADLE_OPTS environment variable to use.
  58. */
  59. public void addGradleOpts(String... opts) {
  60. gradleOpts.addAll(Arrays.asList(opts));
  61. }
  62. protected Map doRun(boolean expectFailure) {
  63. if (!gradleHomeDir.isDirectory()) {
  64. fail(gradleHomeDir + " is not a directory.\n"
  65. + "If you are running tests from IDE make sure that gradle tasks that prepare the test image were executed. Last time it was 'intTestImage' task.");
  66. }
  67. CommandBuilder commandBuilder = OperatingSystem.current().isWindows() ? new WindowsCommandBuilder()
  68. : new UnixCommandBuilder();
  69. ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  70. ByteArrayOutputStream errStream = new ByteArrayOutputStream();
  71. ExecHandleBuilder builder = new ExecHandleBuilder() {
  72. @Override
  73. public File getWorkingDir() {
  74. // Override this, so that the working directory is not canonicalised. Some int tests require that
  75. // the working directory is not canonicalised
  76. return ForkingGradleExecuter.this.getWorkingDir();
  77. }
  78. };
  79. builder.setStandardOutput(outStream);
  80. builder.setErrorOutput(errStream);
  81. builder.environment("GRADLE_HOME", "");
  82. builder.environment("JAVA_HOME", Jvm.current().getJavaHome());
  83. builder.environment("GRADLE_OPTS", formatGradleOpts());
  84. builder.environment(getEnvironmentVars());
  85. builder.workingDir(getWorkingDir());
  86. commandBuilder.build(builder);
  87. builder.args(getAllArgs());
  88. LOG.info(String.format("Execute in %s with: %s %s", builder.getWorkingDir(), builder.getExecutable(),
  89. builder.getArgs()));
  90. ExecHandle proc = builder.build();
  91. int exitValue = proc.start().waitForFinish().getExitValue();
  92. String output = outStream.toString();
  93. String error = errStream.toString();
  94. boolean failed = exitValue != 0;
  95. LOG.info("OUTPUT: " + output);
  96. LOG.info("ERROR: " + error);
  97. if (failed != expectFailure) {
  98. String message = String.format("Gradle execution %s in %s with: %s %s%nOutput:%n%s%nError:%n%s%n-----%n",
  99. expectFailure ? "did not fail" : "failed", builder.getWorkingDir(), builder.getExecutable(),
  100. builder.getArgs(), output, error);
  101. System.out.println(message);
  102. throw new RuntimeException(message);
  103. }
  104. return GUtil.map("output", output, "error", error);
  105. }
  106. private String formatGradleOpts() {
  107. StringBuilder result = new StringBuilder();
  108. for (String gradleOpt : gradleOpts) {
  109. if (result.length() > 0) {
  110. result.append(" ");
  111. }
  112. if (gradleOpt.contains(" ")) {
  113. assert !gradleOpt.contains("\"");
  114. result.append('"');
  115. result.append(gradleOpt);
  116. result.append('"');
  117. } else {
  118. result.append(gradleOpt);
  119. }
  120. }
  121. return result.toString();
  122. }
  123. private interface CommandBuilder {
  124. void build(ExecHandleBuilder builder);
  125. }
  126. private class WindowsCommandBuilder implements CommandBuilder {
  127. public void build(ExecHandleBuilder builder) {
  128. String cmd;
  129. if (getExecutable() != null) {
  130. cmd = getExecutable().replace('/', File.separatorChar);
  131. } else {
  132. cmd = "gradle";
  133. }
  134. builder.executable("cmd");
  135. builder.args("/c", cmd);
  136. String gradleHome = gradleHomeDir.getAbsolutePath();
  137. // NOTE: Windows uses Path, but allows asking for PATH, and PATH
  138. // is set within builder object for some things such
  139. // as CommandLineIntegrationTest, try PATH first, and
  140. // then revert to default of Path if null
  141. Object path = builder.getEnvironment().get("PATH");
  142. if (path == null) {
  143. path = builder.getEnvironment().get("Path");
  144. }
  145. builder.environment("Path", String.format("%s\\bin;%s",
  146. gradleHome,
  147. path));
  148. builder.environment("GRADLE_EXIT_CONSOLE", "true");
  149. }
  150. }
  151. private class UnixCommandBuilder implements CommandBuilder {
  152. public void build(ExecHandleBuilder builder) {
  153. if (getExecutable() != null) {
  154. File exe = new File(getExecutable());
  155. if (exe.isAbsolute()) {
  156. builder.executable(exe.getAbsolutePath());
  157. } else {
  158. builder.executable(String.format("%s/%s", getWorkingDir().getAbsolutePath(), getExecutable()));
  159. }
  160. } else {
  161. builder.executable(String.format("%s/bin/gradle", gradleHomeDir.getAbsolutePath()));
  162. }
  163. }
  164. }
  165. private static class ForkedExecutionResult extends AbstractExecutionResult {
  166. private final Map result;
  167. private final Pattern skippedTaskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)\\s+((SKIPPED)|(UP-TO-DATE))");
  168. private final Pattern notSkippedTaskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)");
  169. private final Pattern taskPattern = Pattern.compile("(:\\S+?(:\\S+?)*)(\\s+.+)?");
  170. public ForkedExecutionResult(Map result) {
  171. this.result = result;
  172. }
  173. public String getOutput() {
  174. return result.get("output").toString();
  175. }
  176. public String getError() {
  177. return result.get("error").toString();
  178. }
  179. public List<String> getExecutedTasks() {
  180. return grepTasks(taskPattern);
  181. }
  182. public ExecutionResult assertTasksExecuted(String... taskPaths) {
  183. List<String> expectedTasks = Arrays.asList(taskPaths);
  184. assertThat(String.format("Expected tasks %s not found in process output:%n%s", expectedTasks, getOutput()), getExecutedTasks(), equalTo(expectedTasks));
  185. return this;
  186. }
  187. public Set<String> getSkippedTasks() {
  188. return new HashSet(grepTasks(skippedTaskPattern));
  189. }
  190. public ExecutionResult assertTasksSkipped(String... taskPaths) {
  191. Set<String> expectedTasks = new HashSet<String>(Arrays.asList(taskPaths));
  192. assertThat(String.format("Expected skipped tasks %s not found in process output:%n%s", expectedTasks, getOutput()), getSkippedTasks(), equalTo(expectedTasks));
  193. return this;
  194. }
  195. public ExecutionResult assertTaskSkipped(String taskPath) {
  196. Set<String> tasks = new HashSet<String>(getSkippedTasks());
  197. assertThat(String.format("Expected skipped task %s not found in process output:%n%s", taskPath, getOutput()), tasks, hasItem(taskPath));
  198. return this;
  199. }
  200. public ExecutionResult assertTasksNotSkipped(String... taskPaths) {
  201. Set<String> tasks = new HashSet<String>(grepTasks(notSkippedTaskPattern));
  202. Set<String> expectedTasks = new HashSet<String>(Arrays.asList(taskPaths));
  203. assertThat(String.format("Expected executed tasks %s not found in process output:%n%s", expectedTasks, getOutput()), tasks, equalTo(expectedTasks));
  204. return this;
  205. }
  206. public ExecutionResult assertTaskNotSkipped(String taskPath) {
  207. Set<String> tasks = new HashSet<String>(grepTasks(notSkippedTaskPattern));
  208. assertThat(String.format("Expected executed task %s not found in process output:%n%s", taskPath, getOutput()), tasks, hasItem(taskPath));
  209. return this;
  210. }
  211. private List<String> grepTasks(final Pattern pattern) {
  212. final List<String> tasks = new ArrayList<String>();
  213. eachLine(new Action<String>() {
  214. public void execute(String s) {
  215. java.util.regex.Matcher matcher = pattern.matcher(s);
  216. if (matcher.matches()) {
  217. String taskName = matcher.group(1);
  218. if (!taskName.startsWith(":buildSrc:")) {
  219. tasks.add(taskName);
  220. }
  221. }
  222. }
  223. });
  224. return tasks;
  225. }
  226. private void eachLine(Action<String> action) {
  227. BufferedReader reader = new BufferedReader(new StringReader(getOutput()));
  228. String line;
  229. try {
  230. while ((line = reader.readLine()) != null) {
  231. action.execute(line);
  232. }
  233. } catch (IOException e) {
  234. throw new RuntimeException(e);
  235. }
  236. }
  237. }
  238. private static class ForkedExecutionFailure extends ForkedExecutionResult implements ExecutionFailure {
  239. private final Pattern causePattern = Pattern.compile("(?m)^Cause: ");
  240. public ForkedExecutionFailure(Map result) {
  241. super(result);
  242. }
  243. public ExecutionFailure assertHasLineNumber(int lineNumber) {
  244. assertThat(getError(), containsString(String.format(" line: %d", lineNumber)));
  245. return this;
  246. }
  247. public ExecutionFailure assertHasFileName(String filename) {
  248. assertThat(getError(), containsLine(startsWith(filename)));
  249. return this;
  250. }
  251. public ExecutionFailure assertHasCause(String description) {
  252. assertThatCause(startsWith(description));
  253. return this;
  254. }
  255. public ExecutionFailure assertThatCause(Matcher<String> matcher) {
  256. String error = getError();
  257. java.util.regex.Matcher regExpMatcher = causePattern.matcher(error);
  258. int pos = 0;
  259. while (pos < error.length()) {
  260. if (!regExpMatcher.find(pos)) {
  261. break;
  262. }
  263. int start = regExpMatcher.end();
  264. String cause;
  265. if (regExpMatcher.find(start)) {
  266. cause = error.substring(start, regExpMatcher.start());
  267. pos = regExpMatcher.start();
  268. } else {
  269. cause = error.substring(start);
  270. pos = error.length();
  271. }
  272. if (matcher.matches(cause)) {
  273. return this;
  274. }
  275. }
  276. fail(String.format("No matching cause found in '%s'", error));
  277. return this;
  278. }
  279. public ExecutionFailure assertHasNoCause() {
  280. assertThat(getError(), not(matchesRegexp(causePattern)));
  281. return this;
  282. }
  283. public ExecutionFailure assertHasDescription(String context) {
  284. assertThatDescription(startsWith(context));
  285. return this;
  286. }
  287. public ExecutionFailure assertThatDescription(Matcher<String> matcher) {
  288. assertThat(getError(), containsLine(matcher));
  289. return this;
  290. }
  291. }
  292. }