/*******************************************************************************
 * Copyright (c) 2000, 2013 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
 *******************************************************************************/
package org.eclipse.team.tests.ccvs.core.mappings;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.internal.resources.mapping.SimpleResourceMapping;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.mapping.RemoteResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.jface.util.Util;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.TeamStatus;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IThreeWayDiff;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.core.synchronize.FastSyncInfoFilter;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.synchronize.SyncInfoTree;
import org.eclipse.team.core.variants.CachedResourceVariant;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.ICVSFile;
import org.eclipse.team.internal.ccvs.core.ICVSFolder;
import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile;
import org.eclipse.team.internal.ccvs.core.ICVSResource;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.connection.CVSCommunicationException;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFolderTree;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFolderTreeBuilder;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.ui.operations.CacheBaseContentsOperation;
import org.eclipse.team.internal.ccvs.ui.operations.CacheRemoteContentsOperation;
import org.eclipse.team.internal.core.ResourceVariantCache;
import org.eclipse.team.internal.core.ResourceVariantCacheEntry;
import org.eclipse.team.internal.core.mapping.SyncInfoToDiffConverter;
import org.eclipse.team.tests.ccvs.core.EclipseTest;
import org.eclipse.team.tests.ccvs.core.TeamCVSTestPlugin;

import junit.framework.Test;

/**
 * Tests for using CVS operations with deep and shallow resource mappings.
 */
public class ResourceMapperTests extends EclipseTest {


	public ResourceMapperTests() {
		super();
	}

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

	public static Test suite() {
		return suite(ResourceMapperTests.class);
	}
	
	/**
	 * Update the resources contained in the given mappers and ensure that the
	 * update was performed properly by comparing the result with the reference projects.
	 * @throws Exception 
	 */
	protected void update(ResourceMapping mapper, LocalOption[] options) throws Exception {
		SyncInfoTree incomingSet = getIncoming(mapper.getProjects());
		update(new ResourceMapping[] { mapper }, options);
		assertUpdate(mapper, incomingSet);
	}
	
	/**
	 * Replace the resources contained in the given mappers and ensure that the
	 * update was performed properly by comparing the result with the reference projects.
	 * @throws Exception 
	 */
	protected void replace(ResourceMapping mapper) throws Exception {
		SyncInfoTree incomingSet = getIncoming(mapper.getProjects());
		replace(new ResourceMapping[] { mapper });
		assertUpdate(mapper, incomingSet);
	} 

	/**
	 * Commit and check that all resources in containing project that should have been committed were and
	 * that any not contained by the mappers were not.
	 * @throws CoreException 
	 * @see org.eclipse.team.tests.ccvs.core.EclipseTest#commit(org.eclipse.core.resources.mapping.IResourceMapper[], java.lang.String)
	 */
	protected void commit(ResourceMapping mapper, String message) throws CoreException {
		SyncInfoTree set = getOutgoing(mapper.getProjects());
		commit(new ResourceMapping[] { mapper }, message);
		assertCommit(mapper, set);
	}
	
	/**
	 * Tag the given resource mappings and assert that only the resources
	 * within the mapping were tagged.
	 * @throws CoreException 
	 */
	protected void tag(ResourceMapping mapping, CVSTag tag) throws CoreException {
		tag(new ResourceMapping[] { mapping }, tag, false);
		assertTagged(mapping, tag);
	}
	
	/**
	 * Branch the resources in the given mapping.
	 * @throws CoreException 
	 * @throws IOException 
	 */
	protected void branch(ResourceMapping mapping, CVSTag branch) throws CoreException, IOException {
		CVSTag version = new CVSTag("Root_" + branch.getName(), CVSTag.VERSION);
		branch(new ResourceMapping[] { mapping }, version, branch, true /* update */);
		assertTagged(mapping, version);
		assertBranched(mapping, branch);
	}
	
