blob: 889d6c21e4404be4c6b4d31df93c2c784648849c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 École Polytechnique de Montréal
*
* 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
*******************************************************************************/
package org.eclipse.tracecompass.incubator.scripting.ui.tests;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.ease.IExecutionListener;
import org.eclipse.ease.IScriptEngine;
import org.eclipse.ease.Script;
import org.eclipse.ease.service.EngineDescription;
import org.eclipse.ease.service.IScriptService;
import org.eclipse.ease.service.ScriptService;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.scripting.core.tests.stubs.ScriptingTestUtils;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import com.google.common.collect.ImmutableMap;
/**
* Test that all example scripts in the core plugin work well with their
* respective engine. It only makes sure they do not throw exception with
* default trace, or use scripted methods that are not available anymore.
* Methods themselves should be unit tested on their own.
*
* @author Geneviève Bastien
*/
@RunWith(Parameterized.class)
public class ScriptTest {
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
// TODO Some scripts don't work with rhino: org.eclipse.ease.javascript.rhino
private static final Map<String, String> ENGINES = ImmutableMap.of(
"nashorn", "org.eclipse.ease.javascript.nashorn",
"py4j", "org.eclipse.ease.lang.python.py4j.engine");
private static final @NonNull String SOME_PROJECT_NAME = "myProject";
private static final @NonNull IProgressMonitor PROGRESS_MONITOR = new NullProgressMonitor();
private static final String SCRIPT_FOLDER = "scripts/tracecompass-ease-scripting/";
// Final fields for the test
private final IScriptEngine fScriptEngine;
private final Path fScriptFile;
// Environment variables
private IProject fProject;
private ITmfTrace fTrace;
private @Nullable Script fScript;
// ------------------------------------------------------------------------
// Initialization
// ------------------------------------------------------------------------
/**
* For each engine, get all the example files. Parameters are an engine and
* file
*
* @return The arrays of parameters
* @throws IOException
* Exception thrown by getting files
*/
@Parameters(name = "{0}")
public static Iterable<Object[]> getParameters() throws IOException {
List<Object[]> parameters = new ArrayList<>();
final IScriptService scriptService = ScriptService.getService();
for (Entry<String, String> entry : ENGINES.entrySet()) {
final EngineDescription engineDescription = scriptService.getEngineByID(entry.getValue());
if (engineDescription == null) {
throw new NullPointerException("Script engine not found " + entry.getKey());
}
List<Path> filesForEngine = getFilesForEngine(engineDescription);
assertFalse(filesForEngine.isEmpty());
for (Path file : filesForEngine) {
/*
* A separate engine needs to be created for each script,
* otherwise, only the first script works
*/
IScriptEngine engine = engineDescription.createEngine();
Object[] engineValues = { entry.getKey() + ", " + file.getFileName(), engine, file };
parameters.add(engineValues);
}
}
return parameters;
}
/**
* Constructor
*
* @param testName
* The name of the test
* @param scriptEngine
* The engine to use
* @param scriptFile
* The file to test
*/
public ScriptTest(String testName, IScriptEngine scriptEngine, Path scriptFile) {
fScriptEngine = scriptEngine;
fScriptFile = scriptFile;
}
/**
* Setup a project with traces
*
* @throws CoreException
* Exception thrown during project creation
*/
@Before
public void setUpEnvironment() throws CoreException {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
// Create a project inside workspace location to store script files
IWorkspaceRoot wsRoot = workspace.getRoot();
IProject project = wsRoot.getProject(SOME_PROJECT_NAME);
if (!project.exists()) {
project.create(null);
}
if (!project.isOpen()) {
project.open(null);
}
fProject = project;
/*
* Get a trace and make sure there is an active trace, as script may
* need to get the active trace
*/
ITmfTrace trace = ScriptingTestUtils.getTrace();
fTrace = trace;
TmfTraceManager.getInstance().traceOpened(new TmfTraceOpenedSignal(this, trace, null));
}
/**
* Delete the project after tests
*
* @throws CoreException
* Exception thrown by project deletion
*/
@After
public void cleanUpEnvironment() throws CoreException {
IProject project = fProject;
if (project != null) {
project.delete(true, PROGRESS_MONITOR);
}
ITmfTrace trace = fTrace;
if (trace != null) {
trace.dispose();
}
}
private static List<Path> getFilesForEngine(EngineDescription engineDescription) throws IOException {
// Get the extension to look for
String extension = engineDescription.getSupportedScriptTypes().get(0).getDefaultExtension();
List<Path> files = new ArrayList<>();
// Get the files from the scripting core plugin's documentation folder
org.eclipse.core.runtime.IPath path = ActivatorTest.getAbsoluteFilePath(SCRIPT_FOLDER);
Files.walkFileTree(Paths.get(path.toOSString()), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// Add the file if it has the correct extension
if (file.toString().endsWith(extension)) {
files.add(file);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
});
return files;
}
private static final IFile createFile(String name, Path scriptPath, IContainer parent) throws CoreException, IOException {
List<String> readAllLines = Files.readAllLines(scriptPath, Charset.forName("UTF-8"));
String code = String.join("\n", readAllLines);
final IFile file = parent.getFile(new org.eclipse.core.runtime.Path(name));
if (!file.exists()) {
file.create(new ByteArrayInputStream(code.getBytes("UTF-8")), false, null);
} else {
file.setContents(new ByteArrayInputStream(code.getBytes("UTF-8")), false, false, null);
}
return file;
}
/**
* Test executing the test script with the given engine and make sure it
* runs
*
* @throws CoreException
* Exception thrown by executing the script
* @throws IOException
* Exception thrown by executing the script
*/
@Ignore
@Test
public void testScriptExecution() throws CoreException, IOException {
/*
* Save the execution script in a field so that listener can assign it
*/
fScript = null;
/* Execution listener to access the script and its result */
fScriptEngine.addExecutionListener(new IExecutionListener() {
@Override
public void notify(IScriptEngine engine, Script script, int status) {
if (status == IExecutionListener.SCRIPT_END && script != null) {
fScript = script;
}
}
});
/*
* Create the file for the script. It needs to be in a IFile so that
* EASE module loading can get bootstrapped and modules are loadable
*/
IFile file = createFile("testScript." + fScriptEngine.getDescription().getSupportedScriptTypes().get(0).getDefaultExtension(), fScriptFile, fProject);
fScriptEngine.executeAsync(file);
runUntilTerminated(fScriptEngine);
// Verify the script result
Script script = fScript;
assertNotNull(fScriptFile.getFileName().toString(), script);
assertNull("Result of " + fScriptFile.getFileName(), script.getResult().getException());
}
private static void runUntilTerminated(IScriptEngine engine) {
// Schedule the script and wait for it to terminate
engine.schedule();
while (!engine.isFinished()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}