From fd0f7ab162705b6ca1f11838c738855e7a5aad22 Mon Sep 17 00:00:00 2001
From: "Bernhard J. Berger" <bernhard.berger@uni-bremen.de>
Date: Thu, 9 Feb 2023 15:06:52 +0100
Subject: [PATCH] Now, we can finally do proper testing using Xtext parsers
 during Maven Junit run. fix #9

---
 src/core/de.evoal.core.arff/pom.xml           |  7 ++
 .../core/arff/ArffPropertiesReaderTest.java   | 10 +--
 .../evoal/core/arff/utils/LanguageUtils.java  | 61 -------------
 .../test/resources/simple/specification.ddl   | 10 +--
 src/core/de.evoal.core.junit/pom.xml          | 17 ++++
 .../evoal/core/junit/dsl/LanguageHelper.java  | 87 +++++++++++++++++++
 .../core/junit/resources}/ResourceUtils.java  |  5 +-
 .../src/main/java/module-info.java            | 28 ++++++
 src/core/de.evoal.releng.parent/pom.xml       |  1 +
 9 files changed, 150 insertions(+), 76 deletions(-)
 delete mode 100644 src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/LanguageUtils.java
 create mode 100644 src/core/de.evoal.core.junit/pom.xml
 create mode 100644 src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/dsl/LanguageHelper.java
 rename src/core/{de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils => de.evoal.core.junit/src/main/java/de/evoal/core/junit/resources}/ResourceUtils.java (91%)
 create mode 100644 src/core/de.evoal.core.junit/src/main/java/module-info.java

diff --git a/src/core/de.evoal.core.arff/pom.xml b/src/core/de.evoal.core.arff/pom.xml
index c9ab7639..e54de0a6 100644
--- a/src/core/de.evoal.core.arff/pom.xml
+++ b/src/core/de.evoal.core.arff/pom.xml
@@ -24,6 +24,13 @@
 			<artifactId>junit-jupiter</artifactId>
 		</dependency>
 
+		<dependency>
+			<groupId>de.evoal</groupId>
+			<artifactId>core.junit</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+
 		<dependency>
 			<groupId>org.eclipse.xtext</groupId>
 			<artifactId>org.eclipse.xtext.util</artifactId>
diff --git a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/ArffPropertiesReaderTest.java b/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/ArffPropertiesReaderTest.java
index 6d543b36..69c19e69 100644
--- a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/ArffPropertiesReaderTest.java
+++ b/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/ArffPropertiesReaderTest.java
@@ -6,9 +6,8 @@ import de.evoal.core.api.properties.PropertySpecification;
 import de.evoal.core.api.properties.io.PropertiesReader;
 import de.evoal.core.api.utils.EvoalIOException;
 import de.evoal.core.arff.io.ArffPropertiesReader;
