/*******************************************************************************
 *  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
 *     James Blackburn (Broadcom Corp.) - ongoing development
 *******************************************************************************/
package org.eclipse.core.tests.resources;

import java.io.*;
import java.io.File;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.watson.IPathRequestor;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;

public class MarkerTest extends ResourceTest {

	public static final String TRANSIENT_MARKER = "org.eclipse.core.tests.resources.transientmarker";
	public static final String TEST_PROBLEM_MARKER = "org.eclipse.core.tests.resources.testproblem";

	/** The collection of resources used for testing. */
	IResource[] resources;

	/**
	 * Need a zero argument constructor to satisfy the test harness.
	 * This constructor should not do any real work nor should it be
	 * called by user code.
	 */
	public MarkerTest() {
		super();
	}

	/**
	 * Creates a new markers test.
	 */
	public MarkerTest(String name) {
		super(name);
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerChangesInDelta3() {
		debug("TestMarkerChangesInDelta3");

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			IResource resource = getWorkspace().getRoot().findMember("1");
			IResource destinationResource = null;
			IResource child;
			IResource destinationChild;
			IPath destination;
			IMarker[] markers = new IMarker[4];

			// MOVE the resource
			try {
				destination = resource.getFullPath().removeLastSegments(1).append(resource.getFullPath().lastSegment() + "new");
				markers[0] = resource.createMarker(IMarker.BOOKMARK);
				child = ((IProject) resource).members()[0];
				markers[1] = child.createMarker(IMarker.TASK);
				listener.reset();
				resource.move(destination, false, getMonitor());
				destinationResource = getWorkspace().getRoot().findMember(destination);
				markers[2] = destinationResource.getMarker(markers[0].getId());
				destinationChild = ((IProject) destinationResource).findMember(child.getName());
				markers[3] = destinationChild.getMarker(markers[1].getId());
				assertEquals("1.1." + resource.getFullPath(), 4, listener.numAffectedResources());
				assertTrue("1.2." + resource.getFullPath(), listener.checkChanges(resource, null, new IMarker[] {markers[0]}, null));
				assertTrue("1.3." + resource.getFullPath(), listener.checkChanges(child, null, new IMarker[] {markers[1]}, null));
				assertTrue("1.4." + destinationResource.getFullPath(), listener.checkChanges(destinationResource, new IMarker[] {markers[2]}, null, null));
				assertTrue("1.5." + destinationResource.getFullPath(), listener.checkChanges(destinationChild, new IMarker[] {markers[3]}, null, null));
			} catch (CoreException e) {
				fail("1.99", e);
			}

			// COPY the resource and look at the deltas -
			// there should be no changes since markers are not copied
			try {
				resource = getWorkspace().getRoot().findMember("2");
				destination = resource.getFullPath().removeLastSegments(1).append(resource.getFullPath().lastSegment() + "copy");
				resource.createMarker(IMarker.BOOKMARK);
				listener.reset();
				resource.copy(destination, false, getMonitor());
				assertEquals("2.1." + resource.getFullPath(), 0, listener.numAffectedResources());
			} catch (CoreException e) {
				fail("2.99", e);
			}

			// delete all markers for a clean run next time
			try {
				getWorkspace().getRoot().deleteMarkers(null, true, IResource.DEPTH_INFINITE);
			} catch (CoreException e) {
				fail("99.99", e);
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	public void _testPerformanceManyResources() {
		debug("testPerformanceManyResources");
		long start;
		long stop;

		// cleanup old resources and create our own
		IResource[] testResources = null;
		try {
			getWorkspace().getRoot().delete(false, getMonitor());
			testResources = createLargeHierarchy();
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// header info
		final int markersPerResource = 20;
		final int numMarkers = testResources.length * markersPerResource;
		display("\nNumber of resources: " + testResources.length);
		display("Markers per resource: " + markersPerResource);
		display("Total Number of Markers: " + numMarkers);

		// Create an array with a bunch of markers.
		IWorkspaceRunnable body = monitor -> {
			IResourceVisitor visitor = resource -> {
				for (int i = 0; i < markersPerResource; i++)
					resource.createMarker(IMarker.PROBLEM);
				return true;
			};
			getWorkspace().getRoot().accept(visitor);
		};
		try {
			start = System.currentTimeMillis();
			getWorkspace().run(body, getMonitor());
			stop = System.currentTimeMillis();
			display("Task: creating markers");
			display(start, stop);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// gather the markers for use. don't time this one.
		final IMarker[] markers = new IMarker[numMarkers];
		try {
			IMarker[] temp = getWorkspace().getRoot().findMarkers(null, true, IResource.DEPTH_INFINITE);
			assertEquals("0.1", numMarkers, temp.length);
			for (int i = 0; i < temp.length; i++)
				markers[i] = temp[i];
		} catch (CoreException e) {
			fail("0.2", e);
		}

		// create attributes on each marker
		body = monitor -> {
			for (int i = 0; i < markers.length; i++)
				markers[i].setAttribute(IMarker.MESSAGE, getRandomString());
		};
		try {
			start = System.currentTimeMillis();
			getWorkspace().run(body, getMonitor());
			stop = System.currentTimeMillis();
			display("Task: setting an attribute on each marker");
			display(start, stop);
		} catch (CoreException e) {
			fail("1.0", e);
		}

		// get the attribute from each marker
		body = monitor -> {
			for (int i = 0; i < markers.length; i++)
				markers[i].getAttribute(IMarker.MESSAGE);
		};
		try {
			start = System.currentTimeMillis();
			getWorkspace().run(body, getMonitor());
			stop = System.currentTimeMillis();
			display("Task: getting an attribute on each marker");
			display(start, stop);
		} catch (CoreException e) {
			fail("2.0", e);
		}
	}

	public void _testPerformanceOneResource() {
		debug("testPerformanceOneResource");
		long start;
		long stop;
		final int numMarkers = 4000;

		// header info
		display("Number of resources: 1");
		display("Number of Markers: " + numMarkers);

		// Create an array with a bunch of markers.
		final IMarker markers[] = new IMarker[numMarkers];
		IWorkspaceRunnable body = monitor -> {
			IResource resource = getWorkspace().getRoot();
			for (int i = 0; i < markers.length; i++) {
				markers[i] = resource.createMarker(IMarker.PROBLEM);
			}
		};
		try {
			start = System.currentTimeMillis();
			getWorkspace().run(body, getMonitor());
			stop = System.currentTimeMillis();
			display("Task: creating markers");
			display(start, stop);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// create attributes on each marker
		body = monitor -> {
			for (int i = 0; i < markers.length; i++)
				markers[i].setAttribute(IMarker.MESSAGE, getRandomString());
		};
		try {
			start = System.currentTimeMillis();
			getWorkspace().run(body, getMonitor());
			stop = System.currentTimeMillis();
			display("Task: setting an attribute on each marker");
			display(start, stop);
		} catch (CoreException e) {
			fail("1.0", e);
		}

		java.util.Comparator<IMarker> c = (o1, o2) -> {
			try {
				String name1 = (String) o1.getAttribute(IMarker.MESSAGE);
				String name2 = (String) o2.getAttribute(IMarker.MESSAGE);
				if (name1 == null)
					name1 = "";
				if (name2 == null)
					name2 = "";
				int result = name1.compareToIgnoreCase(name2);
				return result;
			} catch (CoreException e) {
				fail("2.0", e);
			}
			// avoid compiler error
			return -1;
		};
		start = System.currentTimeMillis();
		Arrays.sort(markers, c);
		stop = System.currentTimeMillis();
		display("Task: sort arrays based on MESSAGE attribute");
		display(start, stop);
	}

	protected void addChildren(ArrayList<String> result, IPath root, int breadth, int depth) {
		for (int i = 1; i < breadth + 1; i++) {
			IPath child = root.append(i + "");
			if (depth == 0) {
				result.add(child.toString());
				return;
			}
			child = child.addTrailingSeparator();
			result.add(child.toString());
			addChildren(result, child, breadth, depth - 1);
		}
	}

	protected void assertDoesNotExist(String message, IMarker[] markers) {
		for (int i = 0; i < markers.length; i++)
			assertDoesNotExist(message, markers[i]);
	}

	protected void assertDoesNotExist(String message, IMarker marker) {
		assertTrue(message, !marker.exists());
	}

	/**
	 * Asserts that the given collection of expected markers contains
	 * the same markers as the given collection of actual markers.  The
	 * markers do not have to be in the same order.
	 */
	protected void assertEquals(String message, IMarker[] expectedMarkers, IMarker[] actualMarkers) {
		int n = expectedMarkers.length;
		if (n != actualMarkers.length)
			fail(message);
		boolean[] seen = new boolean[n];
		for (int i = 0; i < n; ++i) {
			boolean found = false;
			for (int j = 0; j < n; ++j) {
				if (!seen[j] && equals(expectedMarkers[i], actualMarkers[j])) {
					found = true;
					seen[j] = true;
					break;
				}
			}
			if (!found) {
				fail(message);
			}
		}
	}

	protected void assertEquals(String message, Map<String, ? extends Object> map, Object[] keys, Object[] values) {
		assertEquals(message, keys.length, values.length);
		assertEquals(message, keys.length, map.size());
		for (Map.Entry<String, ? extends Object> entry : map.entrySet()) {
			Object key = entry.getKey();
			Object value = entry.getValue();
			boolean found = false;
			for (int j = 0; !found && j < keys.length; j++) {
				if (keys[j].equals(key)) {
					found = true;
					if (!values[j].equals(value))
						fail(message);
				}
			}
			if (!found)
				assertTrue(message, false);
		}
	}

	protected void assertExists(String message, IMarker[] markers) {
		for (int i = 0; i < markers.length; i++)
			assertExists(message, markers[i]);
	}

	protected void assertExists(String message, IMarker marker) {
		assertTrue(message, marker.exists());
	}

	public IResource[] createLargeHierarchy() {
		ArrayList<String> result = new ArrayList<>();
		result.add("/");
		new MarkerTest().addChildren(result, Path.ROOT, 3, 4);
		String[] names = result.toArray(new String[result.size()]);
		IResource[] created = buildResources(getWorkspace().getRoot(), names);
		ensureExistsInWorkspace(created, true);
		return created;
	}

	protected IMarker[] createMarkers(final IResource[] hosts, final String type) throws CoreException {
		final IMarker[] result = new IMarker[hosts.length];
		getWorkspace().run((IWorkspaceRunnable) monitor -> {
			for (int i = 0; i < hosts.length; i++) {
				result[i] = hosts[i].createMarker(type);
			}
		}, getMonitor());
		return result;
	}

	public void createProblem(IResource host, int severity) {
		try {
			IMarker marker = host.createMarker(IMarker.PROBLEM);
			marker.setAttribute(IMarker.SEVERITY, severity);
		} catch (CoreException e) {
			fail("Failed to create problem on resource: " + host, e);
		}
	}

	/**
	 * Return a string array which defines the hierarchy of a tree.
	 * Folder resources must have a trailing slash.
	 */
	@Override
	public String[] defineHierarchy() {
		return new String[] {"/", "1/", "1/1", "1/2/", "1/2/1", "1/2/2/", "2/", "2/1", "2/2/", "2/2/1", "2/2/2/"};
	}

	public void display(long start, long stop) {
		display("Start: " + start);
		display("Stop: " + stop);
		display("Duration: " + (stop - start));
	}

	public void display(String message) {
		System.out.println(message);
	}

	/**
	 * Returns whether the given markers are equal.
	 */
	public static boolean equals(IMarker a, IMarker b) {
		try {
			if (a.getType() != b.getType())
				return false;
			if (a.getId() != b.getId())
				return false;
			return true;
		} catch (CoreException e) {
			return false;
		}
	}

	/**
	 * Returns whether two object are both null, or both non-null and equal.
	 */
	protected static boolean equalsOrNull(Object a, Object b) {
		return a == b || (a != null && b != null && a.equals(b));
	}

	@Override
	public void setUp() throws Exception {
		super.setUp();
		resources = createHierarchy();
	}

	/**
	 * Configures the markers test suite.
	 */
	public static Test suite() {
		return new TestSuite(MarkerTest.class);

		//		TestSuite suite = new TestSuite();
		//		suite.addTest(new MarkerTest("testMarkerChangesInDelta3"));
		//		return suite;
	}

	@Override
	public void tearDown() throws Exception {
		super.tearDown();
		try {
			getWorkspace().getRoot().delete(true, null);
		} catch (CoreException e) {
			fail("#tearDown", e);
		}
	}

	/**
	 * Tests whether markers correctly copy with resources.
	 */
	public void testCopyResource() {
		debug("TestCopyResource");
	}

	public void testCreateMarker() {
		debug("TestCreateMarker");

		// Create and register a listener.
		MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		// create markers on our hierarchy of resources
		for (int i = 0; i < resources.length; i++) {
			listener.reset();
			IResource resource = resources[i];
			IMarker[] markers = new IMarker[3];
			try {
				markers[0] = resource.createMarker(IMarker.PROBLEM);
				markers[1] = resource.createMarker(IMarker.BOOKMARK);
				markers[2] = resource.createMarker(IMarker.TASK);
				assertExists("1.0." + resource.getFullPath(), markers);
			} catch (CoreException e) {
				fail("1.1." + resource.getFullPath(), e);
			}
			assertEquals("1.2." + resource.getFullPath(), 1, listener.numAffectedResources());
			assertTrue("1.3." + resource.getFullPath(), listener.checkChanges(resource, markers, null, null));

			// expect an AssertionFailedException from a null type
			try {
				resource.createMarker(null);
				fail("2.0." + resource.getFullPath());
			} catch (CoreException e) {
				fail("2.1." + resource.getFullPath(), e);
			} catch (RuntimeException e) {
				// expected
			}
		}

		// try creating a marker on a resource which does't exist
		IResource testResource = getWorkspace().getRoot().getFile(new Path("non/existant/resource"));
		assertTrue("3.0", !testResource.exists());
		try {
			testResource.createMarker(IMarker.PROBLEM);
			fail("3.1");
		} catch (CoreException e) {
			// expected
		}

		// cleanup
		getWorkspace().removeResourceChangeListener(listener);
	}

	public void testCreationTime() {

		for (int i = 0; i < resources.length; i++) {
			IMarker marker = null;
			try {
				marker = resources[i].createMarker(IMarker.PROBLEM);
			} catch (CoreException e) {
				fail("0.0", e);
			}

			// make sure the marker has a non-zero creation time
			try {
				assertTrue("1.0." + i, 0 != marker.getCreationTime());
			} catch (CoreException e) {
				fail("1.1", e);
			}
		}
	}

	public void testDeleteMarker() {
		debug("TestDeleteMarker");
		IMarker marker = null;

		// Create and register a listener.
		MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		// for each resource in the hierarchy do...
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];

			// create the marker, assert that it exists, and then remove it
			try {
				listener.reset();
				marker = resource.createMarker(IMarker.PROBLEM);
				assertEquals("2.0." + resource.getFullPath(), 1, listener.numAffectedResources());
				assertTrue("2.1." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {marker}, null, null));
			} catch (CoreException e) {
				fail("2.2." + resource.getFullPath(), e);
			}
			assertExists("2.3." + resource.getFullPath(), marker);
			try {
				listener.reset();
				marker.delete();
				assertDoesNotExist("2.4." + resource.getFullPath(), marker);
				assertEquals("2.5." + resource.getFullPath(), 1, listener.numAffectedResources());
				assertTrue("2.6." + resource.getFullPath(), listener.checkChanges(resource, null, new IMarker[] {marker}, null));
			} catch (CoreException e) {
				fail("2.7." + resource.getFullPath(), e);
			}

			// Check that a non-existant marker can be removed
			try {
				marker.delete();
			} catch (CoreException e) {
				fail("3.0." + resource.getFullPath(), e);
			}

			// create multiple markers, assert they exist, and then remove them.
			IMarker[] markers = new IMarker[3];
			try {
				markers[0] = resource.createMarker(IMarker.BOOKMARK);
				assertExists("4.0." + resource.getFullPath(), markers[0]);
				markers[1] = resource.createMarker(IMarker.TASK);
				assertExists("4.1." + resource.getFullPath(), markers[1]);
				markers[2] = resource.createMarker(IMarker.PROBLEM);
				assertExists("4.2." + resource.getFullPath(), markers[2]);
			} catch (CoreException e) {
				fail("4.3." + resource.getFullPath(), e);
			}
			try {
				listener.reset();
				getWorkspace().deleteMarkers(markers);
				assertEquals("4.4." + resource.getFullPath(), 1, listener.numAffectedResources());
				assertTrue("4.5." + resource.getFullPath(), listener.checkChanges(resource, null, markers, null));
			} catch (CoreException e) {
				fail("4.6." + resource.getFullPath(), e);
			}
			assertDoesNotExist("4.7." + resource.getFullPath(), markers);
		}

		// cleanup
		getWorkspace().removeResourceChangeListener(listener);
	}

	public void testDeleteMarkers() {
		debug("TestDeleteMarkers");
		IMarker[] markers = null;
		try {
			markers = createMarkers(resources, IMarker.PROBLEM);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// Check that a collection of markers can be removed.
		try {
			getWorkspace().deleteMarkers(markers);
		} catch (CoreException e) {
			fail("1.0", e);
		}
		for (int i = 0; i < markers.length; i++)
			assertTrue("1.1", !markers[i].exists());

		// Check that an empty collection of markers can be removed.
		try {
			getWorkspace().deleteMarkers(new IMarker[0]);
		} catch (CoreException e) {
			fail("1.2", e);
		}
	}

	public void testFindMarkers() {
		debug("TestFindMarkers");

		// test finding some markers which actually exist
		IMarker[] markers = null;
		try {
			markers = createMarkers(resources, IMarker.PROBLEM);
		} catch (CoreException e) {
			fail("0.0", e);
		}
		try {
			IMarker[] found = getWorkspace().getRoot().findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE);
			assertEquals("1.0", markers, found);
		} catch (CoreException e) {
			fail("1.1", e);
		}
		try {
			IMarker[] found = getWorkspace().getRoot().findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
			assertEquals("1.2", markers, found);
		} catch (CoreException e) {
			fail("1.3", e);
		}

		// test finding some markers which don't exist
		try {
			IMarker[] found = getWorkspace().getRoot().findMarkers(IMarker.BOOKMARK, false, IResource.DEPTH_INFINITE);
			assertTrue("2.0", found.length == 0);
		} catch (CoreException e) {
			fail("2.1", e);
		}

		// add more markers and do a search on all marker types
		Vector<IMarker> allMarkers = new Vector<>(markers.length * 3);
		for (int i = 0; i < markers.length; i++)
			allMarkers.add(markers[i]);
		try {
			markers = createMarkers(resources, IMarker.BOOKMARK);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		for (int i = 0; i < markers.length; i++)
			allMarkers.add(markers[i]);
		try {
			markers = createMarkers(resources, IMarker.TASK);
		} catch (CoreException e) {
			fail("3.1", e);
		}
		for (int i = 0; i < markers.length; i++)
			allMarkers.add(markers[i]);
		try {
			IMarker[] found = getWorkspace().getRoot().findMarkers(null, false, IResource.DEPTH_INFINITE);
			assertEquals("3.2", allMarkers.toArray(new IMarker[allMarkers.size()]), found);
		} catch (CoreException e) {
			fail("3.3", e);
		}
		try {
			IMarker[] found = getWorkspace().getRoot().findMarkers(IMarker.MARKER, true, IResource.DEPTH_INFINITE);
			assertEquals("3.4", allMarkers.toArray(new IMarker[allMarkers.size()]), found);
		} catch (CoreException e) {
			fail("3.5", e);
		}
	}

	/*
	 * Bug 35300 - ClassCastException if marker transient attribute is set to a non-boolean
	 */
	public void test_35300() {
		IProject project = getWorkspace().getRoot().getProject(getUniqueString());
		ensureExistsInWorkspace(project, true);
		String MARKER_ID = "foomarker.example.com";
		IMarker marker = null;
		int expected = 4;

		// setup
		try {
			marker = project.createMarker(MARKER_ID);
			marker.setAttribute(IMarker.TRANSIENT, expected);
		} catch (CoreException e) {
			fail("1.0", e);
		} catch (Exception e) {
			fail("1.1", e);
		}

		try {
			int actual = marker.getAttribute(IMarker.TRANSIENT, -1);
			assertEquals("2.1", expected, actual);
			try {
				marker.setAttribute(IMarker.MESSAGE, getRandomString());
			} catch (CoreException e) {
				fail("2.2", e);
			}
		} catch (Exception e) {
			fail("2.3", e);
		}
	}

	public void test_10989() {
		debug("test_10989");

		try {
			IProject project = getWorkspace().getRoot().getProject("MyProject");
			project.create(null);
			project.open(null);
			IFile file = project.getFile("foo.txt");
			file.create(getRandomContents(), true, null);
			file.createMarker(IMarker.PROBLEM);
			IMarker[] found = file.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO);
			assertEquals("1.0", 1, found.length);
			found = file.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
			assertEquals("1.1", 1, found.length);
			project.delete(true, true, null);
		} catch (CoreException e) {
			fail("1.99", e);
		}
	}

	/*
	 * Bug 289811 - ArrayIndexOutOfBoundsException in MarkerAttributeMap
	 */
	public void test_289811() {
		debug("test_289811");

		IFile file = null;
		String testValue = getRandomString();
		try {
			IProject project = getWorkspace().getRoot().getProject(getUniqueString());
			project.create(null);
			project.open(null);
			file = project.getFile("foo.txt");
			file.create(getRandomContents(), true, null);
			IMarker marker = file.createMarker(IMarker.PROBLEM);
			marker.setAttributes(new HashMap<String, String>());
			marker.setAttribute(IMarker.SEVERITY, testValue);
			Object value = marker.getAttribute(IMarker.SEVERITY);
			assertEquals("1.0." + file.getFullPath(), value, testValue);
			project.delete(true, true, null);
		} catch (CoreException e) {
			fail("1.1." + file.getFullPath(), e);
		} catch (ArrayIndexOutOfBoundsException e) {
			fail("1.2." + file.getFullPath(), e);
		} catch (RuntimeException e) {
			fail("1.3." + file.getFullPath(), e);
		}
	}

	/**
	 * Tests public API method IResource#findMaxProblemSeverity
	 */
	public void testFindMaxProblemSeverity() throws CoreException {
		final IWorkspaceRoot root = getWorkspace().getRoot();
		IProject project = root.getProject("testFindMaxProblemSeverity");
		IFolder folder = project.getFolder("top");
		IFolder sub = folder.getFolder("sub");
		IFile topFile = folder.getFile("a.txt");
		IFile subFile = sub.getFile("b.txt");
		IResource[] allResources = new IResource[] {project, folder, sub, topFile, subFile};
		ensureExistsInWorkspace(allResources, true);

		assertEquals("1.0", -1, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("1.1", -1, root.findMaxProblemSeverity(IMarker.TASK, true, IResource.DEPTH_INFINITE));
		assertEquals("1.2", -1, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));

		createProblem(subFile, IMarker.SEVERITY_INFO);
		assertEquals("2.0", IMarker.SEVERITY_INFO, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("2.1", -1, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("2.2", -1, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));
		assertEquals("2.3", -1, root.findMaxProblemSeverity(IMarker.TASK, true, IResource.DEPTH_INFINITE));

		assertEquals("3.0", IMarker.SEVERITY_INFO, folder.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("3.1", -1, folder.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("3.2", -1, folder.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));
		assertEquals("3.3", -1, folder.findMaxProblemSeverity(IMarker.TASK, true, IResource.DEPTH_INFINITE));

		assertEquals("4.1", IMarker.SEVERITY_INFO, sub.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("4.2", IMarker.SEVERITY_INFO, sub.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("4.3", -1, sub.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));
		assertEquals("4.4", -1, sub.findMaxProblemSeverity(IMarker.TASK, true, IResource.DEPTH_INFINITE));

		assertEquals("5.1", IMarker.SEVERITY_INFO, subFile.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("5.2", IMarker.SEVERITY_INFO, subFile.findMaxProblemSeverity(IMarker.PROBLEM, false, IResource.DEPTH_ONE));
		assertEquals("5.3", IMarker.SEVERITY_INFO, subFile.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));
		assertEquals("5.4", -1, subFile.findMaxProblemSeverity(IMarker.TASK, true, IResource.DEPTH_INFINITE));

		createProblem(topFile, IMarker.SEVERITY_ERROR);
		assertEquals("6.1", IMarker.SEVERITY_ERROR, root.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE));
		assertEquals("6.2", IMarker.SEVERITY_ERROR, folder.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("6.3", IMarker.SEVERITY_ERROR, topFile.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("6.4", IMarker.SEVERITY_INFO, sub.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ONE));
		assertEquals("6.5", IMarker.SEVERITY_INFO, subFile.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO));

	}

	/**
	 * Tests public API method IMarker#isSubTypeOf
	 */
	public void testIsSubTypeOf() {
		IProject project = getWorkspace().getRoot().getProject("testisSubType");
		IMarker marker, task, problem, testProblem, invalid;

		final String INVALID_MARKER = "does.not.exist.at.AllMarker";

		try {
			ensureExistsInWorkspace(project, true);
			marker = project.createMarker(IMarker.MARKER);
			task = project.createMarker(IMarker.TASK);
			problem = project.createMarker(IMarker.PROBLEM);
			testProblem = project.createMarker(TEST_PROBLEM_MARKER);
			invalid = project.createMarker(INVALID_MARKER);

			assertTrue("1.0", marker.isSubtypeOf(IMarker.MARKER));
			assertTrue("1.1", !marker.isSubtypeOf(IMarker.TASK));
			assertTrue("1.2", !marker.isSubtypeOf(IMarker.PROBLEM));
			assertTrue("1.3", !marker.isSubtypeOf(TEST_PROBLEM_MARKER));
			assertTrue("1.4", !marker.isSubtypeOf(INVALID_MARKER));

			assertTrue("2.0", task.isSubtypeOf(IMarker.MARKER));
			assertTrue("2.1", task.isSubtypeOf(IMarker.TASK));
			assertTrue("2.2", !task.isSubtypeOf(IMarker.PROBLEM));
			assertTrue("2.3", !task.isSubtypeOf(TEST_PROBLEM_MARKER));
			assertTrue("2.4", !task.isSubtypeOf(INVALID_MARKER));

			assertTrue("3.0", problem.isSubtypeOf(IMarker.MARKER));
			assertTrue("3.1", !problem.isSubtypeOf(IMarker.TASK));
			assertTrue("3.2", problem.isSubtypeOf(IMarker.PROBLEM));
			assertTrue("3.3", !problem.isSubtypeOf(TEST_PROBLEM_MARKER));
			assertTrue("3.4", !problem.isSubtypeOf(INVALID_MARKER));

			assertTrue("4.0", testProblem.isSubtypeOf(IMarker.MARKER));
			assertTrue("4.1", !testProblem.isSubtypeOf(IMarker.TASK));
			assertTrue("4.2", testProblem.isSubtypeOf(IMarker.PROBLEM));
			assertTrue("4.3", testProblem.isSubtypeOf(TEST_PROBLEM_MARKER));
			assertTrue("4.4", !testProblem.isSubtypeOf(INVALID_MARKER));

			// behaviour with an undefined marker type is not specified, but
			// test current behaviour to give us advance warning of accidental
			// behavioural change
			assertTrue("5.0", !invalid.isSubtypeOf(IMarker.MARKER));
			assertTrue("5.1", !invalid.isSubtypeOf(IMarker.TASK));
			assertTrue("5.2", !invalid.isSubtypeOf(IMarker.PROBLEM));
			assertTrue("5.3", !invalid.isSubtypeOf(TEST_PROBLEM_MARKER));
			assertTrue("5.4", invalid.isSubtypeOf(INVALID_MARKER));

		} catch (CoreException e) {
			fail("1.99", e);
		}

	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerChangesInDelta() {
		debug("TestMarkerChangesInDelta");

		// Create and register a listener.
		MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			IResource resource;
			IMarker[] markers;
			IMarker marker;
			for (int i = 0; i < resources.length; i++) {
				resource = resources[i];
				markers = new IMarker[3];

				// ADD a marker
				listener.reset();
				try {
					markers[0] = resource.createMarker(IMarker.PROBLEM);
					assertExists("1.0." + resource.getFullPath(), markers[0]);
					assertEquals("1.1." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("1.2." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {markers[0]}, null, null));
				} catch (CoreException e) {
					fail("1.99." + resource.getFullPath(), e);
				}

				// ADD more markers to the same resource
				listener.reset();
				try {
					markers[1] = resource.createMarker(IMarker.BOOKMARK);
					markers[2] = resource.createMarker(IMarker.TASK);
					assertExists("2.0." + resource.getFullPath(), new IMarker[] {markers[1], markers[2]});
					assertEquals("2.1." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("2.2." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {markers[1], markers[2]}, null, null));
				} catch (CoreException e) {
					fail("2.99." + resource.getFullPath(), e);
				}

				// CHANGE a marker
				listener.reset();
				try {
					markers[0].setAttribute(IMarker.MESSAGE, "My text.");
					assertEquals("3.0." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("3.1." + resource.getFullPath(), listener.checkChanges(resource, null, null, new IMarker[] {markers[0]}));
				} catch (CoreException e) {
					fail("3.99." + resource.getFullPath(), e);
				}

				// CHANGE more markers
				listener.reset();
				try {
					markers[1].setAttribute(IMarker.SEVERITY, "Low");
					markers[2].setAttribute(IMarker.PRIORITY, "Normal");
					assertEquals("4.0." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("4.1." + resource.getFullPath(), listener.checkChanges(resource, null, null, new IMarker[] {markers[1], markers[2]}));
				} catch (CoreException e) {
					fail("4.99." + resource.getFullPath(), e);
				}

				// DELETE a marker
				listener.reset();
				try {
					markers[0].delete();
					assertDoesNotExist("5.0." + resource.getFullPath(), markers[0]);
					assertEquals("5.1." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("5.2." + resource.getFullPath(), listener.checkChanges(resource, null, new IMarker[] {markers[0]}, null));
				} catch (CoreException e) {
					fail("5.99." + resource.getFullPath(), e);
				}

				// DELETE more markers
				listener.reset();
				try {
					resource.deleteMarkers(null, false, IResource.DEPTH_ZERO);
					assertDoesNotExist("6.0." + resource.getFullPath(), new IMarker[] {markers[1], markers[2]});
					assertEquals("6.1." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("6.2." + resource.getFullPath(), listener.checkChanges(resource, null, new IMarker[] {markers[1], markers[2]}, null));
				} catch (CoreException e) {
					fail("6.99." + resource.getFullPath(), e);
				}

				// ADD, REMOVE and CHANGE markers
				try {
					markers[0] = resource.createMarker(IMarker.PROBLEM);
					markers[1] = resource.createMarker(IMarker.BOOKMARK);
					listener.reset();
					markers[0].delete();
					assertDoesNotExist("7.0." + resource.getFullPath(), markers[0]);
					markers[1].setAttribute(IMarker.MESSAGE, getRandomString());
					markers[2] = resource.createMarker(IMarker.TASK);
					assertEquals("7.1." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("7.2." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {markers[2]}, new IMarker[] {markers[0]}, new IMarker[] {markers[1]}));
				} catch (CoreException e) {
					fail("7.99." + resource.getFullPath(), e);
				}
			}

			// DELETE the resource and see what the marker delta is
			try {
				resource = getWorkspace().getRoot();
				resource.deleteMarkers(null, true, IResource.DEPTH_INFINITE);
				marker = resource.createMarker(IMarker.BOOKMARK);
				listener.reset();
				resource.delete(true, getMonitor());
				assertDoesNotExist("8.0", marker);
				assertTrue("8.1", listener.checkChanges(resource, null, new IMarker[] {marker}, null));
			} catch (CoreException e) {
				fail("8.99", e);
			}

		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 * Particularly, checks that the MarkerDelta attributes reflect the
	 * state of the marker before the change occurred.
	 */
	public void testMarkerDeltaAttributes() {
		debug("testMarkerDeltaAttributes");

		// create markers on various resources
		final IMarker[] markers = new IMarker[3];
		IWorkspaceRunnable body = monitor -> {
			markers[0] = resources[0].createMarker(IMarker.BOOKMARK);
			markers[1] = resources[1].createMarker(IMarker.BOOKMARK);
			markers[1].setAttribute(IMarker.CHAR_START, 5);
			markers[2] = resources[2].createMarker(IMarker.PROBLEM);
			markers[2].setAttribute(IMarker.DONE, true);
			markers[2].setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
			markers[2].setAttribute(IMarker.MESSAGE, "Hello");
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("0.99", e);
		}

		//create the attribute change listener
		MarkerAttributeChangeListener listener = new MarkerAttributeChangeListener();
		getWorkspace().addResourceChangeListener(listener);
		try {
			//add a new attribute
			listener.expectChanges(markers[0]);
			markers[0].setAttribute(IMarker.MESSAGE, "Message");
			listener.verifyChanges();

			//change an attribute
			listener.expectChanges(markers[0]);
			markers[0].setAttribute(IMarker.MESSAGE, "NewMessage");
			listener.verifyChanges();

			//remove an attribute
			listener.expectChanges(markers[0]);
			markers[0].setAttribute(IMarker.MESSAGE, null);
			listener.verifyChanges();

			//add attribute to marker that already has attributes
			listener.expectChanges(markers[2]);
			markers[2].setAttribute(IMarker.CHAR_END, 5);
			listener.verifyChanges();

			//add+change
			listener.expectChanges(markers[1]);
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				markers[1].setAttribute(IMarker.CHAR_START, 5);
				markers[1].setAttribute(IMarker.CHAR_END, 10);
			}, getMonitor());
			listener.verifyChanges();

			//change+remove same marker
			listener.expectChanges(markers[1]);
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				markers[1].setAttribute(IMarker.CHAR_START, 5);
				markers[1].setAttribute(IMarker.CHAR_START, null);
			}, getMonitor());
			listener.verifyChanges();

			//change multiple markers
			listener.expectChanges(markers);
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				markers[0].setAttribute(IMarker.CHAR_START, 5);
				markers[1].setAttribute(IMarker.CHAR_START, 10);
				markers[2].setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_LOW);
			}, getMonitor());
			listener.verifyChanges();
		} catch (CoreException e) {
			fail("1.99", e);
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerDeltasCopyResource() {
		debug("testMarkerDeltasCopyResource");

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			// create markers on all the non-project resources
			final Hashtable<IResource, IMarker> table = new Hashtable<>(1);
			final int[] count = new int[1];
			count[0] = 0;
			IWorkspaceRunnable body = monitor -> {
				IResourceVisitor visitor = resource -> {
					if (resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT)
						return true;
					IMarker marker = resource.createMarker(IMarker.BOOKMARK);
					table.put(resource, marker);
					count[0]++;
					return true;
				};
				getWorkspace().getRoot().accept(visitor);
			};
			try {
				getWorkspace().run(body, getMonitor());
			} catch (CoreException e) {
				fail("0.99", e);
			}
			listener.reset();

			// copy all non-project resources
			try {
				IProject[] projects = getWorkspace().getRoot().getProjects();
				for (int i = 0; i < projects.length; i++) {
					IResource[] children = projects[i].members();
					for (int j = 0; j < children.length; j++) {
						IPath destination = new Path(children[j].getName() + "copy");
						children[j].copy(destination, true, getMonitor());
					}
				}
			} catch (CoreException e) {
				fail("1.99", e);
			}

			// TODO
			// verify marker deltas
			//		IResourceVisitor visitor = new IResourceVisitor() {
			//			public boolean visit(IResource resource) throws CoreException {
			//				if (resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT)
			//					return true;
			//				if (!resource.getName().endsWith("copy"))
			//					return false;
			//				String name = resource.getFullPath().segment(0);
			//				IPath path = new Path(name.substring(0, name.length() - 4)).makeAbsolute();
			//				path = path.append(resource.getFullPath().removeFirstSegments(1));
			//				IResource oldResource = ((Workspace) getWorkspace()).newResource(path, resource.getType());
			//				IMarker marker = (IMarker) table.get(oldResource);
			//				assertNotNull("2.1." + oldResource.getFullPath(), marker);
			//				IMarker[] markers = resource.findMarkers(null, true, IResource.DEPTH_ZERO);
			//				assertEquals("2.2." + resource.getFullPath(), 1, markers.length);
			//				assertEquals("2.3." + resource.getFullPath(), marker.getId(), markers[0].getId());
			//				assertTrue("2.4." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] { markers[0] }, null, null));
			//				return true;
			//			}
			//		};
			// marker deltas should not appear after a resource copy
			//assertEquals("2.5", count[0], listener.numAffectedResources());
			assertEquals("2.5", 0, listener.numAffectedResources());
			//try {
			//getWorkspace().getRoot().accept(visitor);
			//} catch (CoreException e) {
			//fail("2.99", e);
			//}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerDeltasMerge() {
		debug("testMarkerDeltasMerge");

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			for (int i = 0; i < resources.length; i++) {
				final IResource resource = resources[i];

				// ADD + REMOVE = nothing
				try {
					IWorkspaceRunnable body = monitor -> {
						listener.reset();
						IMarker marker = resource.createMarker(IMarker.PROBLEM);
						assertExists("1.0." + resource.getFullPath(), marker);
						marker.delete();
						assertDoesNotExist("1.1." + resource.getFullPath(), marker);
					};
					getWorkspace().run(body, getMonitor());
					assertEquals("1.2." + resource.getFullPath(), 0, listener.numAffectedResources());
					assertTrue("1.3." + resource.getFullPath(), listener.checkChanges(resource, null, null, null));
				} catch (CoreException e) {
					fail("1.99." + resource.getFullPath(), e);
				}

				// ADD + CHANGE = ADD
				try {
					// cannot re-assign variable value within the code below, so must
					// put our marker value inside an array and set the element.
					final IMarker[] markers = new IMarker[1];
					IWorkspaceRunnable body = monitor -> {
						listener.reset();
						markers[0] = resource.createMarker(IMarker.PROBLEM);
						assertExists("2.0." + resource.getFullPath(), markers[0]);
						markers[0].setAttribute(IMarker.MESSAGE, "my message text");
						assertEquals("2.1." + resource.getFullPath(), "my message text", markers[0].getAttribute(IMarker.MESSAGE));
					};
					getWorkspace().run(body, getMonitor());
					assertEquals("2.2." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("2.3." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {markers[0]}, null, null));
				} catch (CoreException e) {
					fail("2.99." + resource.getFullPath(), e);
				}

				// TODO
				// REMOVE + ADD = CHANGE
				//try {
				//final IMarker[] markers = new IMarker[1];
				//markers[0] = resource.createMarker(IMarker.PROBLEM);
				//assertExists("3.0." + resource.getFullPath(), markers[0]);
				//IWorkspaceRunnable body = new IWorkspaceRunnable() {
				//public void run(IProgressMonitor monitor) throws CoreException {
				//listener.reset();
				//markers[0].delete();
				//assertDoesNotExist("3.1." + resource.getFullPath(), markers[0]);
				//markers[0] = resource.createMarker(IMarker.PROBLEM);
				//assertExists("3.2." + resource.getFullPath(), markers[0]);
				//}
				//};
				//getWorkspace().run(body, getMonitor());
				//assertEquals("3.3." + resource.getFullPath(), 1, listener.numAffectedResources());
				//assert("3.4." + resource.getFullPath(), listener.checkChanges(resource, null, null, new IMarker[] { markers[0] }));
				//} catch (CoreException e) {
				//fail("3.99." + resource.getFullPath(), e);
				//}

				// CHANGE + CHANGE = CHANGE
				try {
					final IMarker[] markers = new IMarker[1];
					markers[0] = resource.createMarker(IMarker.PROBLEM);
					assertExists("4.0." + resource.getFullPath(), markers[0]);
					IWorkspaceRunnable body = monitor -> {
						listener.reset();
						markers[0].setAttribute(IMarker.MESSAGE, "my message text");
						assertEquals("4.1." + resource.getFullPath(), "my message text", markers[0].getAttribute(IMarker.MESSAGE));
						markers[0].setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
						assertEquals("4.2." + resource.getFullPath(), IMarker.PRIORITY_HIGH, ((Integer) markers[0].getAttribute(IMarker.PRIORITY)).intValue());
					};
					getWorkspace().run(body, getMonitor());
					assertEquals("4.3." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("4.4." + resource.getFullPath(), listener.checkChanges(resource, null, null, new IMarker[] {markers[0]}));
				} catch (CoreException e) {
					fail("4.99." + resource.getFullPath(), e);
				}

				// CHANGE + REMOVE = REMOVE
				try {
					final IMarker[] markers = new IMarker[1];
					markers[0] = resource.createMarker(IMarker.PROBLEM);
					assertExists("5.0." + resource.getFullPath(), markers[0]);
					IWorkspaceRunnable body = monitor -> {
						listener.reset();
						markers[0].setAttribute(IMarker.MESSAGE, "my message text");
						assertEquals("5.1." + resource.getFullPath(), "my message text", markers[0].getAttribute(IMarker.MESSAGE));
						markers[0].delete();
						assertDoesNotExist("5.2." + resource.getFullPath(), markers[0]);
					};
					getWorkspace().run(body, getMonitor());
					assertEquals("5.3." + resource.getFullPath(), 1, listener.numAffectedResources());
					assertTrue("5.4." + resource.getFullPath(), listener.checkChanges(resource, null, new IMarker[] {markers[0]}, null));
				} catch (CoreException e) {
					fail("5.99." + resource.getFullPath(), e);
				}

				// cleanup after each iteration
				try {
					resource.deleteMarkers(null, true, IResource.DEPTH_ZERO);
				} catch (CoreException e) {
					fail("99.99", e);
				}
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerDeltasMoveFolder() {
		debug("testMarkerDeltasMoveFolder");

		IWorkspaceRoot root = getWorkspace().getRoot();
		final IProject project = root.getProject("MyProject");
		IFolder folder = project.getFolder("folder");
		IFile file = project.getFile("file.txt");
		IFile subFile = folder.getFile("subFile.txt");
		ensureExistsInWorkspace(new IResource[] {project, folder, file, subFile}, true);
		IFolder destFolder = project.getFolder("myOtherFolder");
		IFile destSubFile = destFolder.getFile(subFile.getName());
		IMarker folderMarker = null;
		IMarker subFileMarker = null;
		IMarker[] markers = null;

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			// create markers on the resources
			try {
				folderMarker = folder.createMarker(IMarker.BOOKMARK);
			} catch (CoreException e) {
				fail("1.0", e);
			}
			try {
				subFileMarker = subFile.createMarker(IMarker.BOOKMARK);
			} catch (CoreException e) {
				fail("1.1", e);
			}
			listener.reset();

			// move the files
			try {
				folder.move(destFolder.getFullPath(), IResource.FORCE, getMonitor());
			} catch (CoreException e) {
				fail("2.0", e);
			}

			// verify marker deltas
			assertTrue("3.1", listener.checkChanges(folder, null, new IMarker[] {folderMarker}, null));
			try {
				markers = destFolder.findMarkers(null, true, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				fail("3.2", e);
			}
			assertEquals("3.3", 1, markers.length);
			assertEquals("3.4", folderMarker.getId(), markers[0].getId());
			assertTrue("3.5", listener.checkChanges(destFolder, new IMarker[] {markers[0]}, null, null));

			assertTrue("3.7", listener.checkChanges(subFile, null, new IMarker[] {subFileMarker}, null));
			try {
				markers = destSubFile.findMarkers(null, true, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				fail("3.8", e);
			}
			assertEquals("3.9", 1, markers.length);
			assertEquals("3.10", subFileMarker.getId(), markers[0].getId());
			assertTrue("3.11", listener.checkChanges(destSubFile, new IMarker[] {markers[0]}, null, null));

		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerDeltasMoveFile() {
		debug("testMarkerDeltasMoveFile");
		IWorkspaceRoot root = getWorkspace().getRoot();
		final IProject project = root.getProject("MyProject");
		IFolder folder = project.getFolder("folder");
		IFile file = project.getFile("file.txt");
		IFile subFile = folder.getFile("subFile.txt");
		ensureExistsInWorkspace(new IResource[] {project, folder, file, subFile}, true);
		IFile destFile = folder.getFile(file.getName());
		IFile destSubFile = project.getFile(subFile.getName());
		IMarker fileMarker = null;
		IMarker subFileMarker = null;
		IMarker[] markers = null;

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			// create markers on the resources
			try {
				fileMarker = file.createMarker(IMarker.BOOKMARK);
			} catch (CoreException e) {
				fail("1.0", e);
			}
			try {
				subFileMarker = subFile.createMarker(IMarker.BOOKMARK);
			} catch (CoreException e) {
				fail("1.1", e);
			}
			listener.reset();

			// move the files
			try {
				file.move(destFile.getFullPath(), IResource.FORCE, getMonitor());
				subFile.move(destSubFile.getFullPath(), IResource.FORCE, getMonitor());
			} catch (CoreException e) {
				fail("2.0", e);
			}

			// verify marker deltas
			assertTrue("3.1", listener.checkChanges(file, null, new IMarker[] {fileMarker}, null));
			try {
				markers = destFile.findMarkers(null, true, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				fail("3.2", e);
			}
			assertEquals("3.3", 1, markers.length);
			assertEquals("3.4", fileMarker.getId(), markers[0].getId());
			assertTrue("3.5", listener.checkChanges(destFile, new IMarker[] {markers[0]}, null, null));

			assertTrue("3.7", listener.checkChanges(subFile, null, new IMarker[] {subFileMarker}, null));
			try {
				markers = destSubFile.findMarkers(null, true, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				fail("3.8", e);
			}
			assertEquals("3.9", 1, markers.length);
			assertEquals("3.10", subFileMarker.getId(), markers[0].getId());
			assertTrue("3.11", listener.checkChanges(destSubFile, new IMarker[] {markers[0]}, null, null));

		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the appearance of marker changes in the resource delta.
	 */
	public void testMarkerDeltasMoveProject() {
		debug("testMarkerDeltasMoveProject");

		// Create and register a listener.
		final MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		try {
			// create markers on all the resources
			final Hashtable<IResource, IMarker> table = new Hashtable<>(1);
			final int[] count = new int[1];
			count[0] = 0;
			IWorkspaceRunnable body = monitor -> {
				IResourceVisitor visitor = resource -> {
					if (resource.getType() == IResource.ROOT)
						return true;
					IMarker marker = resource.createMarker(IMarker.BOOKMARK);
					table.put(resource, marker);
					count[0]++;
					return true;
				};
				getWorkspace().getRoot().accept(visitor);
			};
			try {
				getWorkspace().run(body, getMonitor());
			} catch (CoreException e) {
				fail("0.99", e);
			}
			listener.reset();

			// move all resources
			IProject[] projects = getWorkspace().getRoot().getProjects();
			for (int i = 0; i < projects.length; i++) {
				IPath destination = new Path(projects[i].getName() + "move");
				try {
					projects[i].move(destination, true, getMonitor());
				} catch (CoreException e) {
					fail("1.99", e);
				}
			}

			// verify marker deltas
			IResourceVisitor visitor = resource -> {
				if (resource.getType() == IResource.ROOT)
					return true;
				String name = resource.getFullPath().segment(0);
				IPath path = new Path(name.substring(0, name.length() - 4)).makeAbsolute();
				path = path.append(resource.getFullPath().removeFirstSegments(1));
				IResource oldResource = ((Workspace) getWorkspace()).newResource(path, resource.getType());
				IMarker marker = table.get(oldResource);
				assertNotNull("2.1." + oldResource.getFullPath(), marker);
				assertTrue("2.2." + oldResource.getFullPath(), listener.checkChanges(oldResource, null, new IMarker[] {marker}, null));
				IMarker[] markers = resource.findMarkers(null, true, IResource.DEPTH_ZERO);
				assertEquals("2.3." + resource.getFullPath(), 1, markers.length);
				assertEquals("2.4." + resource.getFullPath(), marker.getId(), markers[0].getId());
				assertTrue("2.5." + resource.getFullPath(), listener.checkChanges(resource, new IMarker[] {markers[0]}, null, null));
				return true;
			};
			assertEquals("2.6", count[0] * 2, listener.numAffectedResources());
			try {
				getWorkspace().getRoot().accept(visitor);
			} catch (CoreException e) {
				fail("2.99", e);
			}
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	public void testMarkerSave() {
		debug("TestMarkerSave");

		IMarker[] newMarkers = null;
		IMarker[] expected = null;
		try {
			newMarkers = createMarkers(resources, IMarker.PROBLEM);
			expected = new IMarker[newMarkers.length * 3];
			for (int i = 0; i < newMarkers.length; i++)
				expected[i] = newMarkers[i];
			newMarkers = createMarkers(resources, IMarker.BOOKMARK);
			for (int i = 0; i < newMarkers.length; i++)
				expected[i + newMarkers.length] = newMarkers[i];
			newMarkers = createMarkers(resources, IMarker.TASK);
			for (int i = 0; i < newMarkers.length; i++)
				expected[i + (newMarkers.length * 2)] = newMarkers[i];
		} catch (CoreException e) {
			fail("1.0", e);
		}

		final MarkerManager manager = ((Workspace) getWorkspace()).getMarkerManager();

		// write all the markers to the output stream
		File file = Platform.getLocation().append(".testmarkers").toFile();
		OutputStream fileOutput = null;
		DataOutputStream o1 = null;
		try {
			fileOutput = new FileOutputStream(file);
			o1 = new DataOutputStream(fileOutput);
		} catch (FileNotFoundException e) {
			fail("2.0", e);
		}
		final DataOutputStream output = o1;
		final List<String> list = new ArrayList<>(5);
		IResourceVisitor visitor = resource -> {
			try {
				ResourceInfo info = ((Resource) resource).getResourceInfo(false, false);
				if (info == null)
					return true;
				IPathRequestor requestor = new IPathRequestor() {
					@Override
					public IPath requestPath() {
						return resource.getFullPath();
					}

					@Override
					public String requestName() {
						return resource.getName();
					}
				};
				manager.save(info, requestor, output, list);
			} catch (IOException e) {
				fail("2.1", e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("2.2", e);
		} finally {
			try {
				output.close();
			} catch (IOException e) {
				fail("2.3", e);
			}
		}

		// delete all markers resources
		try {
			getWorkspace().getRoot().deleteMarkers(null, true, IResource.DEPTH_INFINITE);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertDoesNotExist("3.1", expected);

		// read in the markers from the file
		try {
			InputStream fileInput = new FileInputStream(file);
			final DataInputStream input = new DataInputStream(fileInput);
			IWorkspaceRunnable body = monitor -> {
				MarkerReader reader = new MarkerReader((Workspace) getWorkspace());
				try {
					reader.read(input, true);
				} catch (IOException e) {
					fail("4.0", e);
				}
			};
			try {
				getWorkspace().run(body, getMonitor());
			} finally {
				try {
					input.close();
				} catch (IOException e) {
					fail("4.1", e);
				}
			}
		} catch (FileNotFoundException e) {
			fail("4.2", e);
		} catch (CoreException e) {
			fail("4.3", e);
		}

		// assert that the markers retrieved are the same as the ones we used
		// to have
		try {
			assertExists("5.0", expected);
			IMarker[] actual = getWorkspace().getRoot().findMarkers(null, false, IResource.DEPTH_INFINITE);
			assertEquals("5.1", expected, actual);
		} catch (CoreException e) {
			fail("5.2", e);
		}

		// cleanup
		assertTrue("6.0", file.delete());
	}

	public void testMarkerSaveTransient() {
		debug("TestMarkerSaveTransient");

		// create the markers on the resources. create both transient
		// and persistent markers.
		final ArrayList<IMarker> persistentMarkers = new ArrayList<>();
		IResourceVisitor visitor = resource -> {
			IMarker marker = resource.createMarker(IMarker.PROBLEM);
			persistentMarkers.add(marker);
			marker = resource.createMarker(IMarker.BOOKMARK);
			persistentMarkers.add(marker);
			marker = resource.createMarker(TRANSIENT_MARKER);
			// create a transient marker of a persistent type
			marker = resource.createMarker(IMarker.BOOKMARK);
			marker.setAttribute(IMarker.TRANSIENT, Boolean.TRUE);
			// create a marker of a persistent type and set TRANSIENT as false (should be persisted)
			marker = resource.createMarker(IMarker.BOOKMARK);
			marker.setAttribute(IMarker.TRANSIENT, Boolean.FALSE);
			persistentMarkers.add(marker);
			// create a marker of a transient type and set TRANSIENT to false (should NOT be persisted)
			marker = resource.createMarker(TRANSIENT_MARKER);
			marker.setAttribute(IMarker.TRANSIENT, Boolean.FALSE);
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("1.0", e);
		}

		final MarkerManager manager = ((Workspace) getWorkspace()).getMarkerManager();
		IMarker[] expected = persistentMarkers.toArray(new IMarker[persistentMarkers.size()]);

		// write all the markers to the output stream
		File file = Platform.getLocation().append(".testmarkers").toFile();
		OutputStream fileOutput = null;
		DataOutputStream o1 = null;
		try {
			fileOutput = new FileOutputStream(file);
			o1 = new DataOutputStream(fileOutput);
		} catch (FileNotFoundException e) {
			fail("2.0", e);
		}
		final DataOutputStream output = o1;
		final List<String> list = new ArrayList<>(5);
		visitor = resource -> {
			try {
				ResourceInfo info = ((Resource) resource).getResourceInfo(false, false);
				if (info == null)
					return true;
				IPathRequestor requestor = new IPathRequestor() {
					@Override
					public IPath requestPath() {
						return resource.getFullPath();
					}

					@Override
					public String requestName() {
						return resource.getName();
					}
				};
				manager.save(info, requestor, output, list);
			} catch (IOException e) {
				fail("2.1", e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("2.2", e);
		} finally {
			try {
				output.close();
			} catch (IOException e) {
				fail("2.3", e);
			}
		}

		// delete all markers resources
		try {
			getWorkspace().getRoot().deleteMarkers(null, true, IResource.DEPTH_INFINITE);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		assertDoesNotExist("3.1", expected);

		// read in the markers from the file
		try {
			InputStream fileInput = new FileInputStream(file);
			final DataInputStream input = new DataInputStream(fileInput);
			IWorkspaceRunnable body = monitor -> {
				MarkerReader reader = new MarkerReader((Workspace) getWorkspace());
				try {
					reader.read(input, true);
				} catch (IOException e) {
					fail("4.0", e);
				}
			};
			try {
				getWorkspace().run(body, getMonitor());
			} finally {
				try {
					input.close();
				} catch (IOException e) {
					fail("4.1", e);
				}
			}
		} catch (FileNotFoundException e) {
			fail("4.2", e);
		} catch (CoreException e) {
			fail("4.3", e);
		}

		// assert that the markers retrieved are the same as the ones we used
		// to have
		try {
			assertExists("5.0", expected);
			IMarker[] actual = getWorkspace().getRoot().findMarkers(null, false, IResource.DEPTH_INFINITE);
			assertEquals("5.1", expected, actual);
		} catch (CoreException e) {
			fail("5.2", e);
		}

		// cleanup
		assertTrue("6.0", file.delete());
	}

	/**
	 * Tests whether markers correctly move with resources.
	 */
	public void testMoveResource() {
		debug("TestMoveResource");
	}

	/*
	 * Test for PR: "1FWT3V5: ITPCORE:WINNT - Task view shows entries for closed projects"
	 */
	public void testProjectCloseOpen() {
		debug("testProjectCloseOpen");
		IProject project = null;
		IMarker marker = null;

		// create a marker on the project
		project = getWorkspace().getRoot().getProjects()[0];
		try {
			marker = project.createMarker(IMarker.BOOKMARK);
		} catch (CoreException e) {
			fail("1.0", e);
		}

		// ensure that the marker was created
		assertTrue("2.0", marker.exists());

		// close the project
		try {
			project.close(getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}

		// now the marker should be inaccessible
		assertTrue("", !marker.exists());

		// open the project
		try {
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("4.0", e);
		}

		// the marker re-appears
		assertTrue("5.0", marker.exists());
	}

	public void testSetGetAttribute() {
		debug("testSetGetAttribute");

		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			IMarker marker = null;

			// getting a non-existant attribute should return null
			try {
				marker = resource.createMarker(IMarker.PROBLEM);
			} catch (CoreException e) {
				fail("1.0", e);
			}
			try {
				assertNull("1.1." + resource.getFullPath(), marker.getAttribute(IMarker.MESSAGE));
			} catch (CoreException e) {
				fail("1.2." + resource.getFullPath(), e);
			}

			// set an attribute, get its value, then remove it
			String testMessage = getRandomString();
			try {
				marker.setAttribute(IMarker.MESSAGE, testMessage);
				Object value = marker.getAttribute(IMarker.MESSAGE);
				assertEquals("2.0." + resource.getFullPath(), testMessage, (String) value);
				marker.setAttribute(IMarker.MESSAGE, null);
				value = marker.getAttribute(IMarker.MESSAGE);
				assertNull("2.1." + resource.getFullPath(), value);
			} catch (CoreException e) {
				fail("2.2." + resource.getFullPath(), e);
			}

			// set more attributes, get their values, then remove one
			try {
				String[] keys = new String[] {IMarker.LOCATION, IMarker.SEVERITY, IMarker.DONE};
				Object[] values = new Object[3];
				values[0] = getRandomString();
				values[1] = Integer.valueOf(5);
				values[2] = Boolean.FALSE;
				marker.setAttributes(keys, values);
				Object[] found = marker.getAttributes(keys);
				assertEquals("3.0." + resource.getFullPath(), values, found);
				marker.setAttribute(IMarker.SEVERITY, null);
				values[1] = null;
				found = marker.getAttributes(keys);
				assertEquals("3.1." + resource.getFullPath(), values, found);
				values[1] = Integer.valueOf(5);
				marker.setAttribute(IMarker.SEVERITY, values[1]);
				Map<String, ? extends Object> all = marker.getAttributes();
				assertEquals("3.2." + resource.getFullPath(), all, keys, values);
			} catch (CoreException e) {
				fail("3.2." + resource.getFullPath(), e);
			}

			// try sending null as args
			try {
				marker.getAttribute(null);
				fail("4.0");
			} catch (CoreException e) {
				fail("4.1." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.2", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				marker.getAttributes(null);
				fail("4.3");
			} catch (CoreException e) {
				fail("4.4." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.5", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				marker.setAttribute(null, getRandomString());
				fail("4.6");
			} catch (CoreException e) {
				fail("4.7." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.8", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				marker.setAttributes(null, new String[] {getRandomString()});
				fail("4.9");
			} catch (CoreException e) {
				fail("4.10." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.11", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				marker.setAttributes(new String[] {IMarker.MESSAGE}, null);
				fail("4.12");
			} catch (CoreException e) {
				fail("4.13." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.14", e);
			} catch (RuntimeException e) {
				// expected
			}
			//set attributes on deleted marker
			try {
				marker.delete();
			} catch (CoreException e) {
				fail("5.0", e);
			}
			try {
				marker.setAttribute(IMarker.MESSAGE, "Hello");
				fail("5.1");
			} catch (CoreException e) {
				// expected
			}
			try {
				marker.setAttributes(new String[] {IMarker.LINE_NUMBER}, new Object[] {Integer.valueOf(4)});
				fail("5.2");
			} catch (CoreException e) {
				// expected
			}
			try {
				HashMap<String, String> attributes = new HashMap<>();
				attributes.put(IMarker.MESSAGE, "Hello");
				marker.setAttributes(attributes);
				fail("5.3");
			} catch (CoreException e) {
				// expected
			}
		}
	}

	public void testSetGetAttribute2() {
		debug("testSetGetAttribute2");

		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			IMarker marker = null;

			// getting a non-existant attribute should return null or the specified default
			try {
				marker = resource.createMarker(IMarker.PROBLEM);
			} catch (CoreException e) {
				fail("0.0" + resource.getFullPath(), e);
			}
			try {
				// #getAttribute(Object)
				assertNull("1.0." + resource.getFullPath(), marker.getAttribute(IMarker.MESSAGE));
				// #getAttribute(String, String)
				assertEquals("1.1." + resource.getFullPath(), "default", marker.getAttribute(IMarker.MESSAGE, "default"));
				// #getAttribute(String, boolean)
				assertEquals("1.2." + resource.getFullPath(), true, marker.getAttribute(IMarker.MESSAGE, true));
				// #getAttribute(String, int)
				assertEquals("1.3." + resource.getFullPath(), 5, marker.getAttribute(IMarker.MESSAGE, 5));
				// #getAttributes()
				assertNull("1.4." + resource.getFullPath(), marker.getAttributes());
				// #getAttributes(String[])
				assertTrue("1.5." + resource.getFullPath(), marker.getAttributes(new String[] {IMarker.MESSAGE})[0] == null);
			} catch (CoreException e) {
				fail("1.99." + resource.getFullPath(), e);
			}

			// set an attribute, get its value, then remove it
			String testMessage = getRandomString();
			try {
				marker.setAttribute(IMarker.MESSAGE, testMessage);
				Object value = marker.getAttribute(IMarker.MESSAGE);
				assertEquals("2.0." + resource.getFullPath(), testMessage, (String) value);
				marker.setAttribute(IMarker.MESSAGE, null);
				value = marker.getAttribute(IMarker.MESSAGE);
				assertNull("2.1." + resource.getFullPath(), value);
			} catch (CoreException e) {
				fail("2.2." + resource.getFullPath(), e);
			}

			// set more attributes, get their values, then remove one
			try {
				String[] keys = new String[] {IMarker.LOCATION, IMarker.SEVERITY, IMarker.DONE};
				Object[] values = new Object[3];
				values[0] = getRandomString();
				values[1] = Integer.valueOf(5);
				values[2] = Boolean.FALSE;
				marker.setAttributes(keys, values);
				Object[] found = marker.getAttributes(keys);
				assertEquals("3.0." + resource.getFullPath(), values, found);
				marker.setAttribute(IMarker.SEVERITY, null);
				values[1] = null;
				found = marker.getAttributes(keys);
				assertEquals("3.1." + resource.getFullPath(), values, found);
				values[1] = Integer.valueOf(5);
				marker.setAttribute(IMarker.SEVERITY, values[1]);
				Map<String, ? extends Object> all = marker.getAttributes();
				assertEquals("3.2." + resource.getFullPath(), all, keys, values);
			} catch (CoreException e) {
				fail("3.2." + resource.getFullPath(), e);
			}

			// try sending null as args
			try {
				// #getAttribute(String)
				marker.getAttribute(null);
				fail("4.0");
			} catch (CoreException e) {
				fail("4.1." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.2", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #getAttribute(String, String)
				marker.getAttribute(null, "default");
				fail("4.3");
			} catch (NullPointerException e) {
				fail("4.5", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #getAttribute(String, boolean)
				marker.getAttribute(null, true);
				fail("4.6");
			} catch (NullPointerException e) {
				fail("4.8", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #getAttribute(String, int)
				marker.getAttribute(null, 5);
				fail("4.9");
			} catch (NullPointerException e) {
				fail("4.11", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #getAttributes(String[])
				marker.getAttributes(null);
				fail("4.12");
			} catch (CoreException e) {
				fail("4.13." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.14", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #setAttribute(String, Object)
				marker.setAttribute(null, getRandomString());
				fail("4.15");
			} catch (CoreException e) {
				fail("4.16." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.17", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #setAttributes(String[], Object[])
				marker.setAttributes(null, new String[] {getRandomString()});
				fail("4.18");
			} catch (CoreException e) {
				fail("4.19." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.20", e);
			} catch (RuntimeException e) {
				// expected
			}
			try {
				// #setAttributes(String[], Object[])
				marker.setAttributes(new String[] {IMarker.MESSAGE}, null);
				fail("4.21");
			} catch (CoreException e) {
				fail("4.22." + resource.getFullPath(), e);
			} catch (NullPointerException e) {
				fail("4.23", e);
			} catch (RuntimeException e) {
				// expected
			}
		}
	}
}
