*** empty log message ***
diff --git a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/TeamTest.java b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/TeamTest.java
index feb37bf..87060a5 100644
--- a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/TeamTest.java
+++ b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/TeamTest.java
@@ -1,18 +1,82 @@
 package org.eclipse.team.tests.core;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.tests.harness.EclipseWorkspaceTest;
 
 public class TeamTest extends EclipseWorkspaceTest {
+	
+	protected static final int RANDOM_CONTENT_SIZE = 3876;
+	protected static final String PLATFORM_NEWLINE = System.getProperty("line.separator");
+	
 	public TeamTest() {
 		super();
 	}
 	public TeamTest(String name) {
 		super(name);
 	}
+
+	// Assert that the two containers have equal contents
+	protected void assertEquals(IContainer container1, IContainer container2) throws CoreException {
+		assertEquals(container1.getName(), container2.getName());
+		List members1 = new ArrayList();
+		members1.addAll(Arrays.asList(container1.members()));
+		
+		List members2 = new ArrayList();
+		members2.addAll(Arrays.asList(container2.members()));
+		
+		assertTrue(members1.size() == members2.size());
+		for (int i=0;i<members1.size();i++) {
+			IResource member1 = (IResource)members1.get(i);
+			IResource member2 = container2.findMember(member1.getName());
+			assertNotNull(member2);
+			assertEquals(member1, member2);
+		}
+	}
+	
+	// Assert that the two files have equal contents
+	protected void assertEquals(IFile file1, IFile file2) throws CoreException {
+		assertEquals(file1.getName(), file2.getName());
+		assertTrue(compareContent(file1.getContents(), file2.getContents()));
+	}
+	
+	// Assert that the two projects have equal contents ignoreing the project name
+	// and the .vcm_meta file
+	protected void assertEquals(IProject container1, IProject container2) throws CoreException {
+		List members1 = new ArrayList();
+		members1.addAll(Arrays.asList(container1.members()));
+		members1.remove(container1.findMember(".project"));
+		
+		List members2 = new ArrayList();
+		members2.addAll(Arrays.asList(container2.members()));
+		members2.remove(container2.findMember(".project"));
+		
+		assertTrue("Number of children differs for " + container1.getFullPath(), members1.size() == members2.size());
+		for (int i=0;i<members1.size();i++) {
+			IResource member1 = (IResource)members1.get(i);
+			IResource member2 = container2.findMember(member1.getName());
+			assertNotNull(member2);
+			assertEquals(member1, member2);
+		}
+	}
+	protected void assertEquals(IResource resource1, IResource resource2) throws CoreException {
+		assertEquals(resource1.getType(), resource2.getType());
+		if (resource1.getType() == IResource.FILE)
+			assertEquals((IFile)resource1, (IFile)resource2);
+		else 
+			assertEquals((IContainer)resource1, (IContainer)resource2);
+	}
 	
 	protected IProject getNamedTestProject(String name) throws CoreException {
 		IProject target = getWorkspace().getRoot().getProject(name);
@@ -32,4 +96,61 @@
 	protected IStatus getTeamTestStatus(int severity) {
 		return new Status(severity, "org.eclipse.team.tests.core", 0, "team status", null);
 	}
+	
+	/**
+	 * Return the average size of randomly generated contents for files that are created
+	 * by the buildResources(IContainer, String[], boolean) methd.
+	 * Subclasses can override to change the behavior
+	 */
+	protected int getAverageRandomContentSize() {
+		return RANDOM_CONTENT_SIZE;
+	}
+	
+	/**
+	 * genertates Random content meand to be written in a File
+	 */
+	protected static InputStream getRandomContents(int averageSize) {
+		
+		StringBuffer content = new StringBuffer();
+		int contentSize;
+		
+		content.append("Random file generated for test" + PLATFORM_NEWLINE);
+		
+		contentSize = (int) Math.round(averageSize * 2 * Math.random());
+		for (int i=0; i < contentSize; i++) {
+			
+			if (Math.random() > 0.9) {
+				content.append(PLATFORM_NEWLINE);
+			}
+			
+			content.append((char)('\u0021' + Math.round(60 * Math.random())));
+		}
+		
+		return new ByteArrayInputStream(content.toString().getBytes());
+	}
+	
+	/**
+	 * Return a collection of resources defined by hierarchy. The resources
+	 * are added to the workspace and to the file system.
+	 */
+	protected IResource[] buildResources(IContainer container, String[] hierarchy, boolean includeContainer) throws CoreException {
+		List resources = new ArrayList(hierarchy.length + 1);
+		resources.addAll(Arrays.asList(buildResources(container, hierarchy)));
+		if (includeContainer)
+			resources.add(container);
+		IResource[] result = (IResource[]) resources.toArray(new IResource[resources.size()]);
+		ensureExistsInWorkspace(result, true);
+		for (int i = 0; i < result.length; i++) {
+			if (result[i].getType() == IResource.FILE)
+				// 3786 bytes is the average size of Eclipse Java files!
+				 ((IFile) result[i]).setContents(getRandomContents(getAverageRandomContentSize()), true, false, null);
+		}
+		return result;
+	}
+	
+	protected IProject createUniqueTestProject(String prefix, String[] hierarchy) throws CoreException {
+		IProject project = getUniqueTestProject(prefix);
+		buildResources(project, hierarchy, true);
+		return project;
+	}
 }
diff --git a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/ClientTest.java b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/ClientTest.java
index 2eea918..05d61db 100644
--- a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/ClientTest.java
+++ b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/ClientTest.java
@@ -14,10 +14,18 @@
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.team.internal.ftp.FTPException;
 import org.eclipse.team.internal.ftp.client.FTPClient;
+import org.eclipse.team.internal.ftp.client.FTPDirectoryEntry;
 import org.eclipse.team.tests.core.TeamTest;
 
 public class ClientTest extends TeamTest {
@@ -48,23 +56,99 @@
 		return FTPTestSetup.openFTPConnection(getURL());
 	}
 	
-	public void testCreateDirectory() throws FTPException {
-		FTPClient client = openFTPConnection();
-		try {
-			client.createDirectory("testCreateDirectory", DEFAULT_PROGRESS_MONITOR);
-			client.deleteDirectory("testCreateDirectory", DEFAULT_PROGRESS_MONITOR);
-		} finally {
-			client.close(DEFAULT_PROGRESS_MONITOR);
+	public void putContainer(IContainer container, FTPClient client) throws FTPException, CoreException {
+		client.createDirectory(container.getName(), DEFAULT_PROGRESS_MONITOR);
+		client.changeDirectory(container.getName(), DEFAULT_PROGRESS_MONITOR);
+		IResource[] members = container.members();
+		for (int i = 0; i < members.length; i++) {
+			IResource resource = members[i];
+			if (resource.getType() == IResource.FILE) {
+				client.putFile(resource.getName(), (IFile)resource, false, DEFAULT_PROGRESS_MONITOR);
+			} else {
+				putContainer((IContainer)resource, client);
+			}
 		}
+		client.changeDirectory(FTPClient.PARENT_DIRECTORY, DEFAULT_PROGRESS_MONITOR);
 	}
 	
-	public void testSimpleTransfer() throws FTPException {
+	public void getAll(String sourceFolder, IContainer container, FTPClient client) throws FTPException, CoreException {
+		if (sourceFolder.indexOf('/') == 0) {
+			sourceFolder = sourceFolder.substring(1);
+		}
+		client.changeDirectory(sourceFolder, DEFAULT_PROGRESS_MONITOR);
+		if ( ! container.exists()) {
+			((IFolder)container).create(false, true, DEFAULT_PROGRESS_MONITOR);
+		}
+		FTPDirectoryEntry[] entries = client.listFiles(null, DEFAULT_PROGRESS_MONITOR);
+		for (int i = 0; i < entries.length; i++) {
+			FTPDirectoryEntry entry = entries[i];
+			if (entry.hasFileSemantics()) {
+				client.getFile(entry.getName(), container.getFile(new Path(entry.getName())), false, false, DEFAULT_PROGRESS_MONITOR);
+			} else if (entry.hasDirectorySemantics()) {
+				getAll(entry.getName(), container.getFolder(new Path(entry.getName())), client);
+			}
+		}
+		// Assumes sourceFolder is a one segment path
+		client.changeDirectory(FTPClient.PARENT_DIRECTORY, DEFAULT_PROGRESS_MONITOR);
+	}
+	
+	public void testSimpleFileTransfer() throws FTPException, CoreException {
+		String fileName = "file1.txt";
+		IProject project = createUniqueTestProject("testSimpleFileTransferSource", new String[] {fileName});
 		FTPClient client = openFTPConnection();
 		try {
-			client.createDirectory("testCreateDirectory", DEFAULT_PROGRESS_MONITOR);
-			client.deleteDirectory("testCreateDirectory", DEFAULT_PROGRESS_MONITOR);
+			client.createDirectory(project.getName(), DEFAULT_PROGRESS_MONITOR);
+			client.changeDirectory(project.getName(), DEFAULT_PROGRESS_MONITOR);
+			client.putFile(fileName, project.getFile(fileName), false, DEFAULT_PROGRESS_MONITOR);
+			client.getFile(fileName, project.getFile("CopyOf" + fileName), false, false, DEFAULT_PROGRESS_MONITOR);
 		} finally {
 			client.close(DEFAULT_PROGRESS_MONITOR);
 		}
+		assertTrue(compareContent(project.getFile(fileName).getContents(), project.getFile("CopyOf" + fileName).getContents()));
 	}
+
+	public void testDeepFileTransfer() throws FTPException, CoreException {
+		String deepFileName = "folder2/folder3/deep.txt";
+		IProject project = createUniqueTestProject("testDeepFileTransfer", 
+			new String[] {"file1.txt", "folder1/a.txt", "folder1/b.txt", deepFileName});
+		FTPClient client = openFTPConnection();
+		try {
+			putContainer(project, client);
+			client.changeDirectory(project.getName(), DEFAULT_PROGRESS_MONITOR);
+			client.putFile(deepFileName, project.getFile(deepFileName), false, DEFAULT_PROGRESS_MONITOR);
+			client.getFile(deepFileName, project.getFile("deepFile"), false, false, DEFAULT_PROGRESS_MONITOR);
+		} finally {
+			client.close(DEFAULT_PROGRESS_MONITOR);
+		}
+		assertTrue(compareContent(project.getFile(deepFileName).getContents(), project.getFile("deepFile").getContents()));
+	}
+		
+	public void testProjectTransfer() throws FTPException, CoreException {
+		IProject project = createUniqueTestProject("testProjectTransfer", 
+			new String[] {"file1.txt", "folder1/a.txt", "folder1/b.txt", "folder2/folder3/"});
+		IProject copy = getUniqueTestProject("testProjectTransferDest");
+		FTPClient client = openFTPConnection();
+		try {
+			putContainer(project, client);
+			getAll(project.getName(), copy, client);
+		} finally {
+			client.close(DEFAULT_PROGRESS_MONITOR);
+		}
+		assertEquals(project, copy);
+	}
+	
+	public void testFolderTransfer() throws FTPException, CoreException {
+		IProject project = createUniqueTestProject("testFolderTransfer", 
+			new String[] {"file1.txt", "folder1/a.txt", "folder1/b.txt", "folder2/folder3/"});
+		IProject copy = getUniqueTestProject("testProjectTransferDest");
+		FTPClient client = openFTPConnection();
+		try {
+			putContainer(project, client);
+			getAll(project.getFolder("folder1").getFullPath().toString(), copy.getFolder("folder1"), client);
+		} finally {
+			client.close(DEFAULT_PROGRESS_MONITOR);
+		}
+		assertEquals(project.getFolder("folder1"), copy.getFolder("folder1"));
+	}
+	
 }
diff --git a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/FTPTestSetup.java b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/FTPTestSetup.java
index 3790be9..35d123f 100644
--- a/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/FTPTestSetup.java
+++ b/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/ftp/FTPTestSetup.java
@@ -34,6 +34,8 @@
 
 	public static final String FTP_URL;
 	public static final boolean SCRUB_URL;
+	public static final boolean DEBUG;
+	public static final String SCRUB_DISABLE_FILE = ".donotscrub";
 	
 	private static final IProgressMonitor DEFAULT_PROGRESS_MONITOR = new NullProgressMonitor();
 	
@@ -44,6 +46,7 @@
 		loadProperties();
 		FTP_URL = System.getProperty("eclipse.ftp.url");
 		SCRUB_URL = Boolean.valueOf(System.getProperty("eclipse.ftp.init", "false")).booleanValue();
+		DEBUG = Boolean.valueOf(System.getProperty("eclipse.ftp.debug", "false")).booleanValue();
 	}
 	
 	public static void loadProperties() {
@@ -84,11 +87,17 @@
 	protected void scrubCurrentDirectory(FTPClient client) throws FTPException {
 		FTPDirectoryEntry[] entries = client.listFiles(null, DEFAULT_PROGRESS_MONITOR);
 		for (int i = 0; i < entries.length; i++) {
+			if (entries[i].getName().equals(SCRUB_DISABLE_FILE)) return;
+		}
+		for (int i = 0; i < entries.length; i++) {
 			FTPDirectoryEntry entry = entries[i];
 			if (entry.hasFileSemantics()) {
 				client.deleteFile(entry.getName(), DEFAULT_PROGRESS_MONITOR);
 			}
 			if (entry.hasDirectorySemantics()) {
+				client.changeDirectory(entry.getName(), DEFAULT_PROGRESS_MONITOR);
+				scrubCurrentDirectory(client);
+				client.changeDirectory(FTPClient.PARENT_DIRECTORY, DEFAULT_PROGRESS_MONITOR);
 				client.deleteDirectory(entry.getName(), DEFAULT_PROGRESS_MONITOR);
 			}
 		}
@@ -97,7 +106,7 @@
 	protected URL setupURL(String urlString) throws MalformedURLException, FTPException {
 
 		// Give some info about which repository the tests are running against
-		System.out.println("Connecting to: " + urlString);
+		if (DEBUG) System.out.println("Connecting to: " + urlString);
 		
 		// Validate that we can connect, also creates and caches the repository location. This
 		// is important for the UI tests.
@@ -108,6 +117,7 @@
 			// Initialize the repo if requested
 			// For safety, do not scrub if no path is provided
 			if( SCRUB_URL && ! new Path(url.getPath()).isEmpty()) {
+				if (DEBUG) System.out.println("Scrubbing: " + url.getPath());
 				scrubCurrentDirectory(client);
 			}
 		} finally {
@@ -125,25 +135,35 @@
 		FTPServerLocation location = FTPServerLocation.fromURL(url, false);
 		FTPClient client = new FTPClient(location, null, getListener());
 		client.open(DEFAULT_PROGRESS_MONITOR);
+		String urlPath = url.getPath();
+		// Strip leading slash
+		if (urlPath.indexOf('/') == 0) {
+			urlPath = urlPath.substring(1);
+		}
 		try {
-			client.createDirectory(url.getPath(), DEFAULT_PROGRESS_MONITOR);
+			client.createDirectory(urlPath, DEFAULT_PROGRESS_MONITOR);
 		} catch (FTPException e) {
 			// Ignore the exception
 		}
-		client.changeDirectory(url.getPath(), DEFAULT_PROGRESS_MONITOR);
+		try {
+			client.changeDirectory(urlPath, DEFAULT_PROGRESS_MONITOR);
+		} catch (FTPException e) {
+			client.close(DEFAULT_PROGRESS_MONITOR);
+			throw e;
+		}
 		return client;
 	}
 	
 	public static IFTPClientListener getListener() {
 		return new IFTPClientListener() {
 			public void responseReceived(int responseCode, String responseText) {
-				System.out.println(responseText);
+				if (DEBUG) System.out.println(responseText);
 			}
 			public void requestSent(String command, String argument) {
 				if (argument != null) {
-					System.out.println(command + " " + argument);
+					if (DEBUG) System.out.println(command + " " + argument);
 				} else {
-					System.out.println(command);
+					if (DEBUG) System.out.println(command);
 				}
 			}
 		};