/
EdeltaAbstractTest.xtend
322 lines (272 loc) · 10.2 KB
/
EdeltaAbstractTest.xtend
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
package edelta.tests
import com.google.inject.Inject
import com.google.inject.Provider
import edelta.edelta.EdeltaEcoreDirectReference
import edelta.edelta.EdeltaEcoreQualifiedReference
import edelta.edelta.EdeltaEcoreReferenceExpression
import edelta.edelta.EdeltaModifyEcoreOperation
import edelta.edelta.EdeltaProgram
import edelta.interpreter.IEdeltaInterpreter
import edelta.resource.EdeltaDerivedStateEPackage
import edelta.tests.input.Inputs
import java.nio.file.Paths
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.EAttribute
import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EClassifier
import org.eclipse.emf.ecore.EEnum
import org.eclipse.emf.ecore.ENamedElement
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EPackage
import org.eclipse.emf.ecore.EcoreFactory
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.emf.ecore.xmi.XMIResource
import org.eclipse.xtext.common.types.JvmGenericType
import org.eclipse.xtext.diagnostics.Severity
import org.eclipse.xtext.resource.XtextResourceSet
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.testing.util.ParseHelper
import org.eclipse.xtext.testing.validation.ValidationTestHelper
import org.eclipse.xtext.xbase.XBlockExpression
import org.eclipse.xtext.xbase.XExpression
import org.eclipse.xtext.xbase.XVariableDeclaration
import org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationResult
import org.eclipse.xtext.xbase.jvmmodel.IJvmModelAssociations
import org.junit.runner.RunWith
import static extension org.junit.Assert.*
@RunWith(XtextRunner)
@InjectWith(EdeltaInjectorProvider)
abstract class EdeltaAbstractTest {
@Inject
Provider<XtextResourceSet> resourceSetProvider
@Inject protected extension ParseHelper<EdeltaProgram>
@Inject protected extension ValidationTestHelper
@Inject extension IJvmModelAssociations
protected extension Inputs = new Inputs
protected static String ECORE_PATH = "src/edelta/tests/input/models/EcoreForTests.ecore"
protected static String PERSON_LIST_ECORE = "PersonList.ecore"
protected static String PERSON_LIST_ECORE_PATH = "src/edelta/tests/input/models/" + PERSON_LIST_ECORE
def protected parseWithTestEcore(CharSequence input) {
input.parse(resourceSetWithTestEcore)
}
def protected parseWithTestEcores(CharSequence input) {
input.parse(resourceSetWithTestEcores)
}
def protected parseWithLoadedEcore(String path, CharSequence input) {
val resourceSet = resourceSetProvider.get
// Loads the Ecore package to ensure it is available during loading.
resourceSet.getResource(createFileURIFromPath(ECORE_PATH), true)
val uri = createFileURIFromPath(path);
resourceSet.getResource(uri, true);
val prog = input.parse(resourceSet)
return prog
}
protected def URI createFileURIFromPath(String path) {
URI.createFileURI(
Paths.get(path).toAbsolutePath().toString())
}
def protected resourceSetWithTestEcore() {
val resourceSet = resourceSetProvider.get
addEPackageForTests(resourceSet)
}
def protected addEPackageForTests(ResourceSet resourceSet) {
resourceSet.createTestResource("foo", EPackageForTests)
}
def protected resourceSetWithTestEcores() {
val resourceSet = resourceSetWithTestEcore
addEPackageForTests2(resourceSet)
}
def protected addEPackageForTests2(ResourceSet resourceSet) {
resourceSet.createTestResource("bar.", EPackageForTests2)
}
def protected createTestResource(ResourceSet resourceSet, String ecoreName, EPackage epackage) {
val resource = resourceSet.createResource(URI.createURI(ecoreName + ".ecore"))
resource.contents += epackage
resourceSet
}
def protected EPackageForTests() {
// if you add something to this ecore, which is created on the fly,
// and you have a test for the generated Java code, then you must also
// update testecores/foo.ecore accordingly
val fooPackage = EcoreFactory.eINSTANCE.createEPackage => [
name = "foo"
nsPrefix = "foo"
nsURI = "http://foo"
]
fooPackage.EClassifiers += EcoreFactory.eINSTANCE.createEClass => [
name = "FooClass"
EStructuralFeatures += EcoreFactory.eINSTANCE.createEAttribute => [
name = "myAttribute"
]
EStructuralFeatures += EcoreFactory.eINSTANCE.createEReference => [
name = "myReference"
]
]
fooPackage.EClassifiers += EcoreFactory.eINSTANCE.createEDataType => [
name = "FooDataType"
]
fooPackage.EClassifiers += EcoreFactory.eINSTANCE.createEEnum => [
name = "FooEnum"
ELiterals += EcoreFactory.eINSTANCE.createEEnumLiteral => [
name = "FooEnumLiteral"
]
]
fooPackage
}
def protected EPackageForTests2() {
val fooPackage = EcoreFactory.eINSTANCE.createEPackage => [
name = "bar"
nsPrefix = "bar"
nsURI = "http://bar"
]
fooPackage.EClassifiers += EcoreFactory.eINSTANCE.createEClass => [
name = "BarClass"
EStructuralFeatures += EcoreFactory.eINSTANCE.createEAttribute => [
name = "myAttribute"
]
EStructuralFeatures += EcoreFactory.eINSTANCE.createEReference => [
name = "myReference"
]
]
fooPackage.EClassifiers += EcoreFactory.eINSTANCE.createEDataType => [
name = "BarDataType"
]
fooPackage
}
def protected assertErrorsAsStrings(EObject o, CharSequence expected) {
expected.toString.trim.assertEqualsStrings(
o.validate.filter[severity == Severity.ERROR].
map[message].sort.join("\n"))
}
def protected assertEqualsStrings(CharSequence expected, CharSequence actual) {
expected.toString.replaceAll("\r", "").
assertEquals(actual.toString.replaceAll("\r", ""))
}
def protected assertNamedElements(Iterable<? extends ENamedElement> elements, CharSequence expected) {
expected.assertEqualsStrings(
elements.map[name].join("\n") + "\n"
)
}
def protected assertAfterInterpretationOfEdeltaModifyEcoreOperation(
IEdeltaInterpreter interpreter, EdeltaProgram program,
boolean doValidate, (EPackage)=>void testExecutor
) {
program.lastModifyEcoreOperation => [
// mimic the behavior of derived state computer that runs the interpreter
// on a copied EPackage, not on the original one
val packages = program.getCopiedEPackages.toList
val packageName = it.epackage.name
val epackage = packages.findFirst[name == packageName]
val inferredJavaClass = program.jvmElements.filter(JvmGenericType).head
val result = interpreter.run(it, epackage, inferredJavaClass, packages)
// result can be null due to a timeout
if (result?.exception !== null)
throw result.exception
testExecutor.apply(epackage)
if (result !== null)
assertTrue(
"not expected result of type " + result.class.name,
result instanceof DefaultEvaluationResult
)
]
}
def protected getEPackageByName(EdeltaProgram context, String packagename) {
context.eResource.resourceSet.resources.filter(XMIResource).
map[contents.head as EPackage].findFirst[name == packagename]
}
def protected getEClassifierByName(EdeltaProgram context, String packagename, String classifiername) {
getEPackageByName(context, packagename).EClassifiers.
findFirst[name == classifiername]
}
def protected lastModifyEcoreOperation(EdeltaProgram p) {
p.modifyEcoreOperations.last
}
def protected getDerivedStateLastEClass(EObject context) {
val derivedEPackage = getDerivedStateLastEPackage(context)
derivedEPackage.EClassifiers.last as EClass
}
protected def EdeltaDerivedStateEPackage getDerivedStateLastEPackage(EObject context) {
context.eResource.contents.last as EdeltaDerivedStateEPackage
}
def protected getLastCopiedEPackageLastEClass(EObject context) {
val copiedEPackage = getLastCopiedEPackage(context)
copiedEPackage.EClassifiers.last as EClass
}
def protected getLastCopiedEPackageFirstEClass(EObject context) {
val copiedEPackage = getLastCopiedEPackage(context)
copiedEPackage.EClassifiers.head as EClass
}
def protected getLastCopiedEPackageFirstEClass(EObject context, String nameToSearch) {
val p = getLastCopiedEPackage(context)
p.EClassifiers.findFirst[name == nameToSearch] as EClass
}
def protected getLastCopiedEPackage(EObject context) {
getCopiedEPackages(context).last
}
def protected getCopiedEPackages(EObject context) {
context.eResource.contents.filter(EPackage).filter[!(it instanceof EdeltaDerivedStateEPackage)]
}
def protected getEClassiferByName(EPackage p, String nameToSearch) {
p.EClassifiers.findFirst[name == nameToSearch]
}
def protected getEStructuralFeatureByName(EClassifier e, String nameToSearch) {
(e as EClass).EStructuralFeatures.findFirst[name == nameToSearch]
}
def protected getEAttributeByName(EClassifier e, String nameToSearch) {
(e as EClass).EStructuralFeatures.
filter(EAttribute).findFirst[name == nameToSearch]
}
def protected getEEnumLiteralByName(EClassifier e, String nameToSearch) {
(e as EEnum).ELiterals.findFirst[name == nameToSearch]
}
def protected getEdeltaEcoreReferenceExpression(XExpression e) {
e as EdeltaEcoreReferenceExpression
}
def protected getEdeltaEcoreDirectReference(EObject e) {
e as EdeltaEcoreDirectReference
}
def protected getEdeltaEcoreQualifiedReference(EObject e) {
e as EdeltaEcoreQualifiedReference
}
def protected getBlockLastExpression(XExpression e) {
(e as XBlockExpression).expressions.last
}
def protected getBlock(XExpression e) {
e as XBlockExpression
}
def protected getVariableDeclaration(XExpression e) {
e as XVariableDeclaration
}
def protected getModifyEcoreOperation(XExpression e) {
e as EdeltaModifyEcoreOperation
}
protected def EClass getLastEClass(EPackage ePackage) {
ePackage.EClassifiers.last as EClass
}
protected def EClass getFirstEClass(EPackage ePackage) {
ePackage.EClassifiers.head as EClass
}
def protected ecoreReferenceExpression(CharSequence ecoreRefString) {
ecoreRefString
.parseInsideModifyEcoreWithTestMetamodelFoo
.lastEcoreReferenceExpression
}
def protected parseInsideModifyEcoreWithTestMetamodelFoo(CharSequence body) {
body
.inputInsideModifyEcoreWithTestMetamodelFoo
.parseWithTestEcore
}
def protected inputInsideModifyEcoreWithTestMetamodelFoo(CharSequence body) {
'''
metamodel "foo"
modifyEcore aTest epackage foo {
«body»
}
'''
}
def protected lastEcoreReferenceExpression(EdeltaProgram p) {
p.lastModifyEcoreOperation.body
.blockLastExpression as EdeltaEcoreReferenceExpression
}
}