| /******************************************************************************* |
| * Copyright (c) 2003, 2015 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 - Initial API and implementation |
| * Stephan Wahlbrink - Test fix for bug 200997. |
| * Dmitry Karasik - Test cases for bug 255384 |
| * Jan Koehnlein - Test case for bug 60964 (454698) |
| <<<<<<< master |
| * Alexander Kurtakov <akurtako@redhat.com> - bug 458490 |
| ======= |
| * Thirumala Reddy Mutchukota (thirumala@google.com) - |
| * Bug 105821, Support for Job#join with timeout and progress monitor |
| >>>>>>> d688b58 Bug 105821: Support Job#join with timeout and progress monitor. |
| *******************************************************************************/ |
| package org.eclipse.core.tests.runtime.jobs; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| import org.eclipse.core.internal.jobs.JobManager; |
| import org.eclipse.core.internal.jobs.Worker; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.core.runtime.jobs.*; |
| import org.eclipse.core.tests.harness.*; |
| import org.junit.Assert; |
| |
| /** |
| * Tests the implemented get/set methods of the abstract class Job |
| */ |
| public class JobTest extends AbstractJobTest { |
| protected Job longJob; |
| protected Job shortJob; |
| private FussyProgressProvider progressProvider; |
| |
| public JobTest(String name) { |
| super(name); |
| } |
| |
| public static Test suite() { |
| return new TestSuite(JobTest.class); |
| // TestSuite suite = new TestSuite(); |
| // for (int i = 0; i < 1000; i++) |
| // suite.addTest(new JobTest("testSetProgressGroup")); |
| // return suite; |
| } |
| |
| //see bug #43591 |
| public void _testDone() { |
| //calling the done method on a job that is not executing asynchronously should have no effect |
| |
| shortJob.done(Status.OK_STATUS); |
| assertTrue("1.0", shortJob.getResult() == null); |
| |
| shortJob.done(Status.CANCEL_STATUS); |
| assertTrue("2.0", shortJob.getResult() == null); |
| |
| //calling the done method after the job is scheduled |
| shortJob.schedule(); |
| shortJob.done(Status.CANCEL_STATUS); |
| waitForState(shortJob, Job.NONE); |
| |
| //the done call should be ignored, and the job should finish execution normally |
| assertTrue("3.0", shortJob.getResult().getSeverity() == IStatus.OK); |
| |
| shortJob.done(Status.CANCEL_STATUS); |
| assertTrue("4.0", shortJob.getResult().getSeverity() == IStatus.OK); |
| |
| //calling the done method before a job is canceled |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| longJob.done(Status.OK_STATUS); |
| longJob.cancel(); |
| waitForState(longJob, Job.NONE); |
| |
| //the done call should be ignored, and the job status should still be canceled |
| assertTrue("5.0", longJob.getResult().getSeverity() == IStatus.CANCEL); |
| |
| longJob.done(Status.OK_STATUS); |
| assertTrue("6.0", longJob.getResult().getSeverity() == IStatus.CANCEL); |
| |
| } |
| |
| private void cancel(Job[] jobs) { |
| for (int i = 0; i < jobs.length; i++) |
| jobs[i].cancel(); |
| } |
| |
| /* |
| * @see TestCase#setUp() |
| */ |
| protected void setUp() throws Exception { |
| super.setUp(); |
| shortJob = new TestJob("Short Test Job", 100, 10); |
| longJob = new TestJob("Long Test Job", 1000000, 10); |
| progressProvider = new FussyProgressProvider(); |
| Job.getJobManager().setProgressProvider(progressProvider); |
| } |
| |
| /* |
| * @see TestCase#tearDown() |
| */ |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| Job.getJobManager().setProgressProvider(null); |
| waitForState(shortJob, Job.NONE); |
| waitForState(longJob, Job.NONE); |
| } |
| |
| //see bug #43566 |
| public void testAsynchJob() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START}; |
| |
| //execute a job asynchronously and check the result |
| AsynchTestJob main = new AsynchTestJob("Test Asynch Finish", status, 0); |
| |
| assertTrue("1.0", main.getThread() == null); |
| assertTrue("2.0", main.getResult() == null); |
| //schedule the job to run |
| main.schedule(); |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING); |
| assertTrue("3.0", main.getState() == Job.RUNNING); |
| //the asynchronous process that assigns the thread the job is going to run in has not been started yet |
| //the job is running in the thread provided to it by the manager |
| assertTrue("3.1" + main.getThread().getName(), main.getThread() instanceof Worker); |
| |
| status[0] = TestBarrier.STATUS_START; |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_WAIT_FOR_START); |
| |
| //the asynchronous process has been started, but the set thread method has not been called yet |
| assertTrue("3.2", main.getThread() instanceof Worker); |
| |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| |
| //make sure the job has set the thread it is going to run in |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING); |
| |
| assertTrue("3.3", status[0] == TestBarrier.STATUS_RUNNING); |
| assertTrue("3.4", main.getThread() instanceof AsynchExecThread); |
| |
| //let the job run |
| status[0] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_DONE); |
| waitForState(main, Job.NONE); |
| |
| //after the job is finished, the thread should be reset |
| assertTrue("4.0", main.getState() == Job.NONE); |
| assertTrue("4.1", main.getResult().getSeverity() == IStatus.OK); |
| assertTrue("4.2", main.getThread() == null); |
| |
| //reset status |
| status[0] = TestBarrier.STATUS_WAIT_FOR_START; |
| |
| //schedule the job to run again |
| main.schedule(); |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING); |
| assertTrue("5.0", main.getState() == Job.RUNNING); |
| |
| //the asynchronous process that assigns the thread the job is going to run in has not been started yet |
| //job is running in the thread provided by the manager |
| assertTrue("5.1", main.getThread() instanceof Worker); |
| |
| status[0] = TestBarrier.STATUS_START; |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_WAIT_FOR_START); |
| |
| //the asynchronous process has been started, but the set thread method has not been called yet |
| assertTrue("5.2", main.getThread() instanceof Worker); |
| |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| |
| //make sure the job has set the thread it is going to run in |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING); |
| |
| assertTrue("5.3", status[0] == TestBarrier.STATUS_RUNNING); |
| assertTrue("5.4", main.getThread() instanceof AsynchExecThread); |
| |
| //cancel the job, then let the job get the cancellation request |
| main.cancel(); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_DONE); |
| waitForState(main, Job.NONE); |
| |
| //thread should be reset to null after cancellation |
| assertTrue("6.0", main.getState() == Job.NONE); |
| assertTrue("6.1", main.getResult().getSeverity() == IStatus.CANCEL); |
| assertTrue("6.2", main.getThread() == null); |
| } |
| |
| public void testAsynchJobComplex() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START}; |
| |
| //test the interaction of several asynchronous jobs |
| AsynchTestJob[] jobs = new AsynchTestJob[5]; |
| |
| for (int i = 0; i < jobs.length; i++) { |
| jobs[i] = new AsynchTestJob("TestJob" + (i + 1), status, i); |
| assertTrue("1." + i, jobs[i].getThread() == null); |
| assertTrue("2." + i, jobs[i].getResult() == null); |
| jobs[i].schedule(); |
| //status[i] = TestBarrier.STATUS_START; |
| } |
| //all the jobs should be running at the same time |
| waitForStart(jobs, status); |
| |
| //every job should now be waiting for the STATUS_START flag |
| for (int i = 0; i < status.length; i++) { |
| assertTrue("3." + i, jobs[i].getState() == Job.RUNNING); |
| assertTrue("4." + i, jobs[i].getThread() instanceof Worker); |
| status[i] = TestBarrier.STATUS_START; |
| } |
| |
| for (int i = 0; i < status.length; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_WAIT_FOR_START); |
| |
| //every job should now be waiting for the STATUS_WAIT_FOR_RUN flag |
| for (int i = 0; i < status.length; i++) { |
| assertTrue("5. " + i, jobs[i].getThread() instanceof Worker); |
| status[i] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| } |
| |
| //wait until all jobs are in the running state |
| for (int i = 0; i < status.length; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_RUNNING); |
| |
| //let the jobs execute |
| for (int i = 0; i < status.length; i++) { |
| assertTrue("6. " + i, jobs[i].getThread() instanceof AsynchExecThread); |
| status[i] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| } |
| |
| for (int i = 0; i < status.length; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_DONE); |
| |
| //the status for every job should be STATUS_OK |
| //the threads should have been reset to null |
| for (int i = 0; i < status.length; i++) { |
| assertEquals("7." + i, TestBarrier.STATUS_DONE, status[i]); |
| assertEquals("8." + i, Job.NONE, jobs[i].getState()); |
| assertEquals("9." + i, IStatus.OK, jobs[i].getResult().getSeverity()); |
| assertNull("10." + i, jobs[i].getThread()); |
| } |
| } |
| |
| public void testAsynchJobConflict() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START}; |
| |
| //test the interaction of several asynchronous jobs when a conflicting rule is assigned to some of them |
| AsynchTestJob[] jobs = new AsynchTestJob[5]; |
| |
| ISchedulingRule rule = new IdentityRule(); |
| |
| for (int i = 0; i < jobs.length; i++) { |
| jobs[i] = new AsynchTestJob("TestJob" + (i + 1), status, i); |
| assertTrue("1." + i, jobs[i].getThread() == null); |
| assertTrue("2." + i, jobs[i].getResult() == null); |
| if (i < 2) { |
| jobs[i].schedule(); |
| } else if (i > 2) { |
| jobs[i].setRule(rule); |
| } else { |
| jobs[i].setRule(rule); |
| jobs[i].schedule(); |
| } |
| |
| } |
| |
| //these 3 jobs should be waiting for the STATUS_START flag |
| for (int i = 0; i < 3; i++) { |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_RUNNING); |
| assertTrue("3." + i, jobs[i].getState() == Job.RUNNING); |
| assertTrue("4." + i, jobs[i].getThread() instanceof Worker); |
| status[i] = TestBarrier.STATUS_START; |
| } |
| |
| //the first 3 jobs should be running at the same time |
| for (int i = 0; i < 3; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_WAIT_FOR_START); |
| |
| //the 3 jobs should now be waiting for the STATUS_WAIT_FOR_RUN flag |
| for (int i = 0; i < 3; i++) { |
| assertTrue("5. " + i, jobs[i].getThread() instanceof Worker); |
| status[i] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| } |
| |
| //wait until jobs block on running state |
| for (int i = 0; i < 3; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_RUNNING); |
| |
| //schedule the 2 remaining jobs |
| jobs[3].schedule(); |
| jobs[4].schedule(); |
| |
| //the 2 newly scheduled jobs should be waiting since they conflict with the third job |
| //no threads were assigned to them yet |
| assertEquals("6.1", Job.WAITING, jobs[3].getState()); |
| assertNull("6.2", jobs[3].getThread()); |
| assertEquals("6.3", Job.WAITING, jobs[4].getState()); |
| assertNull("6.4", jobs[4].getThread()); |
| |
| //let the two non-conflicting jobs execute together |
| for (int i = 0; i < 2; i++) { |
| assertTrue("7. " + i, jobs[i].getThread() instanceof AsynchExecThread); |
| status[i] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| } |
| //wait until the non-conflicting jobs are done |
| TestBarrier.waitForStatus(status, 1, TestBarrier.STATUS_DONE); |
| |
| //the third job should still be in the running state |
| assertEquals("8.1", Job.RUNNING, jobs[2].getState()); |
| //the 2 conflicting jobs should still be in the waiting state |
| assertEquals("8.2", Job.WAITING, jobs[3].getState()); |
| assertEquals("8.3", Job.WAITING, jobs[4].getState()); |
| |
| //let the third job finish execution |
| assertTrue("8.4", jobs[2].getThread() instanceof AsynchExecThread); |
| status[2] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| |
| //wait until the third job is done |
| TestBarrier.waitForStatus(status, 2, TestBarrier.STATUS_DONE); |
| |
| //the fourth job should now start running, the fifth job should still be waiting |
| TestBarrier.waitForStatus(status, 3, TestBarrier.STATUS_RUNNING); |
| assertEquals("9.1", Job.RUNNING, jobs[3].getState()); |
| assertEquals("9.2", Job.WAITING, jobs[4].getState()); |
| |
| //let the fourth job run, the fifth job is still waiting |
| status[3] = TestBarrier.STATUS_START; |
| assertEquals("9.3", Job.WAITING, jobs[4].getState()); |
| TestBarrier.waitForStatus(status, 3, TestBarrier.STATUS_WAIT_FOR_START); |
| status[3] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| assertEquals("9.4", Job.WAITING, jobs[4].getState()); |
| TestBarrier.waitForStatus(status, 3, TestBarrier.STATUS_RUNNING); |
| assertEquals("9.5", Job.WAITING, jobs[4].getState()); |
| |
| //cancel the fifth job, finish the fourth job |
| jobs[4].cancel(); |
| assertTrue("9.6", jobs[3].getThread() instanceof AsynchExecThread); |
| status[3] = TestBarrier.STATUS_WAIT_FOR_DONE; |
| |
| //wait until the fourth job is done |
| TestBarrier.waitForStatus(status, 3, TestBarrier.STATUS_DONE); |
| |
| //the status for the first 4 jobs should be STATUS_OK |
| //the threads should have been reset to null |
| for (int i = 0; i < status.length - 1; i++) { |
| assertEquals("10." + i, TestBarrier.STATUS_DONE, status[i]); |
| assertEquals("11." + i, Job.NONE, jobs[i].getState()); |
| assertEquals("12." + i, IStatus.OK, jobs[i].getResult().getSeverity()); |
| assertNull("13." + i, jobs[i].getThread()); |
| } |
| |
| //the fifth job should have null as its status (it never finished running) |
| //the thread for it should have also been reset |
| assertEquals("14.1", TestBarrier.STATUS_WAIT_FOR_START, status[4]); |
| assertEquals("14.2", Job.NONE, jobs[4].getState()); |
| assertNull("14.3", jobs[4].getResult()); |
| assertNull("14.4", jobs[4].getThread()); |
| } |
| |
| /** |
| * Tests cancelation of a job from the aboutToRun job event. |
| * See bug 70434 for details. |
| */ |
| public void testCancelFromAboutToRun() { |
| final int[] doneCount = new int[] {0}; |
| final int[] runningCount = new int[] {0}; |
| TestJob job = new TestJob("testCancelFromAboutToRun", 0, 0); |
| job.addJobChangeListener(new JobChangeAdapter() { |
| public void aboutToRun(IJobChangeEvent event) { |
| event.getJob().cancel(); |
| } |
| |
| public void done(IJobChangeEvent event) { |
| doneCount[0]++; |
| } |
| |
| public void running(IJobChangeEvent event) { |
| runningCount[0]++; |
| } |
| }); |
| job.schedule(); |
| try { |
| job.join(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| fail("0.99 " + e.getMessage()); |
| } |
| assertEquals("1.0", 0, job.getRunCount()); |
| assertEquals("1.1", 1, doneCount[0]); |
| assertEquals("1.2", 0, runningCount[0]); |
| } |
| |
| /** |
| * Basic test of {@link Job#shouldRun()}. |
| */ |
| public void testShouldRun() { |
| class ShouldRunJob extends Job { |
| public ShouldRunJob() { |
| super("ShouldRunJob"); |
| } |
| |
| int runCount = 0; |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| ++runCount; |
| return Status.OK_STATUS; |
| } |
| |
| public boolean shouldRun() { |
| return false; |
| } |
| } |
| ShouldRunJob j = new ShouldRunJob(); |
| j.schedule(); |
| try { |
| j.join(); |
| } catch (InterruptedException e) { |
| fail("0.99", e); |
| } |
| |
| //ensure the job never ran |
| assertEquals(0, j.runCount); |
| |
| } |
| |
| /** |
| * Test of an ill-behaving {@link Job#shouldRun()}. |
| */ |
| public void testShouldRunFailure() { |
| class ShouldRunJob extends Job { |
| public ShouldRunJob() { |
| super("ShouldRunJob"); |
| } |
| |
| int runCount = 0; |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| ++runCount; |
| return Status.OK_STATUS; |
| } |
| |
| public boolean shouldRun() { |
| throw new RuntimeException("Exception thrown on purpose as part of a test"); |
| } |
| } |
| ShouldRunJob j = new ShouldRunJob(); |
| j.schedule(); |
| waitForState(j, Job.NONE); |
| |
| //ensure the job never ran |
| assertEquals(0, j.runCount); |
| |
| } |
| |
| /** |
| * Tests canceling a job from the shouldRun method. See bug 255384. |
| */ |
| public void testCancelShouldRun() { |
| final String[] failure = new String[1]; |
| final Job j = new Job("Test") { |
| volatile int runningCount = 0; |
| boolean cancelled; |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| if (++runningCount > 1) |
| failure[0] = "Multiple running at once!"; |
| try { |
| Thread.sleep(500); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } finally { |
| if (--runningCount != 0) |
| failure[0] = "Multiple were running at once!"; |
| } |
| return Status.OK_STATUS; |
| } |
| |
| public boolean belongsTo(Object family) { |
| return JobTest.this == family; |
| } |
| |
| public boolean shouldRun() { |
| if (!cancelled) { |
| cancelled = true; |
| this.sleep(); |
| this.cancel(); |
| this.schedule(); |
| try { |
| Thread.sleep(500); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| return true; |
| } |
| }; |
| j.schedule(); |
| try { |
| Thread.sleep(1000); |
| Job.getJobManager().join(this, null); |
| } catch (OperationCanceledException e) { |
| fail("4.99", e); |
| } catch (InterruptedException e) { |
| fail("4.99", e); |
| } |
| assertNull(failure[0], failure[0]); |
| } |
| |
| /** |
| * Tests the hook method {@link Job#canceling}. |
| */ |
| public void testCanceling() { |
| final TestBarrier barrier = new TestBarrier(); |
| barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_START); |
| final int[] canceling = new int[] {0}; |
| Job job = new Job("Testing#testCanceling") { |
| protected void canceling() { |
| canceling[0]++; |
| } |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_RUN); |
| barrier.waitForStatus(TestBarrier.STATUS_RUNNING); |
| return Status.OK_STATUS; |
| } |
| }; |
| //schedule the job and wait on the barrier until it is running |
| job.schedule(); |
| barrier.waitForStatus(TestBarrier.STATUS_WAIT_FOR_RUN); |
| assertTrue("1.0", canceling[0] == 0); |
| job.cancel(); |
| assertTrue("1.1", canceling[0] == 1); |
| job.cancel(); |
| assertTrue("1.2", canceling[0] == 1); |
| //let the job finish |
| barrier.setStatus(TestBarrier.STATUS_RUNNING); |
| waitForState(job, Job.NONE); |
| } |
| |
| /** |
| * Tests the hook method {@link Job#canceling}. |
| */ |
| public void testCancelingByMonitor() { |
| final TestBarrier barrier = new TestBarrier(); |
| barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_START); |
| final int[] canceling = new int[] {0}; |
| final IProgressMonitor[] jobmonitor = new IProgressMonitor[1]; |
| Job job = new Job("Testing#testCancelingByMonitor") { |
| protected void canceling() { |
| canceling[0]++; |
| } |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| jobmonitor[0] = monitor; |
| barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_RUN); |
| barrier.waitForStatus(TestBarrier.STATUS_RUNNING); |
| return Status.OK_STATUS; |
| } |
| }; |
| //run test twice to ensure job is left in a clean state after first cancelation |
| for (int i = 0; i < 2; i++) { |
| canceling[0] = 0; |
| //schedule the job and wait on the barrier until it is running |
| job.schedule(); |
| barrier.waitForStatus(TestBarrier.STATUS_WAIT_FOR_RUN); |
| assertEquals(Integer.toString(i) + ".1.0", 0, canceling[0]); |
| jobmonitor[0].setCanceled(true); |
| assertEquals(Integer.toString(i) + ".1.1", 1, canceling[0]); |
| jobmonitor[0].setCanceled(true); |
| assertEquals(Integer.toString(i) + ".1.2", 1, canceling[0]); |
| //let the job finish |
| barrier.setStatus(TestBarrier.STATUS_RUNNING); |
| waitForState(job, Job.NONE); |
| } |
| } |
| |
| public void testCancelAboutToSchedule() { |
| final boolean[] failure = new boolean[1]; |
| final Job j = new Job("testCancelAboutToSchedule") { |
| volatile int runningCount = 0; |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| if (++runningCount > 1) |
| failure[0] = true; |
| try { |
| Thread.sleep(500); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } finally { |
| if (--runningCount != 0) |
| failure[0] = true; |
| } |
| return Status.OK_STATUS; |
| } |
| |
| public boolean belongsTo(Object family) { |
| return JobTest.this == family; |
| } |
| }; |
| JobChangeAdapter listener = new JobChangeAdapter() { |
| boolean canceled = false; |
| |
| public void scheduled(IJobChangeEvent event) { |
| if (event.getJob().belongsTo(JobTest.this) && !canceled) { |
| canceled = true; |
| j.cancel(); |
| j.schedule(); |
| try { |
| Thread.sleep(100); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| }; |
| Job.getJobManager().addJobChangeListener(listener); |
| try { |
| j.schedule(); |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| fail("4.99", e); |
| } |
| try { |
| Job.getJobManager().join(this, null); |
| } catch (OperationCanceledException e) { |
| fail("4.99", e); |
| } catch (InterruptedException e) { |
| fail("4.99", e); |
| } |
| assertFalse("1.0", failure[0]); |
| } finally { |
| Job.getJobManager().removeJobChangeListener(listener); |
| } |
| } |
| |
| public void testGetName() { |
| assertTrue("1.0", shortJob.getName().equals("Short Test Job")); |
| assertTrue("1.1", longJob.getName().equals("Long Test Job")); |
| |
| //try creating a job with a null name |
| try { |
| new TestJob(null); |
| fail("2.0"); |
| } catch (RuntimeException e) { |
| //should fail |
| } |
| } |
| |
| public void testGetPriority() { |
| //set priorities to all allowed options |
| //check if getPriority() returns proper result |
| |
| int[] priority = {Job.SHORT, Job.LONG, Job.INTERACTIVE, Job.BUILD, Job.DECORATE}; |
| |
| for (int i = 0; i < priority.length; i++) { |
| shortJob.setPriority(priority[i]); |
| assertTrue("1." + i, shortJob.getPriority() == priority[i]); |
| } |
| } |
| |
| public void testGetProperty() { |
| QualifiedName n1 = new QualifiedName("org.eclipse.core.tests.runtime", "p1"); |
| QualifiedName n2 = new QualifiedName("org.eclipse.core.tests.runtime", "p2"); |
| assertNull("1.0", shortJob.getProperty(n1)); |
| shortJob.setProperty(n1, null); |
| assertNull("1.1", shortJob.getProperty(n1)); |
| shortJob.setProperty(n1, shortJob); |
| assertTrue("1.2", shortJob.getProperty(n1) == shortJob); |
| assertNull("1.3", shortJob.getProperty(n2)); |
| shortJob.setProperty(n1, "hello"); |
| assertEquals("1.4", "hello", shortJob.getProperty(n1)); |
| shortJob.setProperty(n1, null); |
| assertNull("1.5", shortJob.getProperty(n1)); |
| assertNull("1.6", shortJob.getProperty(n2)); |
| } |
| |
| public void testGetResult() { |
| //execute a short job |
| assertTrue("1.0", shortJob.getResult() == null); |
| shortJob.schedule(); |
| waitForState(shortJob, Job.NONE); |
| assertTrue("1.1", shortJob.getResult().getSeverity() == IStatus.OK); |
| |
| //cancel a long job |
| waitForState(longJob, Job.NONE); |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| longJob.cancel(); |
| waitForState(longJob, Job.NONE); |
| assertTrue("2.0", longJob.getResult().getSeverity() == IStatus.CANCEL); |
| } |
| |
| public void testGetRule() { |
| //set several rules for the job, check if getRule returns the rule that was set |
| //no rule was set yet |
| assertTrue("1.0", shortJob.getRule() == null); |
| |
| shortJob.setRule(new IdentityRule()); |
| assertTrue("1.1", (shortJob.getRule() instanceof IdentityRule)); |
| |
| ISchedulingRule rule = new PathRule("/testGetRule"); |
| shortJob.setRule(rule); |
| assertTrue("1.2", shortJob.getRule() == rule); |
| |
| shortJob.setRule(null); |
| assertTrue("1.3", shortJob.getRule() == null); |
| } |
| |
| public void testGetThread() { |
| //check that getThread returns the thread that was passed in setThread, when the job is not running |
| //if the job is scheduled, only jobs that return the asynch_exec status will run in the indicated thread |
| |
| //main is not running now |
| assertTrue("1.0", shortJob.getThread() == null); |
| |
| Thread t = new Thread(); |
| shortJob.setThread(t); |
| assertTrue("1.1", shortJob.getThread() == t); |
| |
| shortJob.setThread(new Thread()); |
| assertTrue("1.2", shortJob.getThread() != t); |
| |
| shortJob.setThread(null); |
| assertTrue("1.3", shortJob.getThread() == null); |
| } |
| |
| public void testIsBlocking() { |
| IdentityRule rule = new IdentityRule(); |
| TestJob high = new TestJob("TestIsBlocking.long", 10000, 100); |
| high.setRule(rule); |
| high.setPriority(Job.LONG); |
| TestJob medium = new TestJob("TestIsBlocking.build", 10000, 100); |
| medium.setRule(rule); |
| medium.setPriority(Job.BUILD); |
| TestJob low = new TestJob("TestIsBlocking.decorate", 10000, 100); |
| low.setRule(rule); |
| low.setPriority(Job.DECORATE); |
| |
| //start the build job, and make sure it is not blocking |
| medium.schedule(); |
| waitForState(medium, Job.RUNNING); |
| assertTrue("1.0", !medium.isBlocking()); |
| //schedule a lower priority job, and it should still not be blocking |
| low.schedule(); |
| assertTrue("1.1", !medium.isBlocking()); |
| //schedule a higher priority job - now it should be blocking |
| high.schedule(); |
| //wait for the high priority job to become blocked |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| assertTrue("1.2", medium.isBlocking()); |
| |
| //cancel everything |
| Job[] jobs = new Job[] {high, medium, low}; |
| cancel(jobs); |
| waitForState(jobs, Job.NONE); |
| |
| //a higher priority system job should not be blocking |
| high.setSystem(true); |
| medium.schedule(); |
| waitForState(medium, Job.RUNNING); |
| high.schedule(); |
| assertTrue("2.0", !medium.isBlocking()); |
| |
| //clean up |
| cancel(jobs); |
| waitForState(jobs, Job.NONE); |
| } |
| |
| // @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=60964 |
| public void testIsBlocking2() throws InterruptedException { |
| final IJobManager manager = Job.getJobManager(); |
| final ISchedulingRule rule = new IdentityRule(); |
| Thread thread = new Thread("testIsBlocking2") { |
| @Override |
| public void run() { |
| try { |
| manager.beginRule(rule, null); |
| } finally { |
| manager.endRule(rule); |
| } |
| } |
| }; |
| try { |
| manager.beginRule(rule, null); |
| thread.start(); |
| while (thread.getState() != Thread.State.WAITING) |
| Thread.sleep(50); |
| assertTrue(manager.currentJob().isBlocking()); |
| } finally { |
| manager.endRule(rule); |
| thread.join(); |
| } |
| } |
| |
| public void testIsSystem() { |
| //reset the system parameter several times |
| shortJob.setUser(false); |
| shortJob.setSystem(false); |
| assertTrue("1.0", !shortJob.isUser()); |
| assertTrue("1.1", !shortJob.isSystem()); |
| shortJob.setSystem(true); |
| assertTrue("1.2", !shortJob.isUser()); |
| assertTrue("1.3", shortJob.isSystem()); |
| shortJob.setSystem(false); |
| assertTrue("1.4", !shortJob.isUser()); |
| assertTrue("1.5", !shortJob.isSystem()); |
| } |
| |
| public void testIsUser() { |
| //reset the user parameter several times |
| shortJob.setUser(false); |
| shortJob.setSystem(false); |
| assertTrue("1.0", !shortJob.isUser()); |
| assertTrue("1.1", !shortJob.isSystem()); |
| shortJob.setUser(true); |
| assertTrue("1.2", shortJob.isUser()); |
| assertTrue("1.3", !shortJob.isSystem()); |
| shortJob.setUser(false); |
| assertTrue("1.4", !shortJob.isUser()); |
| assertTrue("1.5", !shortJob.isSystem()); |
| } |
| |
| public void testJoin() { |
| longJob.schedule(100000); |
| //create a thread that will join the test job |
| final int[] status = new int[1]; |
| status[0] = TestBarrier.STATUS_WAIT_FOR_START; |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| longJob.join(); |
| } catch (InterruptedException e) { |
| Assert.fail("0.99"); |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| t.start(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_START); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| //putting the job to sleep should not affect the join call |
| longJob.sleep(); |
| //give a chance for the sleep to take effect |
| sleep(100); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| //similarly waking the job up should not affect the join |
| longJob.wakeUp(100000); |
| sleep(100); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| |
| //finally canceling the job will cause the join to return |
| longJob.cancel(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_DONE); |
| } |
| |
| public void testJoinWithTimeout() { |
| longJob.schedule(); |
| final long timeout = 1000; |
| final long duration[] = {-1}; |
| // Create a thread that will join the test job |
| final int[] status = new int[1]; |
| status[0] = TestBarrier.STATUS_WAIT_FOR_START; |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| long start = System.currentTimeMillis(); |
| longJob.join(timeout, null); |
| duration[0] = System.currentTimeMillis() - start; |
| } catch (InterruptedException e) { |
| Assert.fail("0.88"); |
| } catch (OperationCanceledException e) { |
| Assert.fail("0.99"); |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| t.start(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_START); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| int i = 0; |
| for (; i < 11; i++) { |
| if (status[0] == TestBarrier.STATUS_DONE) { |
| // Verify that the join call is blocked for at least for the duration of given timeout |
| assertTrue("2.0 duration: " + duration + " timeout: " + timeout, duration[0] >= timeout); |
| break; |
| } |
| sleep(100); |
| } |
| // Verify that the join call is finished with in reasonable time of 1100 ms (given timeout + 100ms) |
| assertTrue("3.0", i < 11); |
| // Verify that the join call is still running |
| assertEquals("4.0", Job.RUNNING, longJob.getState()); |
| // Finally cancel the job |
| longJob.cancel(); |
| waitForCompletion(longJob); |
| } |
| |
| public void testJoinWithProgressMonitor() { |
| shortJob.schedule(100000); |
| // Create a progress monitor for the join call |
| final FussyProgressMonitor monitor = new FussyProgressMonitor(); |
| // Create a thread that will join the test job |
| final int[] status = new int[1]; |
| status[0] = TestBarrier.STATUS_WAIT_FOR_START; |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| shortJob.join(0, monitor); |
| } catch (InterruptedException e) { |
| Assert.fail("0.88"); |
| } catch (OperationCanceledException e) { |
| Assert.fail("0.99"); |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| t.start(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_START); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| // Wakeup the job to get the join call to complete |
| shortJob.wakeUp(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_DONE); |
| monitor.sanityCheck(); |
| } |
| |
| public void testJoinWithCancelingMonitor() { |
| longJob.schedule(); |
| // Create a progress monitor for the join call |
| final FussyProgressMonitor monitor = new FussyProgressMonitor(); |
| // Create a thread that will join the test job |
| final int[] status = new int[1]; |
| status[0] = TestBarrier.STATUS_WAIT_FOR_START; |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| longJob.join(0, monitor); |
| } catch (InterruptedException e) { |
| Assert.fail("0.88"); |
| } catch (OperationCanceledException e) { |
| // expected |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| t.start(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_START); |
| assertEquals("1.0", TestBarrier.STATUS_START, status[0]); |
| |
| // Cancel the monitor that is attached to the join call |
| monitor.setCanceled(true); |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_DONE); |
| monitor.sanityCheck(); |
| // Verify that the join call is still running |
| assertEquals("2.0", Job.RUNNING, longJob.getState()); |
| // Finally cancel the job |
| longJob.cancel(); |
| waitForCompletion(longJob); |
| } |
| |
| public void testJoinInterruptNonUIThread() throws InterruptedException { |
| final Job job = new TestJob("job", 1000, 100); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| job.schedule(); |
| try { |
| job.join(); |
| } catch (InterruptedException e) { |
| job.cancel(); |
| } |
| } |
| }); |
| t.start(); |
| // make sure the job is running before we interrupt the thread |
| waitForState(job, Job.RUNNING); |
| t.interrupt(); |
| job.join(); |
| assertTrue("Thread not interrupted", job.getResult() == Status.CANCEL_STATUS); |
| } |
| |
| public void testJoinInterruptUIThread() throws InterruptedException { |
| final Job job = new TestJob("job", 1000, 100); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| job.schedule(); |
| try { |
| job.join(); |
| } catch (InterruptedException e) { |
| job.cancel(); |
| } |
| } |
| }); |
| try { |
| Job.getJobManager().setLockListener(new LockListener() { |
| public boolean canBlock() { |
| // pretend to be the UI thread |
| return false; |
| } |
| }); |
| t.start(); |
| // make sure the job is running before we interrupt the thread |
| waitForState(job, Job.RUNNING); |
| t.interrupt(); |
| job.join(); |
| assertTrue("Thread interrupted", job.getResult() == Status.OK_STATUS); |
| } finally { |
| Job.getJobManager().setLockListener(null); |
| } |
| } |
| |
| /** |
| * Asserts that the LockListener is called correctly during invocation of |
| * {@link Job#join()}. |
| * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=195839. |
| */ |
| public void testJoinLockListener() { |
| Job testJob = new TestJob("testJoinLockListener", 5, 500); |
| TestLockListener lockListener = new TestLockListener(); |
| try { |
| Job.getJobManager().setLockListener(lockListener); |
| testJob.join(); |
| } catch (OperationCanceledException e) { |
| fail("4.99", e); |
| } catch (InterruptedException e) { |
| fail("4.99", e); |
| } finally { |
| Job.getJobManager().setLockListener(null); |
| } |
| lockListener.assertNotWaiting("1.0"); |
| } |
| |
| /** |
| * Tests a job change listener that throws an exception. |
| * This would previously cause join attempts on that job to |
| * hang indefinitely because they would miss the notification |
| * required to end the join. |
| */ |
| public void testJoinFailingListener() { |
| shortJob.addJobChangeListener(new JobChangeAdapter() { |
| public void done(IJobChangeEvent event) { |
| throw new RuntimeException("This exception thrown on purpose as part of a test"); |
| } |
| }); |
| final int[] status = new int[1]; |
| //create a thread that will join the job |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| shortJob.join(); |
| } catch (InterruptedException e) { |
| Assert.fail("0.99"); |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| //schedule the job and then fork the thread to join it |
| shortJob.schedule(); |
| t.start(); |
| //wait until the join succeeds |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_DONE); |
| } |
| |
| /** |
| * Tests that a job joining itself is an error. |
| */ |
| public void testJoinSelf() { |
| final Exception[] failure = new Exception[1]; |
| Job selfJoiner = new Job("testJoinSelf") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| this.join(); |
| } catch (RuntimeException e) { |
| failure[0] = e; |
| } catch (InterruptedException e) { |
| failure[0] = e; |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| selfJoiner.schedule(); |
| try { |
| selfJoiner.join(); |
| } catch (InterruptedException e) { |
| fail("Unexpected interrupt"); |
| } |
| assertTrue("1.0", failure[0] != null); |
| } |
| |
| /** |
| * This is a regression test for bug 60323. If a job change listener |
| * removed itself from the listener list during the done() change event, |
| * then anyone joining on that job would hang forever. |
| */ |
| public void testJoinRemoveListener() { |
| final IJobChangeListener listener = new JobChangeAdapter() { |
| public void done(IJobChangeEvent event) { |
| shortJob.removeJobChangeListener(this); |
| } |
| }; |
| shortJob.addJobChangeListener(listener); |
| final int[] status = new int[1]; |
| //create a thread that will join the job |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| status[0] = TestBarrier.STATUS_START; |
| try { |
| shortJob.join(); |
| } catch (InterruptedException e) { |
| Assert.fail("0.99"); |
| } |
| status[0] = TestBarrier.STATUS_DONE; |
| } |
| }); |
| //schedule the job and then fork the thread to join it |
| shortJob.schedule(); |
| t.start(); |
| //wait until the join succeeds |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_DONE); |
| } |
| |
| /* |
| * Test that a canceled job is rescheduled |
| */ |
| public void testRescheduleCancel() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START}; |
| Job job = new Job("Testing") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| //schedule the job, cancel it, then reschedule |
| job.schedule(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| job.cancel(); |
| job.schedule(); |
| //let the first iteration of the job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //wait until the job runs again |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| //let the job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| waitForState(job, Job.NONE); |
| } |
| |
| /* |
| * Test that multiple reschedules of the same job while it is running |
| * only remembers the last reschedule request |
| */ |
| public void testRescheduleComplex() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START}; |
| final int[] runCount = new int[] {0}; |
| Job job = new Job("Testing") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| runCount[0]++; |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| //schedule the job, reschedule when it is running |
| job.schedule(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| //the last schedule value should win |
| job.schedule(1000000); |
| job.schedule(3000); |
| job.schedule(200000000); |
| job.schedule(); |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //wait until the job runs again |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| assertEquals("1.0", 1, runCount[0]); |
| //let the job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| waitForState(job, Job.NONE); |
| assertEquals("1.0", 2, runCount[0]); |
| } |
| |
| /* |
| * Reschedule a running job with a delay |
| */ |
| public void testRescheduleDelay() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START}; |
| final int[] runCount = new int[] {0}; |
| Job job = new Job("Testing") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| runCount[0]++; |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| //schedule the job, reschedule when it is running |
| job.schedule(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| job.schedule(1000000); |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //now wait until the job is scheduled again and put to sleep |
| waitForState(job, Job.SLEEPING); |
| assertEquals("1.0", 1, runCount[0]); |
| |
| //reschedule the job while it is sleeping |
| job.schedule(); |
| //wake up the currently sleeping job |
| job.wakeUp(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //make sure the job was not rescheduled while the executing job was sleeping |
| waitForState(job, Job.NONE); |
| assertTrue("1.0", job.getState() == Job.NONE); |
| assertEquals("1.0", 2, runCount[0]); |
| } |
| |
| /* |
| * Schedule a simple job that repeats several times from within the run method. |
| */ |
| public void testRescheduleRepeat() { |
| final int[] count = new int[] {0}; |
| final int REPEATS = 10; |
| Job job = new Job("testRescheduleRepeat") { |
| protected IStatus run(IProgressMonitor monitor) { |
| count[0]++; |
| schedule(); |
| return Status.OK_STATUS; |
| } |
| |
| public boolean shouldSchedule() { |
| return count[0] < REPEATS; |
| } |
| }; |
| job.schedule(); |
| int timeout = 0; |
| while (timeout++ < 100 && count[0] < REPEATS) { |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| } |
| assertTrue("1.0", timeout < 100); |
| assertEquals("1.1", REPEATS, count[0]); |
| } /* |
| * Schedule a simple job that repeats several times from within the run method. |
| */ |
| |
| public void testRescheduleRepeatWithDelay() { |
| final int[] count = new int[] {0}; |
| final int REPEATS = 10; |
| Job job = new Job("testRescheduleRepeat") { |
| protected IStatus run(IProgressMonitor monitor) { |
| count[0]++; |
| schedule(10); |
| return Status.OK_STATUS; |
| } |
| |
| public boolean shouldSchedule() { |
| return count[0] < REPEATS; |
| } |
| }; |
| job.schedule(); |
| int timeout = 0; |
| while (timeout++ < 100 && count[0] < REPEATS) { |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| } |
| assertTrue("1.0", timeout < 100); |
| assertEquals("1.1", REPEATS, count[0]); |
| } |
| |
| /* |
| * Schedule a job to run, and then reschedule it |
| */ |
| public void testRescheduleSimple() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START}; |
| Job job = new Job("testRescheduleSimple") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| //schedule the job, reschedule when it is running |
| job.schedule(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| job.schedule(); |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //wait until the job runs again |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| //let the job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| waitForState(job, Job.NONE); |
| |
| //the job should only run once the second time around |
| job.schedule(); |
| TestBarrier.waitForStatus(status, TestBarrier.STATUS_WAIT_FOR_RUN); |
| //let the job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //wait until the job truly finishes and has a chance to be rescheduled (it shouldn't reschedule) |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| waitForState(job, Job.NONE); |
| } |
| |
| /* |
| * Reschedule a waiting job. |
| */ |
| public void testRescheduleWaiting() { |
| final int[] status = {TestBarrier.STATUS_WAIT_FOR_START, TestBarrier.STATUS_WAIT_FOR_START}; |
| final int[] runCount = new int[] {0}; |
| final ISchedulingRule rule = new IdentityRule(); |
| Job first = new Job("Testing1") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[0] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| Job second = new Job("Testing2") { |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Testing", 1); |
| status[1] = TestBarrier.STATUS_WAIT_FOR_RUN; |
| TestBarrier.waitForStatus(status, 1, TestBarrier.STATUS_RUNNING); |
| monitor.worked(1); |
| } finally { |
| runCount[0]++; |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| //set the same rule for both jobs so that the second job would have to wait |
| first.setRule(rule); |
| first.schedule(); |
| second.setRule(rule); |
| TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_WAIT_FOR_RUN); |
| second.schedule(); |
| waitForState(second, Job.WAITING); |
| //reschedule the second job while it is waiting |
| second.schedule(); |
| //let the first job finish |
| status[0] = TestBarrier.STATUS_RUNNING; |
| //the second job will start |
| TestBarrier.waitForStatus(status, 1, TestBarrier.STATUS_WAIT_FOR_RUN); |
| //let the second job finish |
| status[1] = TestBarrier.STATUS_RUNNING; |
| |
| //make sure the second job was not rescheduled |
| waitForState(second, Job.NONE); |
| assertEquals("2.0", Job.NONE, second.getState()); |
| assertEquals("2.1", 1, runCount[0]); |
| } |
| |
| /* |
| * see bug #43458 |
| */ |
| public void testSetPriority() { |
| int[] wrongPriority = {1000, -Job.DECORATE, 25, 0, 5, Job.INTERACTIVE - Job.BUILD}; |
| |
| for (int i = 0; i < wrongPriority.length; i++) { |
| //set priority to non-existent type |
| try { |
| shortJob.setPriority(wrongPriority[i]); |
| fail("1." + (i + 1)); |
| } catch (RuntimeException e) { |
| //should fail |
| } |
| } |
| } |
| |
| /** |
| * Tests the API methods Job.setProgressGroup |
| */ |
| public void testSetProgressGroup() { |
| final TestBarrier barrier = new TestBarrier(); |
| Job job = new Job("testSetProgressGroup") { |
| protected IStatus run(IProgressMonitor monitor) { |
| barrier.setStatus(TestBarrier.STATUS_RUNNING); |
| barrier.waitForStatus(TestBarrier.STATUS_WAIT_FOR_DONE); |
| if (monitor.isCanceled()) |
| return Status.CANCEL_STATUS; |
| return Status.OK_STATUS; |
| } |
| }; |
| //null group |
| try { |
| job.setProgressGroup(null, 5); |
| fail("1.0"); |
| } catch (RuntimeException e) { |
| //should fail |
| } |
| IProgressMonitor group = Job.getJobManager().createProgressGroup(); |
| group.beginTask("Group task name", 10); |
| job.setProgressGroup(group, 5); |
| |
| //ignore changes to group while waiting or running |
| job.schedule(100); |
| job.setProgressGroup(group, 0); |
| //wait until job starts and try to set the progress group |
| barrier.waitForStatus(TestBarrier.STATUS_RUNNING); |
| job.setProgressGroup(group, 0); |
| |
| //ensure cancelation still works |
| job.cancel(); |
| barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_DONE); |
| waitForState(job, Job.NONE); |
| assertEquals("1.0", IStatus.CANCEL, job.getResult().getSeverity()); |
| group.done(); |
| } |
| |
| /* |
| * see bug #43459 |
| */ |
| public void testSetRule() { |
| //setting a scheduling rule for a job after it was already scheduled should throw an exception |
| shortJob.setRule(new IdentityRule()); |
| assertTrue("1.0", shortJob.getRule() instanceof IdentityRule); |
| shortJob.schedule(1000000); |
| try { |
| shortJob.setRule(new PathRule("/testSetRule")); |
| fail("1.1"); |
| } catch (RuntimeException e) { |
| //should fail |
| } |
| |
| //wake up the sleeping job |
| shortJob.wakeUp(); |
| |
| //setting the rule while running should fail |
| try { |
| shortJob.setRule(new PathRule("/testSetRule/B")); |
| fail("2.0"); |
| } catch (RuntimeException e1) { |
| //should fail |
| } |
| |
| try { |
| //wait for the job to complete |
| shortJob.join(); |
| } catch (InterruptedException e2) { |
| //ignore |
| } |
| |
| //after the job has finished executing, the scheduling rule for it can once again be reset |
| shortJob.setRule(new PathRule("/testSetRule/B/C/D")); |
| assertTrue("1.2", shortJob.getRule() instanceof PathRule); |
| shortJob.setRule(null); |
| assertTrue("1.3", shortJob.getRule() == null); |
| } |
| |
| public void testSetThread() { |
| //setting the thread of a job that is not an asynchronous job should not affect the actual thread the job will run in |
| assertTrue("0.0", longJob.getThread() == null); |
| |
| longJob.setThread(Thread.currentThread()); |
| assertTrue("1.0", longJob.getThread() == Thread.currentThread()); |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| |
| //the setThread method should have no effect on jobs that execute normally |
| assertTrue("2.0", longJob.getThread() != Thread.currentThread()); |
| |
| longJob.cancel(); |
| waitForState(longJob, Job.NONE); |
| |
| //the thread should reset to null when the job finishes execution |
| assertTrue("3.0", longJob.getThread() == null); |
| |
| longJob.setThread(null); |
| assertTrue("4.0", longJob.getThread() == null); |
| |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| |
| //the thread that the job is executing in is not the one that was set |
| assertTrue("5.0 (state=" + JobManager.printState(longJob.getState()) + ')', longJob.getThread() != null); |
| longJob.cancel(); |
| waitForState(longJob, Job.NONE); |
| |
| //thread should reset to null after execution of job |
| assertTrue("6.0", longJob.getThread() == null); |
| |
| Thread t = new Thread(); |
| longJob.setThread(t); |
| assertTrue("7.0", longJob.getThread() == t); |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| |
| //the thread that the job is executing in is not the one that it was set to |
| assertTrue("8.0", longJob.getThread() != t); |
| longJob.cancel(); |
| waitForState(longJob, Job.NONE); |
| |
| //execution thread should reset to null after job is finished |
| assertTrue("9.0", longJob.getThread() == null); |
| |
| //when the state is changed to RUNNING, the thread should not be null |
| final Thread[] thread = new Thread[1]; |
| IJobChangeListener listener = new JobChangeAdapter() { |
| public void running(IJobChangeEvent event) { |
| thread[0] = event.getJob().getThread(); |
| } |
| }; |
| longJob.addJobChangeListener(listener); |
| longJob.schedule(); |
| waitForState(longJob, Job.RUNNING); |
| longJob.cancel(); |
| longJob.removeJobChangeListener(listener); |
| assertNotNull("10.0", thread[0]); |
| } |
| |
| /** |
| * Several jobs were scheduled to run. |
| * Pause this thread until all the jobs start running. |
| */ |
| private void waitForStart(Job[] jobs, int[] status) { |
| for (int i = 0; i < jobs.length; i++) |
| TestBarrier.waitForStatus(status, i, TestBarrier.STATUS_RUNNING); |
| } |
| |
| /** |
| * A job has been scheduled. Pause this thread so that a worker thread |
| * has a chance to pick up the new job. |
| */ |
| private void waitForState(Job job, int state) { |
| int i = 0; |
| while (job.getState() != state) { |
| try { |
| Thread.yield(); |
| Thread.sleep(100); |
| Thread.yield(); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| //sanity test to avoid hanging tests |
| assertTrue("Timeout waiting for job to change state.", i++ < 100); |
| } |
| } |
| |
| private void waitForState(Job[] jobs, int state) { |
| for (int i = 0; i < jobs.length; i++) |
| waitForState(jobs[i], state); |
| } |
| |
| /** |
| * A job was scheduled to run. Pause this thread so that a worker thread |
| * has a chance to finish the job |
| */ |
| // private void waitForEnd(Job job) { |
| // int i = 0; |
| // while(job.getState() != Job.NONE) { |
| // try { |
| // Thread.sleep(100); |
| // } catch (InterruptedException e) { |
| // |
| // } |
| // |
| // //sanity test to avoid hanging tests |
| // assertTrue("Timeout waiting for job to end", i++ < 1000); |
| // } |
| // } |
| } |