/** * Copyright (C) 2009 STMicroelectronics * Copyright (C) 2013 Schneider-Electric * * This file is part of "Mind Compiler" is free software: you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact: mind@ow2.org * * Authors: Matthieu Leclercq * Contributors: Stephane Seyvoz */ package org.ow2.mind.preproc; import static org.ow2.mind.compilation.DirectiveHelper.splitOptionString; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.Definition; import org.objectweb.fractal.adl.Loader; import org.objectweb.fractal.adl.error.Error; import org.ow2.mind.CommonBackendModule; import org.ow2.mind.CommonFrontendModule; import org.ow2.mind.adl.ADLFrontendModule; import org.ow2.mind.compilation.BasicCompilationCommandExecutor; import org.ow2.mind.compilation.CompilationCommand; import org.ow2.mind.compilation.CompilationCommandExecutor; import org.ow2.mind.compilation.CompilerCommand; import org.ow2.mind.compilation.CompilerWrapper; import org.ow2.mind.compilation.PreprocessorCommand; import org.ow2.mind.error.ErrorCollection; import org.ow2.mind.error.ErrorManager; import org.ow2.mind.idl.IDLFrontendModule; import org.ow2.mind.io.BasicOutputFileLocator; import org.ow2.mind.plugin.PluginLoaderModule; import org.testng.annotations.BeforeTest; import com.google.inject.Guice; import com.google.inject.Injector; public class AbstractTestMPP { protected static final String DEFAULT_CPPFLAGS = "-g -Wall -Wredundant-decls -Wunreachable-code"; protected ErrorManager errorManager; protected MPPWrapper mppWrapper; protected CompilerWrapper compilerWrapper; protected CompilationCommandExecutor executor; protected Loader adlLoader; protected Map<Object, Object> context; protected File buildDir; protected List<String> cppFlags; protected List<String> cFlags; @BeforeTest(alwaysRun = true) public void setUp() { final Injector injector = Guice.createInjector(new ADLFrontendModule(), new IDLFrontendModule(), new CommonFrontendModule(), new PluginLoaderModule(), new CommonBackendModule(), new MPPModule()); errorManager = injector.getInstance(ErrorManager.class); mppWrapper = injector.getInstance(MPPWrapper.class); compilerWrapper = injector.getInstance(CompilerWrapper.class); executor = injector.getInstance(CompilationCommandExecutor.class); adlLoader = injector.getInstance(Loader.class); context = new HashMap<Object, Object>(); final String buildDirName = "target" + File.separator + "build"; buildDir = new File(buildDirName); if (!buildDir.exists()) { buildDir.mkdirs(); } context.put(BasicOutputFileLocator.OUTPUT_DIR_CONTEXT_KEY, buildDir); context.put(BasicCompilationCommandExecutor.FAIL_FAST_CONTEXT_KEY, Boolean.TRUE); cppFlags = splitOptionString(DEFAULT_CPPFLAGS); } // --------------------------------------------------------------------------- // Helper methods // --------------------------------------------------------------------------- protected File locateCFile(final String dirName, final String fileName) throws Exception { final String name = dirName + "/" + fileName + ".c"; final URL url = getClass().getClassLoader().getResource(name); if (url == null) throw new Exception("Can't find file " + name); return new File(url.toURI()); } protected File newBuildFile(final String dirName, final String fileName, final String ext) { final File file = new File(buildDir, dirName + File.separator + fileName + ext); file.getParentFile().mkdirs(); return file; } protected PreprocessorCommand newCPPCommand(final String dirName, final String fileName) throws Exception { final File cInputFile = locateCFile(dirName, fileName); final PreprocessorCommand command = compilerWrapper .newPreprocessorCommand(context); command.setInputFile(cInputFile); command.setOutputFile(newBuildFile(dirName, fileName, ".i")); command.addFlags(cppFlags); return command; } protected MPPCommand newMPPCommand(final String dirName, final String fileName, final boolean singleton) { final MPPCommand command = mppWrapper.newMPPCommand(null, context); command.setInputFile(newBuildFile(dirName, fileName, ".i")); command.setOutputFile(newBuildFile(dirName, fileName, singleton ? ".singleton-mpp.c" : ".multi-mpp.c")); if (singleton) command.setSingletonMode(); return command; } protected MPPCommand newMPPCommandForDef(final String dirName, final String fileName, final Definition hostDefinition, final boolean singleton) { final MPPCommand command = mppWrapper .newMPPCommand(hostDefinition, context); command.setInputFile(newBuildFile(dirName, fileName, ".i")); command.setOutputFile(newBuildFile(dirName, fileName, singleton ? ".singleton-mpp.c" : ".multi-mpp.c")); if (singleton) command.setSingletonMode(); return command; } protected CompilerCommand newGCCCommand(final String dirName, final String fileName, final boolean singleton) throws Exception { final CompilerCommand command = compilerWrapper.newCompilerCommand(context); command.setInputFile(newBuildFile(dirName, fileName, singleton ? ".singleton-mpp.c" : ".multi-mpp.c")); command.setOutputFile(newBuildFile(dirName, fileName, singleton ? ".singleton-mpp.o" : ".multi-mpp.o")); command.addFlags(cppFlags); final String name = "macro_def.h"; final URL url = getClass().getClassLoader().getResource(name); if (url == null) throw new Exception("Can't find file " + name); command.addIncludeFile(new File(url.toURI())); command.addDefine("COMPONENT_NAME", dirName.replace('-', '_')); if (singleton) command.addDefine("SINGLETON"); /* * Since we're now using typedefs instead of direct struct declaration for * private data, we need to declare a real variable in a .c file. */ if (singleton) { final String dataDefName = "private_data_def.c"; final URL dataDefURL = getClass().getClassLoader().getResource( dataDefName); if (dataDefURL == null) throw new Exception("Can't find file " + dataDefName); command.addIncludeFile(new File(dataDefURL.toURI())); } return command; } protected void mppSingleton(final String dirName, final String fileName) throws Exception { errorManager.clear(); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName)); commands.add(newMPPCommand(dirName, fileName, true)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void mppMulti(final String dirName, final String fileName) throws Exception { errorManager.clear(); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName)); commands.add(newMPPCommand(dirName, fileName, false)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void compileSingleton(final String dirName, final String fileName) throws Exception { errorManager.clear(); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName)); commands.add(newMPPCommand(dirName, fileName, true)); commands.add(newGCCCommand(dirName, fileName, true)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void compileMulti(final String dirName, final String fileName) throws Exception { errorManager.clear(); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName)); commands.add(newMPPCommand(dirName, fileName, false)); commands.add(newGCCCommand(dirName, fileName, false)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void compileSingletonForDef(final String dirName, final String fileName, final String hostDefName) throws Exception { errorManager.clear(); final Definition hostDefinition = adlLoader.load(hostDefName, context); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName)); commands.add(newMPPCommandForDef(dirName, fileName, hostDefinition, true)); commands.add(newGCCCommand(dirName, fileName, true)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void compileSplitSingletonForDef(final String dirName, final String fileName0, final String fileName1, final String hostDefName) throws Exception { errorManager.clear(); final Definition hostDefinition = adlLoader.load(hostDefName, context); final Collection<CompilationCommand> commands = new ArrayList<CompilationCommand>(); commands.add(newCPPCommand(dirName, fileName0)); commands.add(newCPPCommand(dirName, fileName1)); commands.add(newMPPCommandForDef(dirName, fileName0, hostDefinition, true)); commands.add(newMPPCommandForDef(dirName, fileName1, hostDefinition, true)); commands.add(newGCCCommand(dirName, fileName0, true)); commands.add(newGCCCommand(dirName, fileName1, true)); executor.exec(commands, context); final List<Error> errors = errorManager.getErrors(); if (!errors.isEmpty()) { throw new ADLException(new ErrorCollection(errors)); } } protected void initSourcePath(final String... rootDirs) { final List<URL> rootDirList = new ArrayList<URL>(); for (String rootDir : rootDirs) { final File rootFile = new File(rootDir); if (rootFile.isAbsolute()) { if (!rootFile.isDirectory()) { fail(rootDir + " is not a valid source directory"); } try { rootDirList.add(rootFile.toURI().toURL()); } catch (final MalformedURLException e) { fail(rootDir + " is not a valid source directory", e); } } else { if (!rootDir.endsWith("/")) rootDir += "/"; Enumeration<URL> resources; try { resources = getClass().getClassLoader().getResources(rootDir); } catch (final IOException e) { fail("Fail to lookup " + rootDir + "in classpath", e); return; } URL rootDirURL = null; while (resources.hasMoreElements()) { final URL resource = resources.nextElement(); if (resource.getProtocol().equals("file")) { rootDirURL = resource; break; } } assertNotNull(rootDirURL, "Can't find directory " + rootDir + " in the classpath"); rootDirList.add(rootDirURL); } } System.out.println("Init src path : " + rootDirList); final ClassLoader srcLoader = new URLClassLoader( rootDirList.toArray(new URL[0]), null); context.put("classloader", srcLoader); } protected File getDepsDir(final String resource) { try { return DepsHelper.unpackDeps(resource, this.getClass().getClassLoader()); } catch (final Exception e) { fail("Can't unpack dependency containing " + resource, e); return null; } } }