/*
 * Copyright 2015-2019 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v20.html
 */

package org.junit.jupiter.engine.extension;

import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;

import java.util.List;

import javax.script.Bindings;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ScriptEvaluationException;
import org.junit.jupiter.engine.script.Script;
import org.junit.jupiter.engine.script.ScriptAccessor;
import org.junit.jupiter.engine.script.ScriptExecutionManager;

Encapsulates javax.script-related evaluation work.

This class is instantiated via reflection in class ScriptExecutionCondition.

Since:5.1
/** * Encapsulates javax.script-related evaluation work. * * <p>This class is instantiated via reflection in class {@link ScriptExecutionCondition}. * * @since 5.1 */
class ScriptExecutionEvaluator implements ScriptExecutionCondition.Evaluator { private static final ConditionEvaluationResult ENABLED_ALL = enabled("All results are enabled"); private final ScriptExecutionManager scriptExecutionManager = new ScriptExecutionManager(); @Override public ConditionEvaluationResult evaluate(ExtensionContext context, List<Script> scripts) { Bindings bindings = createBindings(context); for (Script script : scripts) { ConditionEvaluationResult result = evaluate(scriptExecutionManager, script, bindings); // Report the first result that is disabled, preventing evaluation of remaining scripts. if (result.isDisabled()) { return result; } } return ENABLED_ALL; } private Bindings createBindings(ExtensionContext context) { ScriptAccessor configurationParameterAccessor = new ScriptAccessor.ConfigurationParameterAccessor(context); Bindings bindings = new SimpleBindings(); bindings.put(Script.BIND_JUNIT_TAGS, context.getTags()); bindings.put(Script.BIND_JUNIT_UNIQUE_ID, context.getUniqueId()); bindings.put(Script.BIND_JUNIT_DISPLAY_NAME, context.getDisplayName()); bindings.put(Script.BIND_JUNIT_CONFIGURATION_PARAMETER, configurationParameterAccessor); return bindings; } ConditionEvaluationResult evaluate(ScriptExecutionManager manager, Script script, Bindings bindings) { if (script == null) { return null; } try { Object result = manager.evaluate(script, bindings); return computeConditionEvaluationResult(script, result); } catch (ScriptException e) { throw new ScriptEvaluationException("Script evaluation failed for: " + script.getAnnotationAsString(), e); } } ConditionEvaluationResult computeConditionEvaluationResult(Script script, Object result) { // Treat "null" result as an error. if (result == null) { throw new ScriptEvaluationException("Script returned `null`: " + script.getAnnotationAsString()); } // Trivial case: script returned a custom ConditionEvaluationResult instance. if (result instanceof ConditionEvaluationResult) { return (ConditionEvaluationResult) result; } String resultAsString = String.valueOf(result); String reason = script.toReasonString(resultAsString); // Cast or parse result to a boolean value. boolean isTrue; if (result instanceof Boolean) { isTrue = (Boolean) result; } else { isTrue = Boolean.parseBoolean(resultAsString); } // Flip enabled/disabled result based on the associated annotation type. if (script.getAnnotationType() == EnabledIf.class) { return isTrue ? enabled(reason) : disabled(reason); } if (script.getAnnotationType() == DisabledIf.class) { return isTrue ? disabled(reason) : enabled(reason); } // Still here? Not so good. throw new ScriptEvaluationException("Unsupported annotation type: " + script.getAnnotationType()); } }