/** * Copyright 2011-2017 Asakusa Framework Team. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.asakusafw.testdriver; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.ListResourceBundle; import java.util.Map; import java.util.MissingResourceException; import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; import java.util.TreeMap; import javax.tools.ToolProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.asakusafw.runtime.stage.StageConstants; import com.asakusafw.testdriver.compiler.CompilerConfiguration.DebugLevel; import com.asakusafw.testdriver.compiler.CompilerConfiguration.OptimizeLevel; import com.asakusafw.testdriver.compiler.CompilerConstants; import com.asakusafw.testdriver.core.TestContext; import com.asakusafw.testdriver.core.TestToolRepository; import com.asakusafw.testdriver.core.TestingEnvironmentConfigurator; import com.asakusafw.utils.collections.Maps; /** * Represents contextual information for test drivers. * @since 0.2.0 * @version 0.8.1 */ public class TestDriverContext implements TestContext { static final Logger LOG = LoggerFactory.getLogger(TestDriverContext.class); static final ResourceBundle INFORMATION; static { ResourceBundle bundle; try { bundle = ResourceBundle.getBundle("com.asakusafw.testdriver.information"); //$NON-NLS-1$ } catch (MissingResourceException e) { LOG.warn("Missing framework information resource", e); //$NON-NLS-1$ bundle = new ListResourceBundle() { @Override protected Object[][] getContents() { return new Object[0][]; } }; } INFORMATION = bundle; } /** * The system property key of runtime working directory. * This working directory should be a relative path from the default working directory. * @deprecated Use {@link CompilerConstants#KEY_RUNTIME_WORKING_DIRECTORY} instead */ @Deprecated public static final String KEY_RUNTIME_WORKING_DIRECTORY = CompilerConstants.KEY_RUNTIME_WORKING_DIRECTORY; /** * The system property key of compiler working directory. */ public static final String KEY_COMPILER_WORKING_DIRECTORY = "asakusa.testdriver.compilerwork.dir"; //$NON-NLS-1$ /** * The system property key of the default framework installation path. * This property will overwrite environment variables. * @since 0.6.0 */ public static final String KEY_FRAMEWORK_PATH = "asakusa.testdriver.framework"; //$NON-NLS-1$ /** * The system property key of the default batch applications installation base path. * This property will overwrite environment variables. * @since 0.6.1 */ public static final String KEY_BATCHAPPS_PATH = "asakusa.testdriver.batchapps"; //$NON-NLS-1$ /** * The system property key of ignoring environment checking. * @see #validateExecutionEnvironment() * @since 0.5.2 */ public static final String KEY_FORCE_EXEC = "asakusa.testdriver.exec.force"; //$NON-NLS-1$ /** * Environmental variable: the framework home path. */ public static final String ENV_FRAMEWORK_PATH = "ASAKUSA_HOME"; //$NON-NLS-1$ /** * Environmental variable: the batch applications installation base path. * @since 0.6.1 */ public static final String ENV_BATCHAPPS_PATH = "ASAKUSA_BATCHAPPS_HOME"; //$NON-NLS-1$ /** * The default path of batch application installation base path (relative from the framework home path). * @since 0.6.1 */ public static final String DEFAULT_BATCHAPPS_PATH = "batchapps"; //$NON-NLS-1$ /** * The path to the external dependency libraries folder (relative from working directory). * @since 0.5.1 */ public static final String EXTERNAL_LIBRARIES_PATH = "src/main/libs"; //$NON-NLS-1$ /** * The output directory path in the final artifact. */ private static final String OUTPUT_DIRECTORY_PATH = "usr/lib"; //$NON-NLS-1$ /** * The path to the framework version file (relative from the framework home path). * @since 0.5.2 */ public static final String FRAMEWORK_VERSION_PATH = "VERSION"; //$NON-NLS-1$ /** * The entry key of the test-runtime framework version. * @since 0.5.2 */ public static final String KEY_FRAMEWORK_VERSION = "asakusafw.version"; //$NON-NLS-1$ /** * The system property key of {@link JobExecutorFactory}'s implementation class name. * @see #setJobExecutorFactory(JobExecutorFactory) * @since 0.6.0 */ public static final String KEY_JOB_EXECUTOR_FACTORY = "asakusa.testdriver.exec.factory"; //$NON-NLS-1$ static { TestingEnvironmentConfigurator.initialize(); } private volatile File frameworkHomePath; private final Class<?> callerClass; private final TestToolRepository repository; private final Map<String, String> extraConfigurations; private final Map<String, String> batchArgs; private final Map<String, String> environmentVariables; private final Map<String, String> compilerOptions; private final Map<Class<?>, Object> extensionMap; private volatile OptimizeLevel compilerOptimizeLevel = OptimizeLevel.NORMAL; private volatile DebugLevel compilerDebugLevel = DebugLevel.DISABLED; private final Set<TestExecutionPhase> skipPhases; private volatile File librariesPath; private volatile String currentBatchId; private volatile String currentFlowId; private volatile String currentExecutionId; private volatile File explicitCompilerWorkingDirectory; private volatile File generatedCompilerWorkingDirectory; private volatile boolean useSystemBatchappsHomePath; private volatile File explicitBatchappsHomePath; private volatile File generatedBatchappsHomePath; private volatile JobExecutorFactory jobExecutorFactory; /** * Creates a new instance. * @param contextClass context class (will use to detect test resources) * @throws IllegalArgumentException if some parameters were {@code null} */ public TestDriverContext(Class<?> contextClass) { if (contextClass == null) { throw new IllegalArgumentException("contextClass must not be null"); //$NON-NLS-1$ } this.callerClass = contextClass; this.repository = new TestToolRepository(contextClass.getClassLoader()); this.extraConfigurations = new TreeMap<>(); this.batchArgs = new TreeMap<>(); this.environmentVariables = new HashMap<>(System.getenv()); this.compilerOptions = new LinkedHashMap<>(); this.extensionMap = new LinkedHashMap<>(); this.skipPhases = EnumSet.noneOf(TestExecutionPhase.class); } /** * Validates current compiler environment. * @throws AssertionError if current test environment is invalid * @since 0.5.1 * @deprecated legacy API */ @Deprecated public void validateCompileEnvironment() { if (ToolProvider.getSystemJavaCompiler() == null) { // validates runtime environment first validateExecutionEnvironment(); throw new AssertionError(Messages.getString("TestDriverContext.errorMissingJavaCompiler")); //$NON-NLS-1$ } } /** * Returns the development environment version. * @return the development environment version * @throws IllegalStateException if the version is not defined * @since 0.5.2 */ public String getDevelopmentEnvironmentVersion() { try { String version = INFORMATION.getString(KEY_FRAMEWORK_VERSION); return version; } catch (MissingResourceException e) { throw new IllegalStateException(MessageFormat.format( Messages.getString("TestDriverContext.errorUnknownRunningSdkVersion"), //$NON-NLS-1$ KEY_FRAMEWORK_VERSION), e); } } /** * Returns the runtime environment version. * @return the runtime environment version, or {@code null} if it is not defined * @since 0.5.2 */ public String getRuntimeEnvironmentVersion() { File path = getFrameworkHomePathOrNull(); if (path == null) { return null; } File version = new File(path, FRAMEWORK_VERSION_PATH); if (version.isFile() == false) { LOG.warn(MessageFormat.format( Messages.getString("TestDriverContext.warnMissingDeployedSdkVersionFile"), //$NON-NLS-1$ version.getAbsolutePath())); return null; } Properties p = new Properties(); try (InputStream in = new FileInputStream(version)) { p.load(in); } catch (IOException e) { LOG.warn(MessageFormat.format( Messages.getString("TestDriverContext.warnInvalidDeployedSdkVersionFile"), //$NON-NLS-1$ version.getAbsolutePath()), e); return null; } String value = p.getProperty(KEY_FRAMEWORK_VERSION); if (value == null) { LOG.warn(MessageFormat.format( Messages.getString("TestDriverContext.warnMissingDeployedSdkVersionProperty"), //$NON-NLS-1$ version.getAbsolutePath(), KEY_FRAMEWORK_VERSION)); return null; } return value; } /** * Validates current test execution environment. * @throws AssertionError if current test environment is invalid * @since 0.5.1 */ public void validateExecutionEnvironment() { getJobExecutor().validateEnvironment(); } /** * Validates current test environment. * @throws AssertionError if current test environment is invalid * @since 0.5.0 */ public void validateEnvironment() { validateExecutionEnvironment(); } /** * Sets the path to the framework installed location. * @param frameworkHomePath the path to the framework install location, or {@code null} to reset location */ public void setFrameworkHomePath(File frameworkHomePath) { this.frameworkHomePath = frameworkHomePath; } /** * Returns the framework home path. * @return the path, or default path from environmental variable {@code ASAKUSA_HOME} * @throws IllegalStateException if neither the framework home path nor the environmental variable were set */ public File getFrameworkHomePath() { File result = getFrameworkHomePathOrNull(); if (result == null) { throw new IllegalStateException(MessageFormat.format( Messages.getString("TestDriverContext.errorUndefinedEnvironmentVariable"), //$NON-NLS-1$ ENV_FRAMEWORK_PATH)); } return result; } /** * Returns the framework home path. * @return the path, default path from environmental variable {@code ASAKUSA_HOME}, or {@code null} */ public File getFrameworkHomePathOrNull() { if (frameworkHomePath == null) { String homePath = System.getProperty(KEY_FRAMEWORK_PATH); if (homePath != null) { return new File(homePath); } String defaultHomePath = getEnvironmentVariables0().get(ENV_FRAMEWORK_PATH); if (defaultHomePath != null) { return new File(defaultHomePath); } return null; } return frameworkHomePath; } /** * Enable to use the system batch applications installation base location instead of using generated path. * @param use {@code true} to use system location, or {@code false} otherwise * @since 0.6.1 */ public void useSystemBatchApplicationsInstallationPath(boolean use) { this.useSystemBatchappsHomePath = use; } /** * Sets the path to the batch applications installation location. * @param path the path to the batch applications installation location, or {@code null} to reset location * @since 0.6.1 */ public void setBatchApplicationsInstallationPath(File path) { this.explicitBatchappsHomePath = path; } /** * Returns the path to the batch applications installation location. * @return path to the batch applications installation location * @since 0.6.1 */ public File getBatchApplicationsInstallationPath() { if (explicitBatchappsHomePath != null) { return explicitBatchappsHomePath; } if (generatedBatchappsHomePath != null) { return generatedBatchappsHomePath; } String path = System.getProperty(KEY_BATCHAPPS_PATH); if (path != null) { return new File(path); } if (useSystemBatchappsHomePath) { String envPath = getEnvironmentVariables0().get(ENV_BATCHAPPS_PATH); if (envPath != null) { return new File(envPath); } File frameworkHome = getFrameworkHomePathOrNull(); if (frameworkHome != null) { return new File(frameworkHome, DEFAULT_BATCHAPPS_PATH); } } generatedBatchappsHomePath = createTempDirPath(); return generatedBatchappsHomePath; } /** * Returns the path to the jobflow package (*.jar) deployment directory. * This method refers the {@link #getFrameworkHomePath() framework installed location}. * @param batchId target batch ID * @return the path * @throws IllegalArgumentException if some parameters were {@code null} * @see #setFrameworkHomePath(File) */ public File getJobflowPackageLocation(String batchId) { if (batchId == null) { throw new IllegalArgumentException("batchId must not be null"); //$NON-NLS-1$ } File apps = getBatchApplicationsInstallationPath(); File batch = new File(apps, batchId); File lib = new File(batch, "lib"); //$NON-NLS-1$ return lib; } /** * Returns the path to the external libraries (*.jar) deployment directory. * @param batchId target batch ID * @return the path * @throws IllegalArgumentException if some parameters were {@code null} * @see #setLibrariesPath(File) * @since 0.5.1 */ public File getLibrariesPackageLocation(String batchId) { if (batchId == null) { throw new IllegalArgumentException("batchId must not be null"); //$NON-NLS-1$ } File apps = getBatchApplicationsInstallationPath(); File batch = new File(apps, batchId); File lib = new File(batch, OUTPUT_DIRECTORY_PATH); return lib; } /** * Returns the compiler working directory. * @return the compiler working directory */ public File getCompilerWorkingDirectory() { return new File(getCompileWorkBaseDir()); } /** * Sets the compiler working directory. * @param path the compiler working directory * @since 0.5.2 */ public void setCompilerWorkingDirectory(File path) { this.explicitCompilerWorkingDirectory = path; } /** * Returns the current user name in OS. * @return the current user name */ public String getOsUser() { Map<String, String> envp = getEnvironmentVariables0(); String user = System.getProperty("user.name", envp.get("USER")); //$NON-NLS-1$ //$NON-NLS-2$ return user; } /** * Returns the path to the compiler working directory. * Clients can configure this property using system property {@value #KEY_COMPILER_WORKING_DIRECTORY}. * @return the compiler working directory */ public String getCompileWorkBaseDir() { String dir = System.getProperty(KEY_COMPILER_WORKING_DIRECTORY); if (dir == null) { if (explicitCompilerWorkingDirectory != null) { return explicitCompilerWorkingDirectory.getAbsolutePath(); } if (generatedCompilerWorkingDirectory == null) { generatedCompilerWorkingDirectory = createTempDirPath(); LOG.debug("Created a temporary compiler working directory: {}", //$NON-NLS-1$ generatedCompilerWorkingDirectory); } return generatedCompilerWorkingDirectory.getAbsolutePath(); } return dir; } private File createTempDirPath() { try { File file = File.createTempFile("asakusa", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$ if (file.delete() == false) { throw new IOException(MessageFormat.format( Messages.getString("TestDriverContext.errorFailedToPrepareTemporaryDirectory"), //$NON-NLS-1$ file)); } return file; } catch (IOException e) { throw (AssertionError) new AssertionError( Messages.getString("TestDriverContext.errorFailedToCreateTemporaryDirectory")) //$NON-NLS-1$ .initCause(e); } } /** * Returns the path to the runtime working directory. * This working directory is relative path from cluster's default working directory. * Clients can configure this property using system property {@value #KEY_RUNTIME_WORKING_DIRECTORY}. * @return the runtime working directory * @deprecated Use {@link CompilerConstants#getRuntimeWorkingDirectory()} instead */ @Deprecated public String getClusterWorkDir() { return CompilerConstants.getRuntimeWorkingDirectory(); } /** * Returns the path to the dependency libraries path. * The dependency library files are in the target folder directly. * @return the librariesPath the libraries path * @since 0.5.1 */ public File getLibrariesPath() { if (librariesPath == null) { return new File(EXTERNAL_LIBRARIES_PATH); } return librariesPath; } /** * Sets the path to the external dependency libraries folder. * @param librariesPath the libraries folder path * @throws IllegalArgumentException if some parameters were {@code null} * @since 0.5.1 */ public void setLibrariesPath(File librariesPath) { this.librariesPath = librariesPath; } /** * Returns the caller class. * This is ordinary used for detect test dataset on the classpath. * @return the caller class */ public Class<?> getCallerClass() { return callerClass; } /** * Returns the test tool repository. * @return the repository * @since 0.2.3 */ public TestToolRepository getRepository() { return repository; } /** * Returns the current execution ID. * @return current execution ID * @see #setCurrentExecutionId(String) */ public String getExecutionId() { if (currentExecutionId == null) { throw new IllegalStateException("prepareCurrentJobflow was not invoked"); //$NON-NLS-1$ } return currentExecutionId; } /** * Returns extra configurations for the runtime. * For Hadoop, these configurations are passed using {@code -D <key>=<value>}. * @return the extra configurations (key value pairs) */ public Map<String, String> getExtraConfigurations() { return extraConfigurations; } /** * Returns the batch arguments. * @return the batch arguments */ public Map<String, String> getBatchArgs() { return batchArgs; } @Override public Map<String, String> getEnvironmentVariables() { File home = getFrameworkHomePathOrNull(); Map<String, String> envp = getEnvironmentVariables0(); if (home != null) { envp.put(ENV_FRAMEWORK_PATH, home.getAbsolutePath()); } envp.put(ENV_BATCHAPPS_PATH, getBatchApplicationsInstallationPath().getAbsolutePath()); return envp; } private Map<String, String> getEnvironmentVariables0() { return environmentVariables; } @Override public Map<String, String> getArguments() { Map<String, String> copy = Maps.from(getBatchArgs()); if (currentBatchId != null) { copy.put(StageConstants.VAR_BATCH_ID, currentBatchId); } if (currentFlowId != null) { copy.put(StageConstants.VAR_FLOW_ID, currentFlowId); } if (currentExecutionId != null) { copy.put(StageConstants.VAR_EXECUTION_ID, currentExecutionId); } return Collections.unmodifiableMap(copy); } /** * Sets the compiler optimization level. * @param newValue the compiler optimization level */ public void setCompilerOptimizeLevel(OptimizeLevel newValue) { Objects.requireNonNull(newValue); this.compilerOptimizeLevel = newValue; } /** * Sets the compiler debug level. * @param newValue the compiler debug level */ public void setCompilerDebugLevel(DebugLevel newValue) { Objects.requireNonNull(newValue); this.compilerDebugLevel = newValue; } /** * Returns the compiler optimization level. * @return the compiler optimization level * @since 0.8.0 */ public OptimizeLevel getCompilerOptimizeLevel() { return compilerOptimizeLevel; } /** * Returns the compiler debug level. * @return the compiler debug level * @since 0.8.0 */ public DebugLevel getCompilerDebugLevel() { return compilerDebugLevel; } /** * Returns the compiler specific options. * @return the compiler specific options * @since 0.8.0 */ public Map<String, String> getCompilerOptions() { return compilerOptions; } /** * Returns the extension object. * @param <T> the extension type * @param type the extension type * @return the related extension, or {@code null} if it is not registered * @since 0.8.1 */ public <T> T getExtension(Class<T> type) { return type.cast(extensionMap.get(type)); } /** * Returns the registered extension types. * @return the extension types * @since 0.8.1 * @see #getExtension(Class) */ public Set<Class<?>> getExtensionTypes() { return Collections.unmodifiableSet(extensionMap.keySet()); } /** * Puts the extension object. * @param <T> the extension type * @param type the extension type * @param object the extension object, or {@code null} to remove the target extension * @since 0.8.1 */ public <T> void putExtension(Class<T> type, T object) { if (object == null) { extensionMap.remove(type); } else { extensionMap.put(type, object); } } @Override public ClassLoader getClassLoader() { return callerClass.getClassLoader(); } /** * Returns the current batch ID. * @return the current batch ID, or {@code null} if not set * @see #setCurrentBatchId(String) */ public String getCurrentBatchId() { return currentBatchId; } /** * Configures the current batch ID. * @param currentBatchId the ID */ public void setCurrentBatchId(String currentBatchId) { this.currentBatchId = currentBatchId; } /** * Returns the current flow ID. * @return the ID, or {@code null} if not set * @see #setCurrentFlowId(String) */ public String getCurrentFlowId() { return currentFlowId; } /** * Configures the current flow ID. * @param currentFlowId the ID */ public void setCurrentFlowId(String currentFlowId) { this.currentFlowId = currentFlowId; } /** * Returns the current execution ID. * @return the ID, or {@code null} if not set * @see #setCurrentExecutionId(String) */ public String getCurrentExecutionId() { return currentExecutionId; } /** * Returns the current execution ID. * @param currentExecutionId the ID */ public void setCurrentExecutionId(String currentExecutionId) { this.currentExecutionId = currentExecutionId; } /** * Returns whether this test skips to cleanup input data source. * @return {@code true} to skip, otherwise {@code false} * @since 0.7.0 */ public boolean isSkipValidateCondition() { return skipPhases.contains(TestExecutionPhase.VALIDATE_CONDITION); } /** * Sets whether this test skips to cleanup input data source (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} * @since 0.7.0 */ public void setSkipValidateCondition(boolean skip) { setSkipPhase(TestExecutionPhase.VALIDATE_CONDITION, skip); } /** * Returns whether this test skips to cleanup input data source. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipCleanInput() { return skipPhases.contains(TestExecutionPhase.CLEAN_INPUT); } /** * Sets whether this test skips to cleanup input data source (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipCleanInput(boolean skip) { setSkipPhase(TestExecutionPhase.CLEAN_INPUT, skip); } /** * Returns whether this test skips to cleanup input data source. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipCleanOutput() { return skipPhases.contains(TestExecutionPhase.CLEAN_OUTPUT); } /** * Sets whether this test skips to cleanup output data source (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipCleanOutput(boolean skip) { setSkipPhase(TestExecutionPhase.CLEAN_OUTPUT, skip); } /** * Returns whether this test skips to cleanup input data source. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipPrepareInput() { return skipPhases.contains(TestExecutionPhase.PREPARE_INPUT); } /** * Sets whether this test skips to prepare input data source (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipPrepareInput(boolean skip) { setSkipPhase(TestExecutionPhase.PREPARE_INPUT, skip); } /** * Returns whether this test skips to prepare output data source. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipPrepareOutput() { return skipPhases.contains(TestExecutionPhase.PREPARE_OUTPUT); } /** * Sets whether this test skips to prepare output data source (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipPrepareOutput(boolean skip) { setSkipPhase(TestExecutionPhase.PREPARE_OUTPUT, skip); } /** * Returns whether this test skips to execute jobflows. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipRunJobflow() { return skipPhases.contains(TestExecutionPhase.EXECUTE); } /** * Sets whether this test skips to execute jobflows (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipRunJobflow(boolean skip) { setSkipPhase(TestExecutionPhase.EXECUTE, skip); } /** * Returns whether this test skips to verify the testing result. * @return {@code true} to skip, otherwise {@code false} */ public boolean isSkipVerify() { return skipPhases.contains(TestExecutionPhase.VERIFY); } /** * Sets whether this test skips to verify the testing result (default: {@code false}). * @param skip {@code true} to skip, otherwise {@code false} */ public void setSkipVerify(boolean skip) { setSkipPhase(TestExecutionPhase.VERIFY, skip); } private void setSkipPhase(TestExecutionPhase phase, boolean skip) { assert phase != null; if (skip) { skipPhases.add(phase); } else { skipPhases.remove(phase); } } /** * Removes all temporary resources generated in this context. * @since 0.5.2 */ public void cleanUpTemporaryResources() { if (generatedCompilerWorkingDirectory != null && generatedCompilerWorkingDirectory.exists()) { LOG.debug("Deleting temporary compiler working directory: {}", //$NON-NLS-1$ generatedCompilerWorkingDirectory); removeAll(generatedCompilerWorkingDirectory); this.generatedCompilerWorkingDirectory = null; } if (generatedBatchappsHomePath != null && generatedBatchappsHomePath.exists()) { LOG.debug("Deleting temporary batchapps directory: {}", //$NON-NLS-1$ generatedBatchappsHomePath); removeAll(generatedBatchappsHomePath); this.generatedBatchappsHomePath = null; } } /** * Sets the {@link JobExecutorFactory} for executing jobs in this context. * @param factory the factory, or {@code null} to use a default implementation * @since 0.6.0 * @see #getJobExecutor() */ public void setJobExecutorFactory(JobExecutorFactory factory) { if (factory == null) { this.jobExecutorFactory = new DefaultJobExecutorFactory(); } else { this.jobExecutorFactory = factory; } } /** * Returns the {@link JobExecutor} for executes jobs in this context. * @return the {@link JobExecutor} instance * @since 0.6.0 */ public JobExecutor getJobExecutor() { if (jobExecutorFactory != null) { return jobExecutorFactory.newInstance(this); } String className = System.getProperty(KEY_JOB_EXECUTOR_FACTORY, DefaultJobExecutorFactory.class.getName()); try { Class<?> aClass = Class.forName(className, false, getClassLoader()); this.jobExecutorFactory = aClass.asSubclass(JobExecutorFactory.class).newInstance(); } catch (Exception e) { throw (AssertionError) new AssertionError(MessageFormat.format( Messages.getString("TestDriverContext.errorFailedToCreateJobExecutorFactory"), //$NON-NLS-1$ KEY_JOB_EXECUTOR_FACTORY, className)).initCause(e); } return jobExecutorFactory.newInstance(this); } private boolean removeAll(File path) { assert path != null; boolean deleted = true; if (path.isDirectory()) { for (File child : list(path)) { deleted &= removeAll(child); } } if (deleted) { if (path.delete() == false) { LOG.warn(MessageFormat.format( Messages.getString("TestDriverContext.warnFailedToDeleteTemporaryFile"), //$NON-NLS-1$ path.getAbsolutePath())); deleted = false; } } return deleted; } private static List<File> list(File file) { return Optional.ofNullable(file.listFiles()) .map(Arrays::asList) .orElse(Collections.emptyList()); } /** * Represents each phase in test execution. * @since 0.6.0 */ public enum TestExecutionPhase { /** * Validating test conditions. * @since 0.7.0 */ VALIDATE_CONDITION, /** * Cleaning input. */ CLEAN_INPUT, /** * Cleaning output. */ CLEAN_OUTPUT, /** * Preparing input. */ PREPARE_INPUT, /** * Preparing output. */ PREPARE_OUTPUT, /** * Performing execution. */ EXECUTE, /** * Performing verification. */ VERIFY, } }