diff options
author | Christian W. Damus | 2014-02-05 22:07:03 +0000 |
---|---|---|
committer | Christian W. Damus | 2014-02-07 23:55:46 +0000 |
commit | 4df3b971ddb0910600402cc93640cbdb538cb036 (patch) | |
tree | d1f7b4408353e0e26b2f5419386c5a612d8f7700 /tests/junit/plugins/infra/gmfdiag | |
parent | 65af346c9b891ea496ff9e69f8b7c4bf702dff7b (diff) | |
download | org.eclipse.papyrus-4df3b971ddb0910600402cc93640cbdb538cb036.tar.gz org.eclipse.papyrus-4df3b971ddb0910600402cc93640cbdb538cb036.tar.xz org.eclipse.papyrus-4df3b971ddb0910600402cc93640cbdb538cb036.zip |
402525: [Widgets / Transactions] Papyrus dialogs should be transactional
https://bugs.eclipse.org/bugs/show_bug.cgi?id=402525
JUnit tests for nesting command stacks and related APIs.
Diffstat (limited to 'tests/junit/plugins/infra/gmfdiag')
10 files changed, 666 insertions, 0 deletions
diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.classpath b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.classpath new file mode 100644 index 00000000000..64c5e31b7a2 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.project b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.project new file mode 100644 index 00000000000..a7434ea3fe4 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.papyrus.infra.gmfdiag.commands.tests</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..3eff40b8b33 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Mon Nov 08 19:25:55 CET 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..0afee83d834 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-Vendor: %providerName +Bundle-SymbolicName: org.eclipse.papyrus.infra.gmfdiag.commands.tests +Bundle-Version: 1.0.0.qualifier +Bundle-Localization: fragment +Fragment-Host: org.eclipse.papyrus.infra.gmfdiag.commands;bundle-version="1.0.0" +Require-Bundle: org.junit;bundle-version="4.10.0", + com.google.guava;bundle-version="11.0.0", + org.eclipse.papyrus.infra.emf.readonly;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Export-Package: org.eclipse.papyrus.infra.gmfdiag.commands.tests diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/build.properties b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/build.properties new file mode 100644 index 00000000000..c61f1594f78 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + fragment.properties,\ + org.eclipse.papyrus.infra.gmfdiag.commands.tests.launch diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/fragment.properties b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/fragment.properties new file mode 100644 index 00000000000..6242c967488 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/fragment.properties @@ -0,0 +1,14 @@ +################################################################################# +# Copyright (c) 2014 CEA 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: +# +# Christian W. Damus (CEA) - initial API and Implementation. +# +################################################################################## +pluginName=Papyrus GMF Diagram Commands Infrastructure Tests (Incubation) +providerName=Eclipse Modeling Project diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/org.eclipse.papyrus.infra.gmfdiag.commands.tests.launch b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/org.eclipse.papyrus.infra.gmfdiag.commands.tests.launch new file mode 100644 index 00000000000..5afacf2f348 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/org.eclipse.papyrus.infra.gmfdiag.commands.tests.launch @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig"> +<booleanAttribute key="append.args" value="true"/> +<booleanAttribute key="askclear" value="false"/> +<booleanAttribute key="automaticAdd" value="true"/> +<booleanAttribute key="automaticValidate" value="false"/> +<stringAttribute key="bootstrap" value=""/> +<stringAttribute key="checked" value="[NONE]"/> +<booleanAttribute key="clearConfig" value="true"/> +<booleanAttribute key="clearws" value="true"/> +<booleanAttribute key="clearwslog" value="false"/> +<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/> +<booleanAttribute key="default" value="true"/> +<booleanAttribute key="includeOptional" value="true"/> +<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/infra/gmfdiag/commands/tests/AllTests.java"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="1"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.infra.gmfdiag.commands.tests.AllTests"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.infra.gmfdiag.commands.tests"/> +<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=512M"/> +<stringAttribute key="pde.version" value="3.3"/> +<stringAttribute key="product" value="org.eclipse.platform.ide"/> +<booleanAttribute key="run_in_ui_thread" value="true"/> +<booleanAttribute key="show_selected_only" value="false"/> +<booleanAttribute key="tracing" value="false"/> +<booleanAttribute key="useCustomFeatures" value="false"/> +<booleanAttribute key="useDefaultConfig" value="true"/> +<booleanAttribute key="useDefaultConfigArea" value="false"/> +<booleanAttribute key="useProduct" value="true"/> +</launchConfiguration> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/Bug402525.ecore b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/Bug402525.ecore new file mode 100644 index 00000000000..8dea18de3e8 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/Bug402525.ecore @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="bug402525" nsURI="http://www.eclipse.org/schema/Papyrus/tests/bug402525" + nsPrefix="bug"> + <eClassifiers xsi:type="ecore:EClass" name="Foo"/> +</ecore:EPackage> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStackTest.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStackTest.java new file mode 100644 index 00000000000..925cc1b4c0b --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/commands/NestingNotifyingWorkspaceCommandStackTest.java @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2014 CEA 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: + * Christian W. Damus (CEA) - Initial API and implementation + * + */ +package org.eclipse.papyrus.commands; + +import static org.hamcrest.CoreMatchers.both; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; + +import java.net.URL; +import java.util.concurrent.Callable; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.CommandStack; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.ENamedElement; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.TransactionalCommandStack; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.papyrus.infra.emf.readonly.PapyrusROTransactionalEditingDomain; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.base.Objects; + + +/** + * Test suite for the {@link NestingNotifyingWorkspaceCommandStack} class. + */ +public class NestingNotifyingWorkspaceCommandStackTest { + + // No API signatures but the most basic are required for nesting + private CommandStack fixture; + + private TransactionalEditingDomain domain; + + private ResourceSet rset; + + private EPackage testPackage; + + private EClass foo; + + public NestingNotifyingWorkspaceCommandStackTest() { + super(); + } + + // + // Test cases + // + + @Test + public void testCompleteUnnestedCommand() { + Callable<EAttribute> createAttribute = createAttribute(); + + int oldFeatureCount = foo.getEStructuralFeatures().size(); + + // Create two attributes + EAttribute attr1 = execute(createAttribute); + EAttribute attr2 = execute(createAttribute); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount + 2)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr1)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr2)); + + // Undo only undoes one of them + Command undone = undo(); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount + 1)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr1)); + assertThat(foo.getEStructuralFeatures(), not(hasItem(attr2))); + + // Redo is sane + Command redone = redo(); + assertThat(redone, sameInstance(undone)); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount + 2)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr1)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr2)); + } + + @Test + public void testCancelUnnestedCommand() { + Callable<EAttribute> createAttribute = createAttribute(2); + + int oldFeatureCount = foo.getEStructuralFeatures().size(); + + // Try to create two attributes (second one cancels) + EAttribute attr1 = execute(createAttribute); + EAttribute attr2 = execute(createAttribute); + assertThat(attr2, nullValue()); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount + 1)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr1)); + assertThat(foo.getEStructuralFeature("attribute2"), nullValue()); //$NON-NLS-1$ + + // Undo is sane + Command undone = undo(); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount)); + assertThat(foo.getEStructuralFeatures(), not(hasItem(attr1))); + assertThat(foo.getEStructuralFeature("attribute2"), nullValue()); //$NON-NLS-1$ + + // Redo is sane + Command redone = redo(); + assertThat(redone, sameInstance(undone)); + assertThat(foo.getEStructuralFeatures().size(), is(oldFeatureCount + 1)); + assertThat(foo.getEStructuralFeatures(), hasItem(attr1)); + assertThat(foo.getEStructuralFeature("attribute2"), nullValue()); //$NON-NLS-1$ + } + + @Test + public void testCompleteNestedCommand() { + final int FEATURES = 2; + Callable<EClass> createClass = createClass(FEATURES); + + int oldClassifierCount = testPackage.getEClassifiers().size(); + + EClass clas = execute(createClass); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount + 1)); + assertThat(testPackage.getEClassifiers(), hasItem(clas)); + assertThat(clas.getEStructuralFeatures().size(), is(FEATURES)); + assertThat(clas.getEStructuralFeature("attribute1"), notNullValue()); //$NON-NLS-1$ + assertThat(clas.getEStructuralFeature("attribute2"), notNullValue()); //$NON-NLS-1$ + + // Undo is sane and there is only one command to undo + Command undone = undo(); + assertThat(fixture.canUndo(), is(false)); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount)); + assertThat(testPackage.getEClassifiers(), not(hasItem(clas))); + + // Redo is sane + Command redone = redo(); + assertThat(redone, sameInstance(undone)); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount + 1)); + assertThat(testPackage.getEClassifiers(), hasItem(clas)); + assertThat(clas.getEStructuralFeatures().size(), is(FEATURES)); + assertThat(clas.getEStructuralFeature("attribute1"), notNullValue()); //$NON-NLS-1$ + assertThat(clas.getEStructuralFeature("attribute2"), notNullValue()); //$NON-NLS-1$ + } + + @Test + public void testCancelNestedCommand() { + final int FEATURES = 2; + Callable<EClass> createClass = createClass(FEATURES, 2, FEATURES); + + int oldClassifierCount = testPackage.getEClassifiers().size(); + + // Try to create two classes (second one cancels) + EClass class1 = execute(createClass); + EClass class2 = execute(createClass); + assertThat(class2, nullValue()); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount + 1)); + assertThat(testPackage.getEClassifiers(), hasItem(class1)); + assertThat(class1.getEStructuralFeatures().size(), is(FEATURES)); + assertThat(class1.getEStructuralFeature("attribute1"), notNullValue()); //$NON-NLS-1$ + assertThat(class1.getEStructuralFeature("attribute2"), notNullValue()); //$NON-NLS-1$ + + // Undo is sane and there is only one command to undo + Command undone = undo(); + assertThat(fixture.canUndo(), is(false)); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount)); + assertThat(testPackage.getEClassifiers(), not(hasItem(class1))); + + // Redo is sane + Command redone = redo(); + assertThat(redone, sameInstance(undone)); + assertThat(testPackage.getEClassifiers().size(), is(oldClassifierCount + 1)); + assertThat(testPackage.getEClassifiers(), hasItem(class1)); + assertThat(class1.getEStructuralFeatures().size(), is(FEATURES)); + assertThat(class1.getEStructuralFeature("attribute1"), notNullValue()); //$NON-NLS-1$ + assertThat(class1.getEStructuralFeature("attribute2"), notNullValue()); //$NON-NLS-1$ + } + + @Test + public void testCompleteTripleNestedCommand() { + final int CLASSES = 2; + final int FEATURES = 2; + + Callable<EPackage> createPackage = createPackage(CLASSES, FEATURES); + + int oldPackageCount = testPackage.getESubpackages().size(); + + EPackage pkg = execute(createPackage); + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount + 1)); + assertThat(testPackage.getESubpackages(), hasItem(pkg)); + assertThat(pkg.getEClassifiers().size(), is(CLASSES)); + assertThat(pkg.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class1")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertThat(pkg.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class2")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + // Undo is sane and there is only one command to undo + Command undone = undo(); + assertThat(fixture.canUndo(), is(false)); + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount)); + assertThat(testPackage.getESubpackages(), not(hasItem(pkg))); + assertThat(pkg.getName(), nullValue()); + assertThat(pkg.getEClassifiers().size(), is(0)); + assertThat(pkg.getEClassifiers().size(), is(0)); + + // Redo is sane + Command redone = redo(); + assertThat(redone, sameInstance(undone)); + assertThat(fixture.canRedo(), is(false)); + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount + 1)); + assertThat(testPackage.getESubpackages(), hasItem(pkg)); + assertThat(pkg, named("package1")); //$NON-NLS-1$ + assertThat(pkg.getEClassifiers().size(), is(CLASSES)); + assertThat(pkg.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class1")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertThat(pkg.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class2")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + @Test + public void testCancelTripleNestedCommand() { + final int CLASSES = 2; + final int FEATURES = 2; + + Callable<EPackage> createPackage = createPackage(CLASSES, FEATURES, 2, CLASSES, FEATURES); + + int oldPackageCount = testPackage.getESubpackages().size(); + + // Try to create two packages (second one cancels) + EPackage pkg1 = execute(createPackage); + EPackage pkg2 = execute(createPackage); + + // the first package is complete + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount + 1)); + assertThat(testPackage.getESubpackages(), hasItem(pkg1)); + assertThat(pkg1, named("package1")); //$NON-NLS-1$ + assertThat(pkg1.getEClassifiers().size(), is(CLASSES)); + assertThat(pkg1.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class1")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertThat(pkg1.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class2")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + // there is no second package + assertThat(pkg2, nullValue()); + + // Undo is sane and there is only one command to undo + Command undone = undo(); + assertThat(fixture.canUndo(), is(false)); + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount)); + assertThat(testPackage.getESubpackages(), not(hasItem(pkg1))); + assertThat(pkg1.getName(), nullValue()); + assertThat(pkg1.getEClassifiers().size(), is(0)); + + // Redo is sane + Command redone = redo(); + assertThat(fixture.canRedo(), is(false)); + assertThat(redone, sameInstance(undone)); + assertThat(testPackage.getESubpackages().size(), is(oldPackageCount + 1)); + assertThat(testPackage.getESubpackages(), hasItem(pkg1)); + assertThat(pkg1, named("package1")); //$NON-NLS-1$ + assertThat(pkg1.getEClassifiers().size(), is(CLASSES)); + assertThat(pkg1.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class1")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + assertThat(pkg1.getEClassifiers(), hasItem(both(featureCount(FEATURES)).and(named("Class2")).and(hasFeature("attribute1")).and(hasFeature("attribute2")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + // + // Test framework + // + + @Before + public void createFixture() { + rset = new ResourceSetImpl(); + fixture = new NestingNotifyingWorkspaceCommandStack(CheckedOperationHistory.getInstance()); + AdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); + domain = new PapyrusROTransactionalEditingDomain(adapterFactory, (TransactionalCommandStack)fixture, rset); + + URL testModelURL = getClass().getResource("bug402525.ecore"); //$NON-NLS-1$ + Resource testModel = rset.getResource(URI.createURI(testModelURL.toExternalForm(), true), true); + testPackage = (EPackage)testModel.getContents().get(0); + foo = (EClass)testPackage.getEClassifier("Foo"); //$NON-NLS-1$ + } + + @After + public void destroyFixture() { + // This disposes the command stack for us + domain.dispose(); + domain = null; + fixture = null; + + dispose(rset); + rset = null; + } + + void dispose(ResourceSet rset) { + for(Resource next : rset.getResources()) { + next.unload(); + next.eAdapters().clear(); + } + + rset.getResources().clear(); + rset.eAdapters().clear(); + } + + <V> V execute(final Callable<V> operation) { + class TestCommand extends RecordingCommand { + + V result; + + TestCommand() { + super(domain); + } + + @Override + protected void doExecute() { + try { + result = operation.call(); + } catch (OperationCanceledException e) { + // Pass it on + throw e; + } catch (Exception e) { + e.printStackTrace(); + fail("Uncaught exception in operation: " + e.getLocalizedMessage()); //$NON-NLS-1$ + } + } + } + + TestCommand command = new TestCommand(); + fixture.execute(command); + return command.result; + } + + Command undo() { + assertThat("Cannot undo", fixture.canUndo()); //$NON-NLS-1$ + Command result = fixture.getUndoCommand(); + fixture.undo(); + return result; + } + + Command redo() { + assertThat("Cannot redo", fixture.canRedo()); //$NON-NLS-1$ + Command result = fixture.getRedoCommand(); + fixture.redo(); + return result; + } + + Callable<EAttribute> createAttribute() { + return createAttribute(0); + } + + Callable<EAttribute> createAttribute(int cancelOn) { + return createAttribute(foo, cancelOn); + } + + Callable<EAttribute> createAttribute(final EClass owner, final int cancelOn) { + return new Callable<EAttribute>() { + + int i = 0; + + public EAttribute call() throws Exception { + String name = nextName(); + + EAttribute attr = EcoreFactory.eINSTANCE.createEAttribute(); + owner.getEStructuralFeatures().add(attr); + attr.setName(name); + attr.setEType(EcorePackage.Literals.ESTRING); + + checkCancel(); + + return attr; + } + + private String nextName() { + i = i + 1; + return "attribute" + i; //$NON-NLS-1$ + } + + private void checkCancel() { + if(i == cancelOn) { + throw new OperationCanceledException(); + } + } + }; + } + + Callable<EClass> createClass(int attributes) { + return createClass(attributes, 0, 0); + } + + Callable<EClass> createClass(int attributes, int cancelOn, int cancelAttributesOn) { + return createClass(testPackage, attributes, cancelOn, cancelAttributesOn); + } + + Callable<EClass> createClass(final EPackage owner, final int attributes, final int cancelOn, final int cancelAttributesOn) { + return new Callable<EClass>() { + + int i = 0; + + public EClass call() throws Exception { + String name = nextName(); + + EClass clas = EcoreFactory.eINSTANCE.createEClass(); + owner.getEClassifiers().add(clas); + clas.setName(name); + + Callable<?> createAttribute = createAttribute(clas, checkCancelAttributes()); + for(int i = 0; i < attributes; i++) { + // Nested command + execute(createAttribute); + } + + return clas; + } + + private String nextName() { + i = i + 1; + return "Class" + i; //$NON-NLS-1$ + } + + private int checkCancelAttributes() { + return (i == cancelOn) ? cancelAttributesOn : 0; + } + }; + } + + Callable<EPackage> createPackage(int classes, int attributes) { + return createPackage(classes, attributes, 0, 0, 0); + } + + Callable<EPackage> createPackage(final int classes, final int attributes, final int cancelOn, final int cancelClassesOn, final int cancelAttributesOn) { + return new Callable<EPackage>() { + + int i = 0; + + public EPackage call() throws Exception { + String name = nextName(); + + EPackage pkg = EcoreFactory.eINSTANCE.createEPackage(); + testPackage.getESubpackages().add(pkg); + pkg.setName(name); + + Callable<?> createClass = createClass(pkg, attributes, checkCancelClasses(), cancelAttributesOn); + for(int i = 0; i < classes; i++) { + // Nested command + execute(createClass); + } + + return pkg; + } + + private String nextName() { + i = i + 1; + return "package" + i; //$NON-NLS-1$ + } + + private int checkCancelClasses() { + return (i == cancelOn) ? cancelClassesOn : 0; + } + }; + } + + Matcher<ENamedElement> named(final String name) { + return new BaseMatcher<ENamedElement>() { + + public void describeTo(Description desc) { + desc.appendText("is named \"").appendValue(name).appendText("\""); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public boolean matches(Object o) { + return (o instanceof ENamedElement) && Objects.equal(((ENamedElement)o).getName(), name); + } + }; + } + + Matcher<EClass> featureCount(final int count) { + return new BaseMatcher<EClass>() { + + public void describeTo(Description desc) { + desc.appendText("has ").appendValue(count).appendText(" features"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public boolean matches(Object o) { + return (o instanceof EClass) && (((EClass)o).getEStructuralFeatures().size() == count); + } + }; + } + + Matcher<EClass> hasFeature(final String name) { + return new BaseMatcher<EClass>() { + + public void describeTo(Description desc) { + desc.appendText("has a \"").appendValue(name).appendText("\" feature"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public boolean matches(Object o) { + return (o instanceof EClass) && (((EClass)o).getEStructuralFeature(name) != null); + } + }; + } +} diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/infra/gmfdiag/commands/tests/AllTests.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/infra/gmfdiag/commands/tests/AllTests.java new file mode 100644 index 00000000000..ecce7998eb4 --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.commands.tests/src/org/eclipse/papyrus/infra/gmfdiag/commands/tests/AllTests.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 CEA LIST 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: + * Christian W. Damus (CEA) - initial API and implementation + */ +package org.eclipse.papyrus.infra.gmfdiag.commands.tests; + +import org.eclipse.papyrus.commands.NestingNotifyingWorkspaceCommandStackTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +/** + * Master test suite for this test fragment. + */ +@RunWith(Suite.class) +@SuiteClasses({ +// {oep.commands} +NestingNotifyingWorkspaceCommandStackTest.class }) +public class AllTests { + +} |