/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package functionaltests; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.objectweb.proactive.core.node.NodeException; import org.ow2.proactive.scripting.InvalidScriptException; import org.python.icu.impl.Assert; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.io.CharStreams; import com.google.common.io.Closeables; /** * This class is in charge to evaluate all selection scripts available in * {@code PA_SCHEDULER_HOME/samples/scripts/selection} for checking whether they are valid or not * (i.e. no evaluation error and a boolean variable named "selected" is defined at the end of the evaluation). * <p/> * Selections scripts are evaluated in a forked process for having the possibility to change the current * working directory, thus allowing scripts to import files relative to * {@code PA_SCHEDULER_HOME/samples/scripts/selection}. * <p/> * The class uses parameterized Junit tests for generating independent test methods for each selection script * which is tested. */ @RunWith(Parameterized.class) public class SelectionScriptSamplesTest { private static final Logger log = Logger.getLogger(SelectionScriptSamplesTest.class); private static final String PA_SCHEDULER_HOME = System.getProperty("pa.scheduler.home"); private Path selectionScript; // used by reflection with Junit to name test method private String testMethodName; public SelectionScriptSamplesTest(Path selectionScript, String testMethodName) { this.selectionScript = selectionScript; this.testMethodName = testMethodName; } @Parameterized.Parameters(name = "{1}") public static Iterable<Object[]> data() throws IOException { final List<Path> selectionScriptsToTest = getSelectionScriptsToTest(); Object[][] parameters = new Object[selectionScriptsToTest.size()][2]; for (int i = 0; i < parameters.length; i++) { final Path selectionScript = selectionScriptsToTest.get(i); String fileName = selectionScript.getFileName().toString(); parameters[i][0] = selectionScript; parameters[i][1] = "test" + Character.toUpperCase(fileName.charAt(0)) + fileName.substring(1); } return Arrays.asList(parameters); } @Test public void testSelectionScriptValidity() throws IOException, NodeException, InvalidScriptException, ClassNotFoundException, InterruptedException { log.info("Evaluating " + selectionScript); try { evaluateSelectionScript(selectionScript); } catch (ScriptEvaluationException e) { Assert.fail(e); } } public static void evaluateSelectionScript(Path selectionScript) throws IOException, InterruptedException, ScriptEvaluationException { Process process = forkEvaluation(selectionScript); int exitCode = process.waitFor(); if (exitCode > 0) { final InputStream errorStream = process.getErrorStream(); String errorMessage = CharStreams.toString(new InputStreamReader(errorStream, Charsets.UTF_8)); Closeables.closeQuietly(errorStream); throw new ScriptEvaluationException(errorMessage); } } private static Process forkEvaluation(Path selectionScript) throws IOException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; String classpath = System.getProperty("java.class.path"); String className = SelectionScriptEvaluator.class.getCanonicalName(); ProcessBuilder builder = new ProcessBuilder(javaBin, "-cp", classpath, className, selectionScript.toAbsolutePath().toString()); builder.directory(new File(PA_SCHEDULER_HOME)); return builder.start(); } private static List<Path> getSelectionScriptsToTest() throws IOException { ImmutableList.Builder<Path> result = ImmutableList.builder(); try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(PA_SCHEDULER_HOME, "samples", "scripts", "selection"))) { for (Path path : directoryStream) { if (Files.isRegularFile(path) && !com.google.common.io.Files.getFileExtension(path.getFileName().toString()).equals("txt")) { result.add(path); } } } return result.build(); } private static final class ScriptEvaluationException extends Exception { public ScriptEvaluationException(String message) { super(message); } } }