/*******************************************************************************
 *  Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  Contributors:
 *     IBM 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 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;

	/**
	 * 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);
			System.arraycopy(temp, 0, markers, 0, temp.length);
		} catch (CoreException e) {
			fail("0.2", e);
		}

		// create attributes on each marker
		body = monitor -> {
			for (IMarker marker : markers) {
				marker.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 (IMarker marker : markers) {
				marker.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 (IMarker marker : markers) {
				marker.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 (IMarker marker : markers) {
			assertDoesNotExist(message, marker);
		}
	}

	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 (IMarker marker : markers) {
			assertExists(message, marker);
		}
	}

	protected void assertExists(String message, List<IMarker> markers) {
		for (IMarker marker : markers) {
			assertExists(message, marker);
		}
	}


	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();
	}

	@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 (IResource resource : resources) {
			listener.reset();
			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 testCreateMarkerWithAttributes() {
		// Create and register a listener.
		MarkersChangeListener listener = new MarkersChangeListener();
		getWorkspace().addResourceChangeListener(listener);

		// create markers on our hierarchy of resources
		for (IResource resource : resources) {
			listener.reset();

			List<IMarker> markers = new ArrayList<>();
			try {
				markers.add(resource.createMarker(IMarker.PROBLEM, null));
				markers.add(resource.createMarker(IMarker.BOOKMARK, Collections.emptyMap()));
				markers.add(resource.createMarker(IMarker.TASK, Map.of(IMarker.MESSAGE, "My text")));
				assertExists("Markers do not exist" + resource.getFullPath(), markers);
			} catch (CoreException e) {
				fail("Failed to created markers for resource" + resource.getFullPath(), e);
			}
			assertEquals("Not exactly one resource affected by the marker cahnge" + resource.getFullPath(), 1,
					listener.numAffectedResources());
			assertTrue("Not exactly the markers created as defined" + resource.getFullPath(),
					listener.checkChanges(resource, markers.toArray(new IMarker[0]), null, null));

		}

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

	public void testCreateNullMarkerWithAttributesShouldFail() {
		// create markers on our hierarchy of resources
		for (IResource resource : resources) {
			try {
				resource.createMarker(null, null);
				fail("Creating a null marker should not work" + resource.getFullPath());
			} catch (CoreException e) {
				fail("Core exception during the creation of a null marker" + resource.getFullPath(), e);
			} catch (RuntimeException e) {
				// expected
			}
		}

	}

	public void testCreateMarkerWithAttributesOnAResourceWhichDoesNotExistShouldFail() {

		// try creating a marker on a resource which does't exist
		IResource testResource = getWorkspace().getRoot().getFile(new Path("non/existant/resource"));
		assertTrue("Resource should not exist", !testResource.exists());
		try {
			testResource.createMarker(IMarker.PROBLEM, Map.of(IMarker.MESSAGE, "My text"));
			fail("Creating a marker for a non existing resource should not work");
		} catch (CoreException e) {
			// expected
		}
	}

	// testing that markers creation and calling setAttribute trigger multiple
	// resource change
	// events (which is bad for performance hence the better createMarker(String
	// type, Map<String, Object> attributes) method

	public void testThatSettingAttributesTriggerAdditionalResourceChangeEvent() {
		// Create and register a listener.
		MarkersNumberOfDeltasChangeListener listener = new MarkersNumberOfDeltasChangeListener();
		getWorkspace().addResourceChangeListener(listener);
		for (IResource resource : resources) {
			listener.reset();
			// each setAttributes triggers one additional resource change event
			try {
				IMarker marker = resource.createMarker(TEST_PROBLEM_MARKER);
				marker.setAttribute(IMarker.MESSAGE, getRandomString());
				marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
				assertEquals(3, listener.numberOfChanges());
			} catch (CoreException e) {
				fail("Marker creation failed unexpected", e);
			}
		}
		// cleanup
		getWorkspace().removeResourceChangeListener(listener);
	}

	// testing that markers creation with arbiutes
	public void testThatMarkersWithAttributesOnlyTriggerOnResourceChangeEvent() {
		// Create and register a listener.
		MarkersNumberOfDeltasChangeListener listener = new MarkersNumberOfDeltasChangeListener();
		getWorkspace().addResourceChangeListener(listener);
		for (IResource resource : resources) {
			listener.reset();
			// createMarker with attributes triggers only one resource change event
			listener.reset();
			// each setAttributes triggers one resource change event
			try {
				resource.createMarker(TEST_PROBLEM_MARKER,
						Map.of(IMarker.MESSAGE, getRandomString(), IMarker.PRIORITY, IMarker.PRIORITY_HIGH));
				assertEquals(1, listener.numberOfChanges());
			} catch (CoreException e) {
				fail("Marker creation failed unexpected", e);
			}
		}
		// 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 (IResource resource : resources) {
			// 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 (IMarker marker : markers) {
			assertTrue("1.1", !marker.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);
		Collections.addAll(allMarkers, markers);
		try {
			markers = createMarkers(resources, IMarker.BOOKMARK);
		} catch (CoreException e) {
			fail("3.0", e);
		}
		Collections.addAll(allMarkers, markers);
		try {
			markers = createMarkers(resources, IMarker.TASK);
		} catch (CoreException e) {
			fail("3.1", e);
		}
		Collections.addAll(allMarkers, markers);
		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");
			create(project, false);
			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<>());
			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 (IResource resource2 : resources) {
				resource = resource2;
				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 (IProject project : projects) {
					IResource[] children = project.members();
					for (IResource element : children) {
						IPath destination = new Path(element.getName() + "copy");
						element.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 (final IResource resource : resources) {
				// 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);
		waitForProjectEncodingValidation();
		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);
		waitForProjectEncodingValidation();
		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 (IProject project : projects) {
				IPath destination = new Path(project.getName() + "move");
				try {
					project.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];
			System.arraycopy(newMarkers, 0, expected, 0, newMarkers.length);
			newMarkers = createMarkers(resources, IMarker.BOOKMARK);
			System.arraycopy(newMarkers, 0, expected, newMarkers.length, newMarkers.length);
			newMarkers = createMarkers(resources, IMarker.TASK);
			System.arraycopy(newMarkers, 0, expected, newMarkers.length * 2, newMarkers.length);
		} 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 (IResource resource : resources) {
			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 (IResource resource : resources) {
			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
			}
			try {
				Map<String, Object> map2 = marker.getAttributes();
				map2.put("1", null); // allowed for clients using IMarker.getAttributes()
				map2.put("2", 2);
				marker.setAttributes(map2);
				assertNull(marker.getAttribute("1"));
				assertEquals(2, marker.getAttribute("2"));
				map2.put(null, 1); // allowed for clients using IMarker.getAttributes()
			} catch (CoreException e) {
				fail("4.24." + resource.getFullPath(), e);
			}
			try {
				Map<String, Object> map2 = marker.getAttributes();
				map2.put(null, 1); // allowed for clients using IMarker.getAttributes()
				try {
					marker.setAttributes(map2); // not allowed for clients to put null key
					fail("4.25");
				} catch (Exception e) {
					// expected
				}
			} catch (CoreException e) {
				fail("4.24." + resource.getFullPath(), e);
			}
		}
	}
}