-import de.evoal.core.arff.utils.LanguageUtils;
-import de.evoal.core.arff.utils.ResourceUtils;
-import de.evoal.languages.model.ddl.DataDescription;
+import de.evoal.core.junit.dsl.LanguageHelper;
+import de.evoal.core.junit.resources.ResourceUtils;
 import de.evoal.languages.model.ddl.DataDescriptionModel;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -24,10 +23,9 @@ public class ArffPropertiesReaderTest {
     public void testSimpleArff() throws EvoalIOException, IOException {
         final Path temporary = Files.createTempDirectory("evoal");
         final File temporaryFolder = temporary.toFile();
-        ResourceUtils.unpack(getClass().getClassLoader(), temporaryFolder, "simple/input.arff", "simple/specification.ddl");
+        ResourceUtils.unpack(getClass().getClassLoader(), temporaryFolder, "simple/input.arff");
 
-        final File toLoad = new File(temporaryFolder, "simple/specification.ddl");
-        final DataDescriptionModel model = LanguageUtils.load(toLoad, DataDescriptionModel.class);
+        final DataDescriptionModel model = LanguageHelper.loadFromClasspath("simple/specification.ddl");
         final PropertiesSpecification specification = toSpecification(model);
 
         final PropertiesReader testee = new ArffPropertiesReader()
diff --git a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/LanguageUtils.java b/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/LanguageUtils.java
deleted file mode 100644
index 367a2db4..00000000
--- a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/LanguageUtils.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package de.evoal.core.arff.utils;
-
-import de.evoal.languages.model.ddl.DataDescriptionModel;
-import de.evoal.languages.model.ddl.DdlPackage;
-import de.evoal.languages.model.ddl.dsl.DataDescriptionLanguageStandaloneSetup;
-import lombok.NonNull;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
-
-import java.io.File;
-import java.util.List;
-
-public class LanguageUtils {
-
-    /**
-     * Loads an EMF model and returns the model instance.
-     *
-     * @param path Path of the model to load.
-     *
-     * @return A valid reference to the model
-     *
-     * @throws Exception If there is any problem while loading the model
-     */
-    public static <T extends EObject> T load(final @NonNull File path, final Class<T> cl) {
-        loadPackages();
-        
-        final URI modelURI = URI.createFileURI(path.toString());
-        return load(modelURI, cl);
-    }
-
-    private static void loadPackages() {
-        DdlPackage.eINSTANCE.getName();
-        DataDescriptionLanguageStandaloneSetup.doSetup();
-    }
-
-    private static <T extends EObject> T load(final URI modelURI, final Class<T> cl) {
-        final ResourceSet rs = new ResourceSetImpl();
-        final Resource modelResource = rs.getResource(modelURI, true);
-
-        final List<EObject> resourceContents = modelResource.getContents();
-
-        if(resourceContents.isEmpty()) {
-            throw new RuntimeException(String.format("Resource %s is empty.", modelURI));
-        }
-
-        if(resourceContents.size() > 1) {
-            throw new RuntimeException(String.format("Resource %s has to many members.", modelURI));
-        }
-
-        final EObject root = resourceContents.get(0);
-
-        try {
-            return cl.cast(root);
-        } catch(final ClassCastException e) {
-            throw new RuntimeException("Loaded object cannot be casted to " + cl.getName(), e);
-        }
-    }
-}
diff --git a/src/core/de.evoal.core.arff/src/test/resources/simple/specification.ddl b/src/core/de.evoal.core.arff/src/test/resources/simple/specification.ddl
index 03c350f9..c41e1b63 100644
--- a/src/core/de.evoal.core.arff/src/test/resources/simple/specification.ddl
+++ b/src/core/de.evoal.core.arff/src/test/resources/simple/specification.ddl
@@ -1,6 +1,6 @@
 data:
-    cardinal real 'sepallength';
-    cardinal real 'sepalwidth';
-    cardinal real 'petallength';
-    cardinal real 'petalwidth';
-    nominal string 'class';
\ No newline at end of file
+    cardinal real data 'sepallength';
+    cardinal real data 'sepalwidth';
+    cardinal real data 'petallength';
+    cardinal real data 'petalwidth';
+    nominal string data 'class';
\ No newline at end of file
diff --git a/src/core/de.evoal.core.junit/pom.xml b/src/core/de.evoal.core.junit/pom.xml
new file mode 100644
index 00000000..759ecbe3
--- /dev/null
+++ b/src/core/de.evoal.core.junit/pom.xml
@@ -0,0 +1,17 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.evoal</groupId>
+		<artifactId>core.plugin</artifactId>
+		<version>0.9.0-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>core.junit</artifactId>
+	<name>EvoAl - Core - JUnit Helpers</name>
+
+	<dependencies>
+	</dependencies>
+</project>
diff --git a/src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/dsl/LanguageHelper.java b/src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/dsl/LanguageHelper.java
new file mode 100644
index 00000000..c54cfcc5
--- /dev/null
+++ b/src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/dsl/LanguageHelper.java
@@ -0,0 +1,87 @@
+package de.evoal.core.junit.dsl;
+
+import com.google.inject.Injector;
+import de.evoal.languages.model.ddl.DdlPackage;
+import de.evoal.languages.model.ddl.dsl.DataDescriptionLanguageStandaloneSetup;
+import de.evoal.languages.model.dl.dsl.DefinitionLanguageStandaloneSetup;
+import de.evoal.languages.model.dl.impl.DlPackageImpl;
+import de.evoal.languages.model.generator.GeneratorPackage;
+import de.evoal.languages.model.generator.dsl.GeneratorDSLStandaloneSetup;
+import de.evoal.languages.model.mll.MllPackage;
+import de.evoal.languages.model.mll.dsl.MachineLearningLanguageStandaloneSetup;
+import de.evoal.languages.model.ol.OLPackage;
+import de.evoal.languages.model.ol.dsl.OptimisationLanguageStandaloneSetup;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.xtext.ISetup;
+import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.xtext.resource.XtextResourceSet;
+
+@Slf4j
+public final class LanguageHelper {
+    private LanguageHelper() {}
+
+    public static <T extends EObject> T loadFromClasspath(final String name) {
+        initEMFandXTEXT();
+
+        if(name.endsWith(".ddl")) {
+           return loadFromClasspath(name, new DataDescriptionLanguageStandaloneSetup());
+        } else if(name.endsWith(".dl")) {
+            return loadFromClasspath(name, new DefinitionLanguageStandaloneSetup());
+        } else if(name.endsWith(".generator")) {
+            return loadFromClasspath(name, new GeneratorDSLStandaloneSetup());
+        } else if(name.endsWith(".mll")) {
+            return loadFromClasspath(name, new MachineLearningLanguageStandaloneSetup());
+        } else if(name.endsWith(".ol")) {
+            return loadFromClasspath(name, new OptimisationLanguageStandaloneSetup());
+        }
+
+        return null;
+    }
+
+    private static void initEMFandXTEXT() {
+        DdlPackage.eINSTANCE.eClass();
+        DlPackageImpl.eINSTANCE.eClass();
+        GeneratorPackage.eINSTANCE.eClass();
+        MllPackage.eINSTANCE.eClass();
+        OLPackage.eINSTANCE.eClass();
+
+        DataDescriptionLanguageStandaloneSetup.doSetup();
+        DefinitionLanguageStandaloneSetup.doSetup();
+        GeneratorDSLStandaloneSetup.doSetup();
+        MachineLearningLanguageStandaloneSetup.doSetup();
+        OptimisationLanguageStandaloneSetup.doSetup();
+    }
+
+    private static <T extends EObject> T loadFromClasspath(final String name, final ISetup setup) {
+        final Injector injector = setup.createInjectorAndDoEMFRegistration();
+        final XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
+        resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
+        resourceSet.addLoadOption(XtextResource.OPTION_ENCODING, "UTF-8");
+
+        try {
+            final URI modelURI = URI.createURI("classpath:/" + name);
+            final Resource resource = resourceSet.getResource(modelURI, true);
+            resource.load(resourceSet.getLoadOptions());
+
+            if(!resource.getErrors().isEmpty()) {
+                for(Resource.Diagnostic diagnostic : resource.getErrors()) {
+                    System.err.println("Error while processing rule '" + name + "': " + diagnostic);
+                }
+            }
+
+            if(!resource.getWarnings().isEmpty()) {
+                for(Resource.Diagnostic diagnostic : resource.getWarnings()) {
+                    System.err.println("Warning while processing rule '" + name + "': " + diagnostic);
+                }
+            }
+
+            return (T) resource.getContents().get(0);
+        } catch (final Exception e) {
+            log.error("Unable to to generator file '{}'.", name, e);
+            throw new IllegalStateException();
+        }
+    }
+}
diff --git a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/ResourceUtils.java b/src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/resources/ResourceUtils.java
similarity index 91%
rename from src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/ResourceUtils.java
rename to src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/resources/ResourceUtils.java
index aff7f2b5..4cea0a2b 100644
--- a/src/core/de.evoal.core.arff/src/test/java/de/evoal/core/arff/utils/ResourceUtils.java
+++ b/src/core/de.evoal.core.junit/src/main/java/de/evoal/core/junit/resources/ResourceUtils.java
@@ -1,6 +1,5 @@
-package de.evoal.core.arff.utils;
+package de.evoal.core.junit.resources;
 
-import org.junit.jupiter.api.io.TempDir;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -9,8 +8,6 @@ import java.io.InputStream;
 import java.nio.file.*;
 import java.io.IOException;
 import java.net.URL;
-import java.nio.file.attribute.FileAttribute;
-import java.nio.file.attribute.PosixFileAttributes;
 import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermissions;
 import java.util.Enumeration;
diff --git a/src/core/de.evoal.core.junit/src/main/java/module-info.java b/src/core/de.evoal.core.junit/src/main/java/module-info.java
new file mode 100644
index 00000000..ca0735dc
--- /dev/null
+++ b/src/core/de.evoal.core.junit/src/main/java/module-info.java
@@ -0,0 +1,28 @@
+module de.evoal.core.junit {
+    requires jakarta.inject.api;
+    requires jakarta.enterprise.cdi.api;
+
+    requires lombok;
+
+    requires org.slf4j;
+
+    requires com.google.guice;
+    requires org.eclipse.emf.common;
+    requires org.eclipse.emf.ecore;
+    requires org.eclipse.xtext;
+
+    requires de.evoal.languages.model.ddl;
+    requires de.evoal.languages.model.dl;
+    requires de.evoal.languages.model.generator;
+    requires de.evoal.languages.model.mll;
+    requires de.evoal.languages.model.ol;
+
+    requires de.evoal.languages.model.ddl.dsl;
+    requires de.evoal.languages.model.dl.dsl;
+    requires de.evoal.languages.model.generator.dsl;
+    requires de.evoal.languages.model.mll.dsl;
+    requires de.evoal.languages.model.ol.dsl;
+
+    exports de.evoal.core.junit.dsl;
+    exports de.evoal.core.junit.resources;
+}
\ No newline at end of file
diff --git a/src/core/de.evoal.releng.parent/pom.xml b/src/core/de.evoal.releng.parent/pom.xml
index 3b204f2d..c801ed45 100644
--- a/src/core/de.evoal.releng.parent/pom.xml
+++ b/src/core/de.evoal.releng.parent/pom.xml
@@ -30,6 +30,7 @@
         <module>../de.evoal.core.plugin</module>
 
         <module>../de.evoal.core.arff</module>
+        <module>../de.evoal.core.junit</module>
 
         <module>../de.evoal.generator.main</module>
 
-- 
GitLab