/*******************************************************************************
 * Copyright (c) 2000, 2015 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.jdt.core.tests.model;

import java.io.IOException;
import java.util.Vector;

import junit.framework.Test;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.team.core.RepositoryProvider;



@SuppressWarnings({"rawtypes", "unchecked"})
public class WorkingCopyTests extends ModifyingResourceTests {
	ICompilationUnit cu = null;
	ICompilationUnit copy = null;

	public class TestWorkingCopyOwner extends WorkingCopyOwner {
		public IBuffer createBuffer(ICompilationUnit workingCopy) {
			return new TestBuffer(workingCopy);
		}
	}
	public WorkingCopyTests(String name) {
	super(name);
}

public static Test suite() {
	return buildModelTestSuite(WorkingCopyTests.class);
}
protected void setUp() throws Exception {
	super.setUp();

	try {
		this.createJavaProject(
			"P",
			new String[] {"src"},
			new String[] {this.getExternalJCLPathString(), "lib"},
			"bin");
		this.createFolder("P/src/x/y");
		this.createFile("P/src/x/y/A.java",
			"package x.y;\n" +
			"import java.io.File;\n" +
			"public class A {\n" +
			"  public class Inner {\n" +
			"    public class InnerInner {\n" +
			"    }\n" +
			"    int innerField;\n" +
			"    void innerMethod() {\n" +
			"    }\n" +
			"  }\n" +
			"  static String FIELD;\n" +
			"  {\n" +
			"    FIELD = File.pathSeparator;\n" +
			"  }\n" +
			"  int field1;\n" +
			"  boolean field2;\n" +
			"  public void foo() {\n" +
			"  }\n" +
			"}");
		this.cu = this.getCompilationUnit("P/src/x/y/A.java");
		this.copy = this.cu.getWorkingCopy(null);
	} catch (CoreException e) {
		e.printStackTrace();
		throw new RuntimeException(e.getMessage());
	}
}
protected void tearDown() throws Exception {
	if (this.copy != null) this.copy.discardWorkingCopy();
	this.deleteProject("P");
	super.tearDown();
}
/*
 * Ensures that cancelling a make consistent operation doesn't leave the working copy closed
 * (regression test for bug 61719 Incorrect fine grain delta after method copy-rename)
 */
public void testCancelMakeConsistent() throws JavaModelException {
	String newContents =
		"package x.y;\n" +
		"public class A {\n" +
		"  public void bar() {\n" +
		"  }\n" +
		"}";
	this.copy.getBuffer().setContents(newContents);
	NullProgressMonitor monitor = new NullProgressMonitor();
	monitor.setCanceled(true);
	try {
		this.copy.makeConsistent(monitor);
	} catch (OperationCanceledException e) {
		// got exception
	}
	assertTrue("Working copy should be opened", this.copy.isOpen());
}

/**
 */
public void testChangeContent() throws CoreException {
	String newContents =
		"package x.y;\n" +
		"public class A {\n" +
		"  public void bar() {\n" +
		"  }\n" +
		"}";
	this.copy.getBuffer().setContents(newContents);
	this.copy.reconcile(ICompilationUnit.NO_AST, false, null, null);
	assertSourceEquals(
		"Unexpected working copy contents",
		newContents,
		this.copy.getBuffer().getContents());

	this.copy.commitWorkingCopy(true, null);
	assertSourceEquals(
		"Unexpected original cu contents",
		newContents,
		this.cu.getBuffer().getContents());
}

/*
 * Ensures that one cannot commit the contents of a working copy on a read only cu.
 */
public void testChangeContentOfReadOnlyCU1() throws CoreException {
	if (!Util.isReadOnlySupported()) {
		// Do not test if file system does not support read-only attribute
		return;
	}
	IResource resource = this.cu.getUnderlyingResource();
	boolean readOnlyFlag = Util.isReadOnly(resource);
	boolean didComplain = false;
	try {
		Util.setReadOnly(resource, true);
		this.copy.getBuffer().setContents("invalid");
		this.copy.commitWorkingCopy(true, null);
	} catch(JavaModelException e){
		didComplain = true;
	} finally {
		Util.setReadOnly(resource, readOnlyFlag);
	}
	assertTrue("Should have complained about modifying a read-only unit:", didComplain);
	assertTrue("ReadOnly buffer got modified:", !this.cu.getBuffer().getContents().equals("invalid"));
}

