diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/AutoBuildJob.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/AutoBuildJob.java index 0220467..0e5a726 100644 --- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/AutoBuildJob.java +++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/events/AutoBuildJob.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -159,7 +159,7 @@ monitor.done(); } } - + /** * Forces an autobuild to occur, even if nothing has changed since the last * build. This is used to force a build after a clean. @@ -255,6 +255,8 @@ */ private synchronized void setInterrupted(boolean value) { interrupted = value; + if (value) + cancel(); } /** diff --git a/tests/org.eclipse.core.tests.resources/plugin.xml b/tests/org.eclipse.core.tests.resources/plugin.xml index f27c228..05a10e2 100644 --- a/tests/org.eclipse.core.tests.resources/plugin.xml +++ b/tests/org.eclipse.core.tests.resources/plugin.xml @@ -64,6 +64,11 @@ + + + + + diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderTest.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderTest.java index f4fd2b9..8b91e20 100644 --- a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderTest.java +++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,6 +21,7 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.tests.harness.TestBarrier; import org.eclipse.core.tests.harness.TestJob; +import org.eclipse.core.tests.internal.builders.BuilderWithCallback.IBuildCallback; /** * This class tests public API related to building and to build specifications. @@ -1117,6 +1118,69 @@ } } + public void testInterruptLongAutobuild() throws CoreException, InterruptedException { + setAutoBuilding(true); + + IProject project = getWorkspace().getRoot().getProject(getUniqueString()); + final IFile file = project.getFile("file.txt"); + ensureExistsInWorkspace(new IResource[] {project, file}, true); + addBuilder(project, BuilderWithCallback.BUILDER_NAME); + + waitForBuild(); + + final int[] status = new int[] {0}; + // use build callback to simulate user interaction with build + BuilderWithCallback.getInstance().setBuildCallback(new IBuildCallback() { + public IProject[] build(int kind, Map args, IProgressMonitor monitor) { + // let others know that build is running + status[0] = TestBarrier.STATUS_RUNNING; + // build will finish if monitor will be cancelled or the test already ended + while (!monitor.isCanceled() && status[0] != TestBarrier.STATUS_BLOCKED) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // ignore + } + } + // let others know that build is finished + status[0] = TestBarrier.STATUS_DONE; + return null; + } + }); + + // setContents will trigger a build + file.setContents(getRandomContents(), IResource.NONE, getMonitor()); + // wait until build is running + TestBarrier.waitForStatus(status, TestBarrier.STATUS_RUNNING); + // setContents will trigger a build; do it in a separate job so that the main thread is not blocked + Job job = new Job("setContents") { + protected IStatus run(IProgressMonitor monitor) { + try { + file.setContents(getRandomContents(), IResource.NONE, getMonitor()); + } catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + } + }; + job.schedule(); + + try { + // wait until build is finished; this should happen if build started after + // the first setContents call was cancelled by the second setContents call + TestBarrier.waitForStatus(status, TestBarrier.STATUS_DONE); + } finally { + BuilderWithCallback.getInstance().setBuildCallback(null); + // unblock the builder so that the job can finish before ending the test + status[0] = TestBarrier.STATUS_BLOCKED; + job.join(); + assertTrue(job.getResult().isOK()); + } + + waitForBuild(); + ensureDoesNotExistInWorkspace(project); + } + /** * Tests the lifecycle of a builder. */ diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderWithCallback.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderWithCallback.java new file mode 100644 index 0000000..3e19a02 --- /dev/null +++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/BuilderWithCallback.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.tests.internal.builders; + +import java.util.Map; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Test builder that allows to override the build method using a callback interface. + */ +public class BuilderWithCallback extends IncrementalProjectBuilder { + public interface IBuildCallback { + IProject[] build(int kind, Map args, IProgressMonitor monitor); + } + + public static final String BUILDER_NAME = "org.eclipse.core.tests.resources.builderwithcallback"; + + private static BuilderWithCallback instance; + + public static BuilderWithCallback getInstance() { + return instance; + } + + private IBuildCallback buildCallback; + + public BuilderWithCallback() { + instance = this; + } + + protected IProject[] build(int kind, Map args, IProgressMonitor monitor) { + if (buildCallback != null) + return buildCallback.build(kind, args, monitor); + return null; + } + + public void setBuildCallback(IBuildCallback buildCallback) { + this.buildCallback = buildCallback; + } +}