	/**
	 * Add any resources contained by the mapping
	 * @param mapping
	 * @throws CoreException 
	 */
	protected void add(ResourceMapping mapping) throws CoreException {
		SyncInfoTree set = getUnaddedResource(mapping);
		add(new ResourceMapping[] { mapping });
		assertAdded(mapping, set);
	}

	private void assertAdded(ResourceMapping mapping, final SyncInfoTree set) throws CoreException {
		// Assert that all resources covered by the mapping are now under version control (i.e. are in-sync)
		// Remove the resources contained in the mapping from the set of unadded resources.
		visit(mapping, ResourceMappingContext.LOCAL_CONTEXT, (IResourceVisitor) resource -> {
			ICVSResource cvsResource = getCVSResource(resource);
			assertTrue("Resource was not added but should have been: " + resource.getFullPath(), 
					(cvsResource.isManaged() 
							|| (cvsResource.isFolder() 
									&& ((ICVSFolder)cvsResource).isCVSFolder())));
			set.remove(resource);
			return true;
		});
		// Assert that the remaining unadded resources are still unadded
		SyncInfo[] infos = set.getSyncInfos();
		for (SyncInfo info : infos) {
			ICVSResource cvsResource = getCVSResource(info.getLocal());
			assertTrue("Resource was added but should not have been: " + info.getLocal().getFullPath(), !cvsResource.isManaged());
		}
	}

	/*
	 * Need to ensure that only the resources contained in the mapping
	 * have the branch tag associated with them.
	 */
	private void assertBranched(ResourceMapping mapping, CVSTag branch) throws CoreException {
		// First, make sure the proper resources are tagged in the repo
		assertTagged(mapping, branch);
		// Now make sure the proper local files are tagged
		final Map<String, ICVSResource> remotes = getTaggedRemoteFilesByPath(mapping, branch);
		final Map<String, ICVSFile> locals = getTaggedLocalFilesByPath(mapping, branch);
		for (Iterator<String> iter = remotes.keySet().iterator(); iter.hasNext();) {
			String key = iter.next();
			ICVSRemoteFile remote = (ICVSRemoteFile)remotes.get(key);
			ICVSFile local = locals.get(key);
			assertNotNull("Remotely tagged resource was not tagged locally: " + remote.getRepositoryRelativePath(), local);
			assertEquals(local.getIResource().getParent().getFullPath(), remote, local, false, false /* include tags */);
			assertEquals("Remotely tagged resource was not tagged locally: " + remote.getRepositoryRelativePath(), branch, local.getSyncInfo().getTag());
			locals.remove(key);
			iter.remove();
		}
		// The remote map should be empty after traversal
		for (Object element : remotes.keySet()) {
			String path = (String) element;
			fail("Remote file " + path + " was tagged remotely but not locally.");
		}
		// The local map should be empty after traversal
		for (Object element : locals.keySet()) {
			String path = (String) element;
			fail("Local file " + path + " was tagged locally but not remotely.");
		}
	}

	private void assertTagged(ResourceMapping mapping, final CVSTag tag) throws CoreException {
		final Map<String, ICVSResource> tagged = getTaggedRemoteFilesByPath(mapping, tag);
		// Visit all the resources in the traversal and ensure that they are tagged
		visit(mapping, ResourceMappingContext.LOCAL_CONTEXT, (IResourceVisitor) resource -> {
			if (resource.getType() == IResource.FILE) {
				ICVSRemoteFile file = popRemote(resource, tagged);
				assertNotNull("Resource was not tagged: " + resource.getFullPath(), file);
			}
			return true;
		});
		
		for (String path : tagged.keySet()) {
			fail("Remote file " + path + " was tagged but should not have been.");
		}
	}