/*
 * Ensures that one can commit the contents of a working copy on a read only cu if a pessimistic repository
 * provider allows it.
 */
public void testChangeContentOfReadOnlyCU2() throws CoreException {
	if (!Util.isReadOnlySupported()) {
		// Do not test if file system does not support read-only attribute
		return;
	}
	String newContents =
		"package x.y;\n" +
		"public class A {\n" +
		"  public void bar() {\n" +
		"  }\n" +
		"}";
	IResource resource = this.cu.getUnderlyingResource();
	IProject project = resource.getProject();
	boolean readOnlyFlag = Util.isReadOnly(resource);
	try {
		RepositoryProvider.map(project, TestPessimisticProvider.NATURE_ID);
		TestPessimisticProvider.markWritableOnSave = true;
		Util.setReadOnly(resource, true);

		this.copy.getBuffer().setContents(newContents);
		this.copy.commitWorkingCopy(true, null);
		assertSourceEquals(
			"Unexpected original cu contents",
			newContents,
			this.cu.getBuffer().getContents());
	} finally {
		TestPessimisticProvider.markWritableOnSave = false;
		RepositoryProvider.unmap(project);
		Util.setReadOnly(resource, readOnlyFlag);
	}
}

/**
 * Ensures that the source contents of a working copy are
 * not altered by changes to the source of the original compilation
 * unit.
 */
public void testContents() throws CoreException {
	String originalSource = this.cu.getSource();
	IType type = this.cu.getType("A");
	assertDeletion(type);
	assertSourceEquals("source code of copy should still be original", originalSource, this.copy.getSource());
}

/**
 * Test creating a working copy on a class file with a customized buffer.
 * As of https://bugs.eclipse.org/337935 this test is no longer valid.
 */
public void _testOnClassFile() throws JavaModelException, IOException {
	// ensure the external JCL is copied
	setupExternalJCL("jclMin");

	attachSource(this.getPackageFragmentRoot("P", this.getExternalJCLPathString()), this.getExternalJCLSourcePath().toOSString(), "src");
	IClassFile classFile = this.getClassFile("P", this.getExternalJCLPathString(), "java.lang", "Object.class");
	WorkingCopyOwner owner = new TestWorkingCopyOwner();
	ICompilationUnit customizedCopy = classFile.getWorkingCopy(owner, null);
	try {
		IBuffer buffer = customizedCopy.getBuffer();
		assertTrue("Unexpected buffer", buffer instanceof TestBuffer);
		assertTrue("Buffer should be initialized with source", buffer.getCharacters().length > 0);
	} finally {
		customizedCopy.discardWorkingCopy();
	}
}
/**
 * Create the compilation unit place holder for the working copy tests.
 */
public void testCreation() {
	assertTrue("Failed to create X.java compilation unit", this.cu != null && this.cu.exists());
	assertTrue("Failed to create working copy on X.java", this.copy != null && this.copy.exists());
}

/**
 * Test creating a working copy with a customized buffer.
 */
public void testCustomizedBuffer() throws JavaModelException {
	WorkingCopyOwner owner = new TestWorkingCopyOwner();
	ICompilationUnit customizedCopy = this.cu.getWorkingCopy(owner, null);
	try {
		assertTrue("Unexpected buffer", customizedCopy.getBuffer() instanceof TestBuffer);
	} finally {
		customizedCopy.discardWorkingCopy();
	}
}
/**
 * Test closing then reopening a working copy with a customized buffer.
 */
public void testCustomizedBuffer2() throws JavaModelException {
	WorkingCopyOwner owner = new TestWorkingCopyOwner();
	ICompilationUnit customizedCopy = this.cu.getWorkingCopy(owner, null);
	try {
		customizedCopy.close();
		customizedCopy.open(null);
		assertTrue("Unexpected buffer", customizedCopy.getBuffer() instanceof TestBuffer);
	} finally {
		customizedCopy.discardWorkingCopy();
	}
}
/*
 * Test that deleting 2 fields in a JavaCore.run() operation reports the correct delta.
 * (regression test for bug 32225 incorrect delta after deleting 2 fields)
 */
