/*******************************************************************************
 * Copyright (c) 2004, 2017 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
 *******************************************************************************/
package org.eclipse.core.tests.internal.resources;

import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.tests.harness.CancelingProgressMonitor;
import org.eclipse.core.tests.harness.TestBarrier;
import org.eclipse.core.tests.resources.ResourceTest;

/**
 * Tests concurrency issues when dealing with operations on the workspace
 */
public class WorkspaceConcurrencyTest extends ResourceTest {

	public static Test suite() {
		return new TestSuite(WorkspaceConcurrencyTest.class);
	}

	public WorkspaceConcurrencyTest() {
		super("");
	}

	public WorkspaceConcurrencyTest(String name) {
		super(name);
	}

	private void sleep(long duration) {
		try {
			Thread.sleep(duration);
		} catch (InterruptedException e) {
			//ignore
		}
	}

	public void testEndRuleInWorkspaceOperation() {
		try {
			final IProject project = getWorkspace().getRoot().getProject("testEndRuleInWorkspaceOperation");
			getWorkspace().run((IWorkspaceRunnable) monitor -> Job.getJobManager().endRule(project), project, IResource.NONE, getMonitor());
			//should have failed
			fail("1.0");
		} catch (CoreException e) {
			fail("1.99", e);
		} catch (RuntimeException e) {
			//expected
		}
	}

	/**
	 * Tests that it is possible to cancel a workspace operation when it is blocked
	 * by activity in another thread. This is a regression test for bug 56118.
	 */
	public void testCancelOnBlocked() {
		//create a dummy project
		ensureExistsInWorkspace(getWorkspace().getRoot().getProject("P1"), true);
		//add a resource change listener that blocks forever, thus
		//simulating a scenario where workspace lock is held indefinitely
		final int[] barrier = new int[1];
		final Throwable[] error = new Throwable[1];
		IResourceChangeListener listener = event -> {
			//block until we are told to do otherwise
			barrier[0] = TestBarrier.STATUS_START;
			try {
				TestBarrier.waitForStatus(barrier, TestBarrier.STATUS_DONE);
			} catch (Throwable e) {
				error[0] = e;
			}
		};
		getWorkspace().addResourceChangeListener(listener);
		try {
			//create a thread that modifies the workspace. This should
			//hang indefinitely due to the misbehaving listener
			TestWorkspaceJob testJob = new TestWorkspaceJob(10);
			testJob.setTouch(true);
			testJob.setRule(getWorkspace().getRoot());
			testJob.schedule();

			//wait until blocked on the listener
			TestBarrier.waitForStatus(barrier, TestBarrier.STATUS_START);

			//create a second thread that attempts to modify the workspace, but immediately
			//cancels itself. This thread should terminate immediately with a cancelation exception
			final boolean[] canceled = new boolean[] {false};
			Thread t2 = new Thread(() -> {
				try {
					getWorkspace().run((IWorkspaceRunnable) monitor -> {
						//no-op
					}, new CancelingProgressMonitor());
				} catch (CoreException e1) {
					fail("1.99", e1);
				} catch (OperationCanceledException e2) {
					canceled[0] = true;
				}
			});
			t2.start();
			try {
				t2.join();
			} catch (InterruptedException e) {
				fail("1.88", e);
			}
			//should have canceled
			assertTrue("2.0", canceled[0]);

			//finally release the listener and ensure the first thread completes
			barrier[0] = TestBarrier.STATUS_DONE;
			try {
				testJob.join();
			} catch (InterruptedException e1) {
				//ignore
			}
			if (error[0] != null) {
				fail("3.0", error[0]);
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests calling IWorkspace.run with a non-workspace rule.  This should be
	 * allowed. This is a regression test for bug 60114.
	 */
	public void testRunnableWithOtherRule() {
		ISchedulingRule rule = new ISchedulingRule() {
			@Override
			public boolean contains(ISchedulingRule rule) {
				return rule == this;
			}

			@Override
			public boolean isConflicting(ISchedulingRule rule) {
				return rule == this;
			}
		};
		try {
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				//noop
			}, rule, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
	}

	/**
	 * Tests three overlapping jobs
	 *  - Job 1 (root rule) does a build.
	 *  - Job 2 (null rule) overlaps Job 1 and has null scheduling rule
	 *  - Job 3 (project rule) overlaps Job 2
	 *
	 * The POST_BUILD event should occur at the end of Job 1. If it
	 * is delayed until the end of Job 3, an appropriate scheduling rule
	 * will not be available and it will fail.
	 * This is a regression test for bug 	62927.
	 */
	public void testRunWhileBuilding() {
		final IWorkspace workspace = ResourcesPlugin.getWorkspace();
		//create a POST_BUILD listener that will touch a project
		final IProject touch = workspace.getRoot().getProject("ToTouch");
		final IProject rule = workspace.getRoot().getProject("jobThree");
		final IFile ruleFile = rule.getFile("somefile.txt");
		ensureExistsInWorkspace(rule, true);
		ensureExistsInWorkspace(touch, true);
		ensureExistsInWorkspace(ruleFile, true);
		final Throwable[] failure = new Throwable[1];
		IResourceChangeListener listener = event -> {
			try {
				touch.touch(null);
			} catch (CoreException e1) {
				failure[0] = e1;
			} catch (RuntimeException e2) {
				failure[0] = e2;
			}
		};
		workspace.addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD);
		try {
			//create one job that does a build, and then waits
			final int[] status = new int[3];
			Job jobOne = new Job("jobOne") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					try {
						workspace.run((IWorkspaceRunnable) monitor1 -> {
							//do a build
							workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor1);
							//signal that the job has done the build
							status[0] = TestBarrier.STATUS_RUNNING;
							//wait for job two to start
							TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_WAIT_FOR_DONE);
						}, null);
					} catch (CoreException e) {
						return e.getStatus();
					}
					return Status.OK_STATUS;
				}
			};
			//schedule and wait for job one to start
			jobOne.schedule();
			TestBarrier.waitForStatus(status, 0, TestBarrier.STATUS_RUNNING);