	private Map<String, ICVSFile> getTaggedLocalFilesByPath(ResourceMapping mapping, final CVSTag branch)
			throws CoreException {
		final Map<String, ICVSFile> tagged = new HashMap<>();
		IProject[] projects = mapping.getProjects();
		for (IProject project : projects) {
			project.accept(resource -> {
				if (resource.getType() == IResource.FILE) {
					ICVSFile file = (ICVSFile)getCVSResource(resource);
					ResourceSyncInfo info = file.getSyncInfo();
					if (info != null && info.getTag() != null && info.getTag().equals(branch)) {
						tagged.put(file.getRepositoryRelativePath(), file);
					}
				}
				return true;
			});
		}
		return tagged;
	}
	
	private Map<String, ICVSResource> getTaggedRemoteFilesByPath(ResourceMapping mapping, final CVSTag tag)
			throws CVSException {
		IProject[] projects = mapping.getProjects();
		ICVSResource[] remotes = getRemoteTrees(projects, tag);
		final Map<String, ICVSResource> tagged = getFilesByPath(remotes);
		return tagged;
	}

	private ICVSResource[] getRemoteTrees(IProject[] projects, CVSTag tag) throws CVSException {
		List<ICVSResource> result = new ArrayList<>();
		for (IProject project : projects) {
			RemoteFolderTree tree = RemoteFolderTreeBuilder.buildRemoteTree(getRepository(), project, tag, DEFAULT_MONITOR);
			result.add(tree);
		}
		return result.toArray(new ICVSResource[result.size()]);
	}

	private Map<String, ICVSResource> getFilesByPath(ICVSResource[] remotes) throws CVSException {
		Map<String, ICVSResource> result = new HashMap<>();
		for (ICVSResource resource : remotes) {
			collectFiles(resource, result);
		}
		return result;
	}

	private void collectFiles(ICVSResource resource, Map<String, ICVSResource> result) throws CVSException {
		if (resource.isFolder()) {
			ICVSResource[] members = ((ICVSFolder)resource).members(ICVSFolder.ALL_EXISTING_MEMBERS);
			for (ICVSResource member : members) {
				collectFiles(member, result);
			}
		} else {
			result.put(resource.getRepositoryRelativePath(), resource);
		} 
	}

	private ICVSRemoteFile popRemote(IResource resource, Map<String, ICVSResource> tagged) throws CVSException {
		ICVSResource cvsResource = getCVSResource(resource);
		ICVSRemoteFile remote = (ICVSRemoteFile)tagged.get(cvsResource.getRepositoryRelativePath());
		if (remote != null) {
			tagged.remove(remote.getRepositoryRelativePath());
		}
		return remote;
	}
	
