/*******************************************************************************
 *  Copyright (c) 2003, 2018 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  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)
 *     Alexander Kurtakov <akurtako@redhat.com> - bug 458490
 *     Thirumala Reddy Mutchukota (thirumala@google.com) -
 *     		Bug 105821, Support for Job#join with timeout and progress monitor
 *******************************************************************************/
package org.eclipse.core.tests.runtime.jobs;

import java.util.Arrays;
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);
	}

	//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 (Job job : jobs) {
			job.cancel();
		}
	}

	@Override
	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);
	}

	@Override
	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() {
			@Override
			public void aboutToRun(IJobChangeEvent event) {
				event.getJob().cancel();
			}

			@Override
			public void done(IJobChangeEvent event) {
				doneCount[0]++;
			}

			@Override
			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;

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				++runCount;
				return Status.OK_STATUS;
			}

			@Override
			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;

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				++runCount;
				return Status.OK_STATUS;
			}

			@Override
			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;

			@Override
			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;
			}

			@Override
			public boolean belongsTo(Object family) {
				return JobTest.this == family;
			}

			@Override
			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 | 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") {
			@Override
			protected void canceling() {
				canceling[0]++;
			}

			@Override
			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") {
			@Override
			protected void canceling() {
				canceling[0]++;
			}

			@Override
			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(i + ".1.0", 0, canceling[0]);
			jobmonitor[0].setCanceled(true);
			assertEquals(i + ".1.1", 1, canceling[0]);
			jobmonitor[0].setCanceled(true);
			assertEquals(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;

			@Override
			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;
			}

			@Override
			public boolean belongsTo(Object family) {
				return JobTest.this == family;
			}
		};
		JobChangeAdapter listener = new JobChangeAdapter() {
			boolean canceled = false;

			@Override
			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 | 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(() -> {
			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(() -> {
			status[0] = TestBarrier.STATUS_START;
			try {
				long start = System.currentTimeMillis();
				longJob.join(timeout, null);
				duration[0] = System.currentTimeMillis() - start;
			} catch (InterruptedException e1) {
				Assert.fail("0.88");
			} catch (OperationCanceledException e2) {
				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: " + Arrays.toString(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(() -> {
			status[0] = TestBarrier.STATUS_START;
			try {
				shortJob.join(0, monitor);
			} catch (InterruptedException e1) {
				Assert.fail("0.88");
			} catch (OperationCanceledException e2) {
				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(() -> {
			status[0] = TestBarrier.STATUS_START;
			try {
				longJob.join(0, monitor);
			} catch (InterruptedException e1) {
				Assert.fail("0.88");
			} catch (OperationCanceledException e2) {
				// 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(() -> {
			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", 3, org.eclipse.core.internal.jobs.JobManager.MAX_WAIT_INTERVAL);
		Thread t = new Thread(() -> {
			job.schedule();
			try {
				job.join();
			} catch (InterruptedException e) {
				job.cancel();
			}
		});
		try {
			Job.getJobManager().setLockListener(new LockListener() {
				@Override
				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 | 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() {
			@Override
			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(() -> {
			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") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				try {
					this.join();
				} catch (RuntimeException | 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() {
			@Override
			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(() -> {
			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") {
			@Override
			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") {
			@Override
			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") {
			@Override
			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") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				count[0]++;
				schedule();
				return Status.OK_STATUS;
			}

			@Override
			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") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				count[0]++;
				schedule(10);
				return Status.OK_STATUS;
			}

			@Override
			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") {
			@Override
			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") {
			@Override
			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") {
			@Override
			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") {
			@Override
			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() {
			@Override
			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 (Job job : jobs) {
			waitForState(job, 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);
	//		}
	//	}
}
