/*******************************************************************************
 *  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
 *     Alexander Kurtakov <akurtako@redhat.com> - Bug 459343
 *******************************************************************************/
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 ISynchronizerTest extends ResourceTest {
	public static int NUMBER_OF_PARTNERS = 100;
	public IResource[] resources;

	public ISynchronizerTest() {
		super();
	}

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

	protected void assertEquals(String message, byte[] b1, byte[] b2) {
		assertTrue(message, b1.length == b2.length);
		for (int i = 0; i < b1.length; i++)
			assertTrue(message, b1[i] == b2[i]);
	}

	/**
	 * 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/"};
	}

	/*
	 * Internal method used for flushing all sync information for a particular resource
	 * and its children.
	 */
	protected void flushAllSyncInfo(final IResource root) throws CoreException {
		assertNotNull(root);

		final ISynchronizer synchronizer = getWorkspace().getSynchronizer();
		final QualifiedName[] partners = synchronizer.getPartners();
		IWorkspaceRunnable body = monitor -> {
			IResourceVisitor visitor = resource -> {
				for (int i = 0; i < partners.length; i++)
					synchronizer.setSyncInfo(partners[i], resource, null);
				return true;
			};
			root.accept(visitor, IResource.DEPTH_INFINITE, true);
		};
		getWorkspace().run(body, null);
	}

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

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

		//		TestSuite suite = new TestSuite();
		//		suite.addTest(new ISynchronizerTest("testMoveResource2"));
		//		return suite;
	}

	@Override
	public void tearDown() throws Exception {
		// remove all registered sync partners so we don't create
		// phantoms when we delete
		QualifiedName[] names = getWorkspace().getSynchronizer().getPartners();
		for (int i = 0; i < names.length; i++)
			getWorkspace().getSynchronizer().remove(names[i]);

		// delete the root and everything under it
		super.tearDown();
	}

	public void testDeleteResources() {
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// register the target so now we should be able to do stuff
		synchronizer.add(qname);

		// setup the sync bytes
		final Hashtable<IPath, byte[]> table = new Hashtable<>(10);
		IResourceVisitor visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			byte[] b = getRandomString().getBytes();
			table.put(resource.getFullPath(), b);
			synchronizer.setSyncInfo(qname, resource, b);
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// get the info and ensure its the same
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("1.0." + resource.getFullPath(), actual);
					return true;
				} else
					assertNotNull("1.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("1.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("1.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("1.4", e);
		}

		// delete all resources under the projects.
		final IProject[] projects = getWorkspace().getRoot().getProjects();
		IWorkspaceRunnable body = monitor -> {
			for (int i = 0; i < projects.length; i++) {
				IResource[] children = projects[i].members();
				for (int j = 0; j < children.length; j++)
					children[j].delete(false, getMonitor());
			}
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}

		// sync info should remain for the resources since they are now phantoms
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("3.0", actual);
					return true;
				} else
					assertNotNull("3.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("3.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("3.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("3.4", e);
		}

		// delete the projects
		for (int i = 0; i < projects.length; i++) {
			try {
				projects[i].delete(false, getMonitor());
			} catch (CoreException e) {
				ResourcesPlugin.getPlugin().getLog().log(e.getStatus());
				fail("4.0", e);
			}
		}

		// sync info should be gone since projects can't become phantoms
		visitor = resource -> {
			try {
				assertNull("5.0." + resource.getFullPath(), synchronizer.getSyncInfo(qname, resource));
			} catch (CoreException e) {
				fail("5.1." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("5.2", e);
		}
	}

	public void testDeleteResources2() {
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// register the target so now we should be able to do stuff
		synchronizer.add(qname);

		// setup the sync bytes
		final Hashtable<IPath, byte[]> table = new Hashtable<>(10);
		IResourceVisitor visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			byte[] b = getRandomString().getBytes();
			table.put(resource.getFullPath(), b);
			synchronizer.setSyncInfo(qname, resource, b);
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// get the info and ensure its the same
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("1.0." + resource.getFullPath(), actual);
					return true;
				} else
					assertNotNull("1.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("1.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("1.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("1.4", e);
		}

		// delete all resources under the projects.
		final IProject[] projects = getWorkspace().getRoot().getProjects();
		IWorkspaceRunnable body = monitor -> {
			for (int i = 0; i < projects.length; i++) {
				IResource[] children = projects[i].members();
				for (int j = 0; j < children.length; j++) {
					if (!children[j].getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME))
						children[j].delete(false, getMonitor());
				}
			}
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}

		// sync info should remain for the resources since they are now phantoms
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("3.0", actual);
					return true;
				} else
					assertNotNull("3.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("3.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("3.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("3.4", e);
		}

		// remove the sync info for the immediate children of the projects.
		body = monitor -> {
			for (int i = 0; i < projects.length; i++) {
				IResource[] children = projects[i].members(true);
				for (int j = 0; j < children.length; j++)
					synchronizer.setSyncInfo(qname, children[j], null);
			}
		};
		try {
			getWorkspace().run(body, getMonitor());
		} catch (CoreException e) {
			fail("4.99", e);
		}

		// there should be no sync info for any resources except the project
		visitor = resource -> {
			int type = resource.getType();
			if (type == IResource.ROOT || type == IResource.PROJECT)
				return true;
			if (type == IResource.FILE && resource.getParent().getType() == IResource.PROJECT && resource.getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME))
				return true;
			assertNull("5.0." + resource.getFullPath(), synchronizer.getSyncInfo(qname, resource));
			return true;
		};

		try {
			getWorkspace().getRoot().accept(visitor, IResource.DEPTH_INFINITE, true);
		} catch (CoreException e) {
			fail("5.99", e);
		}
	}

	public void testMoveResource() {
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// cleanup auto-created resources
		try {
			getWorkspace().getRoot().delete(true, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// setup
		IResource[] resources = buildResources(getWorkspace().getRoot(), new String[] {"/Foo", "/Foo/file.txt"});
		IProject project = (IProject) resources[0];
		IFile source = (IFile) resources[1];
		// create in workspace
		ensureExistsInWorkspace(resources, true);

		// register partner and add sync info
		synchronizer.add(qname);
		byte[] b = new byte[] {1, 2, 3, 4};
		try {
			synchronizer.setSyncInfo(qname, source, b);
		} catch (CoreException e) {
			fail("2.0", e);
		}

		// move the file
		IFile destination = project.getFile("newFile.txt");
		try {
			source.move(destination.getFullPath(), true, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}

		// check sync info
		try {
			byte[] old = synchronizer.getSyncInfo(qname, source);
			assertNotNull("4.0", old);
			assertEquals("4.1", b, old);
			assertNull("4.2", synchronizer.getSyncInfo(qname, destination));
		} catch (CoreException e) {
			fail("4.3", e);
		}
	}

	public void testMoveResource2() {
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// cleanup auto-created resources
		try {
			getWorkspace().getRoot().delete(true, getMonitor());
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// setup
		IResource[] toTest = buildResources(getWorkspace().getRoot(), new String[] {"/Foo", "/Foo/file.txt"});
		IProject sourceProject = (IProject) toTest[0];
		IFile sourceFile = (IFile) toTest[1];
		// create in workspace
		ensureExistsInWorkspace(toTest, true);

		// register partner and add sync info
		synchronizer.add(qname);
		byte[] b = new byte[] {1, 2, 3, 4};
		try {
			synchronizer.setSyncInfo(qname, sourceProject, b);
			synchronizer.setSyncInfo(qname, sourceFile, b);
		} catch (CoreException e) {
			fail("2.0", e);
		}

		// move the file
		IFile destFile = sourceProject.getFile("newFile.txt");
		try {
			sourceFile.move(destFile.getFullPath(), true, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}

		// check sync info
		try {
			byte[] old = synchronizer.getSyncInfo(qname, sourceFile);
			assertNotNull("4.0", old);
			assertEquals("4.1", b, old);
			assertNull("4.2", synchronizer.getSyncInfo(qname, destFile));
		} catch (CoreException e) {
			fail("4.3", e);
		}

		// move the file back
		try {
			destFile.move(sourceFile.getFullPath(), true, getMonitor());
		} catch (CoreException e) {
			fail("5.0", e);
		}

		// check the sync info
		try {
			byte[] old = synchronizer.getSyncInfo(qname, sourceFile);
			assertNotNull("6.0", old);
			assertEquals("6.1", b, old);
			assertNull("6.2", synchronizer.getSyncInfo(qname, destFile));
		} catch (CoreException e) {
			fail("6.3", e);
		}

		// rename the file and ensure that the sync info is moved with it
		IProject destProject = getWorkspace().getRoot().getProject("newProject");
		try {
			sourceProject.move(destProject.getFullPath(), true, getMonitor());
		} catch (CoreException e) {
			fail("7.0", e);
		}
		try {
			assertNull("7.1", synchronizer.getSyncInfo(qname, sourceProject));
			assertNull("7.2", synchronizer.getSyncInfo(qname, sourceFile));
			byte[] old = synchronizer.getSyncInfo(qname, destProject.getFile(sourceFile.getName()));
			assertNotNull("7.3", old);
			assertEquals("7.4", b, old);
			old = synchronizer.getSyncInfo(qname, destProject);
			assertNotNull("7.5", old);
			assertEquals("7.6", b, old);
		} catch (CoreException e) {
			fail("7.3", e);
		}
	}

	public void testRegistration() {
		// setup
		QualifiedName[] partners = new QualifiedName[NUMBER_OF_PARTNERS];
		for (int i = 0; i < NUMBER_OF_PARTNERS; i++) {
			QualifiedName name = new QualifiedName("org.eclipse.core.deployment", "myTarget" + i);
			partners[i] = name;
		}
		ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// register the targets...twice to ensure dups aren't registered
		for (int i = 0; i < NUMBER_OF_PARTNERS; i++) {
			synchronizer.add(partners[i]);
			synchronizer.add(partners[i]);
		}

		// get the array of targets
		QualifiedName[] list = synchronizer.getPartners();
		assertNotNull("3.0", list);
		assertEquals("3.1", NUMBER_OF_PARTNERS, list.length);

		// unregister all targets
		for (int i = 0; i < NUMBER_OF_PARTNERS; i++)
			synchronizer.remove(partners[i]);
		assertEquals("4.0", 0, synchronizer.getPartners().length);
	}

	public void testSave() {
		final Hashtable<IPath, byte[]> table = new Hashtable<>(10);
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final Synchronizer synchronizer = (Synchronizer) ResourcesPlugin.getWorkspace().getSynchronizer();

		// register the sync partner and set the sync info on the resources
		synchronizer.add(qname);
		IResourceVisitor visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			try {
				byte[] b = getRandomString().getBytes();
				synchronizer.setSyncInfo(qname, resource, b);
				table.put(resource.getFullPath(), b);
			} catch (CoreException e) {
				fail("0.0." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("0.1", e);
		}

		// write out the data
		File file = Platform.getLocation().append(".testsyncinfo").toFile();
		OutputStream fileOutput = null;
		DataOutputStream o1 = null;
		try {
			fileOutput = new FileOutputStream(file);
			o1 = new DataOutputStream(fileOutput);
		} catch (FileNotFoundException e) {
			fail("1.0", e);
		}
		final DataOutputStream output = o1;
		final List<QualifiedName> 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();
					}
				};
				synchronizer.saveSyncInfo(info, requestor, output, list);
			} catch (IOException e) {
				fail("1.1", e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("1.2", e);
		} finally {
			try {
				output.close();
			} catch (IOException e) {
				fail("1.3", e);
			}
		}

		// flush the sync info in memory
		try {
			flushAllSyncInfo(getWorkspace().getRoot());
		} catch (CoreException e) {
			fail("2.0", e);
		}

		// read in the data
		try {
			InputStream fileInput = new FileInputStream(file);
			final DataInputStream input = new DataInputStream(fileInput);
			IWorkspaceRunnable body = monitor -> {
				SyncInfoReader reader = new SyncInfoReader((Workspace) getWorkspace(), synchronizer);
				try {
					reader.readSyncInfo(input);
				} catch (IOException e) {
					fail("3.0", e);
				}
			};
			try {
				getWorkspace().run(body, getMonitor());
			} finally {
				try {
					input.close();
				} catch (IOException e) {
					fail("3.1", e);
				}
			}
		} catch (FileNotFoundException e) {
			fail("3.2", e);
		} catch (CoreException e) {
			fail("3.3", e);
		}

		// confirm the sync bytes are the same
		visitor = resource -> {
			byte[] actual = synchronizer.getSyncInfo(qname, resource);
			if (resource.getType() == IResource.ROOT) {
				assertNull("4.0", actual);
				return true;
			} else
				assertNotNull("4.1." + resource.getFullPath(), actual);
			byte[] expected = table.get(resource.getFullPath());
			assertEquals("4.2." + resource.getFullPath(), expected, actual);
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("4.3", e);
		}
	}

	public void testSnap() {
		/*
		 final Hashtable table = new Hashtable(10);
		 final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		 final Synchronizer synchronizer = (Synchronizer) ResourcesPlugin.getWorkspace().getSynchronizer();

		 // register the sync partner and set the sync info on the resources
		 synchronizer.add(qname);
		 IResourceVisitor visitor = new IResourceVisitor() {
		 public boolean visit(IResource resource) throws CoreException {
		 if (resource.getType() == IResource.ROOT)
		 return true;
		 try {
		 byte[] b = getRandomString().getBytes();
		 synchronizer.setSyncInfo(qname, resource, b);
		 table.put(resource.getFullPath(), b);
		 } catch (CoreException e) {
		 fail("0.0." + resource.getFullPath(), e);
		 }
		 return true;
		 }
		 };
		 try {
		 getWorkspace().getRoot().accept(visitor);
		 } catch (CoreException e) {
		 fail("0.1", e);
		 }

		 // write out the data
		 File file = Platform.getLocation().append(".testsyncinfo.snap").toFile();
		 SafeChunkyOutputStream safeOutput = null;
		 DataOutputStream o1 = null;
		 try {
		 safeOutput = new SafeChunkyOutputStream(file);
		 o1 = new DataOutputStream(safeOutput);
		 } catch (IOException e) {
		 if (safeOutput != null)
		 try {
		 safeOutput.close();
		 } catch (IOException e2) {
		 }
		 fail("1.0", e);
		 }
		 final DataOutputStream output = o1;
		 visitor = new IResourceVisitor() {
		 public boolean visit(IResource resource) throws CoreException {
		 try {
		 synchronizer.snapSyncInfo(resource, output);
		 } catch (IOException e) {
		 fail("1.1", e);
		 }
		 return true;
		 }
		 };
		 try {
		 getWorkspace().getRoot().accept(visitor);
		 safeOutput.succeed();
		 } catch (CoreException e) {
		 fail("1.2", e);
		 } catch (IOException e) {
		 fail("1.3", e);
		 } finally {
		 try {
		 output.close();
		 } catch (IOException e) {
		 fail("1.4", e);
		 }
		 }

		 // flush the sync info in memory
		 try {
		 flushAllSyncInfo(getWorkspace().getRoot());
		 } catch (CoreException e) {
		 fail("2.0", e);
		 }

		 // read in the data
		 try {
		 InputStream safeInput = new SafeChunkyInputStream(file);
		 final DataInputStream input = new DataInputStream(safeInput);
		 IWorkspaceRunnable body = new IWorkspaceRunnable() {
		 public void run(IProgressMonitor monitor) throws CoreException {
		 SyncInfoSnapReader reader = new SyncInfoSnapReader((Workspace) getWorkspace(), synchronizer);
		 try {
		 reader.readSyncInfo(input);
		 } catch (IOException e) {
		 fail("3.0", e);
		 }
		 }
		 };
		 try {
		 getWorkspace().run(body, getMonitor());
		 } finally {
		 try {
		 input.close();
		 } catch (IOException e) {
		 fail("3.1", e);
		 }
		 }
		 } catch (FileNotFoundException e) {
		 fail("3.2", e);
		 } catch (IOException e) {
		 fail("3.3", e);
		 } catch (CoreException e) {
		 fail("3.4", e);
		 }

		 // confirm the sync bytes are the same
		 visitor = new IResourceVisitor() {
		 public boolean visit(IResource resource) throws CoreException {
		 byte[] actual = synchronizer.getSyncInfo(qname, resource);
		 if (resource.getType() == IResource.ROOT) {
		 assertNull("4.0", actual);
		 return true;
		 } else
		 assertNotNull("4.1." + resource.getFullPath(), actual);
		 byte[] expected = (byte[]) table.get(resource.getFullPath());
		 assertEquals("4.2." + resource.getFullPath(), expected, actual);
		 return true;
		 }
		 };
		 try {
		 getWorkspace().getRoot().accept(visitor);
		 } catch (CoreException e) {
		 fail("4.3", e);
		 }
		 */
	}

	public void testSyncInfo() {
		final QualifiedName qname = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final ISynchronizer synchronizer = ResourcesPlugin.getWorkspace().getSynchronizer();

		// setup the sync bytes
		final Hashtable<IPath, byte[]> table = new Hashtable<>(10);
		IResourceVisitor visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			byte[] b = getRandomString().getBytes();
			table.put(resource.getFullPath(), b);
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("0.0", e);
		}

		// should not be able to set sync info before the target has been registered.
		visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			try {
				synchronizer.setSyncInfo(qname, resource, table.get(resource.getFullPath()));
				assertTrue("1.0." + resource.getFullPath(), false);
			} catch (CoreException e) {
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("1.1", e);
		}

		// should not be able to get sync info before the target has been registered
		visitor = resource -> {
			try {
				synchronizer.getSyncInfo(qname, resource);
				assertTrue("2.0." + resource.getFullPath(), false);
			} catch (CoreException e) {
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("2.1", e);
		}

		// register the target so now we should be able to do stuff
		synchronizer.add(qname);

		// there shouldn't be any info yet
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				assertNull("3.0." + resource.getFullPath(), actual);
			} catch (CoreException e) {
				fail("3.1." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("3.2", e);
		}

		// set the sync info
		visitor = resource -> {
			try {
				synchronizer.setSyncInfo(qname, resource, table.get(resource.getFullPath()));
			} catch (CoreException e) {
				fail("4.0." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("4.1", e);
		}

		// get the info and ensure its the same
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("5.0", actual);
					return true;
				} else
					assertNotNull("5.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("5.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("5.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("5.4", e);
		}

		// change the info and then set it
		visitor = resource -> {
			if (resource.getType() == IResource.ROOT)
				return true;
			try {
				byte[] b = getRandomString().getBytes();
				synchronizer.setSyncInfo(qname, resource, b);
				table.put(resource.getFullPath(), b);
			} catch (CoreException e) {
				fail("6.0", e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("6.1", e);
		}

		// get the new info
		visitor = resource -> {
			try {
				byte[] actual = synchronizer.getSyncInfo(qname, resource);
				if (resource.getType() == IResource.ROOT) {
					assertNull("7.0", actual);
					return true;
				} else
					assertNotNull("7.1." + resource.getFullPath(), actual);
				byte[] expected = table.get(resource.getFullPath());
				assertEquals("7.2." + resource.getFullPath(), expected, actual);
			} catch (CoreException e) {
				fail("7.3." + resource.getFullPath(), e);
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("7.4", e);
		}

		// cleanup
		synchronizer.remove(qname);

		// should not be able to get sync info because the target has been unregistered
		visitor = resource -> {
			try {
				synchronizer.getSyncInfo(qname, resource);
				assertTrue("9.0." + resource.getFullPath(), false);
			} catch (CoreException e) {
			}
			return true;
		};
		try {
			getWorkspace().getRoot().accept(visitor);
		} catch (CoreException e) {
			fail("9.1", e);
		}
	}

	/**
	 * Removes resources, sets sync info to <code>null</code> and ensures the
	 * phantoms do not exist any more (see bug 3024)
	 */
	public void testPhantomRemoval() {
		final QualifiedName partner = new QualifiedName("org.eclipse.core.tests.resources", "myTarget");
		final IWorkspace workspace = getWorkspace();
		final ISynchronizer synchronizer = workspace.getSynchronizer();

		// set up
		synchronizer.add(partner);
		IProject project = workspace.getRoot().getProject("MyProject");
		IFolder folder = project.getFolder("foo");
		IFile file1 = folder.getFile("file1.txt");
		IFile file2 = folder.getFile("file2.txt");
		ensureExistsInWorkspace(new IResource[] {file1, file2}, true);

		// sets sync info for the folder and its children
		try {
			synchronizer.setSyncInfo(partner, folder, getRandomString().getBytes());
			synchronizer.setSyncInfo(partner, file1, getRandomString().getBytes());
			synchronizer.setSyncInfo(partner, file2, getRandomString().getBytes());
		} catch (CoreException ce) {
			fail("1.0", ce);
		}

		// 1) tests with one child first
		assertTrue("1.1", file1.exists());
		assertTrue("1.2", !file1.isPhantom());
		// deletes file
		try {
			file1.delete(true, getMonitor());
		} catch (CoreException ce) {
			fail("2.0", ce);
		}
		// file is now a phantom resource
		assertTrue("2.1", !file1.exists());
		assertTrue("2.2", file1.isPhantom());
		// removes sync info
		try {
			synchronizer.setSyncInfo(partner, file1, null);
		} catch (CoreException ce) {
			fail("3.0", ce);
		}
		// phantom should not exist any more
		assertTrue("3.1", !file1.exists());
		assertTrue("3.2", !file1.isPhantom());

		// 2) tests with the folder and remaining child
		assertTrue("4.1", folder.exists());
		assertTrue("4.2", !folder.isPhantom());
		assertTrue("4.3", file2.exists());
		assertTrue("4.4", !file2.isPhantom());
		// deletes the folder and its only child
		try {
			folder.delete(true, getMonitor());
		} catch (CoreException ce) {
			fail("5.0", ce);
		}
		// both resources are now phantom resources
		assertTrue("5.1", !folder.exists());
		assertTrue("5.2", folder.isPhantom());
		assertTrue("5.3", !file2.exists());
		assertTrue("5.4", file2.isPhantom());
		// removes only folder sync info
		try {
			synchronizer.setSyncInfo(partner, folder, null);
		} catch (CoreException ce) {
			fail("6.0", ce);
		}
		// phantoms should not exist any more
		assertTrue("6.1", !folder.exists());
		assertTrue("6.2", !folder.isPhantom());
		assertTrue("6.3", !file2.exists());
		assertTrue("6.4", !file2.isPhantom());

		// clean-up
		synchronizer.remove(partner);
		ensureDoesNotExistInWorkspace(project);
	}
}
