[578265] Add serialization test
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/META-INF/MANIFEST.MF b/tests/org.eclipse.m2m.tests.qvt.oml/META-INF/MANIFEST.MF
index 749ef04..501164d 100644
--- a/tests/org.eclipse.m2m.tests.qvt.oml/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/META-INF/MANIFEST.MF
@@ -51,7 +51,8 @@
  org.eclipse.m2m.tests.qvto.transformationProject,
  org.eclipse.m2m.qvt.oml.runtime.jdt,
  org.eclipse.jdt.core,
- org.eclipse.pde.core
+ org.eclipse.pde.core,
+ org.eclipse.jdt.launching
 Eclipse-RegisterBuddy: org.eclipse.m2m.qvt.oml
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bin/.gitignore b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bin/.gitignore
new file mode 100644
index 0000000..86d0cb2
--- /dev/null
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bin/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
\ No newline at end of file
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bug578265.qvto b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bug578265.qvto
new file mode 100644
index 0000000..da3374f
--- /dev/null
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/bug578265.qvto
@@ -0,0 +1,7 @@
+transformation bug578265();
+
+import org.eclipse.m2m.tests.qvt.oml.Bug578265_Library;
+
+main() {
+	var test : String = doEchoFromSimpleJavaLibrary("test");
+}
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/src/org/eclipse/m2m/tests/qvt/oml/Bug578265_Library.java b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/src/org/eclipse/m2m/tests/qvt/oml/Bug578265_Library.java
new file mode 100644
index 0000000..50f68a0
--- /dev/null
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/parserTestData/sources/bug578265/src/org/eclipse/m2m/tests/qvt/oml/Bug578265_Library.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Christopher Gerking and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ *     Christopher Gerking - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2m.tests.qvt.oml;
+
+public class Bug578265_Library {
+
+	public String doEchoFromSimpleJavaLibrary(String str) {
+		return str;
+	}
+
+}
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/Bug578265.java b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/Bug578265.java
new file mode 100644
index 0000000..f737265
--- /dev/null
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/Bug578265.java
@@ -0,0 +1,108 @@
+package org.eclipse.m2m.tests.qvt.oml;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
+import org.eclipse.m2m.internal.qvt.oml.compiler.ExeXMISerializer;
+import org.eclipse.m2m.internal.qvt.oml.compiler.QVTOCompiler;
+import org.eclipse.m2m.internal.qvt.oml.compiler.QvtCompilerOptions;
+import org.eclipse.m2m.internal.qvt.oml.compiler.UnitProxy;
+import org.eclipse.m2m.internal.qvt.oml.compiler.UnitResolverFactory;
+import org.eclipse.m2m.tests.qvt.oml.ParserTests.TestData;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class Bug578265 extends TestQvtParser {
+		
+	public Bug578265() {
+		super(TestData.createSourceChecked("bug578265", 0, 0)); //$NON-NLS-1$
+	}
+	
+	@Override
+	protected void prepareJava() throws CoreException {
+				
+		super.prepareJava();
+		
+		TestProject testProject = getTestProject();
+		
+		IPath destPath = new Path(getDestinationFolder().getPath());
+
+		IWorkspace workspace = testProject.getProject().getWorkspace();
+		IPath workspacePath = workspace.getRoot().getLocation();
+
+		destPath = destPath.makeRelativeTo(workspacePath).makeAbsolute();
+				
+		IPath srcPath = destPath.append("src"); //$NON-NLS-1$
+		
+		IJavaProject javaProject = JavaCore.create(testProject.getProject());
+				
+		List<IClasspathEntry> classpath = new ArrayList<IClasspathEntry>(Arrays.asList(javaProject.getRawClasspath()));
+				
+		if (workspace.getRoot().exists(srcPath)) {		
+			IClasspathAttribute testAttribute = JavaCore.newClasspathAttribute(IClasspathAttribute.TEST, Boolean.toString(true));
+			classpath.add(JavaCore.newSourceEntry(srcPath, new IPath[] {}, new IPath[] {}, null, new IClasspathAttribute[] {testAttribute}));
+		}
+		
+		IClasspathEntry[] entries = classpath.toArray(new IClasspathEntry[classpath.size()]);
+		
+		javaProject.setRawClasspath(entries, new NullProgressMonitor());
+	}
+	
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		
+		TestProject testProject = getTestProject();
+		
+		testProject.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+		
+	    IMarker[] markers = testProject.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
+	    for (IMarker marker : markers) {
+	    	String message = marker.getAttribute(IMarker.MESSAGE).toString();
+	    	Integer severity = (Integer) marker.getAttribute(IMarker.SEVERITY);
+	    	assertTrue(message, severity < IMarker.SEVERITY_ERROR);
+	    }
+	}
+		
+	@Override
+	public void runTest() throws Exception {
+				
+		super.runTest();
+				
+		CompiledUnit[] compiledUnits = getCompiledResults();
+		ExeXMISerializer.saveUnitXMI(compiledUnits, EPackage.Registry.INSTANCE);
+		
+		QVTOCompiler compiler = new QVTOCompiler();
+		compiler.setUseCompiledXMI(true);
+		
+		for(CompiledUnit unit : compiledUnits) {
+			URI xmiUri = ExeXMISerializer.toXMIUnitURI(unit.getURI());
+			UnitProxy proxy = UnitResolverFactory.Registry.INSTANCE.getUnit(xmiUri);
+			compiler.compile(new UnitProxy[] {proxy}, new QvtCompilerOptions(), new NullProgressMonitor());
+			
+			Resource r = compiler.getResourceSet().getResource(xmiUri, true);
+			EcoreUtil.resolveAll(r);
+			assertTrue(r.getErrors().isEmpty());
+		}		
+	}
+}
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/ParserTests.java b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/ParserTests.java
index ec17203..a020c02 100644
--- a/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/ParserTests.java
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/ParserTests.java
@@ -22,7 +22,7 @@
 import org.junit.runners.Suite.SuiteClasses;
 
 @RunWith(Suite.class)