	private ResourceMapping asResourceMapping(final IResource[] resources, final int depth) {
		return new ResourceMapping() {
			private Object object = new Object();
			@Override
			public Object getModelObject() {
				return object;
			}
			@Override
			public IProject[] getProjects() {
				return getProjects(resources);
			}
			private IProject[] getProjects(IResource[] resources) {
				Set<IProject> projects = new HashSet<>();
				for (IResource resource : resources) {
					projects.add(resource.getProject());
				}
				return projects.toArray(new IProject[projects.size()]);
			}
			@Override
			public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor) throws CoreException {
				return new ResourceTraversal[] {
						new ResourceTraversal(resources, depth, IResource.NONE)
					};
			}
			@Override
			public String getModelProviderId() {
				return "org.eclipse.team.tests.cvs.core.modelProvider";
			}
		};
	}
	
	private void assertUpdate(ResourceMapping mapper, final SyncInfoTree set) throws Exception {
		final Exception[] exception = new Exception[] { null };
		visit(mapper, new SyncInfoSetTraveralContext(set), (IResourceVisitor) resource -> {
			SyncInfo info = set.getSyncInfo(resource);
			if (info != null) {
				set.remove(resource);
				try {
					// Assert that the local sync info matches the remote info
					assertEquals(resource.getParent().getFullPath(), getCVSResource(resource), (ICVSResource)info.getRemote(), false, false);
				} catch (CVSException e1) {
					exception[0] = e1;
				} catch (CoreException e2) {
					exception[0] = e2;
				} catch (IOException e3) {
					exception[0] = e3;
				}
			}
			return true;
		});
		if (exception[0] != null) throw exception[0];
		
		// check the the state of the remaining resources has not changed
		assertUnchanged(set);
	}

	private void assertCommit(ResourceMapping mapper, final SyncInfoTree set) throws CoreException {
		visit(mapper, new SyncInfoSetTraveralContext(set), (IResourceVisitor) resource -> {
			SyncInfo info = set.getSyncInfo(resource);
			if (info != null) {
				set.remove(resource);
				assertTrue("Committed resource is not in-sync: " + resource.getFullPath(), getSyncInfo(resource).getKind() == SyncInfo.IN_SYNC);
			}
			return true;
		});
		// check the the state of the remaining resources has not changed
		assertUnchanged(set);
	}

	/*
	 * Assert that the state of the resources in the set have not changed
	 */
	private void assertUnchanged(SyncInfoTree set) throws TeamException {
		//TODO: Need to refresh the subscriber since flush of remote state is deep
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().refresh(set.getResources(), IResource.DEPTH_ZERO, DEFAULT_MONITOR);
		SyncInfo[] infos = set.getSyncInfos();
		for (SyncInfo info : infos) {
			assertUnchanged(info);
		}
	}

	private void assertUnchanged(SyncInfo info) throws TeamException {
		SyncInfo current = getSyncInfo(info.getLocal());
		assertEquals("The sync info changed for " + info.getLocal().getFullPath(), info, current);
	}

	private SyncInfo getSyncInfo(IResource local) throws TeamException {
		return CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().getSyncInfo(local);
	}

	private SyncInfoTree getIncoming(IProject[] projects) throws TeamException {
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().refresh(projects, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
		SyncInfoTree set = getAllOutOfSync(projects);
		set.removeOutgoingNodes();
		set.removeConflictingNodes();
		return set;
	}
	
	private SyncInfoTree getOutgoing(IProject[] projects) {
		SyncInfoTree set = getAllOutOfSync(projects);
		set.removeIncomingNodes();
		set.removeConflictingNodes();
		return set;
	}

	private SyncInfoTree getUnaddedResource(ResourceMapping mapping) {
		SyncInfoTree set = getAllOutOfSync(mapping.getProjects());
		set.selectNodes(new FastSyncInfoFilter() {
			@Override
			public boolean select(SyncInfo info) {
				try {
					if (info.getLocal().getType() != IResource.PROJECT && info.getRemote() == null && info.getBase() == null) {
						ICVSResource resource = getCVSResource(info.getLocal());
						return !resource.isManaged();
					}
				} catch (CVSException e) {
					fail(e.getMessage());
				}
				return false;
			}
		});
		return set;
	}
	
	private SyncInfoTree getAllOutOfSync(IProject[] projects) {
		SyncInfoTree set = new SyncInfoTree();
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().collectOutOfSync(projects, IResource.DEPTH_INFINITE, set, DEFAULT_MONITOR);
		return set;
	}
	
	private IResourceDiffTree getAllDiffs(IProject[] projects) throws CoreException {
		final ResourceDiffTree tree = new ResourceDiffTree();
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().accept(projects, IResource.DEPTH_INFINITE, delta -> {
			tree.add(delta);
			return true;
		});
		return tree;
	}
	
	private void visit(ResourceMapping mapper, ResourceMappingContext context, IResourceVisitor visitor) throws CoreException {
		ResourceTraversal[] traversals = mapper.getTraversals(context, null);
		for (ResourceTraversal traversal : traversals) {
			visit(traversal, context, visitor);
		}
	}

	private void visit(ResourceTraversal traversal, ResourceMappingContext context, IResourceVisitor visitor) throws CoreException {
		IResource[] resources = traversal.getResources();
		for (IResource resource : resources) {
			visit(resource, visitor, context, traversal.getDepth());
		}
	}

	private void visit(IResource resource, IResourceVisitor visitor, ResourceMappingContext context, int depth)
			throws CoreException {
		if (!visitor.visit(resource) || depth == IResource.DEPTH_ZERO || resource.getType() == IResource.FILE)
			return;
		Set<IResource> members = new HashSet<>();
		members.addAll(Arrays.asList(((IContainer) resource).members(false)));
		if (context instanceof RemoteResourceMappingContext) {
			RemoteResourceMappingContext remoteContext = (RemoteResourceMappingContext) context;
			members.addAll(Arrays.asList(remoteContext.fetchMembers((IContainer) resource, DEFAULT_MONITOR)));
		}
		for (IResource member : members) {
			visit(member, visitor, context,
					depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE);
		}
	}
	
	private boolean isTimeout(Throwable e) {
		if (e == null) {
			return false;
		}

		if (e instanceof InterruptedIOException
				&& e.getMessage() != null
				&& e.getMessage().indexOf(
						"Timeout while writing to output stream") >= 0) {
			return true;
		}

		if (e instanceof CoreException) {
			CoreException ce = (CoreException) e;
			if (ce.getStatus() != null && ce.getStatus().isMultiStatus()) {
				MultiStatus multistatus = (MultiStatus) ce.getStatus();
				for (int i = 0; i < multistatus.getChildren().length; i++) {
					if (isTimeout(multistatus.getChildren()[i].getException())) {
						return true;
					}
				}
			}

		}

		return isTimeout(e.getCause());
	}

	public void testUpdate() throws Exception {
		try{
			// Create a test project, import it into cvs and check it out
			IProject project = createProject("testUpdate", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt" });
	
			// Check the project out under a different name
			IProject copy = checkoutCopy(project, "-copy");
			
			// Perform some operations on the copy and commit them all
			addResources(copy, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
			setContentsAndEnsureModified(copy.getFile("changed.txt"));
			deleteResources(new IResource[] {copy.getFile("deleted.txt")});
			setContentsAndEnsureModified(copy.getFile("folder1/a.txt"));
			setContentsAndEnsureModified(copy.getFile("folder1/subfolder1/c.txt"));
			commit(asResourceMapping(new IResource[] { copy }, IResource.DEPTH_INFINITE), "A commit message");
			
			// Update the project using depth one and ensure we got only what was asked for
			update(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE), null);
			
			// Update a subfolder using depth one and ensure we got only what was asked for
			update(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE), null);
			
			// Update the specific file
			update(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO), null);
			
			// Update the remaining resources
			update(asResourceMapping(new IResource[] { project.getFolder("folder2") }, IResource.DEPTH_INFINITE), null);
			assertEquals(project, copy);
		} catch (Exception e) {
			if (isTimeout(e)) {
				//TODO see Bug 399375
				System.err.println("Timeout while testUpdate");
				e.printStackTrace();
				return;
			}
			throw e;
		}
	}
	
	public void testReplace() throws Exception {
		try{
			// Create a test project, import it into cvs and check it out
			IProject project = createProject("testReplace", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt" });
	
			// Check the project out under a different name
			IProject copy = checkoutCopy(project, "-copy");
			
			// Perform some operations on the copy and commit them all
			addResources(copy, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
			setContentsAndEnsureModified(copy.getFile("changed.txt"));
			deleteResources(new IResource[] {copy.getFile("deleted.txt")});
			setContentsAndEnsureModified(copy.getFile("folder1/a.txt"));
			setContentsAndEnsureModified(copy.getFile("folder1/subfolder1/c.txt"));
			commit(asResourceMapping(new IResource[] { copy }, IResource.DEPTH_INFINITE), "A commit message");
			
			// Update the project using depth one and ensure we got only what was asked for
			replace(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE));
			
			// Update a subfolder using depth one and ensure we got only what was asked for
			deleteResources(new IResource[] {project.getFile("folder1/b.txt")});
			replace(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE));
			
			// Update the specific file
			replace(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO));
			
			// Update the remaining resources
			replace(asResourceMapping(new IResource[] { project.getFolder("folder2") }, IResource.DEPTH_INFINITE));
			assertEquals(project, copy);
		} catch (Exception e) {
			if (isTimeout(e)) {
				//TODO see Bug 399375
				System.err.println("Timeout while testReplace");
				e.printStackTrace();
				return;
			}
			throw e;
		}
	}

	public void testCommit() throws Exception {
		if (TeamCVSTestPlugin.IS_UNSTABLE_TEST && Util.isMac())
			return;

		// Create a test project, import it into cvs and check it out
		IProject project = createProject("testCommit", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt" });
		
		// Perform some operations on the copy and commit only the top level
		addResources(project, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
		setContentsAndEnsureModified(project.getFile("changed.txt"));
		deleteResources(new IResource[] {project.getFile("deleted.txt")});
		setContentsAndEnsureModified(project.getFile("folder1/a.txt"));
		setContentsAndEnsureModified(project.getFile("folder1/subfolder1/c.txt"));
		
		// Commit the project shallow
		commit(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE), "A commit message");
		
		// Commit a subfolder shallow
		commit(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE), "A commit message");
		
		// Now commit the file specifically
		commit(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO), "A commit message");
		
		// Now commit the rest
		commit(asResourceMapping(new IResource[] { project.getFolder("folder2") }, IResource.DEPTH_INFINITE), "A commit message");
		
		// Check the project out under a different name
		IProject copy = checkoutCopy(project, "-copy");
		assertEquals(project, copy);
	}
	
	public void testTag() throws Exception {
		// Create a test project, import it into cvs and check it out
		IProject project = createProject("testTag", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt" });

		tag(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE), new CVSTag("v1", CVSTag.VERSION));
		tag(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE), new CVSTag("v2", CVSTag.VERSION));
		tag(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO), new CVSTag("v3", CVSTag.VERSION));
		tag(asResourceMapping(new IResource[] { project}, IResource.DEPTH_INFINITE), new CVSTag("v4", CVSTag.VERSION));
	}
	
	public void testBranch() throws Exception {

		if (TeamCVSTestPlugin.IS_UNSTABLE_TEST)
			return;

		// Create a test project, import it into cvs and check it out
		IProject project = createProject("testBranch", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt"  });

		branch(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE), new CVSTag("b1", CVSTag.BRANCH));
		branch(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE), new CVSTag("b2", CVSTag.BRANCH));
		branch(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO), new CVSTag("b3", CVSTag.BRANCH));
		branch(asResourceMapping(new IResource[] { project }, IResource.DEPTH_INFINITE), new CVSTag("b4", CVSTag.BRANCH));
	}
	
	public void testAdd() throws TeamException, CoreException {
		// Create an empty project
		IProject project = createProject("testAdd", new String[] { });
		// add some resources
		buildResources(project, new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt"  }, false);
		// add them to CVS
		add(asResourceMapping(new IResource[] { project }, IResource.DEPTH_ONE));
		add(asResourceMapping(new IResource[] { project.getFolder("folder1") }, IResource.DEPTH_ONE));
		add(asResourceMapping(new IResource[] { project.getFile("folder1/subfolder1/c.txt") }, IResource.DEPTH_ZERO));
		add(asResourceMapping(new IResource[] { project }, IResource.DEPTH_INFINITE));
	}

	public void testCacheBase() throws TeamException, CoreException {
		if (TeamCVSTestPlugin.IS_UNSTABLE_TEST && Util.isMac())
			return;

		IProject project = createProject("testCacheBase", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt"  });
		IProject copy = checkoutCopy(project, "-copy");

		// First, make some local changes and then cache the bases
		setContentsAndEnsureModified(project.getFile("changed.txt"), "Uncommitted text");
		setContentsAndEnsureModified(project.getFile("folder1/b.txt"));
		project.getFile("deleted.txt").delete(false, true, null);
		try {
			cacheBase(project, true /* cache for outgoing and conflicting */);
			cacheBase(project, false /* cache for conflicting only*/);

			// Next, retry after releasing some changes (to ensure proper contents are fetched)
			setContentsAndEnsureModified(copy.getFile("changed.txt"), "Text comited from the copy");
			commitProject(copy);
			cacheBase(project, true /* cache for outgoing and conflicting */);
			cacheBase(project, false /* cache for conflicting only */);
		} catch (TeamException e) {
			// see bug 325553
			logIfCausedByInterruptedIOException(e);
		}
	}

	private void logIfCausedByInterruptedIOException(TeamException e)
			throws TeamException {
		IStatus status = e.getStatus();
		if (status.isMultiStatus()) {
			MultiStatus mstatus = (MultiStatus) status;
			status = mstatus.getChildren()[0];
			if (status instanceof TeamStatus) {
				Throwable ex = status.getException();
				if (ex instanceof CVSCommunicationException) {
					CVSCommunicationException cce = (CVSCommunicationException) ex;
					status = cce.getStatus();
					if (status.isMultiStatus()) {
						if (status.getException() instanceof InterruptedIOException) {
							// Prevent the test from failing but log the exception
							log("org.eclipse.team.tests.cvs.core", e.getStatus());
							return;
						}
					}
				}
			}
		}
		throw e;
	}

	public void testCacheRemote() throws TeamException, CoreException {
		IProject project = createProject("testCacheRemote", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/b.txt", "folder1/subfolder1/c.txt"  });
		IProject copy = checkoutCopy(project, "-copy");
		
		// Make some remote changes
		setContentsAndEnsureModified(copy.getFile("changed.txt"), "Uncommitted text");
		setContentsAndEnsureModified(copy.getFile("folder1/b.txt"));
		commitProject(copy);
		// Delete a local file
		project.getFile("deleted.txt").delete(false, true, null);
		cacheRemote(project);
	}

	private void cacheRemote(IProject project) throws CoreException {
		clearCache(project);
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().refresh(new IProject[] { project }, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
		IResourceDiffTree tree = getAllDiffs(new IProject[] { project });
		ResourceMapping[] mappings = new ResourceMapping[] {new SimpleResourceMapping(project)};
		CacheRemoteContentsOperation op = new CacheRemoteContentsOperation(null, mappings, tree);
		executeHeadless(op);
		ensureRemoteCached(tree);
	}

	private void cacheBase(IProject project, boolean includeOutgoing) throws CoreException {
		clearCache(project);
		CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().refresh(new IProject[] { project }, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
		IResourceDiffTree tree = getAllDiffs(new IProject[] { project });
		ResourceMapping[] mappings = new ResourceMapping[] {new SimpleResourceMapping(project)};
		CacheBaseContentsOperation op = new CacheBaseContentsOperation(null, mappings, tree, includeOutgoing);
		executeHeadless(op);
		ensureBaseCached(tree, includeOutgoing);
	}

	private void ensureRemoteCached(IResourceDiffTree tree) {
		IResource[] resources = tree.getAffectedResources();
		for (IResource resource : resources) {
			IDiff node = tree.getDiff(resource);
			if (node instanceof IThreeWayDiff) {
				IThreeWayDiff twd = (IThreeWayDiff) node;
				IResourceVariant remote = SyncInfoToDiffConverter.getRemoteVariant(twd);
				if (remote != null) {
					boolean isCached = ((CachedResourceVariant)remote).isContentsCached();
					int direction = twd.getDirection();
					if (direction == IThreeWayDiff.CONFLICTING || direction == IThreeWayDiff.INCOMING) {
						assertTrue(NLS.bind("The remote contents should be cached for {0}", new String[] {resource.getFullPath().toString()}), isCached);
					} else {
						assertFalse(NLS.bind("The base contents should NOT be cached for {0}", new String[] {resource.getFullPath().toString()}), isCached);
					}
				}
			}
		}
	}
	
	private void ensureBaseCached(IResourceDiffTree tree, boolean includeOutgoing) throws TeamException, CoreException {
		IResource[] resources = tree.getAffectedResources();
		for (IResource resource : resources) {
			IDiff node = tree.getDiff(resource);
			if (node instanceof IThreeWayDiff) {
				IThreeWayDiff twd = (IThreeWayDiff) node;
				IResourceVariant base = SyncInfoToDiffConverter.getBaseVariant(twd);
				if (base != null) {
					boolean isCached = ((CachedResourceVariant)base).isContentsCached();
					int direction = twd.getDirection();
					if (direction == IThreeWayDiff.CONFLICTING || (includeOutgoing && direction == IThreeWayDiff.OUTGOING)) {
						assertTrue(NLS.bind("The base contents should be cached for {0}", new String[] {resource.getFullPath().toString()}), isCached);
						// For conflicts, ensure that the cache contents do not match the remote
						if (direction == SyncInfo.CONFLICTING) {
							IResourceVariant remote = SyncInfoToDiffConverter.getRemoteVariant(twd);
							if (remote != null) {
								InputStream baseIn = base.getStorage(DEFAULT_MONITOR).getContents();
								if (baseIn == null) {
									fail(NLS.bind("Base was not fetched for {0}", new String[] {resource.getFullPath().toString()}));
								}
								InputStream remoteIn = remote.getStorage(DEFAULT_MONITOR).getContents();
								if (compareContent(baseIn, remoteIn)) {
									fail(NLS.bind("The remote was fetched instead of the base for {0}", new String[] {resource.getFullPath().toString()}));
								}
							}
						}
					} else {
						// assertFalse(NLS.bind("The base contents should NOT be cached for {0}", new String[] {resource.getFullPath().toString()}), isCached);
					}
				}
			}
		}
	}

	private void clearCache(IProject project) {
		ResourceVariantCache cache = ResourceVariantCache.getCache(CVSProviderPlugin.ID);
		if (cache != null) {
			ResourceVariantCacheEntry[] entries = cache.getEntries();
			for (ResourceVariantCacheEntry entry : entries) {
				entry.dispose();
			}
		}
	}
	
	public void testBug134517() throws Exception {
		IProject project = createProject("testBug134517", new String[] { "file1.txt", "file2.txt"});
		IProject copy = checkoutCopy(project, "-copy");
		addResources(copy, new String[] { "file0.txt", 
				"new_folder1/", "new_folder1/file2.txt", "new_folder1/new_folder2/", 
				"new_folder1/new_folder2/new_folder3/", "new_folder1/new_folder2/new_folder3/file3.txt"  }, true);
		IResource[] resources = new IResource[] {
				project.getFile("file0.txt"),
				project.getFile("file1.txt"),
				project.getFile("new_folder1/file2.txt"),
				project.getFile("new_folder1/new_folder2/new_folder3/file3.txt")
		};
		update(asResourceMapping(resources, IResource.DEPTH_ZERO), null);
		assertEquals(project, copy);
	}
	
	public void testDeepNewFolder() throws Exception {
		IProject project = createProject("testBug134517", new String[] { "file1.txt", "file2.txt"});
		IProject copy = checkoutCopy(project, "-copy");
		addResources(copy, new String[] {
				"new_folder1/", 
				"new_folder1/new_folder2/", 
				"new_folder1/new_folder2/new_folder3/", 
				"new_folder1/new_folder2/new_folder3/file3.txt"  }, true);
		IResource[] resources = new IResource[] {
				project.getFolder("new_folder1/new_folder2/new_folder3/")
		};
		update(asResourceMapping(resources, IResource.DEPTH_INFINITE), null);
		assertEquals(project, copy);
	}
}
