/*******************************************************************************
 * Copyright (c) 2000, 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 Corporation - Initial API and implementation
 * 		tammo.freese@offis.de - tests for swapping files and folders
 ******************************************************************************/
package org.eclipse.core.tests.resources;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;

/**
 * Tests behavior of IResourceChangeListener, including validation
 * that correct deltas are received for all types of workspace changes.
 */
public class IResourceChangeListenerTest extends ResourceTest {
	class SimpleListener implements IResourceChangeListener {
		Object source;
		int trigger;

		@Override
		public void resourceChanged(IResourceChangeEvent event) {
			source = event.getSource();
			trigger = event.getBuildKind();
		}
	}

	protected static final String VERIFIER_NAME = "TestListener";
	IFile file1; //below folder1
	IFile file2; //below folder1
	IFile file3; //below folder2
	IFolder folder1; //below project2
	IFolder folder2; //below folder1
	IFolder folder3; //same as file1
	/* some random resource handles */
	IProject project1;
	IFile project1MetaData;
	IProject project2;
	IFile project2MetaData;
	ResourceDeltaVerifier verifier;

	public static Test suite() {
		//	TestSuite suite = new TestSuite();
		//	suite.addTest(new IResourceChangeListenerTest("testMoveProject1"));
		//	return suite;
		return new TestSuite(IResourceChangeListenerTest.class);
	}

	public IResourceChangeListenerTest() {
		super();
	}

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

	public void _testBenchMark_1GBYQEZ() {
		// start with a clean workspace
		getWorkspace().removeResourceChangeListener(verifier);
		try {
			getWorkspace().getRoot().delete(false, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}
		// create the listener
		IResourceChangeListener listener = new IResourceChangeListener() {
			public int fCounter;

			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				try {
					System.out.println("Start");
					for (int i = 0; i < 10; i++) {
						fCounter = 0;
						long start = System.currentTimeMillis();
						IResourceDelta delta = event.getDelta();
						delta.accept(delta2 -> {
							fCounter++;
							return true;
						});
						long end = System.currentTimeMillis();
						System.out.println("    Number of deltas: " + fCounter + ". Time needed: " + (end - start));
					}
					System.out.println("End");
				} catch (CoreException e) {
					fail("1.0", e);
				}
			}
		};
		// add the listener
		getWorkspace().addResourceChangeListener(listener);
		// setup the test data
		IWorkspaceRunnable body = monitor -> {
			IProject project = getWorkspace().getRoot().getProject("Test");
			IProjectDescription description = getWorkspace().newProjectDescription(project.getName());
			IPath root = getWorkspace().getRoot().getLocation();
			IPath contents = root.append("temp/testing");
			description.setLocation(contents);
			project.create(description, getMonitor());
			project.open(getMonitor());
			project.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// touch all resources (so that they appear in the delta)
		body = monitor -> {
			IResourceVisitor visitor = resource -> {
				resource.touch(getMonitor());
				return true;
			};
			getWorkspace().getRoot().accept(visitor);
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}
		// un-register our listener
		getWorkspace().removeResourceChangeListener(listener);
	}

	/**
	 * Tests that the builder is receiving an appropriate delta
	 *
	 * @see SortBuilderPlugin
	 * @see SortBuilder
	 */
	public void assertDelta() {
		assertTrue(verifier.getMessage(), verifier.isDeltaValid());
	}

	/**
	 * Asserts that a manual traversal of the delta does not find the given
	 * resources.
	 */
	void assertNotDeltaIncludes(String message, IResourceDelta delta, IResource[] resources) {
		try {
			IResource deltaResource = delta.getResource();
			for (int i = 0; i < resources.length; i++) {
				assertTrue(message, !deltaResource.equals(resources[i]));
			}
			IResourceDelta[] children = delta.getAffectedChildren();
			for (IResourceDelta element : children) {
				assertNotDeltaIncludes(message, element, resources);
			}
		} catch (RuntimeException e) {
			fail(message, e);
		}
	}

	/**
	 * Asserts that a visitor traversal of the delta does not find the given
	 * resources.
	 */
	void assertNotDeltaVisits(final String message, IResourceDelta delta, final IResource[] resources) {
		try {
			delta.accept(delta2 -> {
				IResource deltaResource = delta2.getResource();
				for (int i = 0; i < resources.length; i++) {
					assertTrue(message, !deltaResource.equals(resources[i]));
				}
				return true;
			});
		} catch (CoreException e) {
			fail(message, e);
		} catch (RuntimeException e) {
			fail(message, e);
		}
	}

	/**
	 * Runs code to handle a core exception
	 */
	protected void handleCoreException(CoreException e) {
		fail("IResourceChangeListenerTest", e);
	}

	/**
	 * Sets the workspace autobuilding to the desired value.
	 */
	protected void setAutoBuilding(boolean value) {
		IWorkspace workspace = getWorkspace();
		if (workspace.isAutoBuilding() == value) {
			return;
		}
		IWorkspaceDescription desc = workspace.getDescription();
		desc.setAutoBuilding(value);
		try {
			workspace.setDescription(desc);
		} catch (CoreException e) {
			fail("failed to set workspace description", e);
		}
	}

	/**
	 * Sets up the fixture, for example, open a network connection. This method
	 * is called before a test is executed.
	 */
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		// Create some resource handles
		project1 = getWorkspace().getRoot().getProject("Project" + 1);
		project2 = getWorkspace().getRoot().getProject("Project" + 2);
		folder1 = project1.getFolder("Folder" + 1);
		folder2 = folder1.getFolder("Folder" + 2);
		folder3 = folder1.getFolder("File" + 1);
		file1 = folder1.getFile("File" + 1);
		file2 = folder1.getFile("File" + 2);
		file3 = folder2.getFile("File" + 1);
		project1MetaData = project1.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
		project2MetaData = project2.getFile(IProjectDescription.DESCRIPTION_FILE_NAME);
		// Create and open a project, folder and file
		IWorkspaceRunnable body = monitor -> {
			project1.create(getMonitor());
			project1.open(getMonitor());
			folder1.create(true, true, getMonitor());
			file1.create(getRandomContents(), true, getMonitor());
		};
		verifier = new ResourceDeltaVerifier();
		getWorkspace().addResourceChangeListener(verifier, IResourceChangeEvent.POST_CHANGE);
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		//ensure all background jobs are done before we reset the delta verifier
		waitForBuild();
		waitForRefresh();
		verifier.reset();
	}