-@SuiteClasses({QvtLibraryASTTest.class, TestQvtParser.class, Bug577992.class})
+@SuiteClasses({QvtLibraryASTTest.class, TestQvtParser.class, Bug577992.class, Bug578265.class})
 public class ParserTests {
     
     static class TestData {
diff --git a/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/TestQvtParser.java b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/TestQvtParser.java
index 099c9d9..b65a1fc 100644
--- a/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/TestQvtParser.java
+++ b/tests/org.eclipse.m2m.tests.qvt.oml/src/org/eclipse/m2m/tests/qvt/oml/TestQvtParser.java
@@ -44,12 +44,20 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.plugin.EcorePlugin;
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaConventions;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.JavaRuntime;
 import org.eclipse.m2m.internal.qvt.oml.QvtMessage;
 import org.eclipse.m2m.internal.qvt.oml.blackbox.BlackboxRegistry;
 import org.eclipse.m2m.internal.qvt.oml.common.MDAConstants;
@@ -70,6 +78,7 @@
 import org.eclipse.pde.core.plugin.IPluginExtension;
 import org.eclipse.pde.core.plugin.IPluginImport;
 import org.eclipse.pde.core.project.IBundleProjectDescription;
+import org.eclipse.pde.internal.core.ClasspathComputer;
 import org.eclipse.pde.internal.core.bundle.WorkspaceBundlePluginModel;
 import org.eclipse.pde.internal.core.plugin.WorkspacePluginModelBase;
 import org.eclipse.pde.internal.core.project.PDEProject;
@@ -275,6 +284,24 @@
 		if(myProject == null) {
 			myProject = new TestProject(name, new String[] {}, 0);
 		}
+		
+		copyData("sources/" + myData.getDir(), "parserTestData/sources/" + myData.getDir()); //$NON-NLS-1$ //$NON-NLS-2$
+		
+		prepareJava();
+
+		final File folder = getDestinationFolder();
+		assertTrue("Invalid folder " + folder, folder.exists() && folder.isDirectory()); //$NON-NLS-1$
+
+		resSet = TestUtil.getMetamodelResolutionRS(new ResourceSetImpl(), myData.getMetamodels(), new TestUtil.UriProvider() {
+
+			@Override
+			public URI getModelUri(String model) {
+				String absolutePath = getFile(folder, model).getAbsolutePath();
+				return URI.createFileURI(absolutePath);
+			}
+		});
+
+		setupPluginXml();
 	}
 
 	@Override
@@ -290,10 +317,12 @@
 
 		IJavaProject javaProject = JavaCore.create(myProject.getProject());
 		if (javaProject.exists()) {
-			javaProject.setOutputLocation(javaProject.getPath().append("bin"), new NullProgressMonitor());
+			IProgressMonitor monitor = new NullProgressMonitor();
+			javaProject.setRawClasspath(null, monitor);
+			javaProject.setOutputLocation(javaProject.getPath().append("bin"), monitor); //$NON-NLS-1$
 			IProjectDescription desc = myProject.getProject().getDescription();
 			NatureUtils.removeNature(desc, JavaCore.NATURE_ID);
-			myProject.getProject().setDescription(desc, new NullProgressMonitor());
+			myProject.getProject().setDescription(desc, monitor);
 		}
 		
 		IFile pluginXml = PDEProject.getPluginXml(myProject.getProject());
@@ -310,24 +339,8 @@
 	@Override
 	@Test
 	public void runTest() throws Exception {
-		copyData("sources/" + myData.getDir(), "parserTestData/sources/" + myData.getDir()); //$NON-NLS-1$ //$NON-NLS-2$
-
-		prepareJava();
-
-		final File folder = getDestinationFolder();
-		assertTrue("Invalid folder " + folder, folder.exists() && folder.isDirectory()); //$NON-NLS-1$
-
-		resSet = TestUtil.getMetamodelResolutionRS(new ResourceSetImpl(), myData.getMetamodels(), new TestUtil.UriProvider() {
-
-			@Override
-			public URI getModelUri(String model) {
-				String absolutePath = getFile(folder, model).getAbsolutePath();
-				return URI.createFileURI(absolutePath);
-			}
-		});
-
-		setupPluginXml();
-
+		File folder = getDestinationFolder();
+		
 		myCompiled = compile(folder);
 
 		assertTrue("No results", myCompiled.length > 0); //$NON-NLS-1$
@@ -387,13 +400,14 @@
 
 			IPluginBase pluginBase = pluginModel.getPluginBase();
 			pluginBase.setId(myProject.getProject().getName());
+			pluginBase.setVersion(Platform.getBundle(AllTests.BUNDLE_ID).getVersion().toString());
 
 			IPluginExtension pluginExtension = pluginModel.createExtension();
-			pluginExtension.setPoint("org.eclipse.emf.ecore.generated_package");
+			pluginExtension.setPoint(EcorePackage.eCONTENT_TYPE + "." + EcorePlugin.GENERATED_PACKAGE_PPID); //$NON-NLS-1$
 
 			for (URI metamodelUri : myData.getMetamodels()) {
 				String metamodelFileName = metamodelUri.trimFileExtension().lastSegment();
-				URI genmodelUri = metamodelUri.trimSegments(1).appendSegment(metamodelFileName).appendFileExtension("genmodel");
+				URI genmodelUri = metamodelUri.trimSegments(1).appendSegment(metamodelFileName).appendFileExtension(GenModelPackage.eNAME);
 				IPath genmodelPath = relativePath.append(genmodelUri.toString());
 
 				if (workspace.getRoot().exists(genmodelPath)) {
@@ -519,7 +533,7 @@
 		myProject.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
 	}
 
-	private void prepareJava() throws CoreException {
+	protected void prepareJava() throws CoreException {
 		IPath destPath = new Path(getDestinationFolder().getPath());
 
 		IWorkspace workspace = myProject.getProject().getWorkspace();
@@ -533,16 +547,26 @@
 			IProjectDescription desc = myProject.getProject().getDescription();
 
 			NatureUtils.addNature(desc, JavaCore.NATURE_ID);
-
-			myProject.getProject().setDescription(desc,
-					new NullProgressMonitor());
+			
+			IProgressMonitor monitor = new NullProgressMonitor();
+			
+			myProject.getProject().setDescription(desc, monitor);
 
 			IJavaProject javaProject = JavaCore.create(myProject.getProject());
-
-			if (workspace.getRoot().exists(binPath)) {
-				javaProject.setOutputLocation(binPath,
-						new NullProgressMonitor());
-			}
+			
+			javaProject.setOutputLocation(binPath, monitor);
+			
+			List<IClasspathEntry> classpath = new ArrayList<IClasspathEntry>(2);
+			
+			classpath.add(JavaRuntime.getDefaultJREContainerEntry());				
+			classpath.add(ClasspathComputer.createContainerEntry());
+						
+			IClasspathEntry[] entries = classpath.toArray(new IClasspathEntry[classpath.size()]);
+			
+			assertFalse(javaProject.hasClasspathCycle(entries));
+			IJavaModelStatus status = JavaConventions.validateClasspath(javaProject, entries, binPath);
+			assertTrue(status.isOK());
+			javaProject.setRawClasspath(entries, monitor);
 		}
 	}