/**************************************************************************** * Copyright (c) 2008, 2012 Andreas Unger and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andreas Unger - initial API and implementation ****************************************************************************/ package org.yakindu.sct.generator.c.gtest; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; 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.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.yakindu.sct.generator.builder.EclipseContextGeneratorExecutorLookup; import org.yakindu.sct.generator.core.execution.IGeneratorEntryExecutor; import org.yakindu.sct.model.sgen.GeneratorModel; import org.yakindu.sct.model.sgraph.Statechart; import org.yakindu.sct.test.models.SCTUnitTestModels; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.name.Names; import com.google.inject.util.Modules; /** * @author Andreas Unger - Initial contribution and API * @author Markus Mühlbrandt * */ public class GTestHelper { private final Object owner; public GTestHelper(Object owner) { this.owner = owner; } public void compile() { copyFilesFromBundleToFolder(); IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(getTargetPath()); File directory = resource.getLocation().toFile(); List<String> command = createCommand(); getCommandExecutor().execute(command, directory); } public void generate() { IPath targetPath = getTargetPath(); // copy model to JUnit workspace copyFileFromBundleToFolder(getModelBundle(), getModelPath(), targetPath); String sgenFileName = getTestProgram() + ".sgen"; copyFileFromBundleToFolder(getTestBundle(), sgenFileName, targetPath); IPath path = new Path(sgenFileName); Resource sgenResource = loadResource(getWorkspaceFileFor(path)); GeneratorModel model = (GeneratorModel) sgenResource.getContents().get(0); model.getEntries().get(0).setElementRef(getStatechart()); performFullBuild(); new EclipseContextGeneratorExecutorLookup() { @Override protected Module getContextModule() { return Modules.override(super.getContextModule()).with(new Module() { @Override public void configure(Binder binder) { binder.bind(boolean.class).annotatedWith(Names.named(IGeneratorEntryExecutor.SKIP_VALIDATION)) .toInstance(true); } }); } }.execute(model); } protected GCCCommandExecutor getCommandExecutor() { return new GCCCommandExecutor(); } protected void performFullBuild() { try { ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); } catch (CoreException e) { throw new RuntimeException(e); } } protected IFile getWorkspaceFileFor(IPath filePath) { return ResourcesPlugin.getWorkspace().getRoot().getFile(getTargetProjectPath().append(filePath)); } protected Statechart getStatechart() { IPath path = new Path(getTargetPath().toString() + "/" + getModelPath().lastSegment()); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); Resource resource = loadResource(file); return (Statechart) resource.getContents().get(0); } protected Resource loadResource(IFile file) { URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true); Resource resource = new ResourceSetImpl().getResource(uri, true); return resource; } protected Bundle getModelBundle() { Bundle bundle = getAnnotatedTestBundle(); if (bundle == null) { return FrameworkUtil.getBundle(SCTUnitTestModels.class); } return bundle; } private void copyFilesFromBundleToFolder() { IPath targetPath = getTargetPath(); List<String> testDataFiles = new ArrayList<String>(); getTestDataFiles(testDataFiles); for (String file : testDataFiles) { copyFileFromBundleToFolder(getTestBundle(), file, targetPath); } } protected List<String> createCommand() { String gTestDirectory = getGTestDirectory(); List<String> includes = new ArrayList<String>(); getIncludes(includes); List<String> sourceFiles = new ArrayList<String>(); getSourceFiles(sourceFiles); List<String> command = new ArrayList<String>(); command.add(getCompilerCommand()); command.add("-o"); command.add(getFileName(getTestProgram())); command.add("-O2"); if (gTestDirectory != null) command.add("-I" + gTestDirectory + "/include"); for (String include : includes) { command.add("-I" + include); } if (gTestDirectory != null) command.add("-L" + gTestDirectory); for (String sourceFile : sourceFiles) { command.add(sourceFile); } command.add("-lgtest"); command.add("-lgtest_main"); command.add("-lstdc++"); command.add("-pthread"); // command.add("-pg"); return command; } /** * @return */ protected String getCompilerCommand() { return "gcc"; } /** * @return */ private String getGTestDirectory() { String gTestDirectory = System.getenv("GTEST_DIR"); // if (gTestDirectory == null) { // throw new RuntimeException("GTEST_DIR environment variable not set"); // } // System.out.println("GTEST_DIR = " + gTestDirectory); return gTestDirectory; } protected String getFileName(String path) { return new Path(path).lastSegment(); } protected IPath getTargetPath() { return getTargetProjectPath().append(new Path(getTestProgram()).removeLastSegments(1)); } protected IPath getModelPath() { return new Path(getModelAnnotation()); } protected void getIncludes(Collection<String> includes) { } protected void getSourceFiles(Collection<String> files) { files.add(getFileName(getTestSourceFile())); } protected String getTestSourceFile() { return owner.getClass().getAnnotation(GTest.class).sourceFile(); } protected void getTestDataFiles(Collection<String> files) { files.add(getTestSourceFile()); } protected String getTestProgram() { return owner.getClass().getAnnotation(GTest.class).program(); } protected String getModelAnnotation() { return owner.getClass().getAnnotation(GTest.class).model(); } protected String getTestBundleAnnotation() { return owner.getClass().getAnnotation(GTest.class).testBundle(); } protected IPath getTargetProjectPath() { return new Path(getTestBundleAnnotation()); } protected void copyFileFromBundleToFolder(Bundle bundle, String sourcePath, String targetPath) { copyFileFromBundleToFolder(bundle, new Path(sourcePath), new Path(targetPath)); } protected void copyFileFromBundleToFolder(Bundle bundle, String sourcePath, IPath targetPath) { copyFileFromBundleToFolder(bundle, new Path(sourcePath), targetPath); } protected void copyFileFromBundleToFolder(Bundle bundle, IPath sourcePath, IPath targetPath) { String fileName = sourcePath.lastSegment(); copyFileFromBundle(bundle, sourcePath, targetPath.append(fileName)); } protected void copyFileFromBundle(Bundle bundle, String sourcePath, String targetPath) { copyFileFromBundle(bundle, sourcePath, new Path(targetPath)); } protected void copyFileFromBundle(Bundle bundle, String sourcePath, IPath targetPath) { copyFileFromBundle(bundle, new Path(sourcePath), targetPath); } protected void copyFileFromBundle(Bundle bundle, IPath sourcePath, IPath targetPath) { try { InputStream is = FileLocator.openStream(bundle, sourcePath, false); createFile(targetPath, is); } catch (IOException e) { throw new RuntimeException(e); } } protected Bundle getTestBundle() { Bundle bundle = getAnnotatedTestBundle(); if (bundle == null) { return FrameworkUtil.getBundle(owner.getClass()); } return bundle; } protected Bundle getAnnotatedTestBundle() { String testProject = getTestBundleAnnotation(); if (!testProject.isEmpty()) { Bundle testBundle = Platform.getBundle(testProject); if (testBundle != null) { return testBundle; } } return null; } protected void copyFileFromBundle(String sourcePath, IFile targetFile) { copyFileFromBundle(new Path(sourcePath), targetFile); } protected void copyFileFromBundle(IPath sourcePath, IFile targetFile) { try { InputStream is = FileLocator.openStream(getTestBundle(), sourcePath, false); createFile(targetFile, is); } catch (IOException e) { throw new RuntimeException(e); } } protected void createFile(String path, InputStream source) { createFile(new Path(path), source); } protected void createFile(IPath path, InputStream source) { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); createFile(file, source); } protected void createFile(IFile file, InputStream source) { ensureContainerExists(file.getParent()); try { if (file.exists()) { file.setContents(source, true, false, new NullProgressMonitor()); } else { file.create(source, true, new NullProgressMonitor()); } } catch (CoreException e) { throw new RuntimeException(e); } } protected IFolder getFolder(String path) { return ensureContainerExists(ResourcesPlugin.getWorkspace().getRoot().getFolder(new Path(path))); } protected IFolder getFolder(IPath path) { return ensureContainerExists(ResourcesPlugin.getWorkspace().getRoot().getFolder(path)); } protected <T extends IContainer> T ensureContainerExists(T container) { IProgressMonitor monitor = new NullProgressMonitor(); IProject project = container.getProject(); if (project.exists()) { if (!project.isOpen()) { throw new RuntimeException("Project " + project.getName() + " closed"); } } else { try { createTestProject(project, monitor); project.open(monitor); } catch (CoreException e) { throw new RuntimeException(e); } } if (container instanceof IFolder) { doEnsureFolderExists((IFolder) container, monitor); } return container; } protected void createTestProject(IProject projectHandle, IProgressMonitor monitor) throws CoreException { projectHandle.create(monitor); } private void doEnsureFolderExists(IFolder folder, IProgressMonitor monitor) { if (!folder.exists()) { if (!folder.getParent().exists() && folder.getParent() instanceof IFolder) { doEnsureFolderExists((IFolder) folder.getParent(), monitor); } try { folder.create(true, true, monitor); } catch (CoreException e) { throw new RuntimeException(e); } } } }