| package org.eclipse.acceleo.tests.evaluation; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.acceleo.Module; |
| import org.eclipse.acceleo.ModuleElement; |
| import org.eclipse.acceleo.Template; |
| import org.eclipse.acceleo.aql.AcceleoEnvironment; |
| import org.eclipse.acceleo.aql.evaluation.AcceleoEvaluator; |
| import org.eclipse.acceleo.aql.evaluation.writer.DefaultGenerationStrategy; |
| import org.eclipse.acceleo.aql.parser.AcceleoParser; |
| import org.eclipse.acceleo.query.runtime.IQueryEnvironment; |
| import org.eclipse.acceleo.query.runtime.Query; |
| import org.eclipse.acceleo.tests.utils.AbstractLanguageTestSuite; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| /** |
| * This will test the template lookup through various scenarios involving imports and extends. |
| * |
| * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> |
| */ |
| public class TemplateLookupTest { |
| /** Name of the first parameter on all of our templates. */ |
| private static final String PARAM1 = "param1"; |
| |
| /** The aql environment used to read and parse the modules from disk. */ |
| private IQueryEnvironment aqlEnvironment; |
| |
| /** The Acceleo environment we'll use to test the lookup. */ |
| private AcceleoEnvironment acceleoEnvironment; |
| |
| /** First of the tested modules. See M1 through M4.acceleo beside this class. */ |
| private Module module1; |
| |
| /** Second of the tested modules. See M1 through M4.acceleo beside this class. */ |
| private Module module2; |
| |
| /** Third of the tested modules. See M1 through M4.acceleo beside this class. */ |
| private Module module3; |
| |
| /** Fourth of the tested modules. See M1 through M4.acceleo beside this class. */ |
| private Module module4; |
| |
| /** |
| * Prepares the environment. This will load the 4 modules and register them against a new environment |
| * before each test. |
| * |
| * @throws IOException |
| * If we couldn't read the modules from disk. |
| */ |
| @Before |
| public void loadModules() throws IOException { |
| aqlEnvironment = Query.newEnvironmentWithDefaultServices(null); |
| module1 = readModule(aqlEnvironment, "/org/eclipse/acceleo/tests/evaluation/M1.acceleo"); |
| module2 = readModule(aqlEnvironment, "/org/eclipse/acceleo/tests/evaluation/M2.acceleo"); |
| module3 = readModule(aqlEnvironment, "/org/eclipse/acceleo/tests/evaluation/M3.acceleo"); |
| module4 = readModule(aqlEnvironment, "/org/eclipse/acceleo/tests/evaluation/M4.acceleo"); |
| |
| acceleoEnvironment = new AcceleoEnvironment(new DefaultGenerationStrategy(), URI.createURI("")); |
| acceleoEnvironment.registerModule("org::eclipse::acceleo::aql::tests::evaluation::m1", module1); |
| acceleoEnvironment.registerModule("org::eclipse::acceleo::aql::tests::evaluation::m2", module2); |
| acceleoEnvironment.registerModule("org::eclipse::acceleo::aql::tests::evaluation::m3", module3); |
| acceleoEnvironment.registerModule("org::eclipse::acceleo::aql::tests::evaluation::m4", module4); |
| } |
| |
| /** |
| * Calls "M1.t11(EPackage)". This doesn't call any other module's templates. |
| */ |
| @Test |
| public void testCallM1T11EPackage() { |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, EcoreFactory.eINSTANCE.createEPackage()); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| final ModuleElement start = module1.getModuleElements().get(0); |
| assertTrue(start instanceof Template && "t11".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module1), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m1.t11(EPackage)" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, |
| result); |
| assertNull(acceleoEnvironment.getCurrentStack()); |
| } |
| |
| /** |
| * Calls "M1.t11(EClass)". This calls two other templates that should be found in the same module. |
| */ |
| @Test |
| public void testCallM1T11EClass() { |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, EcoreFactory.eINSTANCE.createEClass()); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| final ModuleElement start = module1.getModuleElements().get(1); |
| assertTrue(start instanceof Template && "t11".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module1), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m1.overrideMe(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m1.privateInBoth(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, result); |
| assertNull(acceleoEnvironment.getCurrentStack()); |
| } |
| |
| /** |
| * M2.t21 calls "t11" which is not overriden in M2, so goes up to M1.t11, which calls "overrideMe", |
| * overriden in M2 so we go down to M2.overrideMe, and "privateInBoth" which should call the one in M1 at |
| * that point in the stack. |
| */ |
| @Test |
| public void testCallM2T21() { |
| EPackage pack = EcoreFactory.eINSTANCE.createEPackage(); |
| EClass clazz = EcoreFactory.eINSTANCE.createEClass(); |
| pack.getEClassifiers().add(clazz); |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, pack); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| ModuleElement start = module2.getModuleElements().get(0); |
| assertTrue(start instanceof Template && "t21".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module2), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m2.t21(EPackage)" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| // CHECKSTYLE:OFF don't share values across tests |
| + "generated from m2.overrideMe(EClass)" |
| // CHECKSTYLE:ON don't share values across tests |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m1.privateInBoth(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, result); |
| } |
| |
| /** |
| * Calls M2.overrideMe(), which is overriden in M1 but M1 is not in the scope, so we're not going to call |
| * anything in other modules. |
| */ |
| @Test |
| public void testCallM2OverrideMe() { |
| EPackage pack = EcoreFactory.eINSTANCE.createEPackage(); |
| EClass clazz = EcoreFactory.eINSTANCE.createEClass(); |
| pack.getEClassifiers().add(clazz); |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, pack); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| ModuleElement start = module2.getModuleElements().get(1); |
| assertTrue(start instanceof Template && "overrideMe".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module2), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m2.overrideMe(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, result); |
| } |
| |
| /** |
| * We're calling M2.toImportsAndBack as a starting point. This will call m4.t41 that's accessible through |
| * the import of m2. This then tries to call "t31" which is available on m3 through the extends of m4, |
| * which in turns tries to call "overrideMe". This is available on both m3 (the current template) and m4 |
| * (the one we were called from), we'll thus call m4.overrideMe since it's the one doing the overriding. |
| * m4.overrideMe, m3.t31 and m4.t41 don't have more statements to evaluate, so we go back to |
| * m2.toImportsAndBack, which will call "overrideMe" on his own. We're no longer in the import's |
| * hierarchy, so this is expected to call m2.overrideMe. |
| */ |
| @Test |
| public void testCallM2ToImportsAndBack() { |
| EPackage pack = EcoreFactory.eINSTANCE.createEPackage(); |
| EClass clazz = EcoreFactory.eINSTANCE.createEClass(); |
| pack.getEClassifiers().add(clazz); |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, clazz); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| ModuleElement start = module2.getModuleElements().get(3); |
| assertTrue(start instanceof Template && "toImportsAndBack".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module2), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER + "generated from m4.t41(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER + "generated from m3.t31(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m4.overrideMe(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m2.overrideMe(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, result); |
| } |
| |
| /** |
| * We're calling m2.toImportsExtends as a starting point. this tries to call "t31" which is not available |
| * in our hierarchy, not available on the import, but available on the import's extends hierarchy, on m3. |
| * We thus call m3.t31 which calls "overrideMe". Since m3 is not the one which was imported, we expect |
| * that "overrideMe" to be the one from m4. |
| */ |
| @Test |
| public void testCallM2ToImportsExtends() { |
| EPackage pack = EcoreFactory.eINSTANCE.createEPackage(); |
| EClass clazz = EcoreFactory.eINSTANCE.createEClass(); |
| pack.getEClassifiers().add(clazz); |
| final Map<String, Object> variables = new HashMap<String, Object>(); |
| variables.put(PARAM1, clazz); |
| |
| final AcceleoEvaluator evaluationEngine = new AcceleoEvaluator(acceleoEnvironment); |
| ModuleElement start = module2.getModuleElements().get(4); |
| assertTrue(start instanceof Template && "toImportsExtends".equals(((Template)start).getName())); |
| acceleoEnvironment.pushImport(acceleoEnvironment.getModuleQualifiedName(module2), start); |
| |
| final String result = (String)evaluationEngine.generate(start, variables); |
| |
| assertEquals("" + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER + "generated from m3.t31(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + "generated from m4.overrideMe(EClass)" |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER |
| + AbstractLanguageTestSuite.DEFAULT_END_OF_LINE_CHARACTER, result); |
| } |
| |
| /** |
| * Reads a module from disk, parses it and returns the AST. |
| * |
| * @param env |
| * The AQL environment with which to parse this module. |
| * @param name |
| * Name of the module file to read. This can be a path relative to this current class. |
| * @return The parsed AST. |
| * @throws IOException |
| * if we couldn't read the file from disk. |
| */ |
| private Module readModule(IQueryEnvironment env, String name) throws IOException { |
| AcceleoParser parser = new AcceleoParser(env); |
| InputStream content = getClass().getResourceAsStream(name); |
| try (InputStream stream = (InputStream)content) { |
| String moduleSource = AbstractLanguageTestSuite.getContent(stream, "UTF-8"); |
| return parser.parse(moduleSource).getModule(); |
| } |
| } |
| } |