diff options
author | Geza Kulcsar | 2019-05-27 14:43:46 +0000 |
---|---|---|
committer | Geza Kulcsar | 2019-05-28 13:53:45 +0000 |
commit | 58965145a0961f20806bac03de417e707ef5904c (patch) | |
tree | b8d2c62479105302babcd3f882f01a096aa4d32d | |
parent | a47f3de2f2d9677f31f85802d52d667f29a79621 (diff) | |
download | org.eclipse.viatra-58965145a0961f20806bac03de417e707ef5904c.tar.gz org.eclipse.viatra-58965145a0961f20806bac03de417e707ef5904c.tar.xz org.eclipse.viatra-58965145a0961f20806bac03de417e707ef5904c.zip |
[547075] Extends test framework with custom EMF object serialization
The snapshot helper has been extended by a configurable map for custom
functions, which can be used for creating custom substitutions for EMF
objects of given types. A collection of tests has been also created.
Change-Id: If932372a343e832b7649e5d8626dddfaaa88e8a9
Signed-off-by: Geza Kulcsar <geza.kulcsar@incquerylabs.com>
18 files changed, 520 insertions, 61 deletions
diff --git a/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/releases/viatra-2.2.adoc b/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/releases/viatra-2.2.adoc index 3bfc87772..f0235f1a4 100644 --- a/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/releases/viatra-2.2.adoc +++ b/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/releases/viatra-2.2.adoc @@ -47,4 +47,16 @@ Prior to version 2.2, the filter settings of batch transformation rules were ign 2. If either the transformation rule or the statement define a filter (but not both), the filter is used. 3. If both the transformation rule and the statement defines a filter, the filter defined by the statement overrides the default filter. -This behavior might change the behavior of existing transformations when transformation rule filters were defined but filterless statements were used: in such case, the default rule filters will be applied. In such cases, the unnecessary default filters should be removed; or if necessary, a new filter could be used to override the default filter where the rule was activate.
\ No newline at end of file +This behavior might change the behavior of existing transformations when transformation rule filters were defined but filterless statements were used: in such case, the default rule filters will be applied. In such cases, the unnecessary default filters should be removed; or if necessary, a new filter could be used to override the default filter where the rule was activate. + +=== API break in the query test framework + +Prior to version 2.2, the main test class `ViatraQueryTest` had a field `accessMap` for storing the mapping of plain Java types to their handler objects for snapshot creation. In version 2.2, the encouraged way of providing this and further serialization information is in form of a single `SnapshotHelper` instance, initialized at the same time when the test case is created. + +*Details*: +The field `accessMap` and the API method `withClasses` for updating the mapping have been removed. Instead, a SnapshotHelper can (and should) be provided while calling the first method, `test`, for test case initialization. Accordingly, `test` has a new signature now, which accepts a SnapshotHelper instance. For example, very often, a helper might be created on spot when the test case gets initialized: + +[source,xtend] +---- +ViatraQueryTest.test(SomeQuerySpecification.instance, new SnapshotHelper(accessMap, customEMFSerializerMap)) +----
\ No newline at end of file diff --git a/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/tools/query-tests.adoc b/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/tools/query-tests.adoc index 956d45a85..4dcfa31d2 100644 --- a/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/tools/query-tests.adoc +++ b/documentation/org.eclipse.viatra.documentation.help/src/main/asciidoc/tools/query-tests.adoc @@ -112,10 +112,28 @@ public class CustomIntegerAccess extends JavaObjectAccess{ ... Map<String, JavaObjectAccess> objectAccess = Maps.newHashMap(); map.put(CustomInteger.class.getName(),new CustomIntegerAccess()); - ViatraQueryTest.test(specs, objectAccess).on(new EMFScope([MODEL])).with([SNAPSHOT]).assertEquals(); + ViatraQueryTest.test(specs, new SnapshotHelper(objectAccess)).on(new EMFScope([MODEL])).with([SNAPSHOT]).assertEquals(); ... ---- +== Specifying custom serialization for EMF objects + +In the default configuration of the snapshot generator, any EMF object is converted to a generic EMF substitution. However, in some scenarios, the user might want to specify a (list of) custom function(s), which define how EMF objects should be represented in the snapshot. + +The framework allows for registering such custom functions, in form of a map indexed by the types (EClass) desired to be handled in a user-defined way, where the corresponding map value stores the substitution function. Such functions are expected to receive an EObject and return a String. + +The following example shows how to specify a simple custom function for the class ApplicationType from the CPS metamodel, and how to set up a corresponding test case. + +[source,xtend] +---- +customMap.put(CyberPhysicalSystemPackage.Literals.APPLICATION_TYPE, [at | (at as ApplicationType).identifier]) + +ViatraQueryTest.test(ApplicationTypesQuerySpecification.instance, snapshotHelper(customMap)) + .on(new EMFScope([MODEL])) + .with([SNAPSHOT]) + .assertEquals +---- + === Coverage analysis and reporting === Starting with VIATRA 1.6 (see link:http://bugs.eclipse.org/514628[bug 514628]), you can add analyzers to a test object which measure various metrics of query execution. For example, you can analyze coverage during testing: diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/META-INF/MANIFEST.MF b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/META-INF/MANIFEST.MF index 92ecb5d3a..f9c31868c 100644 --- a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/META-INF/MANIFEST.MF +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/META-INF/MANIFEST.MF @@ -22,7 +22,8 @@ Require-Bundle: org.eclipse.emf.ecore, org.eclipse.viatra.examples.cps.model;bundle-version="[2.0.0,2.3.0)", org.eclipse.viatra.query.runtime.rete;bundle-version="[2.2.0,2.3.0)", org.eclipse.viatra.query.runtime.localsearch;bundle-version="[2.2.0,2.3.0)", - org.eclipse.viatra.query.patternlanguage.emf;bundle-version="[2.2.0,2.3.0)" + org.eclipse.viatra.query.patternlanguage.emf;bundle-version="[2.2.0,2.3.0)", + org.eclipse.viatra.query.patternlanguage.emf.tests;bundle-version="2.2.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Automatic-Module-Name: org.eclipse.viatra.query.runtime.cps.tests Import-Package: com.google.inject, diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_AIwithAT.snapshot b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_AIwithAT.snapshot new file mode 100644 index 000000000..6528ca61f --- /dev/null +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_AIwithAT.snapshot @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="ASCII"?> +<vqSnapshot:QuerySnapshot + xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:vqSnapshot="http://www.eclipse.org/viatra/query/snapshot" + inputSpecification="ResourceSet"> + <matchSetRecords + patternQualifiedName="org.eclipse.viatra.query.runtime.cps.tests.queries.applicationInstancesOfApplicationType"> + <matches> + <substitutions + xsi:type="vqSnapshot:EMFSubstitution" + parameterName="AI"> + <value + href="../instances/demo.cyberphysicalsystem#simple.cps.app.FirstAppClass0.inst0"/> + </substitutions> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="simple.cps.app.FirstAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <matches> + <substitutions + xsi:type="vqSnapshot:EMFSubstitution" + parameterName="AI"> + <value + href="../instances/demo.cyberphysicalsystem#simple.cps.app.FirstAppClass0.inst1"/> + </substitutions> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="simple.cps.app.FirstAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <matches> + <substitutions + xsi:type="vqSnapshot:EMFSubstitution" + parameterName="AI"> + <value + href="../instances/demo.cyberphysicalsystem#simple.cps.app.SecondAppClass0.inst0"/> + </substitutions> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="simple.cps.app.SecondAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <filter/> + </matchSetRecords> + <modelRoots + href="../instances/demo.cyberphysicalsystem#testModel6504822858552"/> +</vqSnapshot:QuerySnapshot> diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot new file mode 100644 index 000000000..d44f89a85 --- /dev/null +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="ASCII"?> +<vqSnapshot:QuerySnapshot + xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:vqSnapshot="http://www.eclipse.org/viatra/query/snapshot" + inputSpecification="ResourceSet"> + <matchSetRecords + patternQualifiedName="org.eclipse.viatra.query.runtime.cps.tests.queries.applicationTypes"> + <matches> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="simple.cps.app.FirstAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <matches> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="simple.cps.app.SecondAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <filter/> + </matchSetRecords> + <modelRoots + href="../instances/demo.cyberphysicalsystem#testModel6504822858552"/> +</vqSnapshot:QuerySnapshot> diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes_id.snapshot b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes_id.snapshot new file mode 100644 index 000000000..3c869be60 --- /dev/null +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes_id.snapshot @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="ASCII"?> +<vqSnapshot:QuerySnapshot + xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:vqSnapshot="http://www.eclipse.org/viatra/query/snapshot" + inputSpecification="ResourceSet"> + <matchSetRecords + patternQualifiedName="org.eclipse.viatra.query.runtime.cps.tests.queries.applicationTypes"> + <matches> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="IDsimple.cps.app.FirstAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <matches> + <substitutions + xsi:type="vqSnapshot:CustomEMFSubstitution" + parameterName="AT" + value="IDsimple.cps.app.SecondAppClass0"> + <type + href="http://org.eclipse.viatra/model/cps#//ApplicationType"/> + </substitutions> + </matches> + <filter/> + </matchSetRecords> + <modelRoots + href="../instances/demo.cyberphysicalsystem#testModel6504822858552"/> +</vqSnapshot:QuerySnapshot> diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/plugin.xml b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/plugin.xml index 1dd4d4444..f8d21602f 100644 --- a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/plugin.xml +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/plugin.xml @@ -48,6 +48,11 @@ <query-specification fqn="org.eclipse.viatra.query.runtime.cps.tests.queries.AppInstanceAllocatedToHostInstance"/> </group> </extension> + <extension id="org.eclipse.viatra.query.runtime.cps.tests.queries.CustomEMFTestQueries" point="org.eclipse.viatra.query.runtime.queryspecification"> + <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:org.eclipse.viatra.query.runtime.cps.tests.queries.CustomEMFTestQueries" id="org.eclipse.viatra.query.runtime.cps.tests.queries.CustomEMFTestQueries"> + <query-specification fqn="org.eclipse.viatra.query.runtime.cps.tests.queries.ChildAndCommon"/> + </group> + </extension> <extension id="org.eclipse.viatra.query.runtime.cps.tests.queries.DanglingTestQueries" point="org.eclipse.viatra.query.runtime.queryspecification"> <group group="org.eclipse.viatra.query.runtime.extensibility.SingletonExtensionFactory:org.eclipse.viatra.query.runtime.cps.tests.queries.DanglingTestQueries" id="org.eclipse.viatra.query.runtime.cps.tests.queries.DanglingTestQueries"> <query-specification fqn="org.eclipse.viatra.query.runtime.cps.tests.queries.stateToState1"/> diff --git a/query/tests/org.eclipse.viatra.query.runtime.cps.tests/src/org/eclipse/viatra/query/runtime/cps/tests/CustomEMFObjectTest.xtend b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/src/org/eclipse/viatra/query/runtime/cps/tests/CustomEMFObjectTest.xtend new file mode 100644 index 000000000..4e730e988 --- /dev/null +++ b/query/tests/org.eclipse.viatra.query.runtime.cps.tests/src/org/eclipse/viatra/query/runtime/cps/tests/CustomEMFObjectTest.xtend @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2019 Geza Kulcsar, IncQuery Labs Ltd. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.viatra.query.runtime.cps.tests + +import java.io.IOException +import java.util.HashMap +import java.util.Map +import java.util.function.Function +import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EClass +import org.eclipse.emf.ecore.EObject +import org.eclipse.emf.ecore.resource.ResourceSet +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl +import org.eclipse.viatra.examples.cps.cyberPhysicalSystem.ApplicationType +import org.eclipse.viatra.examples.cps.cyberPhysicalSystem.CyberPhysicalSystemPackage +import org.eclipse.viatra.examples.cps.cyberPhysicalSystem.Identifiable +import org.eclipse.viatra.query.patternlanguage.emf.tests.pltest.Child1 +import org.eclipse.viatra.query.patternlanguage.emf.tests.pltest.PltestFactory +import org.eclipse.viatra.query.patternlanguage.emf.tests.pltest.PltestPackage +import org.eclipse.viatra.query.runtime.base.api.BaseIndexOptions +import org.eclipse.viatra.query.runtime.cps.tests.queries.util.ApplicationInstancesOfApplicationTypeQuerySpecification +import org.eclipse.viatra.query.runtime.cps.tests.queries.util.ApplicationTypesQuerySpecification +import org.eclipse.viatra.query.runtime.emf.EMFScope +import org.eclipse.viatra.query.testing.core.SnapshotHelper +import org.eclipse.viatra.query.testing.core.XmiModelUtil +import org.eclipse.viatra.query.testing.core.XmiModelUtil.XmiModelUtilRunningOptionEnum +import org.eclipse.viatra.query.testing.core.api.ViatraQueryTest +import org.eclipse.viatra.query.testing.snapshot.CustomEMFSubstitution +import org.eclipse.viatra.query.testing.snapshot.QuerySnapshot +import org.junit.Assert +import org.junit.Test + +class CustomEMFObjectTest { + + + val Map<EClass, Function<EObject,String>> customMap + + val ResourceSet rs + + val BackendType type = BackendType.Rete + + def snapshot(String snp, ResourceSet rs) { + val modelUri = XmiModelUtil::resolvePlatformURI(XmiModelUtilRunningOptionEnum.BOTH, snp) + val snr = rs.getResource(modelUri, true) + return snr.allContents.filter(QuerySnapshot).head + } + + def snapshotHelper(Map<EClass, Function<EObject,String>> customMap) { + return new SnapshotHelper(new HashMap, customMap) + } + + def EMFScope makeScope(String snp, ResourceSet rSet) { + val options = new BaseIndexOptions().withDanglingFreeAssumption(false) + val uri = XmiModelUtil::resolvePlatformURI(XmiModelUtilRunningOptionEnum.BOTH, snp) + rSet.getResource(uri , true) + return new EMFScope(rSet, options) + } + + + def QuerySnapshot loadSnapshotFromUri(ResourceSet set, URI uri) throws IOException { + val res = set.getResource(uri, true); + if (!res.loaded) { + res.load(newHashMap) + } + val snapshot = res.getContents()?.findFirst[it instanceof QuerySnapshot] + if (snapshot instanceof QuerySnapshot) { + return snapshot + } else { + throw new IOException(String.format("Resource at uri %S does not contain a query snapshot.", uri.toString())); + } + } + + new() { + + customMap = new HashMap + rs = new ResourceSetImpl + + } + + @Test + def void basicCustomTest() { + + customMap.put(CyberPhysicalSystemPackage.Literals.APPLICATION_TYPE, [at | (at as ApplicationType).identifier]) + + ViatraQueryTest.test(ApplicationTypesQuerySpecification.instance, snapshotHelper(customMap)) + .on(makeScope("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot", rs)) + .with(snapshot("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot", rs)) + .with(type.hints) + .assertEquals + } + + @Test + def void hybridPatternTest() { + + customMap.put(CyberPhysicalSystemPackage.Literals.APPLICATION_TYPE, [at | (at as ApplicationType).identifier]) + + ViatraQueryTest.test(ApplicationInstancesOfApplicationTypeQuerySpecification.instance, snapshotHelper(customMap)) + .on(makeScope("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_AIwithAT.snapshot", rs)) + .with(snapshot("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_AIwithAT.snapshot", rs)) + .with(type.hints) + .assertEquals + } + + + @Test + def void classOnlySupertypeHasCustomTest() { + + customMap.put(CyberPhysicalSystemPackage.Literals.IDENTIFIABLE, [id | "ID" + (id as Identifiable).identifier]) + + ViatraQueryTest.test(ApplicationTypesQuerySpecification.instance, snapshotHelper(customMap)) + .on(makeScope("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes_id.snapshot", rs)) + .with(snapshot("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes_id.snapshot", rs)) + .with(type.hints) + .assertEquals + } + + @Test + def void classAndSupertypeHasCustomTest() { + + customMap.put(CyberPhysicalSystemPackage.Literals.IDENTIFIABLE, [id | "ID" + (id as Identifiable).identifier]) + customMap.put(CyberPhysicalSystemPackage.Literals.APPLICATION_TYPE, [at | (at as ApplicationType).identifier]) + + ViatraQueryTest.test(ApplicationTypesQuerySpecification.instance, snapshotHelper(customMap)) + .on(makeScope("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot", rs)) + .with(snapshot("org.eclipse.viatra.query.runtime.cps.tests/models/snapshots/customemftest_apptypes.snapshot", rs)) + .with(type.hints) + .assertEquals + } + + @Test + def void grandparentHasCustomTest() { + + val child = PltestFactory.eINSTANCE.createChild1() + child.name = "Child1" + + customMap.put(PltestPackage.Literals.BASE, [ch | "BASE:" + (ch as Child1).name]) + + Assert.assertEquals((snapshotHelper(customMap).createSubstitution("Child1", child) as CustomEMFSubstitution).value, "BASE:Child1") + + } + + @Test + def void grandparentAndParentHasCustomTest() { + + val child = PltestFactory.eINSTANCE.createChild1() + child.name = "Child1" + + customMap.put(PltestPackage.Literals.BASE, [ch | "BASE:" + (ch as Child1).name]) + customMap.put(PltestPackage.Literals.COMMON, [ch | "COMMON:" + (ch as Child1).name]) + + Assert.assertEquals((snapshotHelper(customMap).createSubstitution("Child1", child) as CustomEMFSubstitution).value, "COMMON:Child1") + + } + + @Test + def void grandparentAndOtherParentHasCustomTest() { + + val child = PltestFactory.eINSTANCE.createChild1() + child.name = "Child1" + + customMap.put(PltestPackage.Literals.BASE, [ch | "BASE:" + (ch as Child1).name]) + customMap.put(PltestPackage.Literals.INTERFACE, [ch | "INTERFACE:" + (ch as Child1).name]) + + Assert.assertEquals((snapshotHelper(customMap).createSubstitution("Child1", child) as CustomEMFSubstitution).value, "INTERFACE:Child1") + + } + +}
\ No newline at end of file diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/PatternBasedMatchSetModelProvider.java b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/PatternBasedMatchSetModelProvider.java index c9dce846d..28135e1f0 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/PatternBasedMatchSetModelProvider.java +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/PatternBasedMatchSetModelProvider.java @@ -8,7 +8,6 @@ */ package org.eclipse.viatra.query.testing.core; -import java.util.HashMap; import java.util.Map; import org.eclipse.emf.ecore.resource.ResourceSet; @@ -29,13 +28,26 @@ public class PatternBasedMatchSetModelProvider implements IMatchSetModelProvider private AdvancedViatraQueryEngine engine; public PatternBasedMatchSetModelProvider(QueryEvaluationHint hint) { - this(hint, new HashMap<String, JavaObjectAccess>()); + this(hint, new SnapshotHelper()); } - + + /** + * @deprecated + * Use @link #PatternMatchSetModelProvider(QueryEvaluationHint, SnapshotHelper) instead + */ + @Deprecated public PatternBasedMatchSetModelProvider(QueryEvaluationHint engineHints, Map<String, JavaObjectAccess> accessmap) { this.engineHints = engineHints; this.helper = new SnapshotHelper(accessmap); } + + /** + * @since 2.2 + */ + public PatternBasedMatchSetModelProvider(QueryEvaluationHint engineHints, SnapshotHelper helper) { + this.engineHints = engineHints; + this.helper = helper; + } /** * Subclasses may override this method to customize engine options diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/SnapshotHelper.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/SnapshotHelper.xtend index 2794732d3..4f1db6d2f 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/SnapshotHelper.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/SnapshotHelper.xtend @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010-2012, Abel Hegedus, Istvan Rath and Daniel Varro + * Copyright (c) 2010-2019, Geza Kulcsar, Abel Hegedus, Istvan Rath and Daniel Varro * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-v20.html. @@ -40,6 +40,9 @@ import org.eclipse.viatra.query.testing.snapshot.QuerySnapshot import org.eclipse.viatra.query.testing.snapshot.SerializedJavaObjectSubstitution import org.eclipse.viatra.query.testing.snapshot.SnapshotFactory import org.eclipse.viatra.query.testing.snapshot.StringSubstitution +import org.eclipse.viatra.query.testing.snapshot.CustomEMFSubstitution +import java.util.function.Function +import org.eclipse.emf.ecore.EClass /** * Helper methods for dealing with snapshots and match set records. @@ -48,6 +51,8 @@ class SnapshotHelper { final Map<String, JavaObjectAccess> accessMap; + final Map<EClass, Function<EObject,String>> customEObjectSerializerMap; + new(){ this(Maps.newHashMap) } @@ -57,9 +62,22 @@ class SnapshotHelper { * serialization and deserialization of plain Java types. * * @since 1.6 + * + * @deprecated + * Use @link #SnapshotHelper(Map<String, JavaObjectAccess>, Map<EClass, Function<EObject,String>>) instead */ + @Deprecated new(Map<String, JavaObjectAccess> accessMap){ this.accessMap = accessMap + this.customEObjectSerializerMap = Maps.newHashMap + } + + /** + * @since 2.2 + */ + new(Map<String, JavaObjectAccess> accessMap, Map<EClass, Function<EObject,String>> customMap) { + this.accessMap = accessMap + this.customEObjectSerializerMap = customMap } /** @@ -78,6 +96,8 @@ class SnapshotHelper { MiscellaneousSubstitution: substitution.value StringSubstitution: substitution.value SerializedJavaObjectSubstitution: substitution + /* TODO we don't check if the type attributes match */ + CustomEMFSubstitution: substitution.value } } @@ -239,10 +259,25 @@ class SnapshotHelper { sub } EObject : { - val sub = SnapshotFactory::eINSTANCE.createEMFSubstitution - sub.setValue(value) - sub.setParameterName(parameterName) - sub + + var obj = getMostSpecificSerializationRule(value.eClass) + + if (obj !== null) { + + val sub = SnapshotFactory::eINSTANCE.createCustomEMFSubstitution + sub.setValue(obj.apply(value)) + sub.setType(value.eClass()) + sub.setParameterName(parameterName) + sub + + } else { + + val sub = SnapshotFactory::eINSTANCE.createEMFSubstitution + sub.setValue(value) + sub.setParameterName(parameterName) + sub + + } } Integer : { val sub = SnapshotFactory::eINSTANCE.createIntSubstitution @@ -287,9 +322,9 @@ class SnapshotHelper { sub } default : { - val access = accessMap.get(value.class.name) - if(access !== null){ - val sub = access.toSubstitution(value) + val obj = accessMap.get(value.class.name) + if(obj !== null){ + val sub = obj.toSubstitution(value) sub.parameterName = parameterName sub }else{ @@ -302,6 +337,26 @@ class SnapshotHelper { } } + private def Function<EObject,String> getMostSpecificSerializationRule(EClass cls) { + + var obj = customEObjectSerializerMap.get(cls) + + /* In case of multiple inheritance, the order of traversal is unspecified + * Keep in mind when multiple parents provide separate rules + */ + + if (obj !== null) { + return obj + } else { + for (type : cls.ESuperTypes) { + if (customEObjectSerializerMap.get(type) !== null) { return customEObjectSerializerMap.get(type) } + } + for (type : cls.ESuperTypes) { + return getMostSpecificSerializationRule(type) + } + } + } + /** * Retrieve a human-readable string denoting the given record */ diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/ViatraQueryTestCase.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/ViatraQueryTestCase.xtend index d08f5d87f..6cc31f98b 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/ViatraQueryTestCase.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/ViatraQueryTestCase.xtend @@ -9,10 +9,13 @@ package org.eclipse.viatra.query.testing.core import com.google.common.base.Joiner +import java.util.HashMap import java.util.Iterator import java.util.LinkedList import java.util.List import java.util.Map +import java.util.function.Consumer +import java.util.function.Predicate import org.apache.log4j.Level import org.eclipse.emf.common.notify.Notifier import org.eclipse.emf.common.util.URI @@ -33,9 +36,6 @@ import org.eclipse.viatra.query.testing.core.internal.DefaultMatchRecordEquivale import org.junit.Assert import org.junit.Assume import org.junit.ComparisonFailure -import com.google.common.collect.Maps -import java.util.function.Predicate -import java.util.function.Consumer /** * @author Grill Balazs @@ -52,19 +52,24 @@ class ViatraQueryTestCase { boolean isScopeSet = false final List<IMatchSetModelProvider> modelProviders - extension SnapshotHelper snapshotHelper - Map<String, JavaObjectAccess> accessMap; + final extension SnapshotHelper snapshotHelper val TestingSeverityAggregatorLogAppender appender new() { - this(Maps.newHashMap) + this(new SnapshotHelper) } new(Map<String, JavaObjectAccess> accessMap) { + this(new SnapshotHelper(accessMap, new HashMap)) + } + + /** + * @since 2.2 + */ + new(SnapshotHelper helper) { this.modelProviders = new LinkedList - this.accessMap = accessMap - this.snapshotHelper = new SnapshotHelper(accessMap) + this.snapshotHelper = helper val a = ViatraQueryLoggingUtil.getLogger(ViatraQueryEngine).getAppender( SEVERITY_AGGREGATOR_LOGAPPENDER_NAME) this.appender = if (a instanceof TestingSeverityAggregatorLogAppender) { @@ -77,6 +82,11 @@ class ViatraQueryTestCase { na } } + + def getSnapshotHelper() { + return snapshotHelper + } + def assertLogSeverityThreshold(Level severity) { if (appender.severity.toInt > severity.toInt) { @@ -167,7 +177,7 @@ class ViatraQueryTestCase { def <Match extends IPatternMatch> assertMatchSetsEqual( IQuerySpecification<? extends ViatraQueryMatcher<Match>> querySpecification) { - assertMatchSetsEqual(querySpecification, new DefaultMatchRecordEquivalence(accessMap)) + assertMatchSetsEqual(querySpecification, new DefaultMatchRecordEquivalence(snapshotHelper)) } @@ -198,7 +208,7 @@ class ViatraQueryTestCase { } def assertMatchSetsEqual(IQueryGroup queryGroup) { - assertMatchSetsEqual(queryGroup, new DefaultMatchRecordEquivalence(accessMap)) + assertMatchSetsEqual(queryGroup, new DefaultMatchRecordEquivalence(snapshotHelper)) } /** @@ -249,7 +259,7 @@ class ViatraQueryTestCase { def <Match extends IPatternMatch> getMatchSetDiff( IQuerySpecification<? extends ViatraQueryMatcher<Match>> querySpecification, IMatchSetModelProvider expectedProvider, IMatchSetModelProvider actualProvider) { - getMatchSetDiff(querySpecification, expectedProvider, actualProvider, new DefaultMatchRecordEquivalence(accessMap)) + getMatchSetDiff(querySpecification, expectedProvider, actualProvider, new DefaultMatchRecordEquivalence(snapshotHelper)) } /** diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/MatchRecordEquivalence.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/MatchRecordEquivalence.xtend index c3e98849d..942c418fb 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/MatchRecordEquivalence.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/MatchRecordEquivalence.xtend @@ -22,11 +22,24 @@ abstract class MatchRecordEquivalence extends Equivalence<MatchRecord> { protected extension SnapshotHelper helper protected Map<String, JavaObjectAccess> accessMap + /** + * @deprecated + * Use @link #MatchRecordEquivalence(SnapshotHelper) instead + */ + @Deprecated new(Map<String, JavaObjectAccess> accessMap){ this.accessMap = accessMap; helper = new SnapshotHelper(accessMap); } + /** + * @since 2.2 + */ + new(SnapshotHelper helper){ + this.accessMap = accessMap; + this.helper = helper; + } + def wrap(Iterable<MatchRecord> matches){ Sets.newHashSet(matches.map[it.wrap]) diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/ViatraQueryTest.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/ViatraQueryTest.xtend index c07593f0f..6b0c974f4 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/ViatraQueryTest.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/api/ViatraQueryTest.xtend @@ -9,14 +9,17 @@ package org.eclipse.viatra.query.testing.core.api import com.google.inject.Injector +import java.util.HashMap import java.util.LinkedList import java.util.List import java.util.Map +import java.util.function.Consumer +import java.util.function.Predicate import org.apache.log4j.Level import org.eclipse.emf.common.util.URI import org.eclipse.emf.ecore.EObject -import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternModel import org.eclipse.viatra.query.patternlanguage.emf.specification.SpecificationBuilder +import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternModel import org.eclipse.viatra.query.runtime.api.IPatternMatch import org.eclipse.viatra.query.runtime.api.IQueryGroup import org.eclipse.viatra.query.runtime.api.IQuerySpecification @@ -24,18 +27,16 @@ import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher import org.eclipse.viatra.query.runtime.emf.EMFScope import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint +import org.eclipse.viatra.query.runtime.matchers.util.Preconditions import org.eclipse.viatra.query.runtime.registry.QuerySpecificationRegistry import org.eclipse.viatra.query.testing.core.IMatchSetModelProvider import org.eclipse.viatra.query.testing.core.InitializedSnapshotMatchSetModelProvider +import org.eclipse.viatra.query.testing.core.SnapshotHelper import org.eclipse.viatra.query.testing.core.ViatraQueryTestCase import org.eclipse.viatra.query.testing.core.XmiModelUtil import org.eclipse.viatra.query.testing.core.internal.AnalyzedPatternBasedMatchSetModelProvider import org.eclipse.viatra.query.testing.core.internal.DefaultMatchRecordEquivalence import org.eclipse.viatra.query.testing.snapshot.QuerySnapshot -import java.util.function.Predicate -import java.util.function.Consumer -import java.util.HashMap -import org.eclipse.viatra.query.runtime.matchers.util.Preconditions /** * This class defines an API to easily construct test cases. The base conception is to provide @@ -45,23 +46,15 @@ import org.eclipse.viatra.query.runtime.matchers.util.Preconditions class ViatraQueryTest { val ViatraQueryTestCase testCase; - val List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> patterns = new LinkedList; - Map<String, JavaObjectAccess> accessMap; + val List<IQuerySpecification<? extends ViatraQueryMatcher<? extends IPatternMatch>>> patterns = new LinkedList val List<IPatternExecutionAnalyzer> analyzers = new LinkedList private new() { - this(new HashMap()) - } + this(new SnapshotHelper) + } - /** - * Initializes a {@link ViatraQueryTest} with a map containing {@link JavaObjectAccess} objects for - * serialization and deserialization of plain Java types. - * - * @since 1.6 - */ - private new(Map<String, JavaObjectAccess> accessMap) { - this.accessMap = accessMap - testCase = new ViatraQueryTestCase(accessMap) + private new(SnapshotHelper helper) { + testCase = new ViatraQueryTestCase(helper) } @@ -83,14 +76,29 @@ class ViatraQueryTest { * Tests the given query with the given Java object access settings. */ static def <Match extends IPatternMatch> test(IQuerySpecification<? extends ViatraQueryMatcher<Match>> pattern, Map<String, JavaObjectAccess> accessMap) { - new ViatraQueryTest(accessMap).and(pattern) + new ViatraQueryTest(new SnapshotHelper(accessMap, new HashMap)).and(pattern) + } + + /** + * Tests the given query with the given snapshot helper configuration. + */ + static def <Match extends IPatternMatch> test(IQuerySpecification<? extends ViatraQueryMatcher<Match>> pattern, SnapshotHelper helper) { + new ViatraQueryTest(helper).and(pattern) } /** * Tests every query in the given group with the given Java object access settings. */ static def test(IQueryGroup patterns, Map<String, JavaObjectAccess> accessMap) { - new ViatraQueryTest(accessMap).and(patterns) + new ViatraQueryTest(new SnapshotHelper(accessMap, new HashMap)).and(patterns) + } + + + /** + * Tests every query in the given group with the given snapshot helper configuration. + */ + static def test(IQueryGroup patterns, SnapshotHelper helper) { + new ViatraQueryTest(helper).and(patterns) } /** @@ -165,16 +173,6 @@ class ViatraQueryTest { patterns += allReferredPatterns this } - - /** - * Add Java Object Access elements - * - * @since 1.6 - */ - def withClasses(Map<String, JavaObjectAccess> accessmap) { - this.accessMap = accessmap; - this - } /** * Add an analyzer to pattern executions @@ -200,7 +198,7 @@ class ViatraQueryTest { */ def with(QueryEvaluationHint hint) { - val modelProvider = new AnalyzedPatternBasedMatchSetModelProvider(hint, accessMap, analyzers); + val modelProvider = new AnalyzedPatternBasedMatchSetModelProvider(hint, testCase.snapshotHelper, analyzers); testCase.addMatchSetModelProvider(modelProvider) this } @@ -231,6 +229,7 @@ class ViatraQueryTest { testCase.addMatchSetModelProvider(new InitializedSnapshotMatchSetModelProvider(snapshot)) this } + /** * Initialize test model using EMF Scope @@ -323,7 +322,7 @@ class ViatraQueryTest { */ def assertEquals(Level treshold) { patterns.forEach [ - testCase.assertMatchSetsEqual(it as IQuerySpecification<ViatraQueryMatcher<IPatternMatch>>, new DefaultMatchRecordEquivalence(accessMap)) + testCase.assertMatchSetsEqual(it as IQuerySpecification<ViatraQueryMatcher<IPatternMatch>>, new DefaultMatchRecordEquivalence(testCase.snapshotHelper)) ] testCase.assertLogSeverityThreshold(treshold) } diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/AnalyzedPatternBasedMatchSetModelProvider.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/AnalyzedPatternBasedMatchSetModelProvider.xtend index 2869777d5..e0d1e1611 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/AnalyzedPatternBasedMatchSetModelProvider.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/AnalyzedPatternBasedMatchSetModelProvider.xtend @@ -18,6 +18,7 @@ import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint import org.eclipse.viatra.query.testing.core.PatternBasedMatchSetModelProvider import org.eclipse.viatra.query.testing.core.api.IPatternExecutionAnalyzer import org.eclipse.viatra.query.testing.core.api.JavaObjectAccess +import org.eclipse.viatra.query.testing.core.SnapshotHelper /** * This implementation adds support to call analyzers @@ -28,11 +29,24 @@ class AnalyzedPatternBasedMatchSetModelProvider extends PatternBasedMatchSetMode final Iterable<? extends IPatternExecutionAnalyzer> analyzers; + /** + * @deprecated + * Use @link #AnalyzedPatternMatchSetModelProvider(QueryEvaluationHint, SnapshotHelper, Iterable<? extends IPatternExecutionAnalyzer>) instead + */ + @Deprecated new(QueryEvaluationHint hint, Map<String, JavaObjectAccess> accessmap, Iterable<? extends IPatternExecutionAnalyzer> analyzers) { super(hint, accessmap) this.analyzers = analyzers; } + /** + * @since 2.2 + */ + new(QueryEvaluationHint hint, SnapshotHelper helper, Iterable<? extends IPatternExecutionAnalyzer> analyzers) { + super(hint, helper) + this.analyzers = analyzers; + } + override protected getEngineOptions() { val superOptions = super.engineOptions val updatedHint = analyzers.fold(superOptions.engineDefaultHints, [r, t | t.configure(r)]) diff --git a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/DefaultMatchRecordEquivalence.xtend b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/DefaultMatchRecordEquivalence.xtend index 1f6df473b..1b1e84c09 100644 --- a/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/DefaultMatchRecordEquivalence.xtend +++ b/query/tests/org.eclipse.viatra.query.testing.core/src/org/eclipse/viatra/query/testing/core/internal/DefaultMatchRecordEquivalence.xtend @@ -17,19 +17,33 @@ import org.eclipse.viatra.query.testing.core.api.JavaObjectAccess import org.eclipse.viatra.query.testing.core.api.MatchRecordEquivalence import org.eclipse.viatra.query.testing.snapshot.MatchRecord import org.eclipse.viatra.query.testing.snapshot.SerializedJavaObjectSubstitution +import org.eclipse.viatra.query.testing.core.SnapshotHelper + /** + * TODO for CustomEMFSubstitutions, we don't check if the type attributes match * @author Peter Lunk */ class DefaultMatchRecordEquivalence extends MatchRecordEquivalence { - + /** + * @deprecated + * Use @link #DefaultMatchRecordEquivalence(SnapshotHelper) instead + */ + @Deprecated new(Map<String, JavaObjectAccess> accessMap) { super(accessMap) } + /** + * @since 2.2 + */ + new(SnapshotHelper helper) { + super(helper) + } + new() { - super(Maps.newHashMap) + super(new SnapshotHelper) } override protected boolean doEquivalent(MatchRecord a, MatchRecord b) { @@ -47,7 +61,7 @@ class DefaultMatchRecordEquivalence extends MatchRecordEquivalence { if((a as InternalEObject).eIsProxy && (b as InternalEObject).eIsProxy ){ return (a as InternalEObject).eProxyURI == (b as InternalEObject).eProxyURI } - } + } return Objects.equals(a,b) } diff --git a/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.ecore b/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.ecore index ad1ab31b5..91412b93d 100644 --- a/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.ecore +++ b/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.ecore @@ -68,4 +68,8 @@ <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> <eStructuralFeatures xsi:type="ecore:EAttribute" name="type" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="CustomEMFSubstitution" eSuperTypes="#//MatchSubstitutionRecord"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + <eStructuralFeatures xsi:type="ecore:EReference" name="type" lowerBound="1" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EClass"/> + </eClassifiers> </ecore:EPackage> diff --git a/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.genmodel b/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.genmodel index 0a6406b23..cf1ee72f6 100644 --- a/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.genmodel +++ b/query/tests/org.eclipse.viatra.query.testing.snapshot/model/snapshot.genmodel @@ -70,5 +70,9 @@ <genFeatures createChild="false" ecoreFeature="ecore:EAttribute snapshot.ecore#//SerializedJavaObjectSubstitution/value"/> <genFeatures createChild="false" ecoreFeature="ecore:EAttribute snapshot.ecore#//SerializedJavaObjectSubstitution/type"/> </genClasses> + <genClasses ecoreClass="snapshot.ecore#//CustomEMFSubstitution"> + <genFeatures createChild="false" ecoreFeature="ecore:EAttribute snapshot.ecore#//CustomEMFSubstitution/value"/> + <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference snapshot.ecore#//CustomEMFSubstitution/type"/> + </genClasses> </genPackages> </genmodel:GenModel> diff --git a/query/tests/org.eclipse.viatra.query.testing.snapshot/plugin.xml b/query/tests/org.eclipse.viatra.query.testing.snapshot/plugin.xml index bf4f12b0c..68f8ba373 100644 --- a/query/tests/org.eclipse.viatra.query.testing.snapshot/plugin.xml +++ b/query/tests/org.eclipse.viatra.query.testing.snapshot/plugin.xml @@ -5,7 +5,8 @@ <!-- @generated snapshot --> <package uri="http://www.eclipse.org/viatra/query/snapshot" - class="org.eclipse.viatra.query.testing.snapshot.SnapshotPackage"/> + class="org.eclipse.viatra.query.testing.snapshot.SnapshotPackage" + genModel="model/snapshot.genmodel"/> </extension> </plugin> |