Skip to content

Commit accae1c

Browse files
authored
Make ProjectUtils.waitForProjects() more robust (#1552)
1 parent 2fc1a33 commit accae1c

1 file changed

Lines changed: 52 additions & 31 deletions

File tree

  • plugins/com.google.cloud.tools.eclipse.test.util/src/com/google/cloud/tools/eclipse/test/util/project

plugins/com.google.cloud.tools.eclipse.test.util/src/com/google/cloud/tools/eclipse/test/util/project/ProjectUtils.java

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,19 @@
2020
import static org.junit.Assert.assertTrue;
2121

2222
import com.google.common.base.Joiner;
23+
import com.google.common.base.Stopwatch;
2324
import java.io.File;
2425
import java.io.IOException;
2526
import java.net.URL;
2627
import java.util.ArrayList;
2728
import java.util.Collection;
2829
import java.util.Collections;
2930
import java.util.Enumeration;
31+
import java.util.HashSet;
3032
import java.util.LinkedHashSet;
3133
import java.util.List;
3234
import java.util.Set;
35+
import java.util.concurrent.TimeUnit;
3336
import java.util.zip.ZipEntry;
3437
import java.util.zip.ZipFile;
3538
import org.eclipse.core.resources.IMarker;
@@ -135,13 +138,13 @@ public static void failIfBuildErrors(String message, Collection<IProject> projec
135138

136139
/** Fail if there are any build errors on the specified projects. */
137140
public static void failIfBuildErrors(String message, IProject... projects) throws CoreException {
138-
List<String> errors = getAllBuildErrors(projects);
141+
Set<String> errors = getAllBuildErrors(projects);
139142
assertTrue(message + "\n" + Joiner.on("\n").join(errors), errors.isEmpty());
140143
}
141144

142145
/** Return a list of all build errors on the specified projects. */
143-
public static List<String> getAllBuildErrors(IProject... projects) throws CoreException {
144-
List<String> errors = new ArrayList<>();
146+
public static Set<String> getAllBuildErrors(IProject... projects) throws CoreException {
147+
Set<String> errors = new LinkedHashSet<>();
145148
for (IProject project : projects) {
146149
IMarker[] problems = project.findMarkers(IMarker.PROBLEM, true /* includeSubtypes */,
147150
IResource.DEPTH_INFINITE);
@@ -183,49 +186,67 @@ public void run() {
183186

184187
/** Wait for any spawned jobs and builds to complete (e.g., validation jobs). */
185188
public static void waitForProjects(Runnable delayTactic, IProject... projects) {
186-
IJobManager jobManager = Job.getJobManager();
189+
Stopwatch timer = Stopwatch.createStarted();
187190
try {
188-
Set<Job> jobs = new LinkedHashSet<>();
189-
List<String> allBuildErrors;
191+
Collection<Job> jobs = Collections.emptyList();
192+
Set<String> previousBuildErrors = Collections.emptySet();
193+
boolean buildErrorsChanging;
190194
do {
195+
// wait a little bit to give the builders a chance
191196
delayTactic.run();
197+
198+
// wait for any previously-identified build jobs
192199
for (Job job : jobs) {
193200
job.join();
194201
}
195-
jobs.clear();
196-
197-
Collections.addAll(jobs, jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD));
198-
Collections.addAll(jobs, jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD));
199-
// J2EEElementChangedListener.PROJECT_COMPONENT_UPDATE_JOB_FAMILY
200-
Collections.addAll(jobs, jobManager.find("org.eclipse.jst.j2ee.refactor.component"));
201-
// ServerPlugin.SHUTDOWN_JOB_FAMILY
202-
Collections.addAll(jobs, jobManager.find("org.eclipse.wst.server.core.family"));
203-
Collections.addAll(jobs, jobManager.find("org.eclipse.wst.server.ui.family"));
204-
Collections.addAll(jobs, jobManager.find(ValidationBuilder.FAMILY_VALIDATION_JOB));
205-
allBuildErrors = getAllBuildErrors(projects);
206-
if (DEBUG) {
202+
203+
// identify any pending build-related jobs
204+
jobs = findPendingBuildJobs();
205+
206+
// track whether we've reached a fixpoint in the build errors
207+
Set<String> currentBuildErrors = getAllBuildErrors(projects);
208+
buildErrorsChanging = !previousBuildErrors.equals(currentBuildErrors);
209+
previousBuildErrors = currentBuildErrors;
210+
211+
if (DEBUG || timer.elapsed(TimeUnit.SECONDS) > 10) {
207212
if (!jobs.isEmpty()) {
208-
System.err.printf("ProjectUtils#waitForProjects: waiting for %d jobs: %s\n",
213+
System.err.printf("ProjectUtils#waitForProjects[%s]: waiting for %d jobs: %s\n", timer,
209214
jobs.size(), jobs);
210-
} else if (!allBuildErrors.isEmpty()) {
211-
System.err.printf("ProjectUtils#waitForProjects: waiting for %d build errors\n",
212-
allBuildErrors.size());
213-
} else {
214-
// report any other jobs found in case we're missing something above
215-
Job[] otherJobs = jobManager.find(null);
216-
System.err.printf("Ignoring %d unrelated jobs:\n", otherJobs.length);
217-
for (Job job : otherJobs) {
218-
System.err.printf(" %s: %s\n", job.getClass().getName(), job);
219-
}
220-
// new ThreadDumpingWatchdog(0, TimeUnit.DAYS).run();
221215
}
216+
if (buildErrorsChanging) {
217+
System.err.printf("ProjectUtils#waitForProjects[%s]: waiting for %d build errors\n",
218+
timer, currentBuildErrors.size());
219+
}
220+
// Uncomment if tests are failing to identify any other build-related jobs.
221+
// Job[] otherJobs = Job.getJobManager().find(null);
222+
// if (otherJobs.length > 0) {
223+
// System.err.printf("Ignoring %d unrelated jobs:\n", otherJobs.length);
224+
// for (Job job : otherJobs) {
225+
// System.err.printf(" %s: %s\n", job.getClass().getName(), job);
226+
// }
227+
// }
222228
}
223-
} while (!(jobs.isEmpty() && allBuildErrors.isEmpty()));
229+
} while (!jobs.isEmpty() || buildErrorsChanging);
224230
} catch (CoreException | InterruptedException ex) {
225231
throw new RuntimeException(ex);
226232
}
227233
}
228234

235+
/** Identify all jobs that we know of that are related to building. */
236+
private static Collection<Job> findPendingBuildJobs() {
237+
Set<Job> jobs = new HashSet<>();
238+
IJobManager jobManager = Job.getJobManager();
239+
Collections.addAll(jobs, jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD));
240+
Collections.addAll(jobs, jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD));
241+
// J2EEElementChangedListener.PROJECT_COMPONENT_UPDATE_JOB_FAMILY
242+
Collections.addAll(jobs, jobManager.find("org.eclipse.jst.j2ee.refactor.component"));
243+
// ServerPlugin.SHUTDOWN_JOB_FAMILY
244+
Collections.addAll(jobs, jobManager.find("org.eclipse.wst.server.core.family"));
245+
Collections.addAll(jobs, jobManager.find("org.eclipse.wst.server.ui.family"));
246+
Collections.addAll(jobs, jobManager.find(ValidationBuilder.FAMILY_VALIDATION_JOB));
247+
return jobs;
248+
}
249+
229250
private static IWorkspace getWorkspace() {
230251
return ResourcesPlugin.getWorkspace();
231252
}

0 commit comments

Comments
 (0)