Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp')
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/AppearanceTest.xtend46
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CanonicalTests.xtend59
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteChildLabelNodesTest.xtend80
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteTest.xtend268
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DeleteTest.xtend45
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DirectEditTest.xtend45
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DropTest.xtend45
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPComponent.java154
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPModule.xtend179
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/SynchronizationTest.xtend322
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TestExceptionManager.xtend90
-rw-r--r--tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TransformationUtilities.xtend765
12 files changed, 2098 insertions, 0 deletions
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/AppearanceTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/AppearanceTest.xtend
new file mode 100644
index 00000000000..d1fef65f460
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/AppearanceTest.xtend
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.papyrus.tests.framework.gmfgenuml2utp.TransformationUtilities.TestPackageBuilder
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to appearance tests in the UTP test model.
+ */
+class AppearanceTest {
+ @Inject extension TransformationUtilities
+
+ @FrameworkConfig Collection<String> elementTypesAppearanceTests = Collections.emptyList
+
+ @TestPackageRule val appearancePackage = [
+ name = 'appearance'
+
+ testContextRules += mapNone -> topNodeAppearance
+ ]
+
+ @TestContextRule val topNodeAppearance = [
+ simple('AbstractAppearanceNodeTest', 'AppearanceTest')
+ topEditParts += gmfgen.getTopNodes(elementTypesAppearanceTests)
+ testBehaviors += mapTests(topEditParts) [toCallTestNodeOperationActivity('AbstractAppearanceNodeTest', 'AppearanceNodeTest', false)]
+ testCaseRule = testCaseRule('testAppearanceNode')
+ ]
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CanonicalTests.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CanonicalTests.xtend
new file mode 100644
index 00000000000..4f70a41b626
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CanonicalTests.xtend
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import javax.inject.Inject
+import javax.inject.Singleton
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.uml2.uml.Model
+import org.eclipse.uml2.uml.UMLFactory
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to UTP test model.
+ */
+@Singleton
+class CanonicalTests {
+ static extension UMLFactory = UMLFactory.eINSTANCE
+
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+
+ @Inject extension AppearanceTest
+ @Inject extension CreateFromPaletteTest
+ @Inject extension DirectEditTest
+ @Inject extension DropTest
+ @Inject extension DeleteTest
+ @Inject extension SynchronizationTest
+
+ @FrameworkConfig String diagramTestPackageName
+
+ def create createModel toUTPModel(Model gmfgenModel, Resource extent) {
+ name = diagramTestPackageName
+
+ // Add the output model to a resource-set context now to support the static UTP profile
+ extent.contents.add(it)
+ applyProfile(utp)
+
+ createTestPackage(gmfgenModel, appearancePackage)
+ createTestPackage(gmfgenModel, createFromPalettePackage)
+ createTestPackage(gmfgenModel, directEditPackage)
+ createTestPackage(gmfgenModel, dropPackage)
+ createTestPackage(gmfgenModel, deletePackage)
+ createTestPackage(gmfgenModel, synchronizationPackage)
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteChildLabelNodesTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteChildLabelNodesTest.xtend
new file mode 100644
index 00000000000..f25621cdcf3
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteChildLabelNodesTest.xtend
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.UMLFactory
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to child label palette tests in the UTP test model.
+ */
+class CreateFromPaletteChildLabelNodesTest {
+ static extension UMLFactory = UMLFactory.eINSTANCE
+
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+
+ protected def getContainerCompartmentNames(InstanceSpecification node) {
+ node.containerCompartments.map[editPart]
+ }
+
+ protected def getParentNodeNames(InstanceSpecification node) {
+ node.parentNodes.map[editPart]
+ }
+
+ protected def toCallTestChildLabelNodeOperationActivity(InstanceSpecification labelEditPart,
+ InstanceSpecification compartmentEditPart, InstanceSpecification parentNodeEditPart) {
+
+ createActivity => [
+ name = labelEditPart.editPart.replace('EditPart', '').toFirstLower
+
+ ownedNodes += createCallOperationAction => [
+ name = 'ChildLabelTestNodeActivity_' + parentNodeEditPart.name + '_' + labelEditPart.name + '_' + compartmentEditPart.name
+ operation = frameworkClass('AbstractCreateChildLabelNodeFromPaletteTest').allOperations.head
+ arguments += #[
+ parentNodeEditPart.toValuePin('parentNode'),
+ labelEditPart.toValuePin('childNode'),
+ compartmentEditPart.toIntegerValuePin('compartment'),
+ true.toValuePin('mustPass')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestChildLabelNodeOperationActivity(InstanceSpecification labelEditPart,
+ InstanceSpecification compartmentEditPart, InstanceSpecification nestedNodeEditPart,
+ InstanceSpecification topNodeCompartmentEditPart, InstanceSpecification topNodeEditPart) {
+
+ createActivity => [
+ name = labelEditPart.editPart.replace('EditPart', '').toFirstLower
+
+ ownedNodes += createCallOperationAction => [
+ name = 'ChildLabelTestNodeActivity_' + nestedNodeEditPart.name + '_' + labelEditPart.name + '_' + compartmentEditPart.name
+ operation = frameworkClass('AbstractCreateChildLabelNodeFromPaletteTest').allOperations.head
+ arguments += #[
+ topNodeEditPart.toValuePin('topNode'),
+ topNodeCompartmentEditPart.toIntegerValuePin('topNodeCompartment'),
+ nestedNodeEditPart.toValuePin('parentNode'),
+ labelEditPart.toValuePin('childNode'),
+ compartmentEditPart.toIntegerValuePin('compartment'),
+ true.toValuePin('mustPass')
+ ]
+ ]
+ ]
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteTest.xtend
new file mode 100644
index 00000000000..21cdd38d9f5
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/CreateFromPaletteTest.xtend
@@ -0,0 +1,268 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.UMLFactory
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+import org.apache.log4j.Logger
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to palette tests in the UTP test model.
+ */
+class CreateFromPaletteTest {
+ static extension UMLFactory = UMLFactory.eINSTANCE
+
+ @Inject(optional=true) Logger log = Logger.getLogger(CreateFromPaletteTest)
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+ @Inject extension CreateFromPaletteChildLabelNodesTest
+
+ @FrameworkConfig String topContainerEditPart = ''
+ @FrameworkConfig Collection<String> topNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> childNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> childLabelNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> linksToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> linksOwnedBySourceToTest = Collections.emptyList
+
+ @TestPackageRule val createFromPalettePackage = [
+ name = 'createFromPalette'
+
+ testContextRules += #[
+ mapNone -> topNodeCreation,
+ childLabelNodesToTest.mapChildLabelNode -> childLabelNodeCreation,
+ topNodesToTest.mapTopNode -> childNodeCreation,
+ linksToTest.mapLink -> linkCreation,
+ linksOwnedBySourceToTest.mapLink -> linkOwnedBySourceCreation
+ ]
+ ]
+
+ @TestContextRule val topNodeCreation = [
+ common('AbstractCreateNodeFromPaletteTest', 'TopNodesTest')
+ topEditParts += gmfgen.getTopNodes(topNodesToTest)
+ testBehaviors += mapTests(topEditParts) [
+ toCallTestNodeOperationActivity('AbstractCreateNodeFromPaletteTest', 'TestTopNode')
+ ]
+ testCaseRule = testCaseRule('testTopNode')
+ ]
+
+ @TestContextRule val childLabelNodeCreation = [
+ common('AbstractCreateChildLabelNodeFromPaletteTest', 'Label' + selfInstance.editPart + 'Test')
+ childLabelEditParts += selfInstance
+
+ val validLabels = childLabelEditParts.filter[getSlot('containers') != null]
+ validLabels.forEach[label |
+ label.containerCompartments.forEach[compartment |
+ val allParentNodes = compartment.parentNodes
+ val nestedParentNodes = allParentNodes.filter[isChildNode && containerCompartments.exists[parentNodes.exists[isTopNode]]]
+ val topParentNodes = allParentNodes.filter[isTopNode]
+
+ testBehaviors += mapTestsByInstance(#[label], #[compartment], topParentNodes) [
+ labelEditPart, compartmentEditPart, parentNodeEditPart |
+ labelEditPart.toCallTestChildLabelNodeOperationActivity(compartmentEditPart, parentNodeEditPart)
+ ]
+
+ for (nested : nestedParentNodes) {
+ // Compute a representative top node and compartment in which to create the nested node (in which to create the label)
+ val topNodeCompartment = nested.containerCompartments.filter[parentNodes.exists[isTopNode]].head
+ val topNode = topNodeCompartment.parentNodes.filter[isTopNode].head
+
+ testBehaviors += mapTestsByInstance(#[label], #[compartment], #[nested]) [
+ labelEditPart, compartmentEditPart, parentNodeEditPart |
+ labelEditPart.toCallTestChildLabelNodeOperationActivity(compartmentEditPart, parentNodeEditPart, topNodeCompartment, topNode)
+ ]
+ }
+ ]
+ ]
+ testCaseRule = testCaseRule('testChildLabel')
+ ]
+
+ @TestContextRule val childNodeCreation = [
+ common('AbstractCreateNodeFromPaletteTest', 'ChildNodeIn' + selfInstance.editPart + 'Test')
+ containerEditPart = selfInstance
+
+ selfInstance.compartments.forEach[compartment |
+ val contents = compartment.childNodes.filter[childNodesToTest.contains(editPart)]
+ childEditParts += contents
+ testBehaviors += mapTestsByInstance(#[containerEditPart], contents) [parent, child |
+ child.toCallTestChildNodeOperationActivity(parent, 'AbstractCreateNodeFromPaletteTest', 'TestChildNode')
+ ]
+ ]
+ testCaseRule = testCaseRule('testChildNode')
+ ]
+
+ @TestContextRule val linkCreation = [
+ common('AbstractCreateLinkFromPaletteTest', selfInstance.editPart + 'Test')
+ linkEditParts += selfInstance
+
+ if (!selfInstance.canCreateTests) {
+ log.warn('Cannot create test cases for ' + selfInstance.editPart + ' because it is missing either source or target edit-parts.')
+ } else {
+ val ctx = it
+
+ testBehaviors += mapTests(linkEditParts, topNodesToTest.filter[linksTo(ctx.selfInstance)], topNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target)
+ ]
+
+ testBehaviors += mapTests(linkEditParts, childNodesToTest.filter[linksTo(ctx.selfInstance)], childNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, gmfgen.getNode(topContainerEditPart))
+ ]
+
+ testCaseRule = testCaseRule('testLink')
+ }
+ ]
+
+ @TestContextRule val linkOwnedBySourceCreation = [
+ common('AbstractCreateLinkOwnedBySourceFromPaletteTest', selfInstance.editPart + 'Test')
+ linkOwnedBySourceEditParts += selfInstance
+
+ if (!selfInstance.canCreateTests) {
+ log.warn('Cannot create test cases for ' + selfInstance.editPart + ' because it is missing either source or target edit-parts.')
+ } else {
+ val ctx = it
+
+ testBehaviors += mapTests(linkOwnedBySourceEditParts, topNodesToTest.filter[linksTo(ctx.selfInstance)], topNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target)
+ ]
+
+ testBehaviors += mapTests(linkOwnedBySourceEditParts, childNodesToTest.filter[linksTo(ctx.selfInstance)], childNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, gmfgen.getNode(topContainerEditPart))
+ ]
+
+ testCaseRule = testCaseRule('testLinkOwnedBySource')
+ }
+ ]
+
+ protected def toCallTestChildNodeOperationActivity(InstanceSpecification childEditPart, InstanceSpecification parentEditPart, String abstractTestClassName, String nodeType) {
+ createActivity => [
+ name = childEditPart.testBehaviorName
+ ownedNodes += createCallOperationAction => [
+ operation = frameworkClass(abstractTestClassName).allOperations.head
+ arguments += #[
+ childEditPart.toValuePin('node'),
+ parentEditPart.toValuePin('container'),
+ true.toValuePin('mustSucceed')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLinkOperationActivity(InstanceSpecification linkEditPart, InstanceSpecification sourceEditPart, InstanceSpecification targetEditPart) {
+ createActivity => [
+ name = String.format('%s_%s_%s',
+ linkEditPart.editPart.replace('EditPart', '').toFirstLower,
+ sourceEditPart.editPart.replace('EditPart', '').toFirstLower,
+ targetEditPart.editPart.replace('EditPart', '').toFirstLower)
+
+ ownedNodes += createCallOperationAction => [
+ operation = frameworkClass('AbstractCreateLinkFromPaletteTest').allOperations.head
+ arguments += #[
+ linkEditPart.toValuePin(sourceEditPart.editPart, 'source'),
+ linkEditPart.toValuePin(targetEditPart.editPart, 'target'),
+ linkEditPart.toValuePin('link'),
+ true.toValuePin('mustSucceed')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLinkOperationActivity(InstanceSpecification linkEditPart, InstanceSpecification sourceEditPart, InstanceSpecification targetEditPart, InstanceSpecification containerEditPart) {
+ createActivity => [
+ name = String.format('%s_%s_%s',
+ linkEditPart.editPart.replace('EditPart', '').toFirstLower,
+ sourceEditPart.editPart.replace('EditPart', '').toFirstLower,
+ targetEditPart.editPart.replace('EditPart', '').toFirstLower)
+
+ ownedNodes += createCallOperationAction => [
+ operation = frameworkClass('AbstractCreateLinkFromPaletteTest').allOperations.head
+ arguments += #[
+ linkEditPart.toValuePin(sourceEditPart.editPart, 'source'),
+ linkEditPart.toValuePin(targetEditPart.editPart, 'target'),
+ linkEditPart.toValuePin('link'),
+ linkEditPart.toValuePin(containerEditPart.editPart, 'container'),
+ true.toValuePin('mustSucceed')
+ ]
+ ]
+ ]
+ }
+
+ /**
+ * Queries whether a node edit-part may be the source of a link edit-part, according to the GMFGen model.
+ */
+ public def linksTo(String sourceNodeEditPart, InstanceSpecification linkEditPart) {
+ linkEditPart.getSlotStringValues('sources').contains(sourceNodeEditPart)
+ }
+
+ /**
+ * Queries whether a node edit-part may be the target of a link edit-part, according to the GMFGen model.
+ */
+ public def linksFrom(String targetNodeEditPart, InstanceSpecification linkEditPart) {
+ linkEditPart.getSlotStringValues('targets').contains(targetNodeEditPart)
+ }
+
+ protected def linksToOrFrom(String nodeEditPart, InstanceSpecification linkEditPart) {
+ nodeEditPart.linksTo(linkEditPart) || nodeEditPart.linksFrom(linkEditPart)
+ }
+
+ /**
+ * Queries whether we can create any tests for the specified link edit-part. This is generally only
+ * {@code false} when the link edit part either has no viable source edit-parts or no viable target
+ * edit-parts.
+ */
+ public def canCreateTests(InstanceSpecification linkEditPart) {
+ !linkEditPart.nodesRequiredForTest.empty
+ }
+
+ protected def nodesRequiredForTest(InstanceSpecification linkEditPart) {
+ val sources = linkEditPart.getSlotStringValues('sources')
+ val targets = linkEditPart.getSlotStringValues('targets')
+
+ val sourceTopNodes = sources.toSet => [retainAll(topNodesToTest)]
+ val sourceChildNodes = sources.toSet => [retainAll(childNodesToTest)]
+ val targetTopNodes = targets.toSet => [retainAll(topNodesToTest)]
+ val targetChildNodes = targets.toSet => [retainAll(childNodesToTest)]
+
+ newLinkedHashSet => [
+ // Handle top nodes together and child nodes together
+ if (!(sourceTopNodes.empty || targetTopNodes.empty)) {
+ it.addAll(sourceTopNodes)
+ it.addAll(targetTopNodes)
+ }
+ if (!(sourceChildNodes.empty || targetChildNodes.empty)) {
+ it.addAll(sourceChildNodes)
+ it.addAll(targetChildNodes)
+ it.add(topContainerEditPart)
+ }
+ ]
+ }
+
+ private def toValuePin(InstanceSpecification linkEditPart, String editPartName, String role) {
+ createValuePin => [
+ val otherInstance = linkEditPart.model.getNode(editPartName)
+ name = role
+ value = createInstanceValue => [
+ name = otherInstance.name
+ instance = otherInstance
+ ]
+ ]
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DeleteTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DeleteTest.xtend
new file mode 100644
index 00000000000..45c4e5b6a8f
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DeleteTest.xtend
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to deletion tests in the UTP test model.
+ */
+class DeleteTest {
+ @Inject extension TransformationUtilities
+
+ @FrameworkConfig Collection<String> elementTypesDeleteTests = Collections.emptyList
+
+ @TestPackageRule val deletePackage = [
+ name = 'delete'
+
+ testContextRules += mapNone -> topNodeDeletion
+ ]
+
+ @TestContextRule val topNodeDeletion = [
+ common('AbstractDeleteNodeTest', 'DeleteTest')
+ topEditParts += gmfgen.getTopNodes(elementTypesDeleteTests)
+ testBehaviors += mapTests(topEditParts) [toCallTestNodeOperationActivity('AbstractDeleteNodeTest', 'DeleteNodeTest', false)]
+ testCaseRule = testCaseRule('testDeleteNode')
+ ]
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DirectEditTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DirectEditTest.xtend
new file mode 100644
index 00000000000..460d4bf99af
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DirectEditTest.xtend
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to direct-edit tests in the UTP test model.
+ */
+class DirectEditTest {
+ @Inject extension TransformationUtilities
+
+ @FrameworkConfig Collection<String> elementTypesEditTests = Collections.emptyList
+
+ @TestPackageRule val directEditPackage = [
+ name = 'directedit'
+
+ testContextRules += mapNone -> topNodeDirectEdit
+ ]
+
+ @TestContextRule val topNodeDirectEdit = [
+ simple('AbstractEditableNodeTest', 'DirectEditTest')
+ topEditParts += gmfgen.getTopNodes(elementTypesEditTests)
+ testBehaviors += mapTests(topEditParts) [toCallTestNodeOperationActivity('AbstractEditableNodeTest', 'DirectEditTest', false)]
+ testCaseRule = testCaseRule('testDirectEdit')
+ ]
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DropTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DropTest.xtend
new file mode 100644
index 00000000000..d2da252c35a
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/DropTest.xtend
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to drag-and-drop tests in the UTP test model.
+ */
+class DropTest {
+ @Inject extension TransformationUtilities
+
+ @FrameworkConfig Collection<String> elementTypesDropTests = Collections.emptyList
+
+ @TestPackageRule val dropPackage = [
+ name = 'drop'
+
+ testContextRules += mapNone -> topNodeDrop
+ ]
+
+ @TestContextRule val topNodeDrop = [
+ simple('AbstractDropNodeTest', 'DropTest')
+ topEditParts += gmfgen.getTopNodes(elementTypesDropTests)
+ testBehaviors += mapTests(topEditParts) [toCallTestNodeOperationActivity('AbstractDropNodeTest', 'DropNodeTest')]
+ testCaseRule = testCaseRule('testDropNode')
+ ]
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPComponent.java b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPComponent.java
new file mode 100644
index 00000000000..f24b05e7ae6
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPComponent.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - bug 464647
+ *
+ ******************************************************************************/
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.utils.AbstractEMFWorkflowComponent;
+import org.eclipse.papyrus.tests.framework.exceptions.TestExceptions;
+import org.eclipse.papyrus.tests.framework.gmfgen2uml.GMFGen2UMLComponent;
+import org.eclipse.uml2.uml.Model;
+import org.eclipse.uml2.uml.Profile;
+import org.eclipse.uml2.uml.UMLPackage;
+import org.eclipse.uml2.uml.resource.UMLResource;
+import org.eclipse.xtext.xbase.lib.Functions.Function3;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * A workflow component that configures and runs a transformation of the UML representation of a
+ * GMFGen model to a UML-UTP model describing the tests to be generated for that diagram.
+ *
+ * @see GMFGen2UMLComponent
+ */
+public class GMFGen2UTPComponent extends AbstractEMFWorkflowComponent {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ private String metamodelSlot;
+
+ private String frameworkBaseSlot;
+
+ private String utpSlot;
+
+ private String outputSlot;
+
+ private Function3<Model, Model, Profile, GMFGen2UTPModule> utpModule;
+
+ public GMFGen2UTPComponent() {
+ super();
+ }
+
+ public String getMetamodelSlot() {
+ return metamodelSlot;
+ }
+
+ public void setMetamodelSlot(String metamodelSlot) {
+ this.metamodelSlot = metamodelSlot;
+ }
+
+ public String getFrameworkBaseSlot() {
+ return frameworkBaseSlot;
+ }
+
+ public void setFrameworkBaseSlot(String frameworkBaseSlot) {
+ this.frameworkBaseSlot = frameworkBaseSlot;
+ }
+
+ public String getUtpSlot() {
+ return utpSlot;
+ }
+
+ public void setUtpSlot(String utpSlot) {
+ this.utpSlot = utpSlot;
+ }
+
+ public String getOutputSlot() {
+ return outputSlot;
+ }
+
+ public void setOutputSlot(String outputSlot) {
+ this.outputSlot = outputSlot;
+ }
+
+ public Function3<Model, Model, Profile, GMFGen2UTPModule> getUtpModule() {
+ return utpModule;
+ }
+
+ public void setUtpModule(Function3<Model, Model, Profile, GMFGen2UTPModule> utpModule) {
+ this.utpModule = utpModule;
+ }
+
+ protected GMFGen2UTPModule createGMFGen2UTPModule(WorkflowContext ctx, Collection<TestExceptions> testExceptions) {
+ TestExceptionManager excmgr = new TestExceptionManager(testExceptions);
+
+ GMFGen2UTPModule result = getUtpModule().apply(
+ (Model) ctx.get(getMetamodelSlot()),
+ (Model) ctx.get(getFrameworkBaseSlot()),
+ (Profile) ctx.get(getUtpSlot()));
+ result.setTestExceptionManager(excmgr);
+
+ return result;
+ }
+
+ @Override
+ protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor,
+ Issues issues) {
+
+ log.info("Transforming GMFGen UML model to UTP test model ...");
+ Object modelSlotContent = ctx.get(getModelSlot());
+ Model model = null;
+ Collection<TestExceptions> testExceptions = Collections.emptyList();
+ if (modelSlotContent instanceof Model) {
+ model = (Model) modelSlotContent;
+ } else if (modelSlotContent instanceof List) {
+ List<?> slotContentList = (List<?>) modelSlotContent;
+ model = Iterables.getFirst(Iterables.filter(slotContentList, Model.class), null);
+ testExceptions = ImmutableList.copyOf(Iterables.filter(slotContentList, TestExceptions.class));
+ }
+ if ((model == null) || !(model instanceof Model)) {
+ log.error("The input model for the transformation was not loaded!");
+ return;
+ }
+
+ GMFGen2UTPModule module = createGMFGen2UTPModule(ctx, testExceptions);
+ module.initEditPartDefaults(model, new TransformationUtilities());
+ Injector injector = Guice.createInjector(module);
+
+ CanonicalTests transformation = injector.getInstance(CanonicalTests.class);
+
+ // Need a resource set context for working with static profiles
+ ResourceSet rset = getResourceSet();
+ rset.getResourceFactoryRegistry().getContentTypeToFactoryMap().put(UMLPackage.eCONTENT_TYPE, UMLResource.Factory.INSTANCE);
+ Resource resource = rset.createResource(URI.createURI("tmp:uml"), UMLPackage.eCONTENT_TYPE);
+
+ Model uml = transformation.toUTPModel(model, resource);
+ ctx.set(getOutputSlot(), uml);
+ log.info("The transformation successfully created Model " + uml.getLabel());
+ }
+
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPModule.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPModule.xtend
new file mode 100644
index 00000000000..0e2c3c78884
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/GMFGen2UTPModule.xtend
@@ -0,0 +1,179 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import static extension org.eclipse.papyrus.tests.framework.m2m.DefaultingList.*
+
+import com.google.common.collect.ImmutableList
+import com.google.inject.AbstractModule
+import com.google.inject.TypeLiteral
+import com.google.inject.name.Names
+import java.util.Collection
+import java.util.List
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+import org.eclipse.papyrus.tests.framework.xtend.annotations.Cached
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.Model
+import org.eclipse.uml2.uml.Profile
+import org.eclipse.uml2.uml.Property
+import org.eclipse.uml2.uml.util.UMLUtil
+import org.eclipse.xtend.lib.annotations.Accessors
+
+/**
+ * Guice module for the GMFGen(UML)-to-UTP transformation.
+ */
+public class GMFGen2UTPModule extends AbstractModule {
+ @Accessors final Model gmfgenMetamodel
+ @Accessors final Model frameworkBase
+ @Accessors final Profile utp
+
+ @Accessors TestExceptionManager testExceptionManager
+
+ @Accessors String diagramTestPackageName;
+ @Accessors String diagramUpdater;
+ @Accessors String diagramCreationCommand;
+ @Accessors String testConstantsInterface;
+
+ @Accessors String topContainerEditPart;
+ @Accessors final List<String> topNodesToTest = newDefaultingList
+ @Accessors final List<String> childNodesToTest = newDefaultingList
+ @Accessors final List<String> childLabelNodesToTest = newDefaultingList
+ @Accessors final List<String> linksToTest = newDefaultingList
+ @Accessors final List<String> linksOwnedBySourceToTest = newDefaultingList
+ @Accessors final List<String> elementTypesAppearanceTests = newDefaultingList
+ @Accessors final List<String> elementTypesDeleteTests = newDefaultingList
+ @Accessors final List<String> elementTypesDropTests = newDefaultingList
+ @Accessors final List<String> elementTypesEditTests = newDefaultingList
+
+ @Accessors final List<String> testExceptionURIs = newArrayList()
+
+ new(Model gmfgenMetamodel, Model frameworkBase, Profile utp) {
+ super()
+
+ this.gmfgenMetamodel = gmfgenMetamodel
+ this.frameworkBase = frameworkBase
+ this.utp = utp
+ }
+
+ protected override configure() {
+ bindLogger()
+
+ bindMetamodels()
+ bindGMFGen2UTP()
+
+ bindTestRules()
+
+ bindTestExceptionManager()
+
+ bindTestParameters()
+ }
+
+ protected def void bindLogger() {
+ // May be overridden if transformation rules are not to use their own loggers
+ }
+
+ protected def void bindMetamodels() {
+ bind(Metamodels).toInstance(new Metamodels(gmfgenMetamodel, frameworkBase, utp))
+ }
+
+ protected def void bindTestRules() {
+ // May be overridden to inject custom transformation rules
+ }
+
+ protected def void bindTestExceptionManager() {
+ bind(TestExceptionManager).toInstance(testExceptionManager ?: new TestExceptionManager)
+ }
+
+ protected def void bindGMFGen2UTP() {
+ // Pass
+ }
+
+ protected def void bindTestParameters() {
+ if(diagramTestPackageName != null) bind(String).annotatedWith(Names.named('diagramTestPackageName')).toInstance(
+ diagramTestPackageName)
+ if(diagramUpdater != null) bind(String).annotatedWith(Names.named('diagramUpdater')).toInstance(diagramUpdater)
+ if(diagramCreationCommand != null) bind(String).annotatedWith(Names.named('diagramCreationCommand')).toInstance(
+ diagramCreationCommand)
+ if(testConstantsInterface != null) bind(String).annotatedWith(Names.named('testConstantsInterface')).toInstance(
+ testConstantsInterface)
+
+ if(topContainerEditPart != null) bind(String).annotatedWith(Names.named('topContainerEditPart')).toInstance(
+ topContainerEditPart)
+
+ val TypeLiteral<Collection<String>> stringsKey = new TypeLiteral<Collection<String>> {
+ }
+ bind(stringsKey).annotatedWith(Names.named('topNodesToTest')).toInstance(ImmutableList.copyOf(topNodesToTest))
+ bind(stringsKey).annotatedWith(Names.named('childNodesToTest')).toInstance(
+ ImmutableList.copyOf(childNodesToTest))
+ bind(stringsKey).annotatedWith(Names.named('childLabelNodesToTest')).toInstance(
+ ImmutableList.copyOf(childLabelNodesToTest))
+ bind(stringsKey).annotatedWith(Names.named('linksToTest')).toInstance(ImmutableList.copyOf(linksToTest))
+ bind(stringsKey).annotatedWith(Names.named('linksOwnedBySourceToTest')).toInstance(
+ ImmutableList.copyOf(linksOwnedBySourceToTest))
+ bind(stringsKey).annotatedWith(Names.named('elementTypesAppearanceTests')).toInstance(
+ ImmutableList.copyOf(elementTypesAppearanceTests))
+ bind(stringsKey).annotatedWith(Names.named('elementTypesDeleteTests')).toInstance(
+ ImmutableList.copyOf(elementTypesDeleteTests))
+ bind(stringsKey).annotatedWith(Names.named('elementTypesDropTests')).toInstance(
+ ImmutableList.copyOf(elementTypesDropTests))
+ bind(stringsKey).annotatedWith(Names.named('elementTypesEditTests')).toInstance(
+ ImmutableList.copyOf(elementTypesEditTests))
+ }
+
+ def void initEditPartDefaults(Model gmfgen, extension TransformationUtilities utilities) {
+ if (topNodesToTest.isDefault) {
+ topNodesToTest += gmfgen.getInstances[isTopNode].map[editPart]
+ }
+ if (childNodesToTest.isDefault) {
+ childNodesToTest += gmfgen.getInstances[isChildNode].map[editPart]
+ }
+ if (childLabelNodesToTest.isDefault) {
+ childLabelNodesToTest += gmfgen.getInstances[isLabelNode].map[editPart]
+ }
+ if (linksToTest.isDefault) {
+ linksToTest += gmfgen.getInstances[isLink && !isOwnedBySource(utilities)].map[editPart]
+ }
+ if (linksOwnedBySourceToTest.isDefault) {
+ linksOwnedBySourceToTest += gmfgen.getInstances[isLink && isOwnedBySource(utilities)].map[editPart]
+ }
+ if (elementTypesAppearanceTests.isDefault) {
+ elementTypesAppearanceTests += topNodesToTest
+ }
+ if (elementTypesDeleteTests.isDefault) {
+ elementTypesDeleteTests += topNodesToTest
+ }
+ if (elementTypesDropTests.isDefault) {
+ elementTypesDropTests += topNodesToTest
+ }
+ if (elementTypesEditTests.isDefault) {
+ elementTypesEditTests += topNodesToTest
+ }
+ }
+
+ private def isOwnedBySource(InstanceSpecification linkEditPart, extension TransformationUtilities utilities) {
+ val modelFacet = linkEditPart.getSlotInstances('modelFacet').head
+ val containment = modelFacet?.getSlotStringValue('containmentMetaFeature')?.umlMetaattribute
+ val source = modelFacet?.getSlotStringValue('sourceMetaFeature')?.umlMetaattribute
+
+ // A feature-link trivially is owned by the source end. Otherwise, if the source is null we assume
+ // ownership by the source end (otherwise, the link can't reference its source)
+ modelFacet.isA('FeatureLinkModelFacet') ||
+ ((containment != null) && ((source == null) || (source.otherEnd == containment)))
+ }
+
+ @Cached def Property umlMetaattribute(String qualifiedName) {
+ if (qualifiedName == null) null else UMLUtil.findNamedElements(utp.eResource.resourceSet, qualifiedName).filter(Property).head
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/SynchronizationTest.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/SynchronizationTest.xtend
new file mode 100644
index 00000000000..f835719decf
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/SynchronizationTest.xtend
@@ -0,0 +1,322 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.inject.Inject
+import java.util.Collection
+import java.util.Collections
+import org.apache.log4j.Logger
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestContextRule
+import org.eclipse.papyrus.tests.framework.xtend.annotations.TestPackageRule
+import org.eclipse.uml2.uml.Activity
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.UMLFactory
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+
+/**
+ * Mapping of UML instance specifications for GMFGen model elements to view synchronization tests in the UTP test model.
+ */
+class SynchronizationTest {
+ static extension UMLFactory = UMLFactory.eINSTANCE
+
+ @Inject(optional=true) Logger log = Logger.getLogger(SynchronizationTest)
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+ @Inject extension CreateFromPaletteTest
+
+ @FrameworkConfig String topContainerEditPart = ''
+ @FrameworkConfig Collection<String> topNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> childNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> childLabelNodesToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> linksToTest = Collections.emptyList
+ @FrameworkConfig Collection<String> linksOwnedBySourceToTest = Collections.emptyList
+
+ @TestPackageRule val synchronizationPackage = [
+ name = 'synchronization'
+
+ // Top node synchronization
+ testContextRules += #[
+ topContainerEditPart.mapTopNode -> topNodeSynchronization,
+ childLabelNodesToTest.mapChildLabelNode -> childLabelNodeSynchronization,
+ topNodesToTest.mapTopNode -> childNodeSynchronization,
+ linksToTest.mapLink -> linkSynchronization,
+ linksOwnedBySourceToTest.mapLink -> linkOwnedBySourceSynchronization
+ ]
+ ]
+
+ @TestContextRule val topNodeSynchronization = [
+ simple('AbstractCSSSynchronizationTest', 'SynchTest')
+ makeSynchSUTProperties('topnode')
+ val abstractTestOperation = superclass.findOperation('testSynchronizeTopNode')
+
+ containerEditPart = selfInstance
+ topEditParts += gmfgen.getTopNodes(topNodesToTest)
+ testBehaviors += mapTests(topEditParts)[toCallTestTopNodeSynchronizationActivity(abstractTestOperation)]
+ testCaseRule = testScenarioRule(abstractTestOperation, 'testSynchronize')
+ ]
+
+ @TestContextRule val childLabelNodeSynchronization = [
+ simple('AbstractCSSSynchronizationTest', 'Label' + selfInstance.editPart + 'SynchTest')
+ makeSynchSUTProperties('labelnode')
+ val abstractTestOperation = superclass.findOperation('testSynchronizeLabelNode')
+
+ childLabelEditParts += selfInstance
+
+ val validLabels = childLabelEditParts.filter[getSlot('containers') != null]
+ validLabels.forEach[label |
+ label.containerCompartments.forEach[compartment |
+ val allParentNodes = compartment.parentNodes
+ val nestedParentNodes = allParentNodes.filter[isChildNode && containerCompartments.exists[parentNodes.exists[isTopNode]]]
+ val topParentNodes = allParentNodes.filter[isTopNode]
+
+ testBehaviors += mapTestsByInstance(#[label], #[compartment], topParentNodes) [
+ labelEditPart, compartmentEditPart, parentNodeEditPart |
+ labelEditPart.toCallTestLabelNodeSynchronizationActivity(compartmentEditPart, parentNodeEditPart, abstractTestOperation)
+ ]
+
+ for (nested : nestedParentNodes) {
+ // Compute a representative top node and compartment in which to create the nested node (in which to create the label)
+ val topNodeCompartment = nested.containerCompartments.filter[parentNodes.exists[isTopNode]].head
+ val topNode = topNodeCompartment.parentNodes.filter[isTopNode].head
+
+ testBehaviors += mapTestsByInstance(#[label], #[compartment], #[nested]) [
+ labelEditPart, compartmentEditPart, parentNodeEditPart |
+ labelEditPart.toCallTestLabelNodeSynchronizationActivity(compartmentEditPart, parentNodeEditPart, topNodeCompartment, topNode, abstractTestOperation)
+ ]
+ }
+ ]
+ ]
+ testCaseRule = testScenarioRule(abstractTestOperation, 'testChildLabel')
+ ]
+
+ @TestContextRule val childNodeSynchronization = [
+ simple('AbstractCSSSynchronizationTest', 'ChildNodeIn' + selfInstance.editPart + 'SynchTest')
+ makeSynchSUTProperties('childnode')
+ val abstractTestOperation = superclass.findOperation('testSynchronizeChildNode')
+ val parentEditPart = selfInstance
+
+ containerEditPart = parentEditPart
+ childEditParts += gmfgen.getChildNodes(childNodesToTest).filter[parentEditPart.canContain(it)]
+ testBehaviors += mapTestsByInstance(#[containerEditPart], childEditParts) [parent, child |
+ child.toCallTestChildNodeSynchronizationActivity(parent, abstractTestOperation)
+ ]
+ testCaseRule = testScenarioRule(abstractTestOperation, 'testSynchronizeChild')
+ ]
+
+ @TestContextRule val linkSynchronization = [
+ common('AbstractCSSSynchronizationTest', selfInstance.editPart + 'SynchTest')
+ makeSynchSUTProperties('link')
+ val linkTestOperation = superclass.findOperation('testSynchronizeLink')
+ val linkTestInContainerOperation = superclass.findOperation('testSynchronizeLinkInContainer')
+
+ linkEditParts += selfInstance
+
+ if (!selfInstance.canCreateTests) {
+ log.warn('Cannot create test cases for ' + selfInstance.editPart +
+ ' because it is missing either source or target edit-parts.')
+ } else {
+ val ctx = it
+
+ testBehaviors += mapTests(linkEditParts, topNodesToTest.filter[linksTo(ctx.selfInstance)], topNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, linkTestOperation)
+ ]
+
+ testBehaviors += mapTests(linkEditParts, childNodesToTest.filter[linksTo(ctx.selfInstance)], childNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, gmfgen.getNode(topContainerEditPart), linkTestInContainerOperation)
+ ]
+
+ testCaseRule = testLinkScenarioRule(linkTestOperation, 'testLink')
+ }
+ ]
+
+ @TestContextRule val linkOwnedBySourceSynchronization = [
+ common('AbstractCSSSynchronizationTest', selfInstance.editPart + 'SynchTest')
+ makeSynchSUTProperties('link')
+ val linkTestOperation = superclass.findOperation('testSynchronizeLink')
+ val linkTestInContainerOperation = superclass.findOperation('testSynchronizeLinkInContainer')
+
+ linkOwnedBySourceEditParts += selfInstance
+
+ if (!selfInstance.canCreateTests) {
+ log.warn('Cannot create test cases for ' + selfInstance.editPart +
+ ' because it is missing either source or target edit-parts.')
+ } else {
+ val ctx = it
+
+ testBehaviors += mapTests(linkOwnedBySourceEditParts, topNodesToTest.filter[linksTo(ctx.selfInstance)], topNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, linkTestOperation)
+ ]
+
+ testBehaviors += mapTests(linkOwnedBySourceEditParts, childNodesToTest.filter[linksTo(ctx.selfInstance)], childNodesToTest.filter[linksFrom(ctx.selfInstance)])[
+ link, source, target | link.toCallTestLinkOperationActivity(source, target, gmfgen.getNode(topContainerEditPart), linkTestInContainerOperation)
+ ]
+
+ testCaseRule = testLinkScenarioRule(linkTestOperation, 'testLinkOwnedBySource')
+ }
+ ]
+
+ def (Object, Activity)=>Operation testScenarioRule(Operation abstractTestOperation, String testName) {
+ [ tuple, test |
+ tuple.toTestCaseOperation(testName, test)
+ ]
+ }
+
+ def (Object, Activity)=>Operation testLinkScenarioRule(Operation abstractTestOperation, String testName) {
+ [ tuple, test |
+ tuple.toTestCaseOperation(testName, test)
+ ]
+ }
+
+ protected def toCallTestTopNodeSynchronizationActivity(InstanceSpecification editPart, Operation abstractTestOperation) {
+ createActivity => [
+ name = editPart.testBehaviorName
+ ownedNodes += createCallOperationAction => [
+ operation = abstractTestOperation
+ arguments += #[
+ editPart.toValuePin('node'),
+ editPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLabelNodeSynchronizationActivity(InstanceSpecification labelEditPart,
+ InstanceSpecification compartmentEditPart, InstanceSpecification topEditPart, Operation abstractTestOperation) {
+
+ createActivity => [
+ name = labelEditPart.editPart.replace('EditPart', '').toFirstLower
+
+ // Find the compartments of the topEditPart that contain the labelEditParts
+ ownedNodes += createCallOperationAction =>[
+ name = 'ChildLabelTestNodeActivity_' + topEditPart.editPart + '_' + labelEditPart.editPart +
+ '_' + compartmentEditPart.editPart
+ operation = abstractTestOperation
+ arguments += #[
+ topEditPart.toValuePin('topNode'),
+ labelEditPart.toValuePin('childNode'),
+ compartmentEditPart.toIntegerValuePin('expectedCompartmentType'),
+ labelEditPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLabelNodeSynchronizationActivity(InstanceSpecification labelEditPart,
+ InstanceSpecification compartmentEditPart, InstanceSpecification nestedEditPart,
+ InstanceSpecification topNodeCompartmentEditPart, InstanceSpecification topNodeEditPart,
+ Operation abstractTestOperation) {
+
+ createActivity => [
+ name = labelEditPart.editPart.replace('EditPart', '').toFirstLower
+
+ // Find the compartments of the topEditPart that contain the labelEditParts
+ ownedNodes += createCallOperationAction => [
+ name = 'ChildLabelTestNodeActivity_' + nestedEditPart.editPart + '_' + labelEditPart.editPart +
+ '_' + compartmentEditPart.editPart
+ operation = abstractTestOperation
+ arguments += #[
+ topNodeEditPart.toValuePin('topNode'),
+ nestedEditPart.toValuePin('nestedNode'),
+ labelEditPart.toValuePin('childNode'),
+ compartmentEditPart.toIntegerValuePin('expectedCompartmentType'),
+ labelEditPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestChildNodeSynchronizationActivity(InstanceSpecification childEditPart,
+ InstanceSpecification parentEditPart, Operation abstractTestOperation) {
+ createActivity => [
+ name = childEditPart.testBehaviorName
+ ownedNodes += createCallOperationAction => [
+ operation = abstractTestOperation
+ arguments += #[
+ parentEditPart.toValuePin('parent'),
+ childEditPart.toValuePin('child'),
+ childEditPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLinkOperationActivity(InstanceSpecification linkEditPart, InstanceSpecification sourceEditPart,
+ InstanceSpecification targetEditPart, Operation linkTestOperation) {
+
+ createActivity => [
+ name = linkEditPart.testBehaviorName
+
+ ownedNodes += createCallOperationAction => [
+ operation = linkTestOperation
+ arguments += #[
+ linkEditPart.toValuePin(sourceEditPart.editPart, 'source'),
+ linkEditPart.toValuePin(targetEditPart.editPart, 'target'),
+ linkEditPart.toValuePin('link'),
+ linkEditPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ protected def toCallTestLinkOperationActivity(InstanceSpecification linkEditPart, InstanceSpecification sourceEditPart,
+ InstanceSpecification targetEditPart, InstanceSpecification containerEditPart, Operation linkTestOperation) {
+
+ createActivity => [
+ name = linkEditPart.testBehaviorName
+
+ ownedNodes += createCallOperationAction => [
+ operation = linkTestOperation
+ arguments += #[
+ linkEditPart.toValuePin(containerEditPart.editPart, 'container'),
+ linkEditPart.toValuePin(sourceEditPart.editPart, 'source'),
+ linkEditPart.toValuePin(targetEditPart.editPart, 'target'),
+ linkEditPart.toValuePin('link'),
+ linkEditPart.toIntegerValuePin('expectedEditPartType')
+ ]
+ ]
+ ]
+ }
+
+ private def toValuePin(InstanceSpecification editPart, String otherEditPartName, String role) {
+ createValuePin => [
+ val otherInstance = editPart.model.getNode(otherEditPartName)
+ name = role
+ value = createInstanceValue => [
+ name = otherInstance.name
+ instance = otherInstance
+ ]
+ ]
+ }
+
+ private def testKindConfigurator(String kind) {
+ [org.eclipse.uml2.uml.Property sutProperty |
+ sutProperty.name = 'syncTestKind'
+
+ val syncTestKindEnum = 'SynchronizationTestKind'.frameworkEnum
+ sutProperty.type = syncTestKindEnum
+ sutProperty.defaultValue = createInstanceValue => [
+ instance = syncTestKindEnum.getOwnedLiteral(kind)
+ ]
+ ]
+ }
+
+ protected def makeSynchSUTProperties(TransformationUtilities.TestContextBuilder tcBuilder, String testKind) {
+ tcBuilder.makeSUTProperty(testKindConfigurator(testKind))
+ tcBuilder.makeSUTProperty('css', stringType, createLiteralString => [value = '* { canonical: true }'])
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TestExceptionManager.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TestExceptionManager.xtend
new file mode 100644
index 00000000000..b59a4fe3da4
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TestExceptionManager.xtend
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * Copyright (c) 2015 Christian W. Damus 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 - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.common.collect.Sets
+import com.google.inject.Singleton
+import java.util.Collection
+import java.util.Collections
+import org.eclipse.emf.common.util.BasicDiagnostic
+import org.eclipse.emf.common.util.BasicEList
+import org.eclipse.papyrus.tests.framework.exceptions.TestExceptions
+import org.eclipse.uml2.uml.Behavior
+import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.UMLFactory
+import org.eclipse.emf.common.util.Diagnostic
+import org.eclipse.papyrus.tests.framework.exceptions.ForbiddenEditPart
+import org.eclipse.papyrus.tests.framework.xtend.annotations.Cached
+
+/**
+ * An injectable component that determines whether a particular permutation of edit-parts may generate a
+ * specific kind of test case.
+ */
+@Singleton
+class TestExceptionManager {
+ Collection<TestExceptions> testExceptions;
+
+ BasicDiagnostic diagnostics = new BasicDiagnostic
+
+ new() {
+ this(Collections.emptyList)
+ }
+
+ new(Collection<TestExceptions> exceptions) {
+ testExceptions = Sets.newHashSet(exceptions);
+ }
+
+ def addTestExceptions(TestExceptions exceptions) {
+ testExceptions.add(exceptions);
+ return this
+ }
+
+ def shouldGenerate(Class abstractTestClass, InstanceSpecification... editPart) {
+ testExceptions.empty || {
+ val editPartsEList = new BasicEList(editPart)
+ testExceptions.forall[validate(editPartsEList, abstractTestClass, diagnostics)]
+ }
+ }
+
+ /** Queries whether an edit-part is absolutely excluded from all tests. */
+ @Cached def boolean isExcluded(InstanceSpecification editPart) {
+ !testExceptions.empty && testExceptions.exists[
+ constraints.filter(ForbiddenEditPart).exists[it.editPart.matches(editPart)]
+ ]
+ }
+
+ def boolean processExclusions(Class abstractTestClass, Behavior testMethod, InstanceSpecification... editPart) {
+ var result = true
+
+ val current = diagnostics.children.size
+ if (!shouldGenerate(abstractTestClass, editPart)) {
+ // Can only reasonably append one annotation in the generated code
+ val newProblem = diagnostics.children.get(current)
+ result = newProblem.severity < Diagnostic.ERROR
+
+ // Don't bother with annotations if we'll be omitting the test case
+ if (result) {
+ testMethod.preconditions += UMLFactory.eINSTANCE.createConstraint => [
+ name = newProblem.data.get(0).toString
+ specification = UMLFactory.eINSTANCE.createLiteralString => [
+ value = newProblem.message
+ ]
+ ]
+ }
+ }
+
+ result
+ }
+}
diff --git a/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TransformationUtilities.xtend b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TransformationUtilities.xtend
new file mode 100644
index 00000000000..1b792cbf4f3
--- /dev/null
+++ b/tests/framework/org.eclipse.papyrus.tests.framework/src/org/eclipse/papyrus/tests/framework/gmfgenuml2utp/TransformationUtilities.xtend
@@ -0,0 +1,765 @@
+/*****************************************************************************
+ * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, 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:
+ * CEA LIST - Initial API and implementation
+ * Christian W. Damus - adapted from QVTo
+ * Christian W. Damus - bug 464647
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.tests.framework.gmfgenuml2utp
+
+import com.google.common.collect.ImmutableList
+import com.google.inject.Inject
+import com.google.inject.Injector
+import com.google.inject.Singleton
+import java.util.Collection
+import java.util.Collections
+import java.util.List
+import java.util.Set
+import org.eclipse.papyrus.tests.framework.m2m.Metamodels
+import org.eclipse.papyrus.tests.framework.xtend.annotations.Cached
+import org.eclipse.papyrus.tests.framework.xtend.annotations.FrameworkConfig
+import org.eclipse.uml2.uml.Activity
+import org.eclipse.uml2.uml.Behavior
+import org.eclipse.uml2.uml.BehavioredClassifier
+import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.Classifier
+import org.eclipse.uml2.uml.InstanceSpecification
+import org.eclipse.uml2.uml.InstanceValue
+import org.eclipse.uml2.uml.Model
+import org.eclipse.uml2.uml.OpaqueExpression
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.Package
+import org.eclipse.uml2.uml.Property
+import org.eclipse.uml2.uml.Type
+import org.eclipse.uml2.uml.UMLFactory
+import org.eclipse.uml2.uml.ValueSpecification
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
+import org.eclipse.xtext.util.Triple
+import org.eclipse.xtext.util.Tuples
+
+/**
+ * Commmon helpers and utilities for the GMFGen (as UML) to UTP transformation.
+ */
+@Singleton
+class TransformationUtilities {
+ static extension UMLFactory = UMLFactory.eINSTANCE
+
+ @Inject extension Metamodels
+ @Inject extension TestExceptionManager
+
+ @Inject Injector guice
+
+ @FrameworkConfig String diagramCreationCommand
+ @FrameworkConfig String testConstantsInterface
+ @FrameworkConfig String diagramUpdater = 'UMLDiagramUpdater'
+
+ def getDiagramName(Model gmfgen) {
+ gmfgen.getInstance('GenEditorGenerator').getSlotStringValue('modelID').replace('PapyrusUML', '')
+ }
+
+ def getInstance(Model gmfgen, String classifierName) {
+ gmfgen.getInstances[isA(classifierName)].head
+ }
+
+ @Cached def InstanceSpecification getInstanceNamed(Model gmfgen, String instanceName) {
+ gmfgen.getInstances[name == instanceName].head
+ }
+
+ def getTopNode(Model gmfgen, String editPart) {
+ gmfgen.getInstanceNamed('GenTopLevelNode_' + editPart)
+ }
+
+ def getChildNode(Model gmfgen, String editPart) {
+ gmfgen.getInstanceNamed('GenChildNode_' + editPart)
+ }
+
+ def getNode(Model gmfgen, String editPart) {
+ gmfgen.getTopNode(editPart) ?: gmfgen.getChildNode(editPart)
+ }
+
+ def getCompartment(Model gmfgen, String editPart) {
+ gmfgen.getInstanceNamed('GenCompartment_' + editPart)
+ }
+
+ def getLink(Model gmfgen, String editPart) {
+ gmfgen.getInstanceNamed('GenLink_' + editPart)
+ }
+
+ def getInstances(Model gmfgen, (InstanceSpecification)=>Boolean predicate) {
+ gmfgen.packagedElements.filter(InstanceSpecification).filter(predicate)
+ }
+
+ def getInstances(Model gmfgen, String classifierName, Collection<String> testedEditParts) {
+ gmfgen.getInstances[is | is.isA(classifierName) && testedEditParts.contains(is.editPart)]
+ }
+
+ def getTopNodes(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | is.isTopNode && editParts.contains(is.editPart)]
+ }
+
+ def isTopNode(InstanceSpecification editPart) {
+ editPart.isA('GenTopLevelNode')
+ }
+
+ def getChildNodes(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | is.isChildNode && editParts.contains(is.editPart)]
+ }
+
+ def isChildNode(InstanceSpecification editPart) {
+ editPart.isA('GenChildNode')
+ }
+
+ def getChildLabels(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | is.isLabelNode && editParts.contains(is.editPart)]
+ }
+
+ def isLabelNode(InstanceSpecification editPart) {
+ editPart.isA('GenChildLabelNode')
+ }
+
+ def getNodes(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | (is.isTopNode || is.isChildNode) && editParts.contains(is.editPart)]
+ }
+
+ def getCompartments(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | is.isCompartment && editParts.contains(is.editPart)]
+ }
+
+ def isCompartment(InstanceSpecification editPart) {
+ editPart.isA('GenCompartment')
+ }
+
+ def getContainerCompartments(InstanceSpecification node) {
+ node.getSlotInstances('containers')
+ }
+
+ def getParentNodes(InstanceSpecification compartment) {
+ compartment.getSlotInstances('node')
+ }
+
+ def getCompartments(InstanceSpecification node) {
+ node.getSlotInstances('compartments')
+ }
+
+ def getChildNodes(InstanceSpecification compartment) {
+ compartment.getSlotInstances('childNodes')
+ }
+
+ def canContain(InstanceSpecification node, InstanceSpecification child) {
+ node.compartments.exists[childNodes.contains(child)]
+ }
+
+ def getLinks(Model gmfgen, Collection<String> editParts) {
+ gmfgen.getInstances[is | is.isLink && editParts.contains(is.editPart)]
+ }
+
+ def isLink(InstanceSpecification editPart) {
+ editPart.isA('GenLink')
+ }
+
+ def getSlot(InstanceSpecification instance, String slotName) {
+ instance.slots.findFirst[definingFeature?.name == slotName]
+ }
+
+ def getSlotStringValue(InstanceSpecification instance, String slotName) {
+ instance.getSlot(slotName)?.values?.head.stringValue
+ }
+
+ def List<String> getSlotStringValues(InstanceSpecification instance, String slotName) {
+ val slot = instance.getSlot(slotName)
+ if (slot != null) {
+ slot.values.map[stringValue]
+ } else {
+ #[]
+ }
+ }
+
+ def List<InstanceSpecification> getSlotInstances(InstanceSpecification instance, String slotName) {
+ val slot = instance.getSlot(slotName)
+ if (slot != null) {
+ slot.values.filter(InstanceValue).map[it.instance].filterNull.toList
+ } else {
+ #[]
+ }
+ }
+
+ def isKindOfEditPart(InstanceSpecification instance) {
+ !instance.classifiers.empty && instance.classifiers.head.conformsToEx('GenCommonBase'.gmfgenMetaclass)
+ }
+
+ def dispatch boolean conformsToEx(Classifier subtype, Classifier supertype) {
+ // No implemented interfaces to worry about
+ (subtype == supertype) || subtype.generals.exists[conformsToEx(supertype)]
+ }
+
+ def dispatch boolean conformsToEx(BehavioredClassifier subtype, Classifier supertype) {
+ (subtype == supertype) || subtype.generals.exists[conformsToEx(supertype)]
+ || subtype.implementedInterfaces.exists[conformsToEx(supertype)]
+ }
+
+ def isA(InstanceSpecification instance, String classifierName) {
+ instance.classifiers.exists[name == classifierName]
+ }
+
+ def computeImports(Model gmfgen, Iterable<? extends String> classNames) {
+ classNames.map[name|createElementImport => [alias = name]]
+ }
+
+ def createSelfProperty(Class class_) {
+ createProperty => [
+ name = 'self'
+ type = class_
+ ]
+ }
+
+ def toDiagramUpdaterProperty(Model gmfgen) {
+ createProperty => [
+ name = 'diagramUpdater'
+ defaultValue = createStringExpression => [
+ symbol = diagramUpdater
+ ]
+ ]
+ }
+
+ def upTo(String string, String substring) {
+ string.substring(0, string.indexOf(substring))
+ }
+
+ def following(String string, String substring) {
+ string.substring(string.indexOf(substring) + substring.length)
+ }
+
+ def toNodeEditPartProperty(InstanceSpecification node, String nodeType) {
+ createProperty => [
+ name = node.name.following('_')
+ type = node.classifiers.head.name.gmfgenMetaclass
+ defaultValue = createInstanceValue => [ instance = node ]
+ ]
+ }
+
+ def toDiagramProperty(InstanceSpecification diagram) {
+ createProperty => [
+ name = 'diagram'
+ type = diagram.name.upTo('_').gmfgenMetaclass;
+ defaultValue = createInstanceValue => [ instance = diagram ]
+ ]
+ }
+
+ def toEditorGeneratorProperty(InstanceSpecification editorGenerator) {
+ createProperty => [
+ name = 'generator'
+ type = 'GenEditorGenerator'.gmfgenMetaclass;
+ defaultValue = createInstanceValue => [ instance = editorGenerator ]
+ ]
+ }
+
+ private def getDiagramCreationCommand(InstanceSpecification editorGenerator) {
+ if (diagramCreationCommand == null) {
+ var commandClassName = editorGenerator.getSlotStringValue('modelID')
+
+ // Strip off 'PapyrusUML' prefix, if any, and ensure that it ends with 'Diagram'
+ commandClassName = commandClassName.replaceFirst('^PapyrusUML', '')
+ commandClassName = commandClassName.replaceFirst('(?<!Diagram)$', 'Diagram')
+
+ diagramCreationCommand = 'Create' + commandClassName + 'Command'
+ }
+ diagramCreationCommand
+ }
+
+ def toCreationCommandProperty(InstanceSpecification editorGenerator) {
+ createProperty => [
+ name = 'diagramCreationCommand'
+ type = stringType
+ defaultValue = createLiteralString => [ value = editorGenerator.diagramCreationCommand]
+ ]
+ }
+
+ private def getTestConstantsInterface(InstanceSpecification editorGenerator) {
+ if (testConstantsInterface == null) {
+ var interfaceName = editorGenerator.getSlotStringValue('modelID')
+
+ // Strip off 'PapyrusUML' prefix, if any, and ensure that it ends with 'Diagram'
+ interfaceName = interfaceName.replaceFirst('^PapyrusUML', '')
+ interfaceName = interfaceName.replaceFirst('(?<!Diagram)$', 'Diagram')
+
+ testConstantsInterface = 'I' + interfaceName + 'TestsConstants'
+ }
+ testConstantsInterface
+ }
+
+ def toTestConstantsInterfaceProperty(InstanceSpecification editorGenerator) {
+ createProperty => [
+ name = 'testConstantsInterface'
+ type = stringType
+ defaultValue = createLiteralString => [ value = editorGenerator.testConstantsInterface]
+ ]
+ }
+
+ def toTestConfigurationProperties(InstanceSpecification editorGenerator) {
+ #[
+ editorGenerator.toEditorGeneratorProperty,
+ editorGenerator.toCreationCommandProperty,
+ editorGenerator.toTestConstantsInterfaceProperty
+ ]
+ }
+
+ def dispatch toTestCaseOperation(Void editPart, String testName, Behavior testBehavior) {
+ createOperation => [
+ name = testName.toFirstLower
+ methods += testBehavior
+ ]
+ }
+
+ def dispatch toTestCaseOperation(InstanceSpecification editPart, String testName, Behavior testBehavior) {
+ editPart.toTestCaseOperationWithBlock([String coreName | testName + coreName], testBehavior)
+ }
+
+ def dispatch toTestCaseOperation(Pair<InstanceSpecification, InstanceSpecification> editParts, String testName, Behavior testBehavior) {
+ val childEditPart = editParts.value.editPart
+ editParts.key.toTestCaseOperationWithBlock([String coreName | String.format("%s%s_%s", testName, coreName, childEditPart)], testBehavior)
+ }
+
+ def dispatch toTestCaseOperation(Triple<InstanceSpecification, InstanceSpecification, InstanceSpecification> editParts, String testName, Behavior testBehavior) {
+ val sourceEditPart = editParts.second.editPart
+ val targetEditPart = editParts.third.editPart
+ editParts.first.toTestCaseOperationWithBlock([String coreName | String.format("%s%s_%s_%s", testName, coreName, sourceEditPart, targetEditPart)], testBehavior)
+ }
+
+ private def toTestCaseOperationWithBlock(InstanceSpecification editPart, (String)=>String testName, Behavior testBehavior) {
+ val isLink = editPart.isA('GenLink')
+ val operationName = testName.apply(editPart.name.following('_'))
+
+ createOperation => [
+ name = if (isLink) operationName.replace('EditPart', '') else operationName
+ ownedParameters += createParameter => [
+ name = if (isLink) 'link' else 'node'
+ defaultValue = createInstanceValue => [ instance = editPart ]
+ ]
+ methods += testBehavior
+ ]
+ }
+
+ def (Object, Activity)=>Operation testCaseRule(String name) {
+ [tuple, test | tuple.toTestCaseOperation(name, test) ]
+ }
+
+ def getEditPart(InstanceSpecification instance) {
+ instance.getSlotStringValue('editPartClassName')
+ }
+
+ def getTestBehaviorName(InstanceSpecification editPartToTest) {
+ editPartToTest.editPart + 'TestCase'
+ }
+
+ def dispatch findOperation(Class testClass, Void operationName) {
+ testClass.allOperations.head
+ }
+
+ def dispatch findOperation(Class testClass, String operationName) {
+ testClass.allOperations.findFirst[name == operationName]
+ }
+
+ def toCallTestNodeOperationActivity(InstanceSpecification nodeEditPart, String abstractTestClassName, String nodeType) {
+ toCallTestNodeOperationActivity(nodeEditPart, abstractTestClassName, nodeType, true)
+ }
+
+ def toCallTestNodeOperationActivity(InstanceSpecification nodeEditPart, String abstractTestClassName, String nodeType, boolean includeMustSucceed) {
+ createActivity => [
+ name = nodeEditPart.testBehaviorName
+ ownedNodes += createCallOperationAction => [
+ operation = frameworkClass(abstractTestClassName).allOperations.head
+ arguments += createValuePin => [
+ name = 'node'
+ value = createInstanceValue => [
+ name = nodeEditPart.name
+ instance = nodeEditPart
+ ]
+ ]
+
+ if (includeMustSucceed) {
+ arguments += true.toValuePin('mustSucceed')
+ }
+ ]
+ ]
+ }
+
+ def toValuePin(boolean value, String role) {
+ createValuePin => [
+ name = role
+ value = createLiteralBoolean => [
+ it.value = value
+ type = booleanType
+ ]
+ ]
+ }
+
+ def toValuePin(String value, String role) {
+ createValuePin => [
+ name = role
+ value = createLiteralString => [
+ it.value = value
+ type = stringType
+ ]
+ ]
+ }
+
+ def toValuePin(InstanceSpecification editPart, String role) {
+ createValuePin => [
+ name = role
+ value = createInstanceValue => [
+ name = editPart.name
+ instance = editPart
+ type = editPart.classifiers.get(0)
+ ]
+ ]
+ }
+
+ /**
+ * Creates a value pin that casts an edit-part to its integer visual ID.
+ */
+ def toIntegerValuePin(InstanceSpecification editPart, String role) {
+ createValuePin => [
+ name = role
+ value = createOpaqueExpression => [
+ languages += 'Java'
+ bodies += editPart.editPart + '.VISUAL_ID'
+ type = integerType
+ ]
+ ]
+ }
+
+ def toContainerDerivedProperty(InstanceSpecification editPart) {
+ createProperty => [
+ name = 'containerEditPart'
+ isDerived = true
+ type = redefinedProperties.head?.type // TODO: What is supposed to be redefined?
+ defaultValue = createInstanceValue => [ instance = editPart ]
+ ]
+ }
+
+ def createTestPackage(Model testsModel, Model gmfgen, (TestPackageBuilder)=>void script) {
+ val builder = new TestPackageBuilder(createPackage, gmfgen, testsModel) => [
+ guice.injectMembers(it)
+
+ testsModel.packagedElements += testPackage // Get the profile context now
+ ]
+ script.apply(builder)
+ builder.build
+ }
+
+ def isEligible(InstanceSpecification editPart) {
+ !editPart.isExcluded
+ }
+
+ //
+ // Nested types: test builder DSL
+ //
+
+ @FinalFieldsConstructor
+ static class TestPackageBuilder {
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+
+ final Package testPackage
+ final Model gmfgen
+ final Model testsModel
+
+ @Accessors(PUBLIC_GETTER)
+ List<Pair<? extends Pair<GenType, ? extends Collection<String>>, (TestContextBuilder)=>void>> testContextRules = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<Class> testContexts = newArrayList
+
+ def void setName(String name) {
+ testPackage.name = testsModel.name + '.' + name
+ }
+
+ def Class mapNone((TestContextBuilder)=>void nodeRule) {
+ (null as InstanceSpecification).createTestContext(gmfgen, nodeRule)
+ }
+
+ def Class mapNode(String editPart, (TestContextBuilder)=>void nodeRule) {
+ gmfgen.getNode(editPart).createTestContext(nodeRule)
+ }
+
+ def Iterable<Class> mapTopNodes(Collection<String> editParts, (TestContextBuilder)=>void topNodeRule) {
+ gmfgen.getTopNodes(editParts).map[createTestContext(topNodeRule)]
+ }
+
+ def Iterable<Class> mapChildNodes(Collection<String> editParts, (TestContextBuilder)=>void childNodeRule) {
+ gmfgen.getChildNodes(editParts).map[createTestContext(childNodeRule)]
+ }
+
+ def Iterable<Class> mapChildLabelNodes(Collection<String> editParts, (TestContextBuilder)=>void childLabelNodeRule) {
+ gmfgen.getChildLabels(editParts).map[createTestContext(childLabelNodeRule)]
+ }
+
+ def Iterable<Class> mapLinks(Collection<String> editParts, (TestContextBuilder)=>void linkRule) {
+ gmfgen.getLinks(editParts).map[createTestContext(linkRule)]
+ }
+
+ def build() {
+ // First, process rules
+ testContextRules.forEach[editParts2block |
+ val genType = editParts2block.key.key
+ val editParts = editParts2block.key.value
+ val block = editParts2block.value
+
+ testContexts += switch (genType) {
+ case TOP_NODE : editParts.mapTopNodes(block)
+ case CHILD_NODE : editParts.mapChildNodes(block)
+ case CHILD_LABEL_NODE : editParts.mapChildLabelNodes(block)
+ case LINK : editParts.mapLinks(block)
+ case NIL : #[mapNone(block)]
+ }
+ ]
+
+ // Now add all of the contexts (including those generated by rules)
+ testPackage.packagedElements += testContexts
+
+ testContexts.forEach[
+ applyTestContext
+ ownedAttributes.forEach[applySUT]
+ ownedOperations.forEach[applyTestCase]
+ ]
+
+ testPackage
+ }
+ }
+
+ def mapTopNode(Collection<String> editParts) { GenType.TOP_NODE -> editParts }
+ def mapTopNode(String editPart) { #[editPart].mapTopNode }
+ def mapChildNode(Collection<String> editParts) { GenType.CHILD_NODE -> editParts }
+ def mapChildNode(String editPart) { #[editPart].mapChildNode }
+ def mapChildLabelNode(Collection<String> editParts) { GenType.CHILD_LABEL_NODE -> editParts }
+ def mapChildLabelNode(String editPart) { #[editPart].mapChildLabelNode }
+ def mapLink(Collection<String> editParts) { GenType.LINK -> editParts }
+ def mapLink(String editPart) { #[editPart].mapLink }
+ def mapNone() { GenType.NIL -> Collections.<String>emptyList }
+ enum GenType { TOP_NODE, CHILD_NODE, CHILD_LABEL_NODE, LINK, NIL }
+
+ private def createTestContext(InstanceSpecification selfInstance, (TestContextBuilder)=>void script) {
+ createTestContext(selfInstance, selfInstance.model, script)
+ }
+
+ private def createTestContext(InstanceSpecification selfInstance, Model gmfgen, (TestContextBuilder)=>void script) {
+ val builder = new TestContextBuilder(selfInstance, gmfgen, createClass) => [
+ guice.injectMembers(it)
+ ]
+ script.apply(builder)
+ builder.build
+ }
+
+ @FinalFieldsConstructor
+ static class TestContextBuilder {
+ @Inject extension Metamodels
+ @Inject extension TransformationUtilities
+ @Inject extension TestExceptionManager
+
+ @Accessors final InstanceSpecification selfInstance
+ @Accessors final Model gmfgen
+ final Class testContext
+
+ @Accessors(PUBLIC_GETTER)
+ Set<String> imports = newHashSet
+
+ @Accessors
+ InstanceSpecification containerEditPart
+
+ @Accessors(PUBLIC_GETTER)
+ List<InstanceSpecification> topEditParts = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<InstanceSpecification> childEditParts = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<InstanceSpecification> childLabelEditParts = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<InstanceSpecification> linkEditParts = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<InstanceSpecification> linkOwnedBySourceEditParts = newArrayList
+
+ @Accessors(PUBLIC_GETTER)
+ List<Pair<?, Activity>> testBehaviors = newArrayList
+
+ @Accessors(PUBLIC_SETTER)
+ (Object, Activity)=>Operation testCaseRule
+
+ def void common(String superclassName, String nameSuffix) {
+ simple(superclassName, nameSuffix)
+ makeDiagramUpdater
+ }
+
+ def void simple(String superclassName, String nameSuffix) {
+ superclass = superclassName
+ name = [it + nameSuffix]
+ makeSelf
+ makeSimpleProperties
+ }
+
+ def void setSuperclass(String abstractTestClass) {
+ testContext.generals += abstractTestClass.frameworkClass
+ }
+
+ def getSuperclass() {
+ testContext.generals.head as Class
+ }
+
+ def void setName((String)=>String name) {
+ testContext.name = name.apply(gmfgen.diagramName)
+ }
+
+ def void makeSelf() {
+ testContext.ownedAttributes += testContext.createSelfProperty
+ }
+
+ def void makeDiagram() {
+ testContext.ownedAttributes += gmfgen.getInstance('GenDiagram').toDiagramProperty
+ }
+
+ def void makeEditor() {
+ testContext.ownedAttributes += gmfgen.getInstance('GenEditorGenerator').toEditorGeneratorProperty
+ }
+
+ def void makeCreationCommand() {
+ testContext.ownedAttributes += gmfgen.getInstance('GenEditorGenerator').toCreationCommandProperty
+ }
+
+ def void makeTestConstants() {
+ testContext.ownedAttributes += gmfgen.getInstance('GenEditorGenerator').toTestConstantsInterfaceProperty
+ }
+
+ def void makeDiagramUpdater() {
+ testContext.ownedAttributes += gmfgen.toDiagramUpdaterProperty
+ }
+
+ private def void makeSimpleProperties() {
+ makeDiagram
+ makeEditor
+ makeCreationCommand
+ makeTestConstants
+ }
+
+ def void makeSUTProperty(String name, Type type, ValueSpecification defaultValue) {
+ testContext.ownedAttributes += UMLFactory.eINSTANCE.createProperty => [
+ it.name = name
+ it.type = type
+ it.defaultValue = defaultValue
+ ]
+ }
+
+ def void makeSUTProperty((Property)=>void propertyConfigurator) {
+ testContext.ownedAttributes += UMLFactory.eINSTANCE.createProperty => [
+ propertyConfigurator.apply(it)
+ ]
+ }
+
+ def <T extends Behavior> Iterable<Pair<InstanceSpecification, T>> mapTests(Iterable<? extends InstanceSpecification> editParts,
+ (InstanceSpecification)=>T testRule) {
+
+ editParts.map[ (it -> testRule.apply(it)) ].filter[
+ processExclusions(testContext, value, key)
+ ].toList // Filter exactly once because of the side-effects
+ }
+
+ def <T extends Behavior> Iterable<Pair<Pair<InstanceSpecification, InstanceSpecification>, T>> mapTests(
+ Iterable<? extends InstanceSpecification> editParts,
+ Iterable<String> children,
+ (InstanceSpecification, InstanceSpecification)=>T testRule) {
+
+ val childEditParts = children.map[gmfgen.getNode(it)].filterNull
+
+ mapTestsByInstance(editParts, childEditParts, testRule)
+ }
+
+ def <T extends Behavior> Iterable<Pair<Pair<InstanceSpecification, InstanceSpecification>, T>> mapTestsByInstance(
+ Iterable<? extends InstanceSpecification> editParts,
+ Iterable<InstanceSpecification> children,
+ (InstanceSpecification, InstanceSpecification)=>T testRule) {
+
+ editParts.map[top |
+ children.map[ ((top -> it) -> testRule.apply(top, it)) ]
+ ].flatten.filter[
+ processExclusions(testContext, value, key.key, key.value)
+ ].toList // Filter exactly once because of the side-effects
+ }
+
+ def <T extends Behavior> Iterable<Pair<Triple<InstanceSpecification, InstanceSpecification, InstanceSpecification>, T>> mapTests(
+ Iterable<? extends InstanceSpecification> linkEditParts,
+ Iterable<String> sources,
+ Iterable<String> targets,
+ (InstanceSpecification, InstanceSpecification, InstanceSpecification)=>T testRule) {
+
+ val sourceEditParts = sources.map[gmfgen.getNode(it)].filterNull
+ val targetEditParts = targets.map[gmfgen.getNode(it)].filterNull
+
+ mapTestsByInstance(linkEditParts, sourceEditParts, targetEditParts, testRule)
+ }
+
+ def <T extends Behavior> Iterable<Pair<Triple<InstanceSpecification, InstanceSpecification, InstanceSpecification>, T>> mapTestsByInstance(
+ Iterable<? extends InstanceSpecification> linkEditParts,
+ Iterable<? extends InstanceSpecification> sources,
+ Iterable<? extends InstanceSpecification> targets,
+ (InstanceSpecification, InstanceSpecification, InstanceSpecification)=>T testRule) {
+
+ linkEditParts.map[link |
+ sources.map[source |
+ targets.map[ (Tuples.create(link, source, it) -> testRule.apply(link, source, it)) ]
+ ].flatten
+ ].flatten.filter[
+ processExclusions(testContext, value, key.first, key.second, key.third)
+ ].toList // Filter exactly once because of the side-effects
+ }
+
+ def build() {
+ if (containerEditPart != null) {
+ testContext.ownedAttributes += containerEditPart.toContainerDerivedProperty
+ }
+ testContext.ownedAttributes += topEditParts.map[toNodeEditPartProperty('GenTopLevelNode')]
+ testContext.ownedAttributes += childEditParts.map[toNodeEditPartProperty('GenChildNode')]
+ testContext.ownedAttributes += childLabelEditParts.map[toNodeEditPartProperty('GenChildLabelNode')]
+ testContext.ownedAttributes += linkEditParts.map[toNodeEditPartProperty('GenLink')]
+ testContext.ownedAttributes += linkOwnedBySourceEditParts.map[toNodeEditPartProperty('GenLinkOwnedBySource')]
+
+ importTypesRequiredByTestBehaviors
+ testContext.elementImports += gmfgen.computeImports(imports)
+
+ testContext.ownedBehaviors += testBehaviors.map[value]
+ if (testCaseRule != null) {
+ testContext.ownedOperations += testBehaviors.map[pair |
+ testCaseRule.apply(pair.key, pair.value) => [
+ if (!pair.value.preconditions.empty) {
+ // Transfer the pre-condition constraints to the operation
+ it.preconditions += ImmutableList.copyOf(pair.value.preconditions)
+ }
+ ]
+ ]
+ }
+
+ testContext
+ }
+
+ protected def void importTypesRequiredByTestBehaviors() {
+ testBehaviors.map[value].forEach[
+ // References to actual edit-part instances
+ allOwnedElements.filter(InstanceValue).filter[instance.isKindOfEditPart].forEach[imports += instance.editPart]
+
+ // References to edit-part types by visual ID
+ allOwnedElements.filter(OpaqueExpression).filter[languages.contains('Java') && bodies.exists[endsWith('.VISUAL_ID')]].forEach[
+ imports += bodies.get(languages.indexOf('Java')).upTo('.VISUAL_ID')
+ ]
+ ]
+ }
+ }
+}

Back to the top