diff options
author | cvs2svn | 2005-10-17 01:05:09 +0000 |
---|---|---|
committer | cvs2svn | 2005-10-17 01:05:09 +0000 |
commit | 18523542e483f6bdf85d7e1bcfc2bd75169c5d94 (patch) | |
tree | 7c95a9d05459cd5108fc8ff30156a5db1b533a06 /tests | |
parent | 4d7f1ed2fba58c1df04d36f0b1a44c09d668d663 (diff) | |
download | eclipse.platform.team-18523542e483f6bdf85d7e1bcfc2bd75169c5d94.tar.gz eclipse.platform.team-18523542e483f6bdf85d7e1bcfc2bd75169c5d94.tar.xz eclipse.platform.team-18523542e483f6bdf85d7e1bcfc2bd75169c5d94.zip |
This commit was manufactured by cvs2svn to create branch
'branch_20050711_LogicalModelSupport'.
Cherrypick from master 2005-10-17 01:05:07 UTC Michael Valenta <mvalenta> 'Bug 57191 (PatchAttached)[Decorators] Display of CVS tag property of a file in mixed project is not correct':
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSResource.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/client/RemovedHandler.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/connection/CVSRepositoryLocation.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java
bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java
bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/dialogs/MultipleYesNoPrompter.java
tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java
tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/ResourceMapperTests.java
tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/SyncInfoSetTraveralContext.java
tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java
Diffstat (limited to 'tests')
4 files changed, 1947 insertions, 0 deletions
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java new file mode 100644 index 000000000..c261a4b0a --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/EclipseTest.java @@ -0,0 +1,1298 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.core; +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +import junit.framework.*; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.tests.resources.ResourceTest; +import org.eclipse.swt.widgets.Display; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.internal.ccvs.core.*; +import org.eclipse.team.internal.ccvs.core.client.*; +import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; +import org.eclipse.team.internal.ccvs.core.connection.*; +import org.eclipse.team.internal.ccvs.core.resources.*; +import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; +import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; +import org.eclipse.team.internal.ccvs.core.util.SyncFileChangeListener; +import org.eclipse.team.internal.ccvs.ui.operations.*; +import org.eclipse.team.internal.core.subscribers.SubscriberSyncInfoCollector; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.internal.decorators.DecoratorManager; + +public class EclipseTest extends ResourceTest { + + private static final int LOCK_WAIT_TIME = 1000; + private static final String CVS_TEST_LOCK_FILE = ".lock"; + private static final String CVS_TEST_LOCK_PROJECT = "cvsTestLock"; + protected static IProgressMonitor DEFAULT_MONITOR = new NullProgressMonitor(); + protected static final int RANDOM_CONTENT_SIZE = 3876; + protected static String eol = System.getProperty("line.separator"); + private static final long LOCK_EXPIRATION_THRESHOLD = 1000 * 60 * 10; // 10 minutes + private static final int MAX_LOCK_ATTEMPTS = 60 * 30; // 30 minutes + private String lockId; + + public static Test suite(Class c) { + String testName = System.getProperty("eclipse.cvs.testName"); + if (testName == null) { + TestSuite suite = new TestSuite(c); + return new CVSTestSetup(suite); + } else { + try { + return new CVSTestSetup((Test)c.getConstructor(new Class[] { String.class }).newInstance(new Object[] {testName})); + } catch (Exception e) { + fail(e.getMessage()); + // Above will throw so below is never actually reached + return null; + } + } + } + + public EclipseTest() { + super(); + if (eol == null) eol = "\n"; + } + + public EclipseTest(String name) { + super(name); + if (eol == null) eol = "\n"; + } + + /* + * Get the resources for the given resource names + */ + public IResource[] getResources(IContainer container, String[] hierarchy) throws CoreException { + IResource[] resources = new IResource[hierarchy.length]; + for (int i=0;i<resources.length;i++) { + resources[i] = container.findMember(hierarchy[i]); + if (resources[i] == null) { + resources[i] = buildResources(container, new String[] {hierarchy[i]})[0]; + } + } + return resources; + } + + /** + * Add the resources to an existing container and upload them to CVS + */ + public IResource[] addResources(IContainer container, String[] hierarchy, boolean checkin) throws CoreException, TeamException { + IResource[] newResources = buildResources(container, hierarchy, false); + addResources(newResources); + if (checkin) commitResources(newResources, IResource.DEPTH_ZERO); + return newResources; + } + + protected void addResources(IResource[] newResources) throws CoreException { + if (newResources.length == 0) return; + ResourceMapping[] mappings = asResourceMappers(newResources, IResource.DEPTH_INFINITE); + add(mappings); + } + + protected void add(ResourceMapping[] mappings) throws CVSException { + executeHeadless(new AddOperation(null, mappings)); + } + + /** + * Perform a CVS edit of the given resources + */ + public IResource[] editResources(IContainer container, String[] hierarchy) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + getProvider(container).edit(resources, true /* recurse */, true /* notifyServer */, false /* notifyForWritable */, ICVSFile.NO_NOTIFICATION, DEFAULT_MONITOR); + assertReadOnly(resources, false /* isReadOnly */, true /* recurse */); + return resources; + } + + /** + * Perform a CVS unedit of the given resources + */ + public IResource[] uneditResources(IContainer container, String[] hierarchy) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + getProvider(container).unedit(resources, true /* recurse */, true/* notifyServer */, DEFAULT_MONITOR); + assertReadOnly(resources, true /* isReadOnly */, true /* recurse */); + return resources; + } + + public void appendText(IResource resource, String text, boolean prepend) throws CoreException, IOException, CVSException { + IFile file = (IFile)resource; + String contents = getFileContents(file); + StringBuffer buffer = new StringBuffer(); + if (prepend) { + buffer.append(text); + } + buffer.append(contents); + if (!prepend) { + buffer.append(eol + text); + } + setContentsAndEnsureModified(file, buffer.toString()); + } + + public void assertEndsWith(IFile file, String text) throws IOException, CoreException { + assertTrue(getFileContents(file).endsWith(text)); + } + + public void assertStartsWith(IFile file, String text) throws IOException, CoreException { + assertTrue(getFileContents(file).startsWith(text)); + } + + public static String getFileContents(IFile file) throws IOException, CoreException { + StringBuffer buf = new StringBuffer(); + Reader reader = new InputStreamReader(new BufferedInputStream(file.getContents())); + try { + int c; + while ((c = reader.read()) != -1) buf.append((char)c); + } finally { + reader.close(); + } + return buf.toString(); + } + + /** + * Delete the resources from an existing container and the changes to CVS + */ + public IResource[] changeResources(IContainer container, String[] hierarchy, boolean checkin) throws CoreException, TeamException { + List changedResources = new ArrayList(hierarchy.length); + for (int i=0;i<hierarchy.length;i++) { + IResource resource = container.findMember(hierarchy[i]); + if (resource.getType() == IResource.FILE) { + changedResources.add(resource); + setContentsAndEnsureModified((IFile)resource); + } + } + IResource[] resources = (IResource[])changedResources.toArray(new IResource[changedResources.size()]); + if (checkin) commitResources(resources, IResource.DEPTH_ZERO); + return resources; + } + + /** + * Delete the resources from an existing container and the changes to CVS + */ + public IResource[] deleteResources(IContainer container, String[] hierarchy, boolean checkin) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + deleteResources(resources); + if (checkin) + commitResources(resources, IResource.DEPTH_INFINITE); + return resources; + } + + /** + * Delete the resources and mark them as outgoing deletions. + * Deleting the resources is enough since the move/delete hook will + * tak care of making them outgoing deletions. + */ + protected void deleteResources(IResource[] resources) throws TeamException, CoreException { + if (resources.length == 0) return; + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + resource.delete(false, DEFAULT_MONITOR); + } + } + /** + * Unmanage the resources + */ + public void unmanageResources(IContainer container, String[] hierarchy) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + unmanageResources(resources); + } + + protected void unmanageResources(IResource[] resources) throws TeamException, CoreException { + for (int i=0;i<resources.length;i++) { + CVSWorkspaceRoot.getCVSResourceFor(resources[i]).unmanage(null); + } + } + + /** + * Update the resources from an existing container with the changes from the CVS repository + */ + public IResource[] updateResources(IContainer container, String[] hierarchy, boolean ignoreLocalChanges) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + return updateResources(resources, ignoreLocalChanges); + } + + /** + * Update the resources from an existing container with the changes from the CVS repository + */ + protected IResource[] updateResources(IResource[] resources, boolean ignoreLocalChanges) throws CVSException { + LocalOption[] options = Command.NO_LOCAL_OPTIONS; + if(ignoreLocalChanges) { + options = new LocalOption[] {Update.IGNORE_LOCAL_CHANGES}; + } + ResourceMapping[] mappers = asResourceMappers(resources, IResource.DEPTH_INFINITE); + update(mappers, options); + return resources; + } + + /** + * Update the resources contained in the given mappers. + */ + protected void update(ResourceMapping[] mappers, LocalOption[] options) throws CVSException { + if (options == null) + options = Command.NO_LOCAL_OPTIONS; + executeHeadless(new UpdateOperation(null, mappers, options, null)); + } + + protected void replace(IContainer container, String[] hierarchy, CVSTag tag, boolean recurse) throws CoreException { + IResource[] resources = getResources(container, hierarchy); + replace(resources, tag, recurse); + } + + protected void replace(IResource[] resources, CVSTag tag, boolean recurse) throws CoreException { + ReplaceOperation op = new ReplaceOperation(null, resources, tag, recurse); + executeHeadless(op); + } + + protected void replace(ResourceMapping[] mappers) throws CVSException { + executeHeadless(new ReplaceOperation(null, mappers, null)); + } + + public void updateProject(IProject project, CVSTag tag, boolean ignoreLocalChanges) throws TeamException { + LocalOption[] options = Command.NO_LOCAL_OPTIONS; + if(ignoreLocalChanges) { + options = new LocalOption[] {Update.IGNORE_LOCAL_CHANGES}; + } + executeHeadless(new UpdateOperation(null, new IResource[] {project}, options, tag)); + } + + public void commitProject(IProject project) throws TeamException, CoreException { + commitResources(project, true); + } + + public void commitResources(IContainer container, boolean deep) throws TeamException, CoreException { + commitResources(new IResource[] {container }, deep?IResource.DEPTH_INFINITE:IResource.DEPTH_ZERO); + } + + /** + * Commit the resources from an existing container to the CVS repository + */ + public IResource[] commitResources(IContainer container, String[] hierarchy) throws CoreException, TeamException { + IResource[] resources = getResources(container, hierarchy); + commitResources(resources, IResource.DEPTH_ZERO); + return resources; + } + + protected void commitResources(IResource[] resources, int depth) throws TeamException, CoreException { + commitResources(resources, depth, ""); + } + + /* + * Commit the provided resources which must all be in the same project + */ + protected void commitResources(IResource[] resources, int depth, String message) throws TeamException, CoreException { + if (resources.length == 0) return; + ResourceMapping[] resourceMappers = asResourceMappers(resources, depth); + commit(resourceMappers, message); + } + + /** + * Commit the resources contained by the mappers. + */ + protected void commit(ResourceMapping[] mappers, String message) throws CVSException { + executeHeadless(new CommitOperation(null, mappers, new Command.LocalOption[0], message)); + } + + /** + * Convert the resources to a resource mapper that traverses the resources + * to the specified depth. + * @param resources the resource + * @return a resource mapper for traversing the resources to the depth specified + */ + protected ResourceMapping[] asResourceMappers(IResource[] resources, int depth) { + return WorkspaceResourceMapper.asResourceMappers(resources, depth); + } + + protected ICVSResource asCVSResource(IResource resource) { + return CVSWorkspaceRoot.getCVSResourceFor(resource); + } + + /** + * Commit the resources from an existing container to the CVS repository + */ + public void tagProject(IProject project, CVSTag tag, boolean force) throws TeamException { + ResourceMapping[] mappings = RepositoryProviderOperation.asResourceMappers(new IResource[] {project}); + tag(mappings, tag, force); + } + + /** + * Tag the resources contained in the given mappings + */ + protected void tag(ResourceMapping[] mappings, CVSTag tag, boolean force) throws TeamException { + ITagOperation op = new TagOperation((IWorkbenchPart)null, mappings); + runTag(op, tag, force); + } + + public void tagRemoteResource(ICVSRemoteResource resource, CVSTag tag, boolean force) throws TeamException { + ITagOperation op = new TagInRepositoryOperation(null, new ICVSRemoteResource[] {resource}); + runTag(op, tag, force); + } + + private void runTag(ITagOperation op, CVSTag tag, boolean force) throws TeamException { + if (force) op.moveTag(); + op.setTag(tag); + try { + ((CVSOperation)op).run(DEFAULT_MONITOR); + } catch (InterruptedException e) { + fail("Tag interrupted."); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof TeamException) { + throw (TeamException) e.getTargetException(); + } else { + e.printStackTrace(); + fail("Unexpected error while tagging"); + } + } + } + public void makeBranch(IResource[] resources, CVSTag version, CVSTag branch, boolean update) throws CVSException { + ResourceMapping[] mappings = asResourceMappers(resources, IResource.DEPTH_INFINITE); + branch(mappings, version, branch, update); + } + + protected void branch(ResourceMapping[] mappings, CVSTag version, CVSTag branch, boolean update) throws CVSException { + BranchOperation op = new BranchOperation(null, mappings); + op.setTags(version, branch, update); + executeHeadless(op); + } + + /** + * Return a collection of resources defined by hierarchy. The resources + * are added to the workspace and to the file system. If the manage flag is true, the + * resources are auto-managed, if false, they are left un-managed. + */ + public 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(RANDOM_CONTENT_SIZE), true, false, null); + } + return result; + } + + /* + * Checkout a copy of the project into a project with the given postfix + */ + protected IProject checkoutCopy(IProject project, String postfix) throws TeamException { + // Check the project out under a different name and validate that the results are the same + IProject copy = getWorkspace().getRoot().getProject(project.getName() + postfix); + checkout(getRepository(), copy, CVSWorkspaceRoot.getCVSFolderFor(project).getFolderSyncInfo().getRepository(), null, DEFAULT_MONITOR); + return copy; + } + + protected IProject checkoutCopy(IProject project, CVSTag tag) throws TeamException { + // Check the project out under a different name and validate that the results are the same + IProject copy = getWorkspace().getRoot().getProject(project.getName() + tag.getName()); + checkout(getRepository(), copy, + CVSWorkspaceRoot.getCVSFolderFor(project).getFolderSyncInfo().getRepository(), + tag, DEFAULT_MONITOR); + return copy; + } + + public static void checkout( + final ICVSRepositoryLocation repository, + final IProject project, + final String sourceModule, + final CVSTag tag, + IProgressMonitor monitor) + throws TeamException { + + RemoteFolder remote = new RemoteFolder(null, repository, sourceModule == null ? project.getName() : sourceModule, tag); + executeHeadless(new CheckoutSingleProjectOperation(null, remote, project, null, false /* the project is not preconfigured */) { + public boolean promptToOverwrite(String title, String msg) { + return true; + } + }); + + } + + protected IProject checkoutProject(IProject project, String moduleName, CVSTag tag) throws TeamException { + if (project == null) + project = getWorkspace().getRoot().getProject(new Path(moduleName).lastSegment()); + checkout(getRepository(), project, moduleName, tag, DEFAULT_MONITOR); + return project; + } + /* + * This method creates a project with the given resources, imports + * it to CVS and checks it out + */ + protected IProject createProject(String prefix, String[] resources) throws CoreException, TeamException { + IProject project = getUniqueTestProject(prefix); + buildResources(project, resources, true); + shareProject(project); + assertValidCheckout(project); + return project; + } + + /* + * Create a test project using the currently running test case as the project name prefix + */ + protected IProject createProject(String[] strings) throws CoreException { + return createProject(getName(), strings); + } + + /* + * Compare two projects by comparing thier providers + */ + protected void assertEquals(IProject project1, IProject project2) throws CoreException, IOException { + assertEquals(project1, project2, false, false); + } + + protected void assertEquals(IProject project1, IProject project2, boolean includeTimestamps, boolean includeTags) throws CoreException, IOException { + assertEquals(getProvider(project1), getProvider(project2), includeTimestamps, includeTags); + } + + /* + * Compare CVS team providers by comparing the cvs resource corresponding to the provider's project + */ + protected void assertEquals(CVSTeamProvider provider1, CVSTeamProvider provider2, boolean includeTimestamps, boolean includeTags) throws CoreException, IOException { + assertEquals(Path.EMPTY, CVSWorkspaceRoot.getCVSFolderFor(provider1.getProject()), + CVSWorkspaceRoot.getCVSFolderFor(provider2.getProject()), + includeTimestamps, includeTags); + } + + protected void assertContentsEqual(IContainer c1, IContainer c2) throws CoreException { + assertTrue("The number of resource in " + c1.getProjectRelativePath().toString() + " differs", + c1.members().length == c2.members().length); + IResource[] resources = c1.members(); + for (int i= 0;i <resources.length;i++) { + assertContentsEqual(resources[i], c2.findMember(resources[i].getName())); + } + } + + protected void assertContentsEqual(IResource resource, IResource resource2) throws CoreException { + if (resource.getType() == IResource.FILE) { + assertContentsEqual((IFile)resource, (IFile)resource2); + } else { + assertContentsEqual((IContainer)resource, (IContainer)resource2); + } + } + + protected void assertContentsEqual(IFile resource, IFile resource2) throws CoreException { + assertTrue("Contents of " + resource.getProjectRelativePath() + " do not match", compareContent(resource.getContents(), resource2.getContents())); + } + /* + * Compare resources by casting them to their prpoer type + */ + protected void assertEquals(IPath parent, ICVSResource resource1, ICVSResource resource2, boolean includeTimestamps, boolean includeTags) throws CoreException, CVSException, IOException { + if ((resource1 == null && resource2 == null) + || (resource1 == null && ! resource2.exists()) + || (resource2 == null && ! resource1.exists())) + return; + assertEquals("Resource types do not match for " + parent.append(resource1.getName()), resource1.isFolder(), resource2.isFolder()); + if (!resource1.isFolder()) + assertEquals(parent, (ICVSFile)resource1, (ICVSFile)resource2, includeTimestamps, includeTags); + else + assertEquals(parent, (ICVSFolder)resource1, (ICVSFolder)resource2, includeTimestamps, includeTags); + } + + /* + * Compare folders by comparing their folder sync info and there children + * + * XXX What about unmanaged children? + */ + protected void assertEquals(IPath parent, ICVSFolder container1, ICVSFolder container2, boolean includeTimestamps, boolean includeTags) throws CoreException, CVSException, IOException { + IPath path = parent.append(container1.getName()); + assertEquals(path, container1.getFolderSyncInfo(), container2.getFolderSyncInfo(), includeTags); + assertTrue("The number of resource in " + path.toString() + " differs", + container1.members(ICVSFolder.ALL_EXISTING_MEMBERS).length + == container2.members(ICVSFolder.ALL_EXISTING_MEMBERS).length); + ICVSResource[] resources = container1.members(ICVSFolder.ALL_EXISTING_MEMBERS); + for (int i= 0;i <resources.length;i++) { + assertEquals(path, resources[i], container2.getChild(resources[i].getName()), includeTimestamps, includeTags); + } + + } + + /* + * Compare the files contents and sync information + */ + protected void assertEquals(IPath parent, ICVSFile file1, ICVSFile file2, boolean includeTimestamps, boolean includeTags) throws CoreException, CVSException, IOException { + if (file1.getName().equals(".project")) return; + // Getting the contents first is important as it will fetch the proper sync info if one of the files is a remote handle + assertTrue("Contents of " + parent.append(file1.getName()) + " do not match", compareContent(getContents(file1), getContents(file2))); + assertEquals(parent.append(file1.getName()), file1.getSyncInfo(), file2.getSyncInfo(), includeTimestamps, includeTags); + } + + /* + * Compare sync info by comparing the entry line generated by the sync info + */ + protected void assertEquals(IPath path, ResourceSyncInfo info1, ResourceSyncInfo info2, boolean includeTimestamp, boolean includeTag) throws CoreException, CVSException, IOException { + if (info1 == null || info2 == null) { + if (info1 == info2) return; + if (info1 == null) { + fail("Expected no resource sync info for " + path.toString() + " but it was " + info2 + " instead"); + } + if (info2 == null) { + fail("Expected resource sync info of " + info1 + " for " + path.toString() + " but there was no sync info."); + } + fail("Shouldn't be able to get here"); + return; + } + String line1; + String line2; + if(includeTimestamp) { + line1 = info1.getEntryLine(); + line2 = info2.getEntryLine(); + } else { + line1 = info1.getServerEntryLine(null); + line2 = info2.getServerEntryLine(null); + } + if (!includeTag) { + // Strip everything past the last slash + line1 = line1.substring(0, line1.lastIndexOf('/')); + line2 = line2.substring(0, line2.lastIndexOf('/')); + } + assertEquals("Resource Sync info differs for " + path.toString(), line1, line2); + } + + /* + * Use the equals of folder sync info unless the tag is not included in which case we just + * compare the root and repository + */ + protected void assertEquals(IPath path, FolderSyncInfo info1, FolderSyncInfo info2, boolean includeTag) throws CoreException, CVSException, IOException { + if (info1 == null && info2 == null) { + return; + } else if (info1 == null) { + fail("Expected " + path.toString() + " not to be a CVS folder but it is."); + } else if (info2 == null) { + fail("Expected " + path.toString() + " to be a CVS folder but it isn't."); + } + + if (includeTag) { + assertTrue("Folder sync info differs for " + path.toString(), info1.equals(info2)); + } else { + assertTrue("Repository Root differs for " + path.toString(), info1.getRoot().equals(info2.getRoot())); + assertTrue("Repository relative path differs for " + path.toString(), info1.getRepository().equals(info2.getRepository())); + } + } + + + /* + * Compare folders by comparing their folder sync info and there children + * + * XXX What about unmanaged children? + */ + protected void assertEquals(IPath parent, RemoteFolder container1, RemoteFolder container2, boolean includeTags) throws CoreException, TeamException, IOException { + IPath path = parent.append(container1.getName()); + assertEquals(path, container1.getFolderSyncInfo(), container2.getFolderSyncInfo(), includeTags); + ICVSRemoteResource[] members1 = container1.getMembers(DEFAULT_MONITOR); + ICVSRemoteResource[] members2 = container2.getMembers(DEFAULT_MONITOR); + assertTrue("Number of members differ for " + path, members1.length == members2.length); + Map memberMap2 = new HashMap(); + for (int i= 0;i <members2.length;i++) { + memberMap2.put(members2[i].getName(), members2[i]); + } + for (int i= 0;i <members1.length;i++) { + ICVSRemoteResource member2 = (ICVSRemoteResource)memberMap2.get(members1[i].getName()); + assertNotNull("Resource does not exist: " + path.append(members1[i].getName()) + member2); + assertEquals(path, members1[i], member2, includeTags); + } + } + protected void assertEquals(IPath parent, ICVSRemoteResource resource1, ICVSRemoteResource resource2, boolean includeTags) throws CoreException, TeamException, IOException { + assertEquals("Resource types do not match for " + parent.append(resource1.getName()), resource1.isContainer(), resource2.isContainer()); + if (resource1.isContainer()) + assertEquals(parent, (RemoteFolder)resource1, (RemoteFolder)resource2, includeTags); + else + assertEquals(parent, (ICVSFile)resource1, (ICVSFile)resource2, false, includeTags); + } + + + /* + * Compare the local project with the remote state by checking out a copy of the project. + */ + protected void assertLocalStateEqualsRemote(IProject project) throws TeamException, CoreException, IOException { + assertEquals(getProvider(project), getProvider(checkoutCopy(project, "-remote")), false, true); + } + + /* + * Compare the local project with the remote state indicated by the given tag by checking out a copy of the project. + */ + protected void assertLocalStateEqualsRemote(String message, IProject project, CVSTag tag) throws TeamException, CoreException, IOException { + assertEquals(getProvider(project), getProvider(checkoutCopy(project, tag)), true, false); + } + + protected void assertHasNoRemote(String prefix, IResource[] resources) throws TeamException { + for (int i=0;i<resources.length;i++) + assertHasNoRemote(prefix, resources[i]); + } + + protected void assertHasNoRemote(String prefix, IResource resource) throws TeamException { + assertTrue(prefix + " resource should not have a remote", !CVSWorkspaceRoot.hasRemote(resource)); + } + + protected void assertHasRemote(String prefix, IResource[] resources) throws TeamException { + for (int i=0;i<resources.length;i++) + assertHasRemote(prefix, resources[i]); + } + + protected void assertHasRemote(String prefix, IResource resource) throws TeamException { + assertTrue(prefix + " resource should have a remote", CVSWorkspaceRoot.hasRemote(resource)); + } + + protected void assertIsModified(String prefix, IResource[] resources) throws TeamException { + for (int i=0;i<resources.length;i++) + assertIsModified(prefix, resources[i]); + } + + protected void assertIsModified(String prefix, IResource resource) throws TeamException { + // Only check for files as CVS doesn't dirty folders + if (resource.getType() == IResource.FILE) + assertTrue(prefix + " resource " + resource.getFullPath() + " should be dirty.", ((ICVSFile)getCVSResource(resource)).isModified(null)); + } + + protected void assertNotModified(String prefix, IResource[] resources) throws TeamException { + for (int i=0;i<resources.length;i++) + assertNotModified(prefix, resources[i]); + } + + protected void assertNotModified(String prefix, IResource resource) throws TeamException { + assertTrue(prefix + " resource should be dirty", !((ICVSFile)getCVSResource(resource)).isModified(null)); + } + + protected void assertIsIgnored(IResource resource, boolean ignoredState) throws TeamException { + assertEquals("Resource " + resource.getFullPath() + " should be ignored but isn't.", + ignoredState, getCVSResource(resource).isIgnored()); + } + + protected void assertValidCheckout(IProject project) { + // NOTE: Add code to ensure that the project was checkout out properly + CVSTeamProvider provider = (CVSTeamProvider)RepositoryProvider.getProvider(project); + assertNotNull(provider); + } + + protected void assertReadOnly(IResource[] resources, final boolean isReadOnly, final boolean recurse) throws CoreException { + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + resource.accept(new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + assertEquals(isReadOnly, resource.isReadOnly()); + } + return recurse; + } + }); + } + } + + protected InputStream getContents(ICVSFile file) throws CVSException, IOException { + if (file instanceof ICVSRemoteFile) + return ((RemoteFile)file).getContents(DEFAULT_MONITOR); + else + return new BufferedInputStream(file.getContents()); + } + + /* + * Get the CVS Resource for the given resource + */ + protected ICVSResource getCVSResource(IResource resource) throws CVSException { + return CVSWorkspaceRoot.getCVSResourceFor(resource); + } + + protected IProject getNamedTestProject(String name) throws CoreException { + IProject target = getWorkspace().getRoot().getProject(name); + if (!target.exists()) { + target.create(null); + target.open(null); + } + assertExistsInFileSystem(target); + return target; + } + protected CVSTeamProvider getProvider(IResource resource) throws TeamException { + return (CVSTeamProvider)RepositoryProvider.getProvider(resource.getProject()); + } + protected static InputStream getRandomContents(int sizeAtLeast) { + StringBuffer randomStuff = new StringBuffer(sizeAtLeast + 100); + while (randomStuff.length() < sizeAtLeast) { + randomStuff.append(getRandomSnippet() + eol); + } + return new ByteArrayInputStream(randomStuff.toString().getBytes()); + } + /** + * Return String with some random text to use + * as contents for a file resource. + */ + public static String getRandomSnippet() { + switch ((int) Math.round(Math.random() * 10)) { + case 0 : + return "este e' o meu conteudo (portuguese)"; + case 1 : + return "Dann brauchen wir aber auch einen deutschen Satz!"; + case 2 : + return "I'll be back"; + case 3 : + return "don't worry, be happy"; + case 4 : + return "there is no imagination for more sentences"; + case 5 : + return "customize yours"; + case 6 : + return "foo"; + case 7 : + return "bar"; + case 8 : + return "foobar"; + case 9 : + return "case 9"; + default : + return "these are my contents"; + } + } + protected IProject getUniqueTestProject(String prefix) throws CoreException { + // manage and share with the default stream create by this class + return getNamedTestProject(prefix + "-" + Long.toString(System.currentTimeMillis())); + } + + protected CVSRepositoryLocation getRepository() { + return CVSTestSetup.repository; + } + protected void importProject(IProject project) throws TeamException { + + // Create the root folder for the import operation + ICVSFolder root = CVSWorkspaceRoot.getCVSFolderFor(project); + + // Perform the import + IStatus status; + Session s = new Session(getRepository(), root); + s.open(DEFAULT_MONITOR, true /* open for modification */); + try { + status = Command.IMPORT.execute(s, + Command.NO_GLOBAL_OPTIONS, + new LocalOption[] {Import.makeArgumentOption(Command.MESSAGE_OPTION, "Initial Import")}, + new String[] { project.getName(), getRepository().getUsername(), "start" }, + null, + DEFAULT_MONITOR); + } finally { + s.close(); + } + + if (status.getCode() == CVSStatus.SERVER_ERROR) { + throw new CVSServerException(status); + } + } + + protected void shareProject(IProject project) throws TeamException, CoreException { + mapNewProject(project); + commitNewProject(project); + } + + protected void mapNewProject(IProject project) throws TeamException { + shareProject(getRepository(), project, null, DEFAULT_MONITOR); + } + + /** + * Map the given local project to remote folder, creating the remote folder or any of + * its ancestors as necessary. + * @param location + * @param project + * @param moduleName + * @param default_monitor + */ + protected void shareProject(CVSRepositoryLocation location, IProject project, String moduleName, IProgressMonitor default_monitor) throws CVSException { + ShareProjectOperation op = new ShareProjectOperation(null, location, project, moduleName); + executeHeadless(op); + } + + protected void commitNewProject(IProject project) throws CoreException, CVSException, TeamException { + List resourcesToAdd = new ArrayList(); + IResource[] members = project.members(); + for (int i = 0; i < members.length; i++) { + if ( ! CVSWorkspaceRoot.getCVSResourceFor(members[i]).isIgnored()) { + resourcesToAdd.add(members[i]); + } + } + addResources((IResource[]) resourcesToAdd.toArray(new IResource[resourcesToAdd.size()])); + commitResources(new IResource[] {project}, IResource.DEPTH_INFINITE); + // Pause to ensure that future operations happen later than timestamp of committed resources + waitMsec(1500); + } + + /** + * Return an input stream with some random text to use + * as contents for a file resource. + */ + public InputStream getRandomContents() { + return getRandomContents(RANDOM_CONTENT_SIZE); + } + + protected void setContentsAndEnsureModified(IFile file) throws CoreException, TeamException { + setContentsAndEnsureModified(file, getRandomContents().toString()); + } + + protected void setContentsAndEnsureModified(IFile file, String contents) throws CoreException, CVSException { + ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file); + int count = 0; + if (contents == null) contents =""; + do { + file.setContents(new ByteArrayInputStream(contents.getBytes()), false, false, null); + assertTrue("Timestamp granularity is too small. Increase test wait factor", count <= CVSTestSetup.WAIT_FACTOR); + if (!cvsFile.isModified(null)) { + waitMsec(1500); + count++; + } + } while (!cvsFile.isModified(null)); + } + + public void waitMsec(int msec) { + try { + Thread.sleep(msec); + } catch(InterruptedException e) { + fail("wait-problem"); + } + } + + public static void waitForJobCompletion(Job job) { + // process UI events first, give the main thread a chance + // to handle any syncExecs or asyncExecs posted as a result + // of the event processing thread. + while (Display.getCurrent().readAndDispatch()) {}; + + // wait for the event handler to process changes. + while(job.getState() != Job.NONE) { + while (Display.getCurrent().readAndDispatch()) {}; + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + } + while (Display.getCurrent().readAndDispatch()) {}; + } + + public static void waitForIgnoreFileHandling() { + waitForJobCompletion(SyncFileChangeListener.getDeferredHandler().getEventHandlerJob()); + waitForDecorator(); + } + + protected static void waitForDecorator() { + // Wait for the decorator job + Job[] decorators = Platform.getJobManager().find(DecoratorManager.FAMILY_DECORATE); + for (int i = 0; i < decorators.length; i++) { + Job job = decorators[i]; + waitForJobCompletion(job); + } + } + + public static void waitForSubscriberInputHandling(SubscriberSyncInfoCollector input) { + input.waitForCollector(new IProgressMonitor() { + public void beginTask(String name, int totalWork) { + } + public void done() { + } + public void internalWorked(double work) { + } + public boolean isCanceled() { + return false; + } + public void setCanceled(boolean value) { + } + public void setTaskName(String name) { + } + public void subTask(String name) { + } + public void worked(int work) { + while (Display.getCurrent().readAndDispatch()) {} + } + }); + } + + protected static void executeHeadless(CVSOperation op) throws CVSException { + try { + try { + // Bypass contxt by executing run(IProgressMonitor) directly + op.run(DEFAULT_MONITOR); + } catch (InvocationTargetException e1) { + throw CVSException.wrapException(e1); + } + } catch (InterruptedException e) { + throw new OperationCanceledException(); + } + } + + protected void setUp() throws Exception { + obtainCVSServerLock(); + super.setUp(); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + releaseCVSServerLock(); + super.tearDown(); + if (CVSTestSetup.logListener != null) { + try { + CVSTestSetup.logListener.checkErrors(); + } catch (CoreException e) { + if (CVSTestSetup.FAIL_IF_EXCEPTION_LOGGED) { + fail("Exception written to log: ", e); + } else { + // Write the log to standard out so it can be more easily seen + write(e.getStatus(), 0); + } + } + } + } + + private void obtainCVSServerLock() { + IProject project = null; + boolean firstTry = true; + while (project == null) { + try { + project = checkoutProject(null, CVS_TEST_LOCK_PROJECT , null); + } catch (TeamException e) { + // The checkout of the lock project failed so lets create it if it doesn't exist + if (firstTry) { + try { + createTestLockProject(DEFAULT_MONITOR); + } catch (TeamException e1) { + // We couldn't check out the project or create it + // It's possible someone beat us to it so we'll try the checkout again. + } + } else { + // We tried twice to check out the project and failed. + // Lets just go ahead and run but we'll log the fact that we couldn't get the lock + write(new CVSStatus(IStatus.ERROR, "Could not obtain the CVS server lock. The test will containue but any performance timings may be affected", e), 0); + return; + } + firstTry = false; + } + } + if (project != null) { + IFile lockFile = project.getFile(CVS_TEST_LOCK_FILE); + boolean obtained = false; + int attempts = 0; + while (!obtained) { + attempts++; + if (lockFile.exists()) { + // If the file exists, check if the lock has expired + if (hasExpired(lockFile)) { + try { + overwriteLock(lockFile); + return; + } catch (CoreException e) { + // Ignore the error and continue + } + } + } else { + try { + writeLock(lockFile); + return; + } catch (CoreException e) { + // Ignore the error, since it probably means someone beat us to it. + } + } + // Wait for a while before testing the lock again + try { + Thread.sleep(LOCK_WAIT_TIME); + } catch (InterruptedException e) { + // Ignore + } + try { + // Update the lockfile in case someone else got to it first + replace(new IResource[] { lockFile }, null, true); + } catch (CoreException e) { + // An error updated is not recoverable so just continue + write(new CVSStatus(IStatus.ERROR, "Could not obtain the CVS server lock. The test will continue but any performance timings may be affected", e), 0); + return; + } + if (attempts > MAX_LOCK_ATTEMPTS) { + write(new CVSStatus(IStatus.ERROR, "Could not obtain the CVS server lock. The test will continue but any performance timings may be affected", new Exception()), 0); + return; + } + } + } + } + + private boolean hasExpired(IFile lockFile) { + long timestamp = lockFile.getLocalTimeStamp(); + return System.currentTimeMillis() - timestamp > LOCK_EXPIRATION_THRESHOLD; + } + + private void overwriteLock(IFile lockFile) throws CoreException { + lockFile.setContents(getLockContents(), true, true, null); + commitResources(new IResource[] { lockFile }, IResource.DEPTH_ZERO); + } + + private void writeLock(IFile lockFile) throws CoreException { + lockFile.create(getLockContents(), false, null); + addResources(new IResource[] { lockFile }); + commitResources(new IResource[] { lockFile }, IResource.DEPTH_ZERO); + } + + private InputStream getLockContents() { + lockId = Long.toString(System.currentTimeMillis()); + return new ByteArrayInputStream(lockId.getBytes()); + } + + private void createTestLockProject(IProgressMonitor monitor) throws TeamException { + CVSRepositoryLocation repository = getRepository(); + RemoteFolderTree root = new RemoteFolderTree(null, repository, Path.EMPTY.toString(), null); + RemoteFolderTree child = new RemoteFolderTree(root, CVS_TEST_LOCK_PROJECT, repository, new Path(null, root.getRepositoryRelativePath()).append(CVS_TEST_LOCK_PROJECT).toString(), null); + root.setChildren(new ICVSRemoteResource[] { child }); + Session s = new Session(repository, root); + s.open(monitor, true /* open for modification */); + try { + IStatus status = Command.ADD.execute(s, + Command.NO_GLOBAL_OPTIONS, + Command.NO_LOCAL_OPTIONS, + new String[] { CVS_TEST_LOCK_PROJECT }, + null, + monitor); + // If we get a warning, the operation most likely failed so check that the status is OK + if (status.getCode() == CVSStatus.SERVER_ERROR || ! status.isOK()) { + throw new CVSServerException(status); + } + } finally { + s.close(); + } + } + + private void releaseCVSServerLock() { + if (lockId != null) { + try { + IProject project = getWorkspace().getRoot().getProject(CVS_TEST_LOCK_PROJECT); + // Update the project and verify we still have the lock + IFile file = project.getFile(CVS_TEST_LOCK_FILE); + String id = getFileContents(file); + if (id.equals(lockId)) { + // We have the lock so let's free it (but first check if someone preempted us) + ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file); + byte[] bytes = cvsFile.getSyncBytes(); + if (bytes != null) { + String revision = ResourceSyncInfo.getRevision(bytes); + updateResources(new IResource[] { file }, true); + bytes = cvsFile.getSyncBytes(); + if (bytes == null || !ResourceSyncInfo.getRevision(bytes).equals(revision)) { + write(new CVSStatus(IStatus.ERROR, "The CVS server lock expired while this test was running. Any performance timings may be affected", new Exception()), 0); + return; + } + } + // Delete the lock file and commit + deleteResources(project, new String[] { CVS_TEST_LOCK_FILE }, true); + } + } catch (CoreException e) { + write(e.getStatus(), 0); + } catch (IOException e) { + write(new CVSStatus(IStatus.ERROR, "An error occurred while reading the lock file", e), 0); + } + } + } + + protected void write(IStatus status, int indent) { + PrintStream output = System.out; + indent(output, indent); + output.println("Severity: " + status.getSeverity()); + + indent(output, indent); + output.println("Plugin ID: " + status.getPlugin()); + + indent(output, indent); + output.println("Code: " + status.getCode()); + + indent(output, indent); + output.println("Message: " + status.getMessage()); + + Throwable t = status.getException(); + if (t != null) { + t.printStackTrace(output); + if (t instanceof CoreException) { + write(((CoreException)t).getStatus(), indent + 1); + } + } + + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) + write(children[i], indent + 1); + } + } + + protected static void indent(OutputStream output, int indent) { + for (int i = 0; i < indent; i++) + try { + output.write(" ".getBytes()); + } catch (IOException e) { + // ignore + } + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#runBare() + */ + public void runBare() throws Throwable { + try { + super.runBare(); + } catch (CVSException e) { + // If a communication exception occurred + // perhaps it is a server problem + // Try again, just in case it is + if (containsCommunicationException(e)) { + super.runBare(); + } else { + throw e; + } + } + } + + private boolean containsCommunicationException(CVSException e) { + if (e instanceof CVSCommunicationException) return true; + IStatus status = e.getStatus(); + if (status.getException() instanceof CVSCommunicationException) return true; + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) { + IStatus child = children[i]; + if (child.getException() instanceof CVSCommunicationException) return true; + } + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.core.tests.harness.EclipseWorkspaceTest#ensureDoesNotExistInWorkspace(org.eclipse.core.resources.IResource) + */ + public void ensureDoesNotExistInWorkspace(IResource resource) { + // Overridden to change how the workspace is deleted on teardown + if (resource.getType() == IResource.ROOT) { + // Delete each project individually + Job[] allJobs = Platform.getJobManager().find(null /* all families */); + IProject[] projects = ((IWorkspaceRoot)resource).getProjects(); + try { + ensureDoesNotExistInWorkspace(projects); + } catch (AssertionFailedError e) { + // The delete failed. Write the active jobs to stdout + System.out.println(e.getMessage()); + System.out.println("Jobs active at time of deletion failure: "); //$NON-NLS-1$ + if (allJobs.length == 0) { + System.out.println("None"); //$NON-NLS-1$ + } + for (int i = 0; i < allJobs.length; i++) { + Job job = allJobs[i]; + System.out.println(job.getName()); + } + if (CVSTestSetup.FAIL_IF_EXCEPTION_LOGGED) { + throw e; + } + } + } else { + ensureNotReadOnly(resource); + super.ensureDoesNotExistInWorkspace(resource); + } + } + + private void ensureNotReadOnly(IResource resource) { + if (resource.exists()) { + try { + resource.accept(new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.exists() && resource.isReadOnly()) { + resource.setReadOnly(false); + } + return true; + } + }); + } catch (CoreException e) { + fail("#ensureNotReadOnly " + resource.getFullPath(), e); + } + } + + } + + /** + * Delete each project from the workspace and return a status that + * contains any failures + */ + public void ensureDoesNotExistInWorkspace(final IProject[] projects) { + final Map failures = new HashMap(); + IWorkspaceRunnable body = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) { + for (int i = 0; i < projects.length; i++) { + try { + if (projects[i].exists()) + projects[i].delete(true, null); + } catch (CoreException e) { + write(new CVSStatus(IStatus.ERROR, "Could not delete project " + projects[i].getName(), e), 0); + failures.put(projects[i], e); + } + } + } + }; + try { + getWorkspace().run(body, null); + } catch (CoreException e) { + fail("#ensureDoesNotExistInWorkspace(IResource[])", e); + } + if (!failures.isEmpty()) { + StringBuffer text = new StringBuffer(); + text.append("Could not delete all projects: "); + for (Iterator iter = failures.keySet().iterator(); iter.hasNext();) { + IProject project = (IProject) iter.next(); + text.append(project.getName()); + } + fail(text.toString()); + } + } + + protected void assertStatusContainsCode(IStatus status, int code) { + if (status.isMultiStatus()) { + IStatus[] children = status.getChildren(); + for (int i = 0; i < children.length; i++) { + IStatus child = children[i]; + if (child.getCode() == code) + return; + } + fail("Expected status code was not present"); + } else { + assertEquals("Status code is not what is expected", status.getCode(), code); + } + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#runTest() + */ + protected void runTest() throws Throwable { + if (!CVSTestSetup.RECORD_PROTOCOL_TRAFFIC) { + super.runTest(); + return; + } + ByteArrayOutputStream os = new ByteArrayOutputStream(); + Policy.recorder = new PrintStream(os); + try { + try { + // Override the runTest method in order to print the entire trace of a + // test that failed due to a CoreException including nested exceptions + super.runTest(); + } catch (CoreException e) { + e.printStackTrace(); + write(e.getStatus(), 0); + throw e; + } + } catch (Throwable e) { + // Transfer the recorded debug info to stdout + Policy.recorder.close(); + System.out.println(new String(os.toByteArray())); + throw e; + } finally { + Policy.recorder.close(); + Policy.recorder = null; + } + } +} + diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/ResourceMapperTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/ResourceMapperTests.java new file mode 100644 index 000000000..f28c6da4e --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/ResourceMapperTests.java @@ -0,0 +1,534 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.core.mappings; + +import java.io.IOException; +import java.util.*; + +import junit.framework.Test; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.mapping.*; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.synchronize.*; +import org.eclipse.team.internal.ccvs.core.*; +import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; +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.tests.ccvs.core.EclipseTest; + +/** + * 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, new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + 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 (int i = 0; i < infos.length; i++) { + SyncInfo info = infos[i]; + 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, IOException { + // 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 remotes = getTaggedRemoteFilesByPath(mapping, branch); + final Map locals = getTaggedLocalFilesByPath(mapping, branch); + for (Iterator iter = remotes.keySet().iterator(); iter.hasNext();) { + String key = (String)iter.next(); + ICVSRemoteFile remote = (ICVSRemoteFile)remotes.get(key); + ICVSFile local = (ICVSFile)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 (Iterator iter = remotes.keySet().iterator(); iter.hasNext();) { + String path = (String) iter.next(); + fail("Remote file " + path + " was tagged remotely but not locally."); + } + // The local map should be empty after traversal + for (Iterator iter = locals.keySet().iterator(); iter.hasNext();) { + String path = (String) iter.next(); + fail("Local file " + path + " was tagged locally but not remotely."); + } + } + + private void assertTagged(ResourceMapping mapping, final CVSTag tag) throws CoreException { + final Map tagged = getTaggedRemoteFilesByPath(mapping, tag); + // Visit all the resources in the traversal and ensure that they are tagged + visit(mapping, ResourceMappingContext.LOCAL_CONTEXT, new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + ICVSRemoteFile file = popRemote(resource, tagged); + assertNotNull("Resource was not tagged: " + resource.getFullPath(), file); + } + return true; + } + }); + + // The tagged map should be empty after traversal + for (Iterator iter = tagged.keySet().iterator(); iter.hasNext();) { + String path = (String) iter.next(); + fail("Remote file " + path + " was tagged but should not have been."); + } + } + + private Map getTaggedLocalFilesByPath(ResourceMapping mapping, final CVSTag branch) throws CoreException { + final Map tagged = new HashMap(); + IProject[] projects = mapping.getProjects(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + project.accept(new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + 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 getTaggedRemoteFilesByPath(ResourceMapping mapping, final CVSTag tag) throws CVSException { + IProject[] projects = mapping.getProjects(); + ICVSResource[] remotes = getRemoteTrees(projects, tag); + final Map tagged = getFilesByPath(remotes); + return tagged; + } + + private ICVSResource[] getRemoteTrees(IProject[] projects, CVSTag tag) throws CVSException { + List result = new ArrayList(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + RemoteFolderTree tree = RemoteFolderTreeBuilder.buildRemoteTree(getRepository(), project, tag, DEFAULT_MONITOR); + result.add(tree); + } + return (ICVSResource[]) result.toArray(new ICVSResource[result.size()]); + } + + private Map getFilesByPath(ICVSResource[] remotes) throws CVSException { + Map result = new HashMap(); + for (int i = 0; i < remotes.length; i++) { + ICVSResource resource = remotes[i]; + collectFiles(resource, result); + } + return result; + } + + private void collectFiles(ICVSResource resource, Map result) throws CVSException { + if (resource.isFolder()) { + ICVSResource[] members = ((ICVSFolder)resource).members(ICVSFolder.ALL_EXISTING_MEMBERS); + for (int i = 0; i < members.length; i++) { + ICVSResource member = members[i]; + collectFiles(member, result); + } + } else { + result.put(resource.getRepositoryRelativePath(), resource); + } + } + + private ICVSRemoteFile popRemote(IResource resource, Map 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() { + public Object getModelObject() { + return ResourcesPlugin.getWorkspace(); + } + public IProject[] getProjects() { + return getProjects(resources); + } + private IProject[] getProjects(IResource[] resources) { + Set projects = new HashSet(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + projects.add(resource.getProject()); + } + return (IProject[]) projects.toArray(new IProject[projects.size()]); + } + public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor) throws CoreException { + return new ResourceTraversal[] { + new ResourceTraversal(resources, depth, IResource.NONE) + }; + } + }; + } + + private void assertUpdate(ResourceMapping mapper, final SyncInfoTree set) throws Exception { + final Exception[] exception = new Exception[] { null }; + visit(mapper, new SyncInfoSetTraveralContext(set), new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + 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 e) { + exception[0] = e; + } catch (CoreException e) { + exception[0] = e; + } catch (IOException e) { + exception[0] = e; + } + } + 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), new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + 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 (int i = 0; i < infos.length; i++) { + SyncInfo info = infos[i]; + 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() { + 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 void visit(ResourceMapping mapper, ResourceMappingContext context, IResourceVisitor visitor) throws CoreException { + ResourceTraversal[] traversals = mapper.getTraversals(context, null); + for (int i = 0; i < traversals.length; i++) { + ResourceTraversal traversal = traversals[i]; + visit(traversal, context, visitor); + } + } + + private void visit(ResourceTraversal traversal, ResourceMappingContext context, IResourceVisitor visitor) throws CoreException { + IResource[] resources = traversal.getResources(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + 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 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 (Iterator iter = members.iterator(); iter.hasNext();) { + IResource member = (IResource) iter.next(); + visit(member, visitor, context, depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE); + } + } + + public void testUpdate() throws Exception { + // 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); + } + + public void testReplace() throws Exception { + // 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); + } + + public void testCommit() throws Exception { + // 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 { + // 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)); + } + +} diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/SyncInfoSetTraveralContext.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/SyncInfoSetTraveralContext.java new file mode 100644 index 000000000..ad14b21ed --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/mappings/SyncInfoSetTraveralContext.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.core.mappings; + +import java.util.*; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.team.core.synchronize.*; +import org.eclipse.team.core.variants.IResourceVariant; + +/** + * A traversal context that traverses the local workspace but also + * adds resources that exist in the given sync info set but do not exist + * locally. + */ +public class SyncInfoSetTraveralContext extends RemoteResourceMappingContext { + + SyncInfoTree set; + + public SyncInfoSetTraveralContext(SyncInfoSet set) { + this.set = new SyncInfoTree(); + this.set.addAll(set); + } + + protected SyncInfo getSyncInfo(IFile file) { + return set.getSyncInfo(file); + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.mapping.ITraversalContext#contentDiffers(org.eclipse.core.resources.IFile, org.eclipse.core.runtime.IProgressMonitor) + */ + public boolean contentDiffers(IFile file, IProgressMonitor monitor) throws CoreException { + return getSyncInfo(file) != null; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.mapping.ITraversalContext#fetchContents(org.eclipse.core.resources.IFile, org.eclipse.core.runtime.IProgressMonitor) + */ + public IStorage fetchContents(IFile file, IProgressMonitor monitor) throws CoreException { + SyncInfo info = getSyncInfo(file); + //TODO: Speced to throw an exception when remote doesn't exist + if (info == null) + return file; + IResourceVariant remote = info.getRemote(); + if (remote == null) + return null; + return remote.getStorage(monitor); + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.mapping.ITraversalContext#fetchMembers(org.eclipse.core.resources.IContainer, org.eclipse.core.runtime.IProgressMonitor) + */ + public IResource[] fetchMembers(IContainer container, IProgressMonitor monitor) throws CoreException { + Set members = new HashSet(); + members.addAll(Arrays.asList(container.members(false))); + members.addAll(Arrays.asList(set.members(container))); + return (IResource[]) members.toArray(new IResource[members.size()]); + } + + public void refresh(ResourceTraversal[] traversals, int flags, IProgressMonitor monitor) throws CoreException { + // Do nothing + } + +} diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java new file mode 100644 index 000000000..ef7d17311 --- /dev/null +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/subscriber/AllTestsTeamSubscriber.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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 + *******************************************************************************/ +package org.eclipse.team.tests.ccvs.core.subscriber; +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.team.tests.ccvs.core.CVSTestSetup; +import org.eclipse.team.tests.ccvs.core.EclipseTest; +import org.eclipse.team.tests.ccvs.ui.SynchronizeViewTestAdapter; + +public class AllTestsTeamSubscriber extends EclipseTest { + + public AllTestsTeamSubscriber() { + super(); + } + + public AllTestsTeamSubscriber(String name) { + super(name); + } + + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTest(CVSMergeSubscriberTest.suite()); + suite.addTest(CVSWorkspaceSubscriberTest.suite()); + suite.addTest(CVSCompareSubscriberTest.suite()); + suite.addTest(SyncSetTests.suite()); + //suite.addTest(CVSChangeSetTests.suite()); + CVSSyncSubscriberTest.setSyncSource(new SynchronizeViewTestAdapter()); + return new CVSTestSetup(suite); + } +} |