public void testDelete2Fields() throws CoreException {
	try {
		startDeltas();
		JavaCore.run(
			new IWorkspaceRunnable() {
				public void run(IProgressMonitor monitor) throws CoreException {
					IType type = WorkingCopyTests.this.copy.getType("A");
					IField field1 = type.getField("field1");
					IField field2 = type.getField("field2");
					field1.delete(false, monitor);
					field2.delete(false, monitor);
				}
			},
			null);
		assertWorkingCopyDeltas(
			"Unexpected delta",
			"A[*]: {CHILDREN | FINE GRAINED}\n" +
			"	field1[-]: {}\n" +
			"	field2[-]: {}"
		);
	} finally {
		stopDeltas();
	}
}
/**
 * Tests the general functionality of a working copy:<ul>
 * <li>ensures that the copy and original compilation unit are not equal</li>
 * <li>ensures the correct retrieval of the original element</li>
 * <li>closing the package of the compilation unit does not close the copy</li>
 * <li>ensures that working copies are unique
 * <li>ensures committing changes from working copies
 */
public void testGeneral() throws JavaModelException, CoreException {

	assertTrue("copy and actual should not be equal", !this.copy.equals(this.cu));

	IType copyType= this.copy.getType("A");

	assertEquals("primary should be the samel", this.cu, this.cu.getPrimary());

	assertEquals("getting working copy from a copy should yield original copy", this.copy, this.copy.getWorkingCopy(null));

	boolean ex= false;
	assertDeletion(copyType);

	// closing the package should not close the copy
	((IOpenable)this.cu.getParent()).close();
	assertTrue("copy should still be open", this.copy.isOpen());

	// verify original still present
	assertTrue("actual type should still be present", this.cu.getType("A").exists());

	// getAnother working copy
	ICompilationUnit copy2= this.cu.getWorkingCopy(null);
	try {
		assertTrue("working copies should be unique ", !(this.copy.equals(copy2)));

		// delete a method from the 2nd working copy.
		IMethod method= copy2.getType("A").getMethod("foo", null);

		assertDeletion(method);
		IMethod originalMethod= this.cu.getType("A").getMethod("foo", null);
		assertTrue("method should still be present in original", originalMethod.exists());

		// commit the changes from the 2nd copy.
		copy2.commitWorkingCopy(false, null);

		assertTrue("copy always has unsaved changes", copy2.hasUnsavedChanges());

		// original method should now be gone
		assertTrue("method should no longer be present in original after commit", !originalMethod.exists());

		// commit the changes from the 1st copy - should fail
		try {
			this.copy.commitWorkingCopy(false, null);
			assertTrue("commit should have failed", ex);
		} catch (JavaModelException jme) {
		}


		// now force the update
		try {
			this.copy.commitWorkingCopy(true, null);
		} catch (JavaModelException jme) {
			assertTrue("commit should work", false);
		}

		// now the type should be gone.
		assertTrue("original type should no longer be present", !this.cu.getType("A").exists());


		this.copy.close();
		ex= false;
		try {
			this.copy.open(null);
		} catch (JavaModelException e) {
			ex= true;
		}
		assertTrue("should be able to open working copy a 2nd time", !ex);

		// now discard the working copy
		this.copy.discardWorkingCopy();
		ex= false;
		try {
			this.copy.open(null);
		} catch (JavaModelException e) {
			ex= true;
		}
		assertTrue("should not be able to open working copy again", ex);
	} finally {
		copy2.discardWorkingCopy();
	}
}
/**
 * Ensures that the primary element of a binary element is itself.
 */
public void testGetPrimaryBinaryElement() throws CoreException {
	/* Evaluate the following in a scrapbook:
	 org.eclipse.jdt.core.tests.model.ModifyingResourceTests.generateClassFile(
		"A",
		"public class A {\n" +
		"}")
	*/
	byte[] bytes = new byte[] {
		-54, -2, -70, -66, 0, 3, 0, 45, 0, 10, 1, 0, 1, 65, 7, 0, 1, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0, 3, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 12, 0, 5, 0, 6, 10, 0, 4, 0, 8, 0, 33, 0, 2, 0, 4, 0, 0, 0,
		0, 0, 1, 0, 1, 0, 5, 0, 6, 0, 1, 0, 7, 0, 0, 0, 17, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 9, -79, 0, 0, 0, 0, 0, 0,
	};
	this.createFile("P/lib/A.class", bytes);
	IClassFile cf = this.getClassFile("P/lib/A.class");
	IJavaElement primary = cf.getPrimaryElement();
	assertEquals("Primary element should be the same", cf, primary);
}
/**
 * Ensures that the primary cu can be retrieved.
 */