	/**
	 * Tears down the fixture, for example, close a network connection. This
	 * method is called after a test is executed.
	 */
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		ensureDoesNotExistInWorkspace(getWorkspace().getRoot());
		getWorkspace().removeResourceChangeListener(verifier);
	}

	/*
	 * Create a resource change listener and register it for POST_BUILD
	 * events. Ensure that you are able to modify the workspace tree.
	 */
	public void test_1GDK9OG() {
		// create the resource change listener
		IResourceChangeListener listener = event -> {
			try {
				IWorkspaceRunnable body = monitor -> {
					// modify the tree.
					IResourceDeltaVisitor visitor = delta -> {
						IResource resource = delta.getResource();
						try {
							resource.touch(getMonitor());
						} catch (RuntimeException e) {
							throw e;
						}
						resource.createMarker(IMarker.PROBLEM);
						return true;
					};
					event.getDelta().accept(visitor);
				};
				getWorkspace().run(body, getMonitor());
			} catch (CoreException e) {
				fail("1.0", e);
			}
		};
		// register the listener with the workspace.
		getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD);
		try {
			IWorkspaceRunnable body = new IWorkspaceRunnable() {
				// cause a delta by touching all resources
				final IResourceVisitor visitor = resource -> {
					resource.touch(getMonitor());
					return true;
				};

				@Override
				public void run(IProgressMonitor monitor) throws CoreException {
					getWorkspace().getRoot().accept(visitor);
				}
			};
			getWorkspace().run(body, getMonitor());
			//wait for autobuild so POST_BUILD will fire
			try {
				Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
			} catch (OperationCanceledException e) {
				//ignore
			} catch (InterruptedException e) {
				//ignore
			}
		} catch (CoreException e) {
			fail("2.0", e);
		} finally {
			// cleanup: ensure that the listener is removed
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	public void testAddAndRemoveFile() {
		try {
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and deleting", 100);
				try {
					file2.create(getRandomContents(), true, SubMonitor.convert(m, 50));
					file2.delete(true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			//should not have been verified since there was no change
			assertTrue("Unexpected notification on no change", !verifier.hasBeenNotified());
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testAddAndRemoveFolder() {
		try {
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and deleting", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					folder2.delete(true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			//should not have been verified since there was no change
			assertTrue("Unexpected notification on no change", !verifier.hasBeenNotified());
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testAddFile() {
		try {
			verifier.addExpectedChange(file2, IResourceDelta.ADDED, 0);
			file2.create(getRandomContents(), true, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testAddFileAndFolder() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, 0);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating folder and file", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file3.create(getRandomContents(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testAddFolder() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			folder2.create(true, true, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testAddProject() {
		try {
			verifier.addExpectedChange(project2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(project2MetaData, IResourceDelta.ADDED, 0);
			project2.create(getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	/*
	 * Create a resource change listener and register it for POST_CHANGE events.
	 * Ensure that you are NOT able to modify the workspace tree.
	 */
	public void testBug45996() {
		// create the resource change listener
		IResourceChangeListener listener = event -> {
			boolean failed = false;
			try {
				IWorkspaceRunnable body = monitor -> {
					// modify the tree.
					IResourceDeltaVisitor visitor = delta -> {
						IResource resource = delta.getResource();
						try {
							resource.touch(getMonitor());
						} catch (RuntimeException e) {
							throw e;
						}
						resource.createMarker(IMarker.PROBLEM);
						return true;
					};
					event.getDelta().accept(visitor);
				};
				getWorkspace().run(body, getMonitor());
			} catch (CoreException e) {
				//should fail
				failed = true;
			}
			assertTrue("1.0", failed);
		};
		// register the listener with the workspace.
		getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
		try {
			IWorkspaceRunnable body = new IWorkspaceRunnable() {
				// cause a delta by touching all resources
				final IResourceVisitor visitor = resource -> {
					resource.touch(getMonitor());
					return true;
				};

				@Override
				public void run(IProgressMonitor monitor) throws CoreException {
					getWorkspace().getRoot().accept(visitor);
				}
			};
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		} finally {
			// cleanup: ensure that the listener is removed
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	public void testBuildKind() {
		SimpleListener preBuild = new SimpleListener();
		SimpleListener postBuild = new SimpleListener();
		SimpleListener postChange = new SimpleListener();
		final IWorkspace workspace = getWorkspace();
		try {
			setAutoBuilding(false);
			workspace.addResourceChangeListener(preBuild, IResourceChangeEvent.PRE_BUILD);
			workspace.addResourceChangeListener(postBuild, IResourceChangeEvent.POST_BUILD);
			workspace.addResourceChangeListener(postChange, IResourceChangeEvent.POST_CHANGE);

			final int[] triggers = new int[] {IncrementalProjectBuilder.INCREMENTAL_BUILD, IncrementalProjectBuilder.FULL_BUILD, IncrementalProjectBuilder.CLEAN_BUILD,};
			for (int i = 0; i < triggers.length; i++) {
				final int trigger = triggers[i];
				workspace.run((IWorkspaceRunnable) monitor -> {
					file1.touch(null);
					workspace.build(trigger, monitor);
				}, getMonitor());
				assertEquals("1.0." + i, workspace, preBuild.source);
				assertEquals("1.1." + i, workspace, postBuild.source);
				assertEquals("1.2." + i, workspace, postChange.source);
				assertEquals("1.3." + i, trigger, preBuild.trigger);
				assertEquals("1.4." + i, trigger, postBuild.trigger);
				assertEquals("1.5." + i, 0, postChange.trigger);

				workspace.run((IWorkspaceRunnable) monitor -> {
					file1.touch(null);
					project1.build(trigger, getMonitor());
				}, getMonitor());
				assertEquals("2.0." + i, project1, preBuild.source);
				assertEquals("2.2." + i, project1, postBuild.source);
				assertEquals("2.2." + i, workspace, postChange.source);
				assertEquals("2.3." + i, trigger, preBuild.trigger);
				assertEquals("2.4." + i, trigger, postBuild.trigger);
				assertEquals("2.5." + i, 0, postChange.trigger);

			}

			//test autobuild trigger
			setAutoBuilding(true);
			file1.touch(null);
			waitForBuild();
			int trigger = IncrementalProjectBuilder.AUTO_BUILD;
			assertEquals("1.0", workspace, preBuild.source);
			assertEquals("1.1", workspace, postBuild.source);
			assertEquals("1.2", workspace, postChange.source);
			assertEquals("1.3", trigger, preBuild.trigger);
			assertEquals("1.4", trigger, postBuild.trigger);
			assertEquals("1.5", 0, postChange.trigger);

		} catch (CoreException e) {
			fail("4.99", e);
		} finally {
			workspace.removeResourceChangeListener(preBuild);
			workspace.removeResourceChangeListener(postBuild);
			workspace.removeResourceChangeListener(postChange);
			setAutoBuilding(true);
		}
	}

	public void testChangeFile() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			file1.setContents(getRandomContents(), true, false, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testChangeFileToFolder() {
		try {
			/* change file1 into a folder */
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.CONTENT | IResourceDelta.TYPE | IResourceDelta.REPLACED);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Deleting and Creating", 100);
				try {
					file1.delete(true, SubMonitor.convert(m, 50));
					folder3.create(true, true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testChangeFolderToFile() {
		try {
			/* change to a folder */
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				file1.delete(true, getMonitor());
				folder3.create(true, true, getMonitor());
			}, null);
			/* now change back to a file and verify */
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.CONTENT | IResourceDelta.TYPE | IResourceDelta.REPLACED);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Deleting and Creating", 100);
				try {
					folder3.delete(true, SubMonitor.convert(m, 50));
					file1.create(getRandomContents(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testChangeProject() {
		try {
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				project2.create(getMonitor());
				project2.open(getMonitor());
			}, null);
			IProjectDescription desc = project2.getDescription();
			desc.setReferencedProjects(new IProject[] {project1});
			verifier.addExpectedChange(project2, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			verifier.addExpectedChange(project2MetaData, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			project2.setDescription(desc, IResource.FORCE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testCopyChangeFile() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, 0, null, null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 150);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.copy(file3.getFullPath(), true, SubMonitor.convert(m, 50));
					file3.setContents(getRandomContents(), IResource.NONE, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testCopyFile() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, 0, null, null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.copy(file3.getFullPath(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testCloseOpenReplaceFile() {
		try {
			// FIXME: how to do this?
			//workspace.save(getMonitor());
			//workspace.close(getMonitor());
			//workspace.open(getMonitor());
			verifier.reset();
			getWorkspace().addResourceChangeListener(verifier);
			/* change file1's contents */
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.REPLACED | IResourceDelta.CONTENT);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Deleting and Creating", 100);
				try {
					file1.delete(true, SubMonitor.convert(m, 50));
					file1.create(getRandomContents(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testDeleteInPostBuildListener() {
		// create the resource change listener
		IResourceChangeListener listener = event -> {
			try {
				event.getDelta().accept(delta -> {
					IResource resource = delta.getResource();
					if (resource.getType() == IResource.FILE) {
						try {
							((IFile) resource).delete(true, true, null);
						} catch (RuntimeException e) {
							throw e;
						}
					}
					return true;
				});
			} catch (CoreException e) {
				fail("1.0", e);
			}
		};
		// register the listener with the workspace.
		getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD);
		try {
			getWorkspace().run((IWorkspaceRunnable) monitor -> getWorkspace().getRoot().accept(resource -> {
				resource.touch(getMonitor());
				return true;
			}), getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		} finally {
			// cleanup: ensure that the listener is removed
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests deleting a file, then moving another file to that deleted location.
	 * See bug 27527.
	 */
	public void testDeleteMoveFile() {
		try {
			verifier.reset();
			file2.create(getRandomContents(), IResource.NONE, getMonitor());
			verifier.reset();
			int flags = IResourceDelta.REPLACED | IResourceDelta.MOVED_FROM | IResourceDelta.CONTENT;
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, flags, file2.getFullPath(), null);
			verifier.addExpectedChange(file2, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file1.getFullPath());
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("deleting and moving", 100);
				try {
					file1.delete(IResource.NONE, SubMonitor.convert(m, 50));
					file2.move(file1.getFullPath(), IResource.NONE, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testDeleteProject() throws CoreException {
		//test that marker deltas are fired when projects are deleted
		verifier.reset();
		final IMarker marker = project1.createMarker(IMarker.TASK);
		class Listener1 implements IResourceChangeListener {
			public boolean done = false;

			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				done = true;
				IMarkerDelta[] deltas = event.findMarkerDeltas(IMarker.TASK, false);
				assertEquals("1.0", 1, deltas.length);
				assertEquals("1.1", marker.getId(), deltas[0].getId());
				assertEquals("1.2", IResourceDelta.REMOVED, deltas[0].getKind());
				synchronized (this) {
					notifyAll();
				}
			}
		}
		Listener1 listener = new Listener1();
		try {
			getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
			project1.delete(true, false, getMonitor());
			synchronized (listener) {
				int i = 0;
				while (!listener.done) {
					try {
						listener.wait(1000);
					} catch (InterruptedException e) {
					}
					assertTrue("2.0", ++i < 60);
				}
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	public void testDeleteFolderDuringRefresh() throws CoreException {
		project1 = getWorkspace().getRoot().getProject(getUniqueString());
		project1.create(getMonitor());
		project1.open(getMonitor());

		project2 = getWorkspace().getRoot().getProject(getUniqueString());
		project2.create(getMonitor());
		project2.open(getMonitor());

		assertTrue("1.0", project1.isOpen());
		assertTrue("2.0", project2.isOpen());

		final IFolder f = project1.getFolder(getUniqueString());
		f.create(true, true, getMonitor());

		// the listener checks if an attempt to modify the tree succeeds if made in a job
		// that belongs to FAMILY_MANUAL_REFRESH
		class Listener1 implements IResourceChangeListener {
			public boolean wasPerformed = false;

			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				new Job("deleteFolder") {
					@Override
					public boolean belongsTo(Object family) {
						return family == ResourcesPlugin.FAMILY_MANUAL_REFRESH;
					}

					@Override
					protected IStatus run(IProgressMonitor monitor) {
						try {
							f.delete(true, getMonitor());
							wasPerformed = true;
						} catch (Exception e) {
							fail("3.0", e);
						}
						return Status.OK_STATUS;
					}
				}.schedule();
			}
		}

		Listener1 listener1 = new Listener1();

		// perform a refresh to test the added listeners
		try {
			getWorkspace().addResourceChangeListener(listener1, IResourceChangeEvent.PRE_REFRESH);

			project2.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, null);

			assertTrue("4.0", listener1.wasPerformed);
			assertDoesNotExistInWorkspace("5.0", f);
		} catch (InterruptedException e) {
			fail("6.0", e);
		} catch (CoreException e) {
			fail("7.0", e);
		} finally {
			getWorkspace().removeResourceChangeListener(listener1);
		}
	}

	public void testRefreshOtherProjectDuringRefresh() throws Exception {
		final IProject p = getWorkspace().getRoot().getProject(getUniqueString());
		p.create(null);
		p.open(null);

		project1 = getWorkspace().getRoot().getProject(getUniqueString());
		project1.create(null);
		project1.open(null);

		assertTrue("1.0", p.isOpen());
		assertTrue("2.0", project1.isOpen());

		// the listener checks if an attempt to modify the tree succeeds if made in a job
		// that belongs to FAMILY_MANUAL_REFRESH
		class Listener1 implements IResourceChangeListener {
			public boolean wasPerformed = false;

			@Override
			public void resourceChanged(final IResourceChangeEvent event) {
				new Job("refreshProject") {
					@Override
					public boolean belongsTo(Object family) {
						return family == ResourcesPlugin.FAMILY_MANUAL_REFRESH;
					}

					@Override
					protected IStatus run(IProgressMonitor monitor) {
						try {
							if (event.getResource() != p) {
								p.refreshLocal(IResource.DEPTH_INFINITE, null);
							}
							wasPerformed = true;
						} catch (Exception e) {
							fail("3.0", e);
						}
						return Status.OK_STATUS;
					}
				}.schedule();
			}
		}

		Listener1 listener1 = new Listener1();

		// the listener checks if an attempt to modify the tree in the refresh thread fails
		class Listener2 implements IResourceChangeListener {
			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				try {
					if (event.getResource() != p) {
						p.refreshLocal(IResource.DEPTH_INFINITE, null);
					}
					fail("4.0");
				} catch (Exception e) {
					// should fail
				}
			}
		}

		Listener2 listener2 = new Listener2();

		// perform a refresh to test the added listeners
		try {
			getWorkspace().addResourceChangeListener(listener1, IResourceChangeEvent.PRE_REFRESH);
			getWorkspace().addResourceChangeListener(listener2, IResourceChangeEvent.PRE_REFRESH);

			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, null);

			assertTrue("5.0", listener1.wasPerformed);
		} catch (InterruptedException e) {
			fail("6.0", e);
		} catch (CoreException e) {
			fail("7.0", e);
		} finally {
			getWorkspace().removeResourceChangeListener(listener1);
			getWorkspace().removeResourceChangeListener(listener2);
		}
	}

	public void testPreRefreshNotification() throws Exception {
		final IWorkspaceRoot root = getWorkspace().getRoot();

		project1 = root.getProject(getUniqueString());
		project1.create(null);
		project1.open(null);

		assertTrue("1.0", project1.isOpen());

		class Listener1 implements IResourceChangeListener {
			public boolean wasPerformed = false;
			public Object eventSource;
			public Object eventResource;

			@Override
			public void resourceChanged(final IResourceChangeEvent event) {
				wasPerformed = true;
				eventSource = event.getSource();
				eventResource = event.getResource();
			}
		}

		Listener1 listener1 = new Listener1();

		// perform a refresh to test the added listeners
		try {
			getWorkspace().addResourceChangeListener(listener1, IResourceChangeEvent.PRE_REFRESH);

			root.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, null);

			assertTrue("2.0", listener1.wasPerformed);
			assertEquals("3.0", getWorkspace(), listener1.eventSource);
			assertEquals("4.0", null, listener1.eventResource);

			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, null);

			assertTrue("5.0", listener1.wasPerformed);
			assertEquals("6.0", project1, listener1.eventSource);
			assertEquals("7.0", project1, listener1.eventResource);
		} catch (InterruptedException e) {
			fail("8.0", e);
		} catch (CoreException e) {
			fail("9.0", e);
		} finally {
			getWorkspace().removeResourceChangeListener(listener1);
		}
	}

	/**
	 * Tests that phantom members don't show up in resource deltas when standard
	 * traversal and visitor are used.
	 */
	public void testHiddenPhantomChanges() {
		final IWorkspace workspace = getWorkspace();
		final IFolder phantomFolder = project1.getFolder("PhantomFolder");
		final IFile phantomFile = folder1.getFile("PhantomFile");
		final IResource[] phantomResources = new IResource[] {phantomFolder, phantomFile};
		final QualifiedName partner = new QualifiedName("Test", "Infected");
		IResourceChangeListener listener = event -> {
			//make sure the delta doesn't include the phantom members
			assertNotDeltaIncludes("1.0", event.getDelta(), phantomResources);
			//make sure a visitor does not find phantom members
			assertNotDeltaVisits("1.1", event.getDelta(), phantomResources);
		};
		workspace.addResourceChangeListener(listener);
		workspace.getSynchronizer().add(partner);
		ensureDoesNotExistInWorkspace(phantomResources);
		try {
			//create a phantom folder
			workspace.run((IWorkspaceRunnable) monitor -> workspace.getSynchronizer().setSyncInfo(partner, phantomFolder, new byte[] {1}), getMonitor());
			//create children in phantom folder
			IFile fileInFolder = phantomFolder.getFile("FileInPrivateFolder");
			workspace.getSynchronizer().setSyncInfo(partner, fileInFolder, new byte[] {1});
			//modify children in phantom folder
			workspace.getSynchronizer().setSyncInfo(partner, fileInFolder, new byte[] {2});
			//delete children in phantom folder
			workspace.getSynchronizer().flushSyncInfo(partner, fileInFolder, IResource.DEPTH_INFINITE);
			//delete phantom folder and change some other file
			workspace.run((IWorkspaceRunnable) monitor -> {
				phantomFolder.delete(IResource.NONE, getMonitor());
				file1.setContents(getRandomContents(), IResource.NONE, getMonitor());
			}, getMonitor());
			//create phantom file
			workspace.run((IWorkspaceRunnable) monitor -> workspace.getSynchronizer().setSyncInfo(partner, phantomFile, new byte[] {2}), getMonitor());
			//modify phantom file
			workspace.getSynchronizer().setSyncInfo(partner, phantomFile, new byte[] {3});
			//delete phantom file
			workspace.getSynchronizer().flushSyncInfo(partner, phantomFile, IResource.DEPTH_INFINITE);
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			workspace.removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests that team private members don't show up in resource deltas when
	 * standard traversal and visitor are used.
	 */
	public void testHiddenTeamPrivateChanges() {
		IWorkspace workspace = getWorkspace();
		final IFolder teamPrivateFolder = project1.getFolder("TeamPrivateFolder");
		final IFile teamPrivateFile = folder1.getFile("TeamPrivateFile");
		final IResource[] privateResources = new IResource[] {teamPrivateFolder, teamPrivateFile};
		IResourceChangeListener listener = event -> {
			//make sure the delta doesn't include the team private members
			assertNotDeltaIncludes("1.0", event.getDelta(), privateResources);
			//make sure a visitor does not find team private members
			assertNotDeltaVisits("1.1", event.getDelta(), privateResources);
		};
		workspace.addResourceChangeListener(listener);
		try {
			//create a team private folder
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFolder.create(true, true, getMonitor());
				teamPrivateFolder.setTeamPrivateMember(true);
			}, getMonitor());
			//create children in team private folder
			IFile fileInFolder = teamPrivateFolder.getFile("FileInPrivateFolder");
			fileInFolder.create(getRandomContents(), true, getMonitor());
			//modify children in team private folder
			fileInFolder.setContents(getRandomContents(), IResource.NONE, getMonitor());
			//delete children in team private folder
			fileInFolder.delete(IResource.NONE, getMonitor());
			//delete team private folder and change some other file
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFolder.delete(IResource.NONE, getMonitor());
				file1.setContents(getRandomContents(), IResource.NONE, getMonitor());
			}, getMonitor());
			//create team private file
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFile.create(getRandomContents(), true, getMonitor());
				teamPrivateFile.setTeamPrivateMember(true);
			}, getMonitor());
			//modify team private file
			teamPrivateFile.setContents(getRandomContents(), IResource.NONE, getMonitor());
			//delete team private file
			teamPrivateFile.delete(IResource.NONE, getMonitor());
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			workspace.removeResourceChangeListener(listener);
		}
	}

	public void testModifyMoveFile() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM | IResourceDelta.CONTENT, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.setContents(getRandomContents(), IResource.NONE, getMonitor());
					file1.move(file3.getFullPath(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveFile() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.move(file3.getFullPath(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveFileAddMarker() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM | IResourceDelta.MARKERS, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.move(file3.getFullPath(), true, SubMonitor.convert(m, 50));
					file3.createMarker(IMarker.TASK);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	/**
	 * Regression test for bug 42514
	 */
	public void testMoveFileDeleteFolder() {
		try {
			//file2 moved to file1, and colliding folder3 is deleted
			file1.delete(IResource.NONE, null);
			file2.create(getRandomContents(), IResource.NONE, null);
			folder3.create(IResource.NONE, true, null);
			verifier.reset();
			verifier.addExpectedChange(file2, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file1.getFullPath());
			int flags = IResourceDelta.MOVED_FROM | IResourceDelta.REPLACED | IResourceDelta.TYPE | IResourceDelta.CONTENT;
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, flags, file2.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Deleting and moving", 100);
				try {
					folder3.delete(IResource.FORCE, SubMonitor.convert(m, 50));
					file2.move(file1.getFullPath(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveFileDeleteSourceParent() {
		try {
			file1.delete(IResource.NONE, null);
			create(file3, true);
			verifier.reset();
			verifier.addExpectedChange(folder2, IResourceDelta.REMOVED, 0, null, null);
			verifier.addExpectedChange(file1, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, file3.getFullPath(), null);
			verifier.addExpectedChange(file3, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file1.getFullPath());
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					file3.move(file1.getFullPath(), true, SubMonitor.convert(m, 50));
					folder2.delete(IResource.NONE, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveModifyFile() {
		try {
			verifier.addExpectedChange(folder2, IResourceDelta.ADDED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM | IResourceDelta.CONTENT, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					folder2.create(true, true, SubMonitor.convert(m, 50));
					file1.move(file3.getFullPath(), true, SubMonitor.convert(m, 50));
					file3.setContents(getRandomContents(), IResource.NONE, getMonitor());
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveMoveFile() {
		file2 = project1.getFile("File2");
		file3 = project1.getFile("File3");
		try {
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("moving and moving file", 100);
				try {
					file1.move(file2.getFullPath(), false, null);
					file2.move(file3.getFullPath(), false, null);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testMoveMoveFolder() {
		folder2 = project1.getFolder("Folder2");
		folder3 = project1.getFolder("Folder3");
		file3 = folder3.getFile(file1.getName());
		try {
			verifier.addExpectedChange(folder1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, folder3.getFullPath());
			verifier.addExpectedChange(folder3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, folder1.getFullPath(), null);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, file3.getFullPath());
			verifier.addExpectedChange(file3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("moving and moving folder", 100);
				try {
					folder1.move(folder2.getFullPath(), false, null);
					folder2.move(folder3.getFullPath(), false, null);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	/**
	 * Move a project via rename. Note that the DESCRIPTION flag should be set
	 * in the delta for the destination only.
	 */
	public void testMoveProject1() {
		try {
			verifier.reset();
			verifier.addExpectedChange(project1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, project2.getFullPath());
			verifier.addExpectedChange(project1.getFile(".project"), IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, project2.getFile(".project").getFullPath());
			verifier.addExpectedChange(folder1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, project2.getFolder(folder1.getProjectRelativePath()).getFullPath());
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, project2.getFile(file1.getProjectRelativePath()).getFullPath());
			verifier.addExpectedChange(project2, IResourceDelta.ADDED, IResourceDelta.OPEN | IResourceDelta.DESCRIPTION | IResourceDelta.MOVED_FROM, project1.getFullPath(), null);
			verifier.addExpectedChange(project2.getFile(".project"), IResourceDelta.ADDED, IResourceDelta.CONTENT | IResourceDelta.MOVED_FROM, project1.getFile(".project").getFullPath(), null);
			verifier.addExpectedChange(project2.getFolder(folder1.getProjectRelativePath()), IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, folder1.getFullPath(), null);
			verifier.addExpectedChange(project2.getFile(file1.getProjectRelativePath()), IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, file1.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					project1.move(project2.getFullPath(), IResource.NONE, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	/**
	 * Move a project via a location change only. Note that the DESCRIPTION flag
	 * should be set in the delta.
	 */
	public void testMoveProject2() {
		final IPath path = getRandomLocation();
		try {
			verifier.addExpectedChange(project1, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Creating and moving", 100);
				try {
					IProjectDescription desc = project1.getDescription();
					desc.setLocation(path);
					project1.move(desc, IResource.NONE, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			Workspace.clear(path.toFile());
		}
	}

	public void testMulti() {
		class Listener1 implements IResourceChangeListener {
			public boolean done = false;

			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				assertEquals("1.0", IResourceChangeEvent.POST_CHANGE, event.getType());
				done = true;
			}
		}
		class Listener2 extends Listener1 implements IResourceChangeListener {
			@Override
			public void resourceChanged(IResourceChangeEvent event) {
				assertEquals("2.0", IResourceChangeEvent.POST_BUILD, event.getType());
				done = true;
			}
		}
		Listener1 listener1 = new Listener1();
		Listener2 listener2 = new Listener2();
		getWorkspace().addResourceChangeListener(listener1, IResourceChangeEvent.POST_CHANGE);
		getWorkspace().addResourceChangeListener(listener2, IResourceChangeEvent.POST_BUILD);
		try {
			try {
				project1.touch(getMonitor());
			} catch (CoreException e) {
				handleCoreException(e);
			}
			int i = 0;
			while (!(listener1.done && listener2.done)) {
				//timeout if the listeners are never called
				assertTrue("3.0", ++i < 600);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e1) {
				}
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener1);
			getWorkspace().removeResourceChangeListener(listener2);
		}
	}

	public void testProjectDescriptionComment() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(project1, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			verifier.addExpectedChange(project1MetaData, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			IProjectDescription description = project1.getDescription();
			description.setComment("new comment");
			project1.setDescription(description, IResource.NONE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testProjectDescriptionDynamicRefs() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(project1, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			IProjectDescription description = project1.getDescription();
			description.setDynamicReferences(new IProject[] {project2});
			project1.setDescription(description, IResource.NONE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testProjectDescriptionNatures() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(project1, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			verifier.addExpectedChange(project1MetaData, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			IProjectDescription description = project1.getDescription();
			description.setNatureIds(new String[] {NATURE_SIMPLE});
			project1.setDescription(description, IResource.NONE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testProjectDescriptionStaticRefs() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(project1, IResourceDelta.CHANGED, IResourceDelta.DESCRIPTION);
			verifier.addExpectedChange(project1MetaData, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			IProjectDescription description = project1.getDescription();
			description.setReferencedProjects(new IProject[] {project2});
			project1.setDescription(description, IResource.NONE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testRemoveFile() {
		try {
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, 0);
			file1.delete(true, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testRemoveFileAndFolder() {
		try {
			verifier.addExpectedChange(folder1, IResourceDelta.REMOVED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.REMOVED, 0);
			folder1.delete(true, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testReplaceFile() {
		try {
			/* change file1's contents */
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.REPLACED | IResourceDelta.CONTENT);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("Deleting and Creating", 100);
				try {
					file1.delete(true, SubMonitor.convert(m, 50));
					file1.create(getRandomContents(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testReplaceFolderWithFolder() {
		try {
			folder2 = project1.getFolder("Folder2");
			folder3 = project1.getFolder("Folder3");
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				file1.delete(false, null);
				folder2.create(false, true, null);
			}, null);
			verifier.reset();
			verifier.addExpectedChange(folder1, IResourceDelta.REMOVED, IResourceDelta.MOVED_TO, null, folder2.getFullPath());
			int flags = IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO | IResourceDelta.REPLACED | IResourceDelta.CONTENT;
			verifier.addExpectedChange(folder2, IResourceDelta.CHANGED, flags, folder1.getFullPath(), folder3.getFullPath());
			verifier.addExpectedChange(folder3, IResourceDelta.ADDED, IResourceDelta.MOVED_FROM, folder2.getFullPath(), null);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("replace folder with folder", 100);
				try {
					folder2.move(folder3.getFullPath(), false, null);
					folder1.move(folder2.getFullPath(), false, null);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testSetLocal() {
		try {
			verifier.reset();
			//set local on a file that is already local -- should be no change
			file1.setLocal(true, IResource.DEPTH_INFINITE, getMonitor());
			assertTrue("Unexpected notification on no change", !verifier.hasBeenNotified());
			//set non-local, still shouldn't appear in delta
			verifier.reset();
			file1.setLocal(false, IResource.DEPTH_INFINITE, getMonitor());
			assertTrue("Unexpected notification on no change", !verifier.hasBeenNotified());
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testSwapFiles() {
		try {
			file1 = project1.getFile("File1");
			file2 = project1.getFile("File2");
			file3 = project1.getFile("File3");
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				file1.create(new ByteArrayInputStream(new byte[] {65}), false, null);
				file2.create(new ByteArrayInputStream(new byte[] {67}), false, null);
			}, null);
			verifier.reset();
			final int flags = IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO | IResourceDelta.REPLACED | IResourceDelta.CONTENT;
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, flags, file2.getFullPath(), file2.getFullPath());
			verifier.addExpectedChange(file2, IResourceDelta.CHANGED, flags, file1.getFullPath(), file1.getFullPath());
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("swap files", 100);
				try {
					file1.move(file3.getFullPath(), false, null);
					file2.move(file1.getFullPath(), false, null);
					file3.move(file2.getFullPath(), false, null);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testSwapFolders() {
		try {
			verifier.reset();
			getWorkspace().run((IWorkspaceRunnable) m -> {
				folder2 = project1.getFolder("Folder2");
				folder3 = project1.getFolder("Folder3");
				file1.delete(false, null);
				folder2.create(false, true, null);
			}, null);
			verifier.reset();
			final int flags = IResourceDelta.MOVED_FROM | IResourceDelta.MOVED_TO | IResourceDelta.REPLACED | IResourceDelta.CONTENT;
			verifier.addExpectedChange(folder1, IResourceDelta.CHANGED, flags, folder2.getFullPath(), folder2.getFullPath());
			verifier.addExpectedChange(folder2, IResourceDelta.CHANGED, flags, folder1.getFullPath(), folder1.getFullPath());
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("swap folders", 100);
				try {
					folder1.move(folder3.getFullPath(), false, null);
					folder2.move(folder1.getFullPath(), false, null);
					folder3.move(folder2.getFullPath(), false, null);
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	/**
	 * Asserts that the delta is correct for changes to team private members.
	 */
	public void testTeamPrivateChanges() {
		IWorkspace workspace = getWorkspace();
		final IFolder teamPrivateFolder = project1.getFolder("TeamPrivateFolder");
		final IFile teamPrivateFile = folder1.getFile("TeamPrivateFile");
		try {
			//create a team private folder
			verifier.reset();
			verifier.addExpectedChange(teamPrivateFolder, IResourceDelta.ADDED, 0);
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFolder.create(true, true, getMonitor());
				teamPrivateFolder.setTeamPrivateMember(true);
			}, getMonitor());
			assertDelta();
			verifier.reset();
			//create children in team private folder
			IFile fileInFolder = teamPrivateFolder.getFile("FileInPrivateFolder");
			verifier.addExpectedChange(fileInFolder, IResourceDelta.ADDED, 0);
			fileInFolder.create(getRandomContents(), true, getMonitor());
			assertDelta();
			verifier.reset();
			//modify children in team private folder
			verifier.addExpectedChange(fileInFolder, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			fileInFolder.setContents(getRandomContents(), IResource.NONE, getMonitor());
			assertDelta();
			verifier.reset();
			//delete children in team private folder
			verifier.addExpectedChange(fileInFolder, IResourceDelta.REMOVED, 0);
			fileInFolder.delete(IResource.NONE, getMonitor());
			assertDelta();
			verifier.reset();
			//delete team private folder and change some other file
			verifier.addExpectedChange(teamPrivateFolder, IResourceDelta.REMOVED, 0);
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFolder.delete(IResource.NONE, getMonitor());
				file1.setContents(getRandomContents(), IResource.NONE, getMonitor());
			}, getMonitor());
			assertDelta();
			verifier.reset();
			//create team private file
			verifier.addExpectedChange(teamPrivateFile, IResourceDelta.ADDED, 0);
			workspace.run((IWorkspaceRunnable) monitor -> {
				teamPrivateFile.create(getRandomContents(), true, getMonitor());
				teamPrivateFile.setTeamPrivateMember(true);
			}, getMonitor());
			assertDelta();
			verifier.reset();
			//modify team private file
			verifier.addExpectedChange(teamPrivateFile, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			teamPrivateFile.setContents(getRandomContents(), IResource.NONE, getMonitor());
			assertDelta();
			verifier.reset();
			//delete team private file
			verifier.addExpectedChange(teamPrivateFile, IResourceDelta.REMOVED, 0);
			teamPrivateFile.delete(IResource.NONE, getMonitor());
			assertDelta();
			verifier.reset();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testTwoFileChanges() {
		try {
			verifier.addExpectedChange(file1, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			verifier.addExpectedChange(file2, IResourceDelta.ADDED, 0);
			getWorkspace().run((IWorkspaceRunnable) m -> {
				m.beginTask("setting contents and creating", 100);
				try {
					file1.setContents(getRandomContents(), true, false, SubMonitor.convert(m, 50));
					file2.create(getRandomContents(), true, SubMonitor.convert(m, 50));
				} finally {
					m.done();
				}
			}, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		}
	}

	public void testRemoveAndCreateUnderlyingFileForLinkedResource() {
		IPath path = getTempDir().addTrailingSeparator().append(getUniqueString());
		try {
			try {
				path.toFile().createNewFile();
			} catch (IOException e) {
				fail("1.0", e);
			}
			IFile linkedFile = project1.getFile(getUniqueString());
			linkedFile.createLink(path, IResource.NONE, getMonitor());

			// check the delta when underlying file is removed
			verifier.addExpectedChange(linkedFile, IResourceDelta.CHANGED, IResourceDelta.LOCAL_CHANGED);
			path.toFile().delete();
			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			assertDelta();

			// check the delta when underlying file is recreated
			verifier.addExpectedChange(linkedFile, IResourceDelta.CHANGED, IResourceDelta.LOCAL_CHANGED | IResourceDelta.CONTENT);
			try {
				path.toFile().createNewFile();
			} catch (IOException e) {
				fail("2.0", e);
			}
			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			if (path.toFile().exists()) {
				path.toFile().delete();
			}
		}
	}

	public void testRemoveAndCreateUnderlyingFolderForLinkedResource() {
		IPath path = getTempDir().addTrailingSeparator().append(getUniqueString());
		try {
			path.toFile().mkdir();
			IFolder linkedFolder = project1.getFolder(getUniqueString());
			linkedFolder.createLink(path, IResource.NONE, getMonitor());

			// check the delta when underlying folder is removed
			verifier.addExpectedChange(linkedFolder, IResourceDelta.CHANGED, IResourceDelta.LOCAL_CHANGED);
			path.toFile().delete();
			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			assertDelta();

			// check the delta when underlying folder is recreated
			verifier.addExpectedChange(linkedFolder, IResourceDelta.CHANGED, IResourceDelta.LOCAL_CHANGED);
			path.toFile().mkdir();
			project1.refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			if (path.toFile().exists()) {
				path.toFile().delete();
			}
		}
	}

	public void testBug228354() {
		IPath path = getTempDir().addTrailingSeparator().append(getUniqueString());
		try {
			path.toFile().mkdir();
			IFolder linkedFolder = project1.getFolder(getUniqueString());
			linkedFolder.createLink(path, IResource.NONE, getMonitor());

			IFolder regularFolder = project1.getFolder(getUniqueString());
			regularFolder.create(true, true, getMonitor());

			// check the delta when underlying folder is removed
			verifier.addExpectedChange(regularFolder, IResourceDelta.REMOVED, 0);
			regularFolder.delete(true, getMonitor());
			assertDelta();
		} catch (CoreException e) {
			handleCoreException(e);
		} finally {
			if (path.toFile().exists()) {
				path.toFile().delete();
			}
		}
	}
}