			//create job two that does an empty workspace operation
			Job jobTwo = new Job("jobTwo") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					try {
						workspace.run((IWorkspaceRunnable) monitor1 -> {
							//signal that this job has started
							status[1] = TestBarrier.STATUS_RUNNING;
							//let job one finish
							status[0] = TestBarrier.STATUS_WAIT_FOR_DONE;
							//wait for job three to start
							TestBarrier.waitForStatus(status, 1, TestBarrier.STATUS_WAIT_FOR_DONE);
						}, null, IResource.NONE, null);
					} catch (CoreException e) {
						return e.getStatus();
					}
					return Status.OK_STATUS;
				}
			};
			jobTwo.schedule();
			//create job three that has a non-null rule
			Job jobThree = new Job("jobThree") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					try {
						workspace.run((IWorkspaceRunnable) monitor1 -> {
							//signal that this job has started
							status[2] = TestBarrier.STATUS_RUNNING;
							//let job two finish
							status[1] = TestBarrier.STATUS_WAIT_FOR_DONE;
							//ensure this job does something so the build listener runs
							ruleFile.touch(null);
							//wait for the ok to complete
							TestBarrier.waitForStatus(status, 2, TestBarrier.STATUS_WAIT_FOR_DONE);
						}, workspace.getRuleFactory().modifyRule(ruleFile), IResource.NONE, null);
					} catch (CoreException e) {
						return e.getStatus();
					}
					return Status.OK_STATUS;
				}
			};
			jobThree.schedule();
			//wait for job two to complete
			waitForCompletion(jobTwo);

			//let job three complete
			status[2] = TestBarrier.STATUS_WAIT_FOR_DONE;

			//wait for job three to complete
			waitForCompletion(jobThree);

			//ensure no jobs failed
			IStatus result = jobOne.getResult();
			if (!result.isOK()) {
				fail("1.0", new CoreException(result));
			}
			result = jobTwo.getResult();
			if (!result.isOK()) {
				fail("1.1", new CoreException(result));
			}
			result = jobThree.getResult();
			if (!result.isOK()) {
				fail("1.2", new CoreException(result));
			}

			if (failure[0] != null) {
				fail("1.3", failure[0]);
			}
		} finally {
			//ensure listener is removed
			workspace.removeResourceChangeListener(listener);
		}
	}

	private void waitForCompletion(Job job) {
		int i = 0;
		while (job.getState() != Job.NONE) {
			sleep(100);
			//sanity test to avoid hanging tests
			assertTrue("Timeout waiting for job to complete", i++ < 1000);
		}
	}
}