public void testGetPrimaryCU() {
	IJavaElement primary= this.copy.getPrimaryElement();
	assertTrue("Element is not a cu", primary instanceof ICompilationUnit && !((ICompilationUnit)primary).isWorkingCopy());
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that the primary field can be retrieved.
 */
public void testGetPrimaryField() {
	IType type = this.copy.getType("A");
	IJavaElement primary = type.getField("FIELD").getPrimaryElement();
	assertTrue("Element is not a field", primary instanceof IField && !((ICompilationUnit)primary.getParent().getParent()).isWorkingCopy());
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that the primary import declaration can be retrieved.
 */
public void testGetPrimaryImportDeclaration()  {
	IImportDeclaration imprt = this.copy.getImport("java.io.File");
	IJavaElement primary = imprt.getPrimaryElement();
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that the primary import container can be retrieved.
 */
public void testGetPrimaryImportContainer() {
	IImportContainer container = this.copy.getImportContainer();
	IJavaElement primary = container.getPrimaryElement();
	assertTrue("Element should not be null", primary != null);
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that the primary initializer can be retrieved.
 */
public void testGetPrimaryInitializer() {
	IType type= this.copy.getType("A");
	IJavaElement primary= type.getInitializer(1).getPrimaryElement();
	assertTrue("Element should exist", primary.exists());
}
/**
 */
public void testGetPrimaryInnerField() {
	IType innerType = this.copy.getType("A").getType("Inner");
	IJavaElement primary = innerType.getField("innerField").getPrimaryElement();
	assertTrue("Element is not a field", primary instanceof IField);
	assertTrue("Element should exist", primary.exists());
}
/**
 */
public void testGetPrimaryInnerMethod() throws JavaModelException {
	IType innerType = this.copy.getType("A").getType("Inner");
	IJavaElement primary = innerType.getMethods()[0].getPrimaryElement();
	assertTrue("Element is not a method", primary instanceof IMethod);
	assertTrue("Element should exist", primary.exists());
}
/**
 */
public void testGetPrimaryInnerType() {
	IType innerInnerType = this.copy.getType("A").getType("Inner").getType("InnerInner");
	IJavaElement primary = innerInnerType.getPrimaryElement();
	assertTrue("Element is not a method", primary instanceof IType);
	assertTrue("Element should exist", primary.exists());

	Vector hierarchy = new Vector(5);
	IJavaElement parent= primary.getParent();
	while (parent.getElementType() > IJavaElement.COMPILATION_UNIT) {
		hierarchy.addElement(parent);
		parent = parent.getParent();
	}
	hierarchy.addElement(parent);
	assertTrue("Compilation Unit should not be a working copy", !((ICompilationUnit)hierarchy.lastElement()).isWorkingCopy());
}
/**
 * Ensures that the primary method can be retrieved.
 */
public void testGetPrimaryMethod() throws JavaModelException {
	IType type = this.copy.getType("A");
	IJavaElement primary= type.getMethods()[0].getPrimaryElement();
	assertTrue("Element is not a method", primary instanceof IMethod);
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that renaming a method of a working copy does
 * not alter the source of the primary compilation
 * unit.
 */
public void testRenameMethod() throws JavaModelException {
	IType type = this.copy.getType("A");
	IMethod method = type.getMethods()[0];
	IJavaElement primary= method.getPrimaryElement();
	method.rename("bar", false, null);
	assertEquals("Invalid name of working copy method", "bar", type.getMethods()[0].getElementName());
	assertEquals("Invalid name of primary method", "foo", primary.getElementName());
}
/**
 * Ensures that the primary package declaration can be retrieved.
 */
public void testGetPrimaryPackageDeclaration() {
	IPackageDeclaration pkg = this.copy.getPackageDeclaration("x.y");
	IJavaElement primary = pkg.getPrimaryElement();
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that the primary type can be retrieved.
 */
public void testGetPrimaryType() {
	IType type = this.copy.getType("A");
	IJavaElement primary= type.getPrimaryElement();
	assertTrue("Element should exist", primary.exists());
}
/**
 * Ensures that a type can be moved to another working copy.
 * (regression test for bug 7881 IType.move() clobbers editing buffer of destination element)
 */
public void testMoveTypeToAnotherWorkingCopy() throws CoreException {
	this.createFile(
		"P/src/x/y/B.java",
		"package x.y;\n" +
		"public class B {\n" +
		"}");
	ICompilationUnit cu2 = this.getCompilationUnit("P/src/x/y/B.java");
	ICompilationUnit copy2 = cu2.getWorkingCopy(null);
	try {
		IType classA = this.copy.getType("A");
		IType classB = copy2.getType("B");
		classA.move(classB, null, null, false, null);
		assertTrue("A should not exist", !classA.exists());
		assertTrue("B.A should exist", classB.getType("A").exists());
		assertTrue("Buffer for A should not be null", this.copy.getBuffer() != null);
		assertSourceEquals("Invalid content for A",
			"package x.y;\n" +
			"import java.io.File;",
			this.copy.getBuffer().getContents());
		assertTrue("Buffer for B should not be null", copy2.getBuffer() != null);
		assertSourceEquals("Invalid content for B",
			"package x.y;\n" +
			"public class B {\n" +
			"\n" +
			"	public class A {\n" +
			"	  public class Inner {\n" +
			"	    public class InnerInner {\n" +
			"	    }\n" +
			"	    int innerField;\n" +
			"	    void innerMethod() {\n" +
			"	    }\n" +
			"	  }\n" +
			"	  static String FIELD;\n" +
			"	  {\n" +
			"	    FIELD = File.pathSeparator;\n" +
			"	  }\n" +
			"	  int field1;\n" +
			"	  boolean field2;\n" +
			"	  public void foo() {\n" +
			"	  }\n" +
			"	}\n" +
			"}",
			copy2.getBuffer().getContents());
	} finally {
		copy2.discardWorkingCopy();
	}
}
/**
 * Test creating a shared working copy.
 */
public void testShared1() throws JavaModelException {
	WorkingCopyOwner owner = new WorkingCopyOwner() {};
	ICompilationUnit shared = this.cu.getWorkingCopy(owner, null);
	try {
		assertTrue("Should find shared working copy", this.cu.findWorkingCopy(owner) == shared);
	} finally {
		shared.discardWorkingCopy();
	}
	assertTrue("Should not find cu with same owner", this.cu.findWorkingCopy(owner) == null);
}
/**
 * Test several call to creating shared working copy.
 */
public void testShared2() throws JavaModelException {
	WorkingCopyOwner owner = new WorkingCopyOwner() {};
	ICompilationUnit shared = this.cu.getWorkingCopy(owner, null);
	try {
		ICompilationUnit shared2 = this.cu.getWorkingCopy(owner, null);
		assertTrue("Second working copy should be identical to first one", shared2 == shared);
	} finally {
		shared.discardWorkingCopy();
		try {
			assertTrue("Should find shared working copy", this.cu.findWorkingCopy(owner) == shared);
		} finally {
			shared.discardWorkingCopy();
		}
	}
	assertTrue("Should not find cu with same owner", this.cu.findWorkingCopy(owner) == null);
}
/**
 * Tests that multiple commits are possible with the same working copy.
 */
public void testMultipleCommit() {

	// Add a method to the working copy
	IType gp = this.copy.getType("A");
	try {
		gp.createMethod("public void anotherMethod() {}\n",null, false, null);
	} catch (JavaModelException jme) {
		assertTrue("creation failed", false);
	}

	// commit the changes from the copy.
	try {
		this.copy.commitWorkingCopy(false, null);
	} catch (JavaModelException t) {
		assertTrue("commit failed", false);
	}

	// new method added
	assertTrue("method should exist after commit",
		this.cu.getType("A").getMethod("anotherMethod", new String[]{}).exists());

	//add another method
	try {
		gp.createMethod("public void anotherAnotherMethod() {}\n", null, false, null);
	} catch (JavaModelException x) {
		assertTrue("Creation failed 2", false);
	}

	//commit the new method
	try {
		this.copy.commitWorkingCopy(false, null);
	} catch (JavaModelException t) {
		assertTrue("commit2 failed", false);
	}

	// new method added
	assertTrue("second method added should exist after commit",
		this.cu.getType("A").getMethod("anotherAnotherMethod", new String[]{}).exists());
}
/**
 * Creates a working copy on a non-existing compilation unit.
 * (regression test for bug 8921  DCR - Need a way to create a working copy ignoring existing files)
 */
public void testNonExistingCU() throws JavaModelException {
	ICompilationUnit nonExistingCU = this.getCompilationUnit("P/src/x/y/NonExisting.java");
	ICompilationUnit workingCopy = null;
	try {
		// getBuffer()
		workingCopy = nonExistingCU.getWorkingCopy(null);
		assertSourceEquals("Buffer should be empty", "", ((IOpenable)workingCopy).getBuffer().getContents());

		// exists()
		assertTrue("Working copy should exists", ((IJavaElement)workingCopy).exists());

		// getCorrespondingResource()
		assertEquals("Corresponding resource should be null", null, ((IJavaElement)workingCopy).getCorrespondingResource());

		// getPrimaryElement()
		assertEquals("Unexpected orginal element", nonExistingCU, workingCopy.getPrimaryElement());

		// getPath()
		assertEquals("Unexpected path", new Path("/P/src/x/y/NonExisting.java"), ((IJavaElement)workingCopy).getPath());

		// getResource()
		assertEquals("Unexpected resource", nonExistingCU.getResource(), ((IJavaElement)workingCopy).getResource());

		// isConsistent()
		assertTrue("Working copy should be consistent", ((IOpenable)workingCopy).isConsistent());

		// restore()
		boolean exception = false;
		try {
			workingCopy.restore();
		} catch (JavaModelException e) {
			exception = true;
		}
		assertTrue("Should not be able to restore from primary element", exception);

		// makeConsistent()
		((IOpenable)workingCopy).getBuffer().setContents(
			"public class X {\n" +
			"}");
		assertTrue("Working copy should not be consistent", !((IOpenable)workingCopy).isConsistent());
		((IOpenable)workingCopy).makeConsistent(null);
		assertTrue("Working copy should be consistent", ((IOpenable)workingCopy).isConsistent());

		// save()
		((IOpenable)workingCopy).getBuffer().setContents(
			"public class Y {\n" +
			"}");
		((IOpenable)workingCopy).save(null, false);
		assertTrue("Working copy should be consistent after save", ((IOpenable)workingCopy).isConsistent());
		assertTrue("Primary cu should not exist", !nonExistingCU.exists());

		// commitWorkingCopy()
		workingCopy.commitWorkingCopy(false, null);
		assertTrue("Primary cu should exist", nonExistingCU.exists());

		// hasResourceChanged()
		assertTrue("Working copy's resource should now not mark as changed", !workingCopy.hasResourceChanged());

	} finally {
		if (workingCopy != null) {
			workingCopy.discardWorkingCopy();
		}
		if (nonExistingCU.exists()) {
			nonExistingCU.delete(true, null);
		}
	}
}
/**
 * Tests the general functionality of a operations working with working copies:<ul>
 * <li>ensures that the copy cannot be renamed</li>
 * <li>ensures that the copy cannot be moved to the same location as the primary cu</li>
 * <li>ensures that the copy can be copied to a different location as the primary cu</li>
 */
public void testOperations() throws JavaModelException {
	// rename working copy
	boolean ex= false;
	try {
		this.copy.rename("someName.java", false, null);
	} catch (JavaModelException jme) {
		assertTrue("Incorrect status code for attempting to rename working copy", jme.getStatus().getCode() == IJavaModelStatusConstants.INVALID_ELEMENT_TYPES);
		ex= true;
	}
	assertTrue("renaming a working copy should fail", ex);

	// move to same location as primary cu
	ex= false;
	try {
		this.copy.move(this.cu.getParent(), null, "someName.java", false, null);
	} catch (JavaModelException jme) {
		assertTrue("Incorrect status code for attempting to move working copy", jme.getStatus().getCode() == IJavaModelStatusConstants.INVALID_ELEMENT_TYPES);
		ex= true;
	}
	assertTrue("moving a working copy should fail", ex);

	// copy working copy to default package
	IPackageFragment pkg= getPackageFragment("P", "src", "");
	this.copy.copy(pkg, null, "someName.java", false, null);
	assertCreation(this.copy);
}
}
