diff options
author | Christian W. Damus | 2016-07-13 19:05:54 +0000 |
---|---|---|
committer | Christian W. Damus | 2016-07-13 19:51:04 +0000 |
commit | ddfb7b0caefdd1be212db31bde24b8a9feb225de (patch) | |
tree | 5c350c81ea1a9fb2985bb62195c06ff50a7a5174 /tests/junit/plugins/infra | |
parent | f68c766e5c5df1bb5c08fd65bc6f5464d3a58208 (diff) | |
download | org.eclipse.papyrus-ddfb7b0caefdd1be212db31bde24b8a9feb225de.tar.gz org.eclipse.papyrus-ddfb7b0caefdd1be212db31bde24b8a9feb225de.tar.xz org.eclipse.papyrus-ddfb7b0caefdd1be212db31bde24b8a9feb225de.zip |
Bug 496299: Controlled Units as Integral Fragments
https://bugs.eclipse.org/bugs/show_bug.cgi?id=496299
Implement a new mode of controlled unit in Papyrus dubbed "shards".
A shard is like any other sub-unit created up to and including the
Neon release, except that it cannot be opened independently in the
editor. The Papyrus editor, when asked to open a "shard", will
instead open the root resource of the model. Likewise, the editor
matcher normalizes editor inputs to the root resource of any shard.
The graph of shard dependencies is inferred from a new workspace-
wide index of cross-resource containment references, when it is
available. Otherwise, the linkage of shards to their parent
references is parsed on-the-fly from the shard annotation's
reference (with a relatively efficient XML parsing that terminates
after reading only a few lines of the XMI text).
A new ResourceLocator is implemented to provide a pluggable hook for
resource loading (including proxy resolution), to ensure when loading
a shard resource that its parent resource chain is first loaded from
the top down to ensure that all context of profile applications is
available before loading the shard, itself, which may have stereotype
applications that depend on those profile applications. The
CoreMultiDiagramEditor installs this resource locator on the ModelSet;
other applications (including in a non-Eclipse context) can make
similar use of it.
Some additional fixes are required in other core components to make
the loading of referenced sharded models as in bug 458837 work:
* the SemanticUMLContentProvider did not detect the final resolution
of containment proxies that changes what looks look a model root
object into just another intermediate element in the content tree.
Besides that it would schedule a large number of redundant
UI refreshes asynchronously (deferred) on the UI thread
* the DiModel and NotationModel would load their adjuncts to the *.uml
resource when that resource is created, not after it has been loaded.
This is much too early and ends up causing the transactional editing
domain to detect the attachment of a resource's contents at the end
of loading as an attempt to edit the model during a read-only
transaction, which logs an exception and bombs the UI action.
Instead, these models now have snippets that load the *.di and
*.notation resources after the semantic resource has been loaded.
* the new model snippets required an additional fix in the loading
of IModels to handle contributions of snippets and dependencies to
models that are overridden by other IModels registered under the
same ID, such as is the case with the NotationModel and the
CSSNotationModel, which latter needs the snippet declared by the
former
* the IModels additionally need to ensure that they start snippets
on loading of an existing model even when it is already found to
be loaded in the ModelSet (as happens often in JUnit tests)
* the AbstractModelFixture in the JUnit test framework is updated to
ensure that the ModelSet is properly initialized, with its own
snippets started and its IModels loaded and their snippets started
* the basic uncontrol command now removes the shard annotation from
the uncontrolled element/resource, if there was one. Because this
bundle now supports a new feature (that being shards), it seems
appropriate to bump its minor version number
General-purpose changes in the core workspace model index framework
that improve overall performance, of particular significance in large
and highly fragmented models:
Implement persistent storage of the workspace model index at workspace
save to support quick start-up without parsing the entire workspace.
Consolidation of indices:
* run a single pool of indexing jobs and a single resource change
listener to trigger (re)-indexing of files
* all indices matching any given file process it
* includes a new extension point from which all indices are loaded
into the shared index manager to initialize them and do the work
(cherry-picked from streams/2.0-maintenance)
Change-Id: Ifd65a71c57134b69d873f17139f3cedbf11c5ba5
Diffstat (limited to 'tests/junit/plugins/infra')
25 files changed, 1027 insertions, 67 deletions
diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.classpath b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.classpath index 4ff9e9735c7..293e77968b0 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.classpath +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.classpath @@ -1,7 +1,11 @@ <?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/JavaSE-1.7"/> - <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"> + <accessrules> + <accessrule kind="accessible" pattern="org/eclipse/papyrus/infra/emf/internal/**"/> + </accessrules> + </classpathentry> <classpathentry kind="src" path="tests"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.settings/org.eclipse.jdt.core.prefs index 9ec8d31b26b..43d10874e2c 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,14 +1,14 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/META-INF/MANIFEST.MF index 3f619512f80..5762bedc61a 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/META-INF/MANIFEST.MF @@ -1,19 +1,20 @@ Manifest-Version: 1.0 Export-Package: org.eclipse.papyrus.infra.emf.advice, + org.eclipse.papyrus.infra.emf.resource, org.eclipse.papyrus.infra.emf.resource.index, org.eclipse.papyrus.infra.emf.tests, org.eclipse.papyrus.infra.emf.utils Require-Bundle: org.eclipse.emf.ecore.xmi;bundle-version="2.8.0", org.junit;bundle-version="4.10.0", org.eclipse.uml2.uml;bundle-version="5.0.0", + org.eclipse.papyrus.infra.emf;bundle-version="1.3.0", org.eclipse.papyrus.junit.framework;bundle-version="1.2.0", org.eclipse.papyrus.junit.utils;bundle-version="1.2.0", - org.eclipse.papyrus.infra.types.core;bundle-version="1.2.0", - org.eclipse.papyrus.infra.emf;bundle-version="1.2.0" + org.eclipse.papyrus.infra.types.core;bundle-version="1.2.0" Bundle-Vendor: %providerName -Bundle-Version: 1.2.0.qualifier +Bundle-Version: 1.4.0.qualifier Bundle-Name: %pluginName Bundle-Localization: fragment Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.infra.emf.tests;singleton:=true -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/pom.xml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/pom.xml index 779f465b911..84adf7aa7c5 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/pom.xml +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/pom.xml @@ -10,6 +10,6 @@ </parent> <groupId>org.eclipse.papyrus</groupId> <artifactId>org.eclipse.papyrus.infra.emf.tests</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> </project> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1.uml new file mode 100644 index 00000000000..c6669a567a2 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1.uml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Package xmi:id="_M6uS4EYCEeagQvw0AruCcg" name="package1"> + <eAnnotations xmi:id="_0iFCIEYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Model" href="root.uml#_-T-r8EYBEeagQvw0AruCcg"/> + </eAnnotations> + <packagedElement xmi:type="uml:Package" href="package1/packageA.uml#_R5WJAEYCEeagQvw0AruCcg"/> + </uml:Package> + <Ecore:EPackage xmi:id="_esXvkEYCEeagQvw0AruCcg" base_Package="_M6uS4EYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA.uml new file mode 100644 index 00000000000..5e245519bcd --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA.uml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Package xmi:id="_R5WJAEYCEeagQvw0AruCcg" name="packageA"> + <eAnnotations xmi:id="_axVn8EYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Package" href="../package1.uml#_M6uS4EYCEeagQvw0AruCcg"/> + </eAnnotations> + <packagedElement xmi:type="uml:Class" href="packageA/foo.uml#_VYUxUEYCEeagQvw0AruCcg"/> + </uml:Package> + <Ecore:EPackage xmi:id="_dxA6kEYCEeagQvw0AruCcg" base_Package="_R5WJAEYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA/foo.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA/foo.uml new file mode 100644 index 00000000000..d538aa7d82a --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package1/packageA/foo.uml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Class xmi:id="_VYUxUEYCEeagQvw0AruCcg" name="Foo"> + <eAnnotations xmi:id="_anqukEYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Package" href="../packageA.uml#_R5WJAEYCEeagQvw0AruCcg"/> + </eAnnotations> + </uml:Class> + <Ecore:EClass xmi:id="_anRicEYCEeagQvw0AruCcg" base_Class="_VYUxUEYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2.uml new file mode 100644 index 00000000000..0d530b1d276 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2.uml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Package xmi:id="_Qdf2EEYCEeagQvw0AruCcg" name="package2"> + <eAnnotations xmi:id="_bGexgEYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Model" href="root.uml#_-T-r8EYBEeagQvw0AruCcg"/> + </eAnnotations> + <packagedElement xmi:type="uml:Package" href="package2/packageB.uml#_THKnAEYCEeagQvw0AruCcg"/> + </uml:Package> + <Ecore:EPackage xmi:id="_fsK_sEYCEeagQvw0AruCcg" base_Package="_Qdf2EEYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB.uml new file mode 100644 index 00000000000..e8b1a5838ba --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB.uml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Package xmi:id="_THKnAEYCEeagQvw0AruCcg" name="packageB"> + <eAnnotations xmi:id="_accWAEYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Package" href="../package2.uml#_Qdf2EEYCEeagQvw0AruCcg"/> + </eAnnotations> + <packagedElement xmi:type="uml:Class" href="packageB/bar.uml#_Yg658EYCEeagQvw0AruCcg"/> + </uml:Package> + <Ecore:EPackage xmi:id="_gopPAEYCEeagQvw0AruCcg" base_Package="_THKnAEYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB/bar.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB/bar.uml new file mode 100644 index 00000000000..db8808c46dd --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/package2/packageB/bar.uml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:Ecore="http://www.eclipse.org/uml2/schemas/Ecore/5" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xsi:schemaLocation="http://www.eclipse.org/uml2/schemas/Ecore/5 pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"> + <uml:Class xmi:id="_Yg658EYCEeagQvw0AruCcg" name="Bar"> + <eAnnotations xmi:id="_P_TowEYDEeagQvw0AruCcg" source="http://www.eclipse.org/papyrus/2016/resource/shard"> + <references xmi:type="uml:Package" href="../packageB.uml#_THKnAEYCEeagQvw0AruCcg"/> + </eAnnotations> + </uml:Class> + <Ecore:EClass xmi:id="_cfH04EYCEeagQvw0AruCcg" base_Class="_Yg658EYCEeagQvw0AruCcg"/> +</xmi:XMI> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/referencing.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/referencing.uml new file mode 100644 index 00000000000..4d575d4e308 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/referencing.uml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_0S-gEEYMEeagQvw0AruCcg" name="referencing"> + <packagedElement xmi:type="uml:Package" xmi:id="_wTjjMEd3Eeayp81rgar4Qw" name="package1"> + <packagedElement xmi:type="uml:Package" xmi:id="_y4j2kEd3Eeayp81rgar4Qw" name="packageA"> + <packagedElement xmi:type="uml:Class" xmi:id="_3QKC4EYMEeagQvw0AruCcg" name="Subclass"> + <generalization xmi:id="_9sFkgEYMEeagQvw0AruCcg"> + <general xmi:type="uml:Class" href="package2/packageB/bar.uml#_Yg658EYCEeagQvw0AruCcg"/> + </generalization> + </packagedElement> + </packagedElement> + </packagedElement> + <packagedElement xmi:type="uml:Package" xmi:id="_yLgjUEd3Eeayp81rgar4Qw" name="package2"> + <packagedElement xmi:type="uml:Package" xmi:id="_0ZwjkEd3Eeayp81rgar4Qw" name="packageB"> + <packagedElement xmi:type="uml:Class" xmi:id="_2f4ikEd3Eeayp81rgar4Qw" name="Quux"> + <generalization xmi:id="_2f4ikUd3Eeayp81rgar4Qw"> + <general xmi:type="uml:Class" href="package2/packageB/bar.uml#_Yg658EYCEeagQvw0AruCcg"/> + </generalization> + </packagedElement> + </packagedElement> + </packagedElement> +</uml:Model> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.di b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.di new file mode 100644 index 00000000000..bf9abab340f --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.di @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.notation b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.notation new file mode 100644 index 00000000000..bf9abab340f --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.notation @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"/> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.uml b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.uml new file mode 100644 index 00000000000..5427fd15867 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/resources/shards/root.uml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_-T-r8EYBEeagQvw0AruCcg" name="root"> + <packagedElement xmi:type="uml:Package" href="package1.uml#_M6uS4EYCEeagQvw0AruCcg"/> + <packagedElement xmi:type="uml:Package" href="package2.uml#_Qdf2EEYCEeagQvw0AruCcg"/> + <profileApplication xmi:id="_-mL2QEYBEeagQvw0AruCcg"> + <eAnnotations xmi:id="_-mNrcEYBEeagQvw0AruCcg" source="http://www.eclipse.org/uml2/2.0.0/UML"> + <references xmi:type="ecore:EPackage" href="pathmap://UML_PROFILES/Ecore.profile.uml#_z1OFcHjqEdy8S4Cr8Rc_NA"/> + </eAnnotations> + <appliedProfile href="pathmap://UML_PROFILES/Ecore.profile.uml#_0"/> + </profileApplication> +</uml:Model> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/AbstractCrossReferenceIndexTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/AbstractCrossReferenceIndexTest.java new file mode 100644 index 00000000000..3c251e5010a --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/AbstractCrossReferenceIndexTest.java @@ -0,0 +1,182 @@ +/***************************************************************************** + * Copyright (c) 2016 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.infra.emf.resource; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +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.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.papyrus.infra.emf.internal.resource.CrossReferenceIndex; +import org.eclipse.papyrus.infra.emf.internal.resource.OnDemandCrossReferenceIndex; +import org.eclipse.papyrus.junit.utils.rules.AbstractHouseKeeperRule.CleanUp; +import org.eclipse.papyrus.junit.utils.rules.AnnotationRule; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.papyrus.junit.utils.rules.ProjectFixture; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.Stereotype; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; + +/** + * Test framework for cross-reference index and shards-related tests. + */ +public abstract class AbstractCrossReferenceIndexTest { + + @ClassRule + public static final ProjectFixture project = new ProjectFixture(); + + @Rule + public final HouseKeeper housekeeper = new HouseKeeper(); + + @Rule + public final AnnotationRule<String[]> resourcePaths = AnnotationRule.create(ProjectResource.class); + + protected ResourceSet fixture; + + @CleanUp + protected List<Resource> initialResources; + + private final Function<? super ResourceSet, ? extends ICrossReferenceIndex> indexFunction; + + /** + * Initializes me. + */ + public AbstractCrossReferenceIndexTest() { + this(null); + } + + /** + * Initializes me. + * + * @param onDemand + * {@code true} to force the on-demand index, {@code false} to force the + * full index, or {@code null} to let the framework decide the best + * available index + */ + public AbstractCrossReferenceIndexTest(Boolean onDemand) { + super(); + + if (onDemand == null) { + // Best available + indexFunction = ICrossReferenceIndex::getInstance; + } else if (onDemand) { + // Force the on-demand index + indexFunction = OnDemandCrossReferenceIndex::new; + } else { + // Force the full index + indexFunction = __ -> CrossReferenceIndex.getInstance(); + } + } + + @BeforeClass + public static void createProjectContents() { + List<String> resources = ImmutableList.of( + "root.uml", + "package1.uml", + "package1/packageA.uml", + "package1/packageA/foo.uml", + "package2.uml", + "package2/packageB.uml", + "package2/packageB/bar.uml", + "referencing.uml"); + + resources.forEach(res -> { + try { + project.createFile(res, AbstractCrossReferenceIndexTest.class, "resources/shards/" + res); + } catch (IOException e) { + e.printStackTrace(); + fail("Failed to create test resource: " + e.getMessage()); + } + }); + } + + @Before + public void createFixture() { + fixture = housekeeper.createResourceSet(); + + new ShardResourceLocator((ResourceSetImpl) fixture, index()); + + // Load resources + if (resourcePaths.get() != null) { + URI base = baseURI(); + initialResources = Stream.of(resourcePaths.get()) + .map(URI::createURI) + .map(uri -> uri.resolve(base)) + .map(uri -> fixture.getResource(uri, true)) + .collect(Collectors.toList()); + } + } + + protected final ICrossReferenceIndex index() { + return indexFunction.apply(fixture); + } + + URI baseURI() { + return URI.createPlatformResourceURI(project.getProject().getName() + "/", true); + } + + protected URI uri(String path) { + URI result = URI.createURI(path, true); + return result.resolve(baseURI()); + } + + protected Resource requireLoaded(String path) { + Resource result = fixture.getResource(uri(path), false); + assertThat("resource not created: " + path, result, notNullValue()); + assertThat("resource not loaded: " + path, result.isLoaded(), is(true)); + return result; + } + + protected Stereotype requireStereotype(Element element, String qualifiedName) { + Stereotype result = element.getApplicableStereotype(qualifiedName); + assertThat("stereotype not applicable: " + qualifiedName, result, notNullValue()); + assertThat("stereotype not applied: " + qualifiedName, element.isStereotypeApplied(result), is(true)); + return result; + } + + protected Stereotype requireEClass(Classifier classifier) { + return requireStereotype(classifier, "Ecore::EClass"); + } + + protected Stereotype requireEPackage(Package package_) { + return requireStereotype(package_, "Ecore::EPackage"); + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface ProjectResource { + String[] value(); + } +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/CrossReferenceIndexTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/CrossReferenceIndexTest.java new file mode 100644 index 00000000000..d3fcca35732 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/CrossReferenceIndexTest.java @@ -0,0 +1,150 @@ +/***************************************************************************** + * Copyright (c) 2016 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.infra.emf.resource; + +import static java.util.Collections.emptySet; +import static java.util.Collections.singleton; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.infra.emf.internal.resource.CrossReferenceIndex; +import org.eclipse.uml2.uml.resource.UMLResource; +import org.junit.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.SetMultimap; + +/** + * Tests for the {@link CrossReferenceIndex} class, the full indexer. + */ +public class CrossReferenceIndexTest extends AbstractCrossReferenceIndexTest { + + /** + * Initializes me. + */ + public CrossReferenceIndexTest() { + super(false); // Always the full indexer + } + + // + // Don't need to load any resources for these tests + // + + @Test + public void isShard() throws Exception { + assertThat(index().isShard(uri("package1/packageA/foo.uml")), is(true)); + assertThat(index().isShard(uri("package1/packageA.uml")), is(true)); + assertThat(index().isShard(uri("package1.uml")), is(true)); + assertThat(index().isShard(uri("root.uml")), is(false)); + } + + @Test + public void shards() throws Exception { + assertThat(index().getShards(uri("package1/packageA/foo.uml")), is(emptySet())); + assertThat(index().getShards(uri("package1/packageA.uml")), is(singleton(uri("package1/packageA/foo.uml")))); + assertThat(index().getShards(uri("package1.uml")), is(singleton(uri("package1/packageA.uml")))); + assertThat(index().getShards(uri("root.uml")), // This one has two shards + is(ImmutableSet.of(uri("package1.uml"), uri("package2.uml")))); + } + + @Test + public void parentShards() throws Exception { + assertThat(index().getParents(uri("package1/packageA/foo.uml")), is(singleton(uri("package1/packageA.uml")))); + assertThat(index().getParents(uri("package1/packageA.uml")), is(singleton(uri("package1.uml")))); + assertThat(index().getParents(uri("package1.uml")), is(singleton(uri("root.uml")))); + assertThat(index().getParents(uri("root.uml")), is(emptySet())); + } + + @Test + public void roots() throws Exception { + assertThat(index().getRoots(uri("package1/packageA/foo.uml")), is(singleton(uri("root.uml")))); + assertThat(index().getRoots(uri("package1/packageA.uml")), is(singleton(uri("root.uml")))); + assertThat(index().getRoots(uri("package1.uml")), is(singleton(uri("root.uml")))); + + // A root has no parents and, therefore, no root + assertThat(index().getRoots(uri("root.uml")), is(emptySet())); + + // And this one has nothing to do with shards + assertThat(index().getRoots(uri("referencing.uml")), is(emptySet())); + } + + @Test + public void outgoingReferences_givenURI() throws Exception { + // Shard relationship (cross-resource containment) is not a cross-reference + assertThat(index().getOutgoingCrossReferences(uri("package1.uml")), is(emptySet())); + + // We find cross-references to non-workspace resources, though those aren't indexed + assertThat(index().getOutgoingCrossReferences(uri("root.uml")), + is(singleton(URI.createURI(UMLResource.ECORE_PROFILE_URI)))); + + // This has a cross-reference in the class generalization + assertThat(index().getOutgoingCrossReferences(uri("referencing.uml")), + is(singleton(uri("package2/packageB/bar.uml")))); + + // This API is generalized for the Papyrus one-file + assertThat(index().getOutgoingCrossReferences(uri("referencing.di")), + is(singleton(uri("package2/packageB/bar.di")))); + } + + @Test + public void incomingReferences_givenURI() throws Exception { + // Parent pointer in shard annotation is not a cross-reference + assertThat(index().getIncomingCrossReferences(uri("root.uml")), is(emptySet())); + assertThat(index().getIncomingCrossReferences(uri("package1.uml")), is(emptySet())); + + // This has a cross-reference in the class generalization + assertThat(index().getIncomingCrossReferences(uri("package2/packageB/bar.uml")), + is(singleton(uri("referencing.uml")))); + + // This API is generalized for the Papyrus one-file + assertThat(index().getIncomingCrossReferences(uri("package2/packageB/bar.di")), + is(singleton(uri("referencing.di")))); + } + + @Test + public void outgoingReferences() throws Exception { + SetMultimap<URI, URI> xrefs = index().getOutgoingCrossReferences(); + + // Shard relationship (cross-resource containment) is not a cross-reference + assertThat(xrefs.get(uri("package1.uml")), is(emptySet())); + + // We find cross-references to non-workspace resources, though those aren't indexed + assertThat(xrefs.get(uri("root.uml")), + is(singleton(URI.createURI(UMLResource.ECORE_PROFILE_URI)))); + + // This has a cross-reference in the class generalization + assertThat(xrefs.get(uri("referencing.uml")), + is(singleton(uri("package2/packageB/bar.uml")))); + + // This API is *not* generalized for the Papyrus one-file + assertThat(xrefs.get(uri("referencing.di")), is(emptySet())); + } + + @Test + public void incomingReferences() throws Exception { + SetMultimap<URI, URI> xrefs = index().getIncomingCrossReferences(); + + // Parent pointer in shard annotation is not a cross-reference + assertThat(xrefs.get(uri("root.uml")), is(emptySet())); + assertThat(xrefs.get(uri("package1.uml")), is(emptySet())); + + // This has a cross-reference in the class generalization + assertThat(xrefs.get(uri("package2/packageB/bar.uml")), + is(singleton(uri("referencing.uml")))); + + // This API is *not* generalized for the Papyrus one-file + assertThat(xrefs.get(uri("package2/packageB/bar.di")), is(emptySet())); + } +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceHelperTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceHelperTest.java new file mode 100644 index 00000000000..d2a8ef84841 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceHelperTest.java @@ -0,0 +1,241 @@ +/***************************************************************************** + * Copyright (c) 2016 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.infra.emf.resource; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Arrays; +import java.util.Collection; +import java.util.Optional; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EModelElement; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.papyrus.infra.emf.internal.resource.AbstractCrossReferenceIndex; +import org.eclipse.papyrus.junit.utils.rules.AnnotationRule; +import org.eclipse.uml2.uml.util.UMLUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests for the {@link ShardResourceHelper} class. + */ +@RunWith(Parameterized.class) +public class ShardResourceHelperTest extends AbstractCrossReferenceIndexTest { + + @Rule + public final AnnotationRule<String> shardElementQualifiedName = AnnotationRule.create(ShardElement.class); + + private final boolean useCommands; + private EditingDomain domain; // In case we are using commands + + private ShardResourceHelper helper; + private EObject shardElement; + private Resource shardResource; + + /** + * Initializes me. + * + * @param useCommands + * whether to use the shard helper's commands for resource manipulation + * (ensures test coverage) + */ + public ShardResourceHelperTest(boolean useCommands) { + super(); + + this.useCommands = useCommands; + } + + @Test + @ProjectResource("referencing.uml") + @ShardElement("referencing::package2::packageB") + public void makeShard() { + setShard(true); + assertAdapter(); + assertAnnotation(); + + undo(); + assertAdapter(); + assertNoAnnotation(); + + redo(); + assertAdapter(); + assertAnnotation(); + } + + @Test + @ProjectResource("root.uml") + @ShardElement("root::package2::packageB") + public void makeNotShard() { + setShard(false); + assertAdapter(); + assertNoAnnotation(); + + undo(); + assertAdapter(); + assertAnnotation(); + + redo(); + assertAdapter(); + assertNoAnnotation(); + } + + @Test(expected = IllegalStateException.class) + @ProjectResource("referencing.uml") + @ShardElement("referencing::package2::packageB") + public void attemptToUseClosedHelper() { + helper.close(); + + setShard(true); + } + + // + // Test framework + // + + @Parameters(name = "{index}: useCommands={0}") + public static Iterable<Object[]> data() { + return Arrays.asList(new Object[][] { + { false }, + { true }, + }); + } + + @Before + public void createShardHelper() { + if (useCommands) { + // Need an editing domain for command execution + domain = housekeeper.createSimpleEditingDomain(fixture); + } + + // Find the shard element + shardElement = initialResources.stream() + .flatMap(res -> UMLUtil.findNamedElements(res, shardElementQualifiedName.get()).stream()) + .findAny() + .orElseThrow(AssertionError::new); + + // Create or find the shard resource + if (((InternalEObject) shardElement).eDirectResource() != null) { + shardResource = shardElement.eResource(); + } else { + shardResource = fixture.createResource(project.getURI("the-shard.uml")); + if (useCommands) { + domain.getCommandStack().execute(new AddCommand(domain, shardResource.getContents(), shardElement)); + } else { + shardResource.getContents().add(shardElement); + } + } + helper = new ShardResourceHelper(shardElement); + } + + @After + public void destroyShardHelper() { + helper.close(); + } + + void setShard(boolean shard) { + if (useCommands) { + Command command = helper.getSetShardCommand(shard); + domain.getCommandStack().execute(command); + } else { + helper.setShard(shard); + } + + assertThat("Changing shard status failed", helper.isShard(), is(shard)); + } + + void undo() { + if (useCommands) { + assertThat("Cannot undo", domain.getCommandStack().canUndo(), is(true)); + domain.getCommandStack().undo(); + } else { + helper.setShard(!helper.isShard()); + } + } + + void redo() { + if (useCommands) { + assertThat("Cannot redo", domain.getCommandStack().canRedo(), is(true)); + domain.getCommandStack().redo(); + } else { + helper.setShard(!helper.isShard()); + } + } + + /** Assert that our model element has the shard adapter attached. */ + void assertAdapter() { + assertThat("Shard adapter not found", findAdapter().isPresent(), is(true)); + } + + /** Assert that our model element does not have the shard adapter attached. */ + void assertNoAdapter() { + assertThat("Shard adapter found", findAdapter().isPresent(), is(false)); + } + + private Optional<Adapter> findAdapter() { + return shardElement.eAdapters().stream() + .filter(a -> a.getClass().getName().contains("ShardResourceHelper$")) + .findAny(); + } + + /** Assert that our model element has the shard annotation. */ + void assertAnnotation() { + Optional<EAnnotation> annotation = findAnnotation(); + assertThat("Shard annotation not found", annotation.isPresent(), is(true)); + assertThat("Shard annotation missing back pointer", + annotation.map(EAnnotation::getReferences).get(), + hasItem(shardElement.eContainer())); + } + + /** Assert that our model element does not have the shard annotation. */ + void assertNoAnnotation() { + assertThat("Shard annotation found", findAnnotation().isPresent(), is(false)); + } + + private Optional<EAnnotation> findAnnotation() { + return Optional.of(shardElement) + .filter(EModelElement.class::isInstance).map(EModelElement.class::cast) + .map(EModelElement::getEAnnotations).map(Collection::stream) + .map(s -> s.filter(a -> AbstractCrossReferenceIndex.SHARD_ANNOTATION_SOURCE.equals(a.getSource()))) + .flatMap(s -> s.findAny()); + } + + // + // Nested types + // + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface ShardElement { + /** The qualified name of the element to make or unmake as a shard. */ + String value(); + } +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceLocatorTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceLocatorTest.java new file mode 100644 index 00000000000..6c602b90670 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/ShardResourceLocatorTest.java @@ -0,0 +1,93 @@ +/***************************************************************************** + * Copyright (c) 2016 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.infra.emf.resource; + +import java.util.Arrays; + +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Package; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests for the {@link ShardResourceLocator} class. These tests are run both + * with the full cross-reference index and with the partial on-demand index that + * only looks for shard parent relationships. + */ +@RunWith(Parameterized.class) +public class ShardResourceLocatorTest extends AbstractCrossReferenceIndexTest { + + /** + * Initializes me. + * + * @param onDemand + * whether to force the on-demand cross-reference index + * @param description + * the description of the test conditions + */ + public ShardResourceLocatorTest(boolean onDemand, String description) { + super(onDemand); + } + + @Test + @ProjectResource("package1/packageA/foo.uml") + public void shardLoadsContainersAndDoesntLoseStereotypes() { + Class foo = (Class) initialResources.get(0).getContents().get(0); + + // The parent chain of Foo is loaded + requireLoaded("root.uml"); + requireLoaded("package1.uml"); + requireLoaded("package1/packageA.uml"); + + // Stereotype applications were not lost + requireEClass(foo); + requireEPackage(foo.getNearestPackage()); + requireEPackage(foo.getNearestPackage().getNestingPackage()); + } + + @Test + @ProjectResource("referencing.uml") + public void proxyResolutionLoadsShardFromTheTop() { + Package referencing = (Package) initialResources.get(0).getContents().get(0); + Class subclass = (Class) referencing.getNestedPackage("package1") + .getNestedPackage("packageA").getOwnedType("Subclass"); + + // Get its general + Class superclass = (Class) subclass.getGeneral("Bar"); + + // The parent chain of Bar is loaded + requireLoaded("root.uml"); + requireLoaded("package2.uml"); + requireLoaded("package2/packageB.uml"); + + // Stereotype applications were not lost + requireEClass(superclass); + requireEPackage(superclass.getNearestPackage()); + requireEPackage(superclass.getNearestPackage().getNestingPackage()); + } + + // + // Test framework + // + + @Parameters(name = "{index}: {1}") + public static Iterable<Object[]> data() { + return Arrays.asList(new Object[][] { + { false, "full index" }, + { true, "on-demand index" }, + }); + } +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/index/WorkspaceModelIndexTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/index/WorkspaceModelIndexTest.java index f94288ef453..1c31edb53d1 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/index/WorkspaceModelIndexTest.java +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/resource/index/WorkspaceModelIndexTest.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2014, 2015 Christian W. Damus and others. + * Copyright (c) 2014, 2016 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 @@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; import java.io.File; import java.io.FileNotFoundException; @@ -31,7 +32,12 @@ import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Supplier; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -41,8 +47,11 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; @@ -51,6 +60,8 @@ import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.papyrus.infra.emf.Activator; +import org.eclipse.papyrus.infra.emf.internal.resource.index.IndexManager; +import org.eclipse.papyrus.infra.emf.internal.resource.index.InternalModelIndex; import org.eclipse.papyrus.infra.emf.utils.EMFHelper; import org.eclipse.papyrus.junit.framework.classification.tests.AbstractPapyrusTest; import org.eclipse.papyrus.junit.utils.LogTracker; @@ -66,16 +77,17 @@ import org.junit.Test; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.io.Files; -import com.google.common.util.concurrent.Uninterruptibles; /** * Test suite for the {@link WorkspaceModelIndex} class. */ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { - private static final CrossReferenceIndexer index = new CrossReferenceIndexer(); + private static final SyncHolder syncHolder = new SyncHolder(); + private static final CrossReferenceIndexer index = new CrossReferenceIndexer(syncHolder); + + private static IndexManager manager; private static WorkspaceModelIndex<CrossReferenceIndex> fixture; - private static boolean delayIndexing; @Rule public final HouseKeeper houseKeeper = new HouseKeeper(); @@ -219,8 +231,8 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { // Initial build Map<IFile, CrossReferenceIndex> index = fixture.getIndex().get(); - // Ensure that indexing will take a bit of time - delayIndexing = true; + // Interlock with the indexing for timing purposes + Semaphore sync = syncHolder.createStandardSync(); final String newFileName = "the_referencing_model.uml"; @@ -231,8 +243,11 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { referencingFile = referencingProject.getFile(new Path(newFileName)); referencingURI = uri(referencingFile); + // Let the indexing start + sync.release(); + // Cancel the index control job - Job[] family = Job.getJobManager().find(fixture); + Job[] family = Job.getJobManager().find(manager); Job controlJob = null; for (Job job : family) { if (job.getClass().getSimpleName().contains("JobWrangler")) { @@ -241,16 +256,25 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { } } assertThat("Control job not found", controlJob, notNullValue()); + + long cancellingAt = System.currentTimeMillis(); + controlJob.cancel(); - long requestIndex = System.currentTimeMillis(); + // Let the indexing finish + sync.release(); - // Check the index - index = fixture.getIndex().get(); + JobWaiter controlJobWaiter = JobWaiter.waitForStart(controlJob); - long gotIndex = System.currentTimeMillis(); + controlJobWaiter.waitForJob(); + + long restartedAt = System.currentTimeMillis(); - assertThat("Didn't have to wait for the index to recover", (gotIndex - requestIndex), greaterThan(1000L)); + assertThat("Didn't have to wait for the index to recover", + (restartedAt - cancellingAt), greaterThan(1000L)); + + // Check the index + index = fixture.getIndex().get(); assertIndex(index); } @@ -311,12 +335,21 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { @BeforeClass public static void createFixture() { - fixture = new WorkspaceModelIndex<CrossReferenceIndex>("test", UMLResource.UML_CONTENT_TYPE_IDENTIFIER, index, 2); + manager = new IndexManager() { + @Override + protected Map<QualifiedName, InternalModelIndex> loadIndices() { + fixture = new WorkspaceModelIndex<>("test", UMLResource.UML_CONTENT_TYPE_IDENTIFIER, index, 2); + return Collections.singletonMap(fixture.getIndexKey(), (InternalModelIndex) fixture); + } + }; + manager.startManager(); } @AfterClass public static void destroyFixture() { - fixture.dispose(); + // This disposes the fixture, too + manager.dispose(); + manager = null; fixture = null; } @@ -346,7 +379,7 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { @After public void reset() { - delayIndexing = false; + syncHolder.clear(); } static URI uri(IFile file) { @@ -393,9 +426,45 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { // Nested types // + static class SyncHolder implements Supplier<Semaphore> { + private volatile Semaphore sync; + + @Override + public Semaphore get() { + return sync; + } + + Semaphore createStandardSync() { + sync = new Semaphore(0); + return sync; + } + + void clear() { + if (sync != null) { + // Make sure that any blocked threads are released to whatever fate + syncHolder.sync.release(100); + syncHolder.sync = null; + } + } + } + static class CrossReferenceIndexer implements WorkspaceModelIndex.IndexHandler<CrossReferenceIndex> { private final Map<IFile, CrossReferenceIndex> index = Maps.newHashMap(); + private final Supplier<? extends Semaphore> syncSupplier; + + /** + * Initializes me. + * + * @param syncSupplier + * a supplier of an optional semaphore to acquire at start and end of indexing a file + */ + public CrossReferenceIndexer(Supplier<? extends Semaphore> syncSupplier) { + super(); + + this.syncSupplier = syncSupplier; + } + private CrossReferenceIndex get(IFile file) { CrossReferenceIndex result; @@ -413,38 +482,48 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { @Override public CrossReferenceIndex index(IFile file) { final CrossReferenceIndex result = get(file); + final Semaphore sync = syncSupplier.get(); - Set<URI> imports = result.imports; - - ResourceSet resourceSet = new IndexingResourceSet(); + if (sync != null) { + // Wait for the test to let us proceed + sync.acquireUninterruptibly(); + } try { - URI uri = uri(file); - - Resource resource = resourceSet.getResource(uri, true); - for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> next : EcoreUtil.ProxyCrossReferencer.find(resource).entrySet()) { - for (EStructuralFeature.Setting setting : next.getValue()) { - Object references = setting.get(false); - - if (references instanceof EObject) { - EObject ref = (EObject) references; - if (ref.eIsProxy()) { - URI href = EcoreUtil.getURI(ref).trimFragment(); - if (href.isPlatformResource() && imports.add(href)) { - // add the corresponding export - IFile other = file.getWorkspace().getRoot().getFile(new Path(href.toPlatformString(true))); - get(other).exports.add(uri); + Set<URI> imports = result.imports; + imports.clear(); + + ResourceSet resourceSet = new IndexingResourceSet(); + + try { + URI uri = uri(file); + + Resource resource = resourceSet.getResource(uri, true); + for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> next : EcoreUtil.ProxyCrossReferencer.find(resource).entrySet()) { + for (EStructuralFeature.Setting setting : next.getValue()) { + Object references = setting.get(false); + + if (references instanceof EObject) { + EObject ref = (EObject) references; + if (ref.eIsProxy()) { + URI href = EcoreUtil.getURI(ref).trimFragment(); + if (href.isPlatformResource() && imports.add(href)) { + // add the corresponding export + IFile other = file.getWorkspace().getRoot().getFile(new Path(href.toPlatformString(true))); + get(other).exports.add(uri); + } } } } } + } finally { + EMFHelper.unload(resourceSet); } } finally { - EMFHelper.unload(resourceSet); - } - - if (delayIndexing) { - Uninterruptibles.sleepUninterruptibly(1L, TimeUnit.SECONDS); + if (sync != null) { + // Wait for the test to let us finish + sync.acquireUninterruptibly(); + } } return result; @@ -552,4 +631,74 @@ public class WorkspaceModelIndexTest extends AbstractPapyrusTest { file.delete(true, monitor); } } + + static final class JobWaiter extends JobChangeAdapter { + private final Job job; + private final boolean waitForStart; + + private final Lock lock = new ReentrantLock(); + private final Condition cond = lock.newCondition(); + private volatile boolean gotIt; + + private JobWaiter(Job job, boolean waitForStart) { + super(); + + this.job = job; + this.waitForStart = waitForStart; + + Job.getJobManager().addJobChangeListener(this); + } + + public static JobWaiter waitForStart(Job job) { + return new JobWaiter(job, true); + } + + public static JobWaiter waitForEnd(Job job) { + return new JobWaiter(job, false); + } + + public void waitForJob() { + lock.lock(); + + try { + while (!gotIt) { + try { + cond.await(); + } catch (InterruptedException e) { + fail("Test was interrupted"); + } + } + } finally { + lock.unlock(); + Job.getJobManager().removeJobChangeListener(this); + } + } + + @Override + public void aboutToRun(IJobChangeEvent event) { + if (waitForStart && (event.getJob() == job)) { + lock.lock(); + try { + gotIt = true; + cond.signalAll(); + } finally { + lock.unlock(); + } + } + } + + @Override + public void done(IJobChangeEvent event) { + if (!waitForStart && (event.getJob() == job)) { + lock.lock(); + try { + gotIt = true; + cond.signalAll(); + } finally { + lock.unlock(); + } + } + } + + } } diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/tests/AllTests.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/tests/AllTests.java index 158a001365e..46aa80c3609 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/tests/AllTests.java +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.emf.tests/tests/org/eclipse/papyrus/infra/emf/tests/AllTests.java @@ -8,13 +8,16 @@ * * Contributors: * Christian W. Damus (CEA) - Initial API and implementation - * Christian W. Damus - bugs 399859, 465416, 485220 + * Christian W. Damus - bugs 399859, 465416, 485220, 496299 * */ package org.eclipse.papyrus.infra.emf.tests; import org.eclipse.papyrus.infra.emf.advice.ReadOnlyObjectEditAdviceTest; import org.eclipse.papyrus.infra.emf.edit.domain.PapyrusTransactionalEditingDomainTest; +import org.eclipse.papyrus.infra.emf.resource.CrossReferenceIndexTest; +import org.eclipse.papyrus.infra.emf.resource.ShardResourceHelperTest; +import org.eclipse.papyrus.infra.emf.resource.ShardResourceLocatorTest; import org.eclipse.papyrus.infra.emf.resource.index.WorkspaceModelIndexTest; import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForResourceTest; import org.eclipse.papyrus.infra.types.core.registries.ElementTypeSetConfigurationRegistry; @@ -37,8 +40,10 @@ import org.junit.runners.Suite.SuiteClasses; PapyrusTransactionalEditingDomainTest.class, // oep.infra.emf.utils ServiceUtilsForResourceTest.class, + // oep.infra.emf.resource + ShardResourceHelperTest.class, ShardResourceLocatorTest.class, CrossReferenceIndexTest.class, // oep.infra.emf.resource.index - WorkspaceModelIndexTest.class + WorkspaceModelIndexTest.class, }) public class AllTests { diff --git a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.classpath b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.classpath index 8a8f1668cdc..eca7bdba8f0 100644 --- a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.classpath +++ b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.classpath @@ -1,7 +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/JavaSE-1.6"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?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/JavaSE-1.8"/> + <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/services/org.eclipse.papyrus.infra.services.controlmode.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.settings/org.eclipse.jdt.core.prefs index 410244d65a6..62a08f4494d 100644 --- a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/META-INF/MANIFEST.MF index be5e009ef29..bef0c0a73be 100644 --- a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/META-INF/MANIFEST.MF @@ -3,14 +3,14 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.106.0", org.junit;bundle-version="4.11.0", org.eclipse.papyrus.junit.framework;bundle-version="1.2.0", org.eclipse.papyrus.infra.core.log;bundle-version="1.2.0", - org.eclipse.papyrus.infra.services.controlmode;bundle-version="1.2.0", + org.eclipse.papyrus.infra.services.controlmode;bundle-version="1.3.0", org.eclipse.papyrus.infra.core;bundle-version="1.2.0", org.eclipse.papyrus.views.modelexplorer;bundle-version="1.2.0", org.eclipse.uml2.uml;bundle-version="5.0.0", org.eclipse.emf.transaction, org.eclipse.papyrus.infra.services.resourceloading;bundle-version="1.2.0", org.eclipse.papyrus.junit.utils;bundle-version="1.2.0", - org.eclipse.papyrus.infra.emf;bundle-version="1.2.0", + org.eclipse.papyrus.infra.emf;bundle-version="1.3.0", org.eclipse.papyrus.infra.widgets;bundle-version="1.2.0", org.eclipse.ui.navigator;bundle-version="3.5.500", com.google.guava;bundle-version="11.0.0", @@ -21,9 +21,9 @@ Export-Package: org.eclipse.papyrus.infra.services.controlmode.tests, org.eclipse.papyrus.infra.services.controlmode.tests.uncontrol Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy -Bundle-Version: 1.2.0.qualifier +Bundle-Version: 1.4.0.qualifier Bundle-Name: %Bundle-Name Bundle-ManifestVersion: 2 Bundle-Activator: org.eclipse.papyrus.infra.services.controlmode.tests.control.Activator Bundle-SymbolicName: org.eclipse.papyrus.infra.services.controlmode.tests -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/pom.xml b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/pom.xml index 5341ea1e2be..ac0785e925e 100644 --- a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/pom.xml +++ b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/pom.xml @@ -10,6 +10,6 @@ </parent> <groupId>org.eclipse.papyrus</groupId> <artifactId>org.eclipse.papyrus.infra.services.controlmode.tests</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> </project> diff --git a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/src/org/eclipse/papyrus/infra/services/controlmode/tests/uncontrol/UncontrolModelTest.java b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/src/org/eclipse/papyrus/infra/services/controlmode/tests/uncontrol/UncontrolModelTest.java index 47316c7bdc3..dac0bb79c44 100644 --- a/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/src/org/eclipse/papyrus/infra/services/controlmode/tests/uncontrol/UncontrolModelTest.java +++ b/tests/junit/plugins/infra/services/org.eclipse.papyrus.infra.services.controlmode.tests/src/org/eclipse/papyrus/infra/services/controlmode/tests/uncontrol/UncontrolModelTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2014, 2016 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 @@ -8,27 +8,34 @@ * Contributors: * Juan Cadavid (CEA) juan.cadavid@cea.fr - Implementation initial and API * Gabriel Pascual (ALL4TEC) gabriel.pascual@all4tec.net - Bug 459427 - * Christian W. Damus - bug 480209 + * Christian W. Damus - bugs 480209, 496299 ******************************************************************************/ package org.eclipse.papyrus.infra.services.controlmode.tests.uncontrol; +import static org.hamcrest.CoreMatchers.anything; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeThat; import java.util.Collections; import org.eclipse.core.resources.IFile; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.papyrus.infra.core.services.ServiceException; +import org.eclipse.papyrus.infra.emf.resource.ShardResourceHelper; import org.eclipse.papyrus.infra.services.controlmode.tests.Messages; import org.eclipse.papyrus.junit.utils.rules.PluginResource; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.PackageableElement; +import org.hamcrest.CoreMatchers; import org.junit.Test; /** @@ -392,4 +399,38 @@ public class UncontrolModelTest extends AbstractUncontrolModelTest { }; uncontrolAssertion.assertUncontrol(); } + + /** + * Test uncontrol of a "shard" resource sub-unit. + */ + @Test + public void testUncontrolShardSubunit() throws ServiceException { + ShardResourceHelper[] helper = { null }; + EModelElement[] element = { null }; + + UncontrolModeAssertion uncontrolAssertion = new UncontrolModeAssertion(Messages.UncontrolModelTest_4) { + @Override + protected void assertBeforeUncontrol() { + super.assertBeforeUncontrol(); + + element[0] = getElementToUnControl(); + helper[0] = new ShardResourceHelper(element[0]); + houseKeeper.cleanUpLater(helper[0], ShardResourceHelper::close); + + editorFixture.execute(helper[0].getSetShardCommand(true)); + assumeThat("Element does not appear to be a shard", helper[0].isShard(), is(true)); + } + }; + uncontrolAssertion.assertUncontrol(); + + assertThat("Element still appears to be a shard", helper[0].isShard(), is(false)); + assertThat("Element still has an annotation", element[0].getEAnnotations(), + not(CoreMatchers.<EAnnotation> hasItem(anything()))); + + undo(); + assertNotSame(model.eResource(), selectedElements.get(0).eResource()); + assertThat("Element does not appear to be a shard", helper[0].isShard(), is(true)); + assertThat("Element does not have any annotation", element[0].getEAnnotations(), + CoreMatchers.<EAnnotation> hasItem(anything())); + } } |