|
20 | 20 | import static org.junit.Assert.assertTrue; |
21 | 21 |
|
22 | 22 | import com.google.common.base.Joiner; |
| 23 | +import com.google.common.base.Stopwatch; |
23 | 24 | import java.io.File; |
24 | 25 | import java.io.IOException; |
25 | 26 | import java.net.URL; |
26 | 27 | import java.util.ArrayList; |
27 | 28 | import java.util.Collection; |
28 | 29 | import java.util.Collections; |
29 | 30 | import java.util.Enumeration; |
| 31 | +import java.util.HashSet; |
30 | 32 | import java.util.LinkedHashSet; |
31 | 33 | import java.util.List; |
32 | 34 | import java.util.Set; |
| 35 | +import java.util.concurrent.TimeUnit; |
33 | 36 | import java.util.zip.ZipEntry; |
34 | 37 | import java.util.zip.ZipFile; |
35 | 38 | import org.eclipse.core.resources.IMarker; |
@@ -135,13 +138,13 @@ public static void failIfBuildErrors(String message, Collection<IProject> projec |
135 | 138 |
|
136 | 139 | /** Fail if there are any build errors on the specified projects. */ |
137 | 140 | public static void failIfBuildErrors(String message, IProject... projects) throws CoreException { |
138 | | - List<String> errors = getAllBuildErrors(projects); |
| 141 | + Set<String> errors = getAllBuildErrors(projects); |
139 | 142 | assertTrue(message + "\n" + Joiner.on("\n").join(errors), errors.isEmpty()); |
140 | 143 | } |
141 | 144 |
|
142 | 145 | /** 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<>(); |
145 | 148 | for (IProject project : projects) { |
146 | 149 | IMarker[] problems = project.findMarkers(IMarker.PROBLEM, true /* includeSubtypes */, |
147 | 150 | IResource.DEPTH_INFINITE); |
@@ -183,49 +186,67 @@ public void run() { |
183 | 186 |
|
184 | 187 | /** Wait for any spawned jobs and builds to complete (e.g., validation jobs). */ |
185 | 188 | public static void waitForProjects(Runnable delayTactic, IProject... projects) { |
186 | | - IJobManager jobManager = Job.getJobManager(); |
| 189 | + Stopwatch timer = Stopwatch.createStarted(); |
187 | 190 | 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; |
190 | 194 | do { |
| 195 | + // wait a little bit to give the builders a chance |
191 | 196 | delayTactic.run(); |
| 197 | + |
| 198 | + // wait for any previously-identified build jobs |
192 | 199 | for (Job job : jobs) { |
193 | 200 | job.join(); |
194 | 201 | } |
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) { |
207 | 212 | 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, |
209 | 214 | 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(); |
221 | 215 | } |
| 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 | + // } |
222 | 228 | } |
223 | | - } while (!(jobs.isEmpty() && allBuildErrors.isEmpty())); |
| 229 | + } while (!jobs.isEmpty() || buildErrorsChanging); |
224 | 230 | } catch (CoreException | InterruptedException ex) { |
225 | 231 | throw new RuntimeException(ex); |
226 | 232 | } |
227 | 233 | } |
228 | 234 |
|
| 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 | + |
229 | 250 | private static IWorkspace getWorkspace() { |
230 | 251 | return ResourcesPlugin.getWorkspace(); |
231 | 252 | } |
|
0 commit comments