![JAR search and dependency download from the Maven repository](/logo.png)
com.github.dakusui.jcunit8.factorspace.Parameter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcunit Show documentation
Show all versions of jcunit Show documentation
Automated combinatorial testing framework on top of JUnit
package com.github.dakusui.jcunit8.factorspace;
import com.github.dakusui.jcunit.core.tuples.Tuple;
import com.github.dakusui.jcunit.exceptions.InvalidTestException;
import com.github.dakusui.jcunit.fsm.FiniteStateMachine;
import com.github.dakusui.jcunit.fsm.spec.FsmSpec;
import com.github.dakusui.jcunit.regex.Expr;
import com.github.dakusui.jcunit.regex.Parser;
import com.github.dakusui.jcunit.regex.RegexComposer;
import com.github.dakusui.jcunit8.core.Utils;
import com.github.dakusui.jcunit8.factorspace.fsm.FsmComposer;
import com.github.dakusui.jcunit8.factorspace.fsm.FsmDecomposer;
import com.github.dakusui.jcunit8.factorspace.fsm.Scenario;
import com.github.dakusui.jcunit8.factorspace.regex.RegexDecomposer;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static com.github.dakusui.jcunit8.exceptions.TestDefinitionException.checkValue;
import static java.util.Collections.*;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
/**
* A user level factor.
*
* @param Type of values held by this class.
*/
public interface Parameter {
String getName();
FactorSpace toFactorSpace();
T composeValue(Tuple tuple);
Optional decomposeValue(T value);
List getKnownValues();
abstract class Base implements Parameter {
protected final String name;
private final List knownValues;
protected Base(String name, List knownValues) {
this.name = requireNonNull(name);
this.knownValues = unmodifiableList(requireNonNull(knownValues));
}
@Override
public String getName() {
return this.name;
}
@Override
public FactorSpace toFactorSpace() {
return FactorSpace.create(decompose(), generateConstraints());
}
@Override
public List getKnownValues() {
return this.knownValues;
}
protected abstract List decompose();
protected abstract List generateConstraints();
static Optional _decomposeValue(V value, Stream tuples, Function valueComposer, Predicate constraints) {
AtomicReference> fallback = new AtomicReference<>(Optional.empty());
return tuples.filter(
(Tuple tuple) -> {
return value.equals(valueComposer.apply(tuple));
}
).filter(
constraints
).findFirst(
);
}
}
interface Factory {
> F addActualValue(T actualValue);
> F addActualValues(List actualValues);
Parameter create(String name);
abstract class Base implements Factory {
protected final List knownValues = new LinkedList<>();
@SuppressWarnings("unchecked")
@Override
public > F addActualValue(T actualValue) {
knownValues.add(actualValue);
return (F) this;
}
@SuppressWarnings("unchecked")
@Override
public > F addActualValues(List actualValues) {
actualValues.forEach(this::addActualValue);
return (F) this;
}
}
}
interface Simple extends Parameter {
class Impl extends Base implements Simple {
final Factor factor;
public Impl(String name, List allLevels) {
super(name, allLevels);
this.factor = Factor.create(name, allLevels.toArray());
}
@Override
protected List decompose() {
return singletonList(factor);
}
@Override
protected List generateConstraints() {
return emptyList();
}
@SuppressWarnings("unchecked")
@Override
public T composeValue(Tuple tuple) {
return (T) tuple.get(getName());
}
@Override
public Optional decomposeValue(T value) {
return Optional.of(Tuple.builder().put(name, value).build());
}
@Override
public String toString() {
return String.format("Simple:%s:%s", factor.getName(), factor.getLevels());
}
}
class Factory extends Parameter.Factory.Base {
private Factory() {
}
public static Factory of(List actualValues) {
return new Factory().addActualValues(actualValues);
}
@Override
public Parameter create(String name) {
return new Impl<>(name, this.knownValues);
}
}
}
interface Regex extends Parameter> {
class Impl extends Parameter.Base> implements Regex {
private final FactorSpace factorSpace;
private final RegexComposer regexComposer;
private final Function func;
public Impl(String name, String regex, List> knownValues, Function func) {
super(name, knownValues);
Expr expr = new Parser().parse(regex);
RegexDecomposer translator = new RegexDecomposer(name, expr);
this.func = func;
this.regexComposer = new RegexComposer(name, expr);
this.factorSpace = translator.decompose();
}
public Optional decomposeValue(List value) {
return _decomposeValue(
value,
this.factorSpace.stream(),
this.regexComposer::compose,
Utils.conjunct(this.factorSpace.getConstraints())
);
}
@Override
public List composeValue(Tuple tuple) {
return composeStringValueFrom(tuple).stream().map(func).collect(toList());
}
@Override
protected List decompose() {
return factorSpace.getFactors();
}
@Override
protected List generateConstraints() {
return factorSpace.getConstraints();
}
private List composeStringValueFrom(Tuple tuple) {
return regexComposer.compose(tuple);
}
}
class Factory extends Parameter.Factory.Base> {
private final String regex;
private final Function func;
@Override
public Regex create(String name) {
return create(name, regex, knownValues, func);
}
public static Factory of(String regex, Function func) {
return new Factory<>(regex, func);
}
public static Factory of(String regex) {
return new Factory<>(regex, s -> s);
}
private Factory(String regex, Function func) {
this.regex = requireNonNull(regex);
this.func = requireNonNull(func);
}
private static Regex create(String name, String regex, List> knownValues, Function func) {
return new Impl<>(name, regex, knownValues, func);
}
}
}
interface Fsm extends Parameter> {
class Impl extends Parameter.Base> implements Fsm {
private final FsmComposer composer;
private final FactorSpace factorSpace;
Impl(String name, FiniteStateMachine model, List> knownValues, int scenarioLength) {
super(name, knownValues);
FsmDecomposer decomposer = new FsmDecomposer<>(name, model, scenarioLength);
this.composer = new FsmComposer<>(name, model, scenarioLength);
this.factorSpace = FactorSpace.create(decomposer.getFactors(), decomposer.getConstraints());
}
@Override
public Optional decomposeValue(Scenario value) {
return _decomposeValue(
value,
this.factorSpace.stream(),
tuple -> {
try {
return this.composer.composeValueFrom(tuple);
} catch (InvalidTestException e) {
return false;
}
},
Utils.conjunct(this.factorSpace.getConstraints())
);
}
@Override
public Scenario composeValue(Tuple tuple) {
return composer.composeValueFrom(tuple);
}
@Override
protected List decompose() {
return factorSpace.getFactors();
}
@Override
protected List generateConstraints() {
return factorSpace.getConstraints();
}
}
class Factory extends Parameter.Factory.Base> {
private final Class extends FsmSpec> fsmSpecClass;
private int scenarioLength;
@Override
public Fsm create(String name) {
return new Impl<>(
name,
new FiniteStateMachine.Impl<>(name, this.fsmSpecClass),
knownValues,
scenarioLength
);
}
public Factory(Class extends FsmSpec> fsmSpecClass, int scenarioLength) {
this.fsmSpecClass = requireNonNull(fsmSpecClass);
this.scenarioLength = checkValue(scenarioLength, (Integer value) -> value > 0);
}
public static Factory of(Class extends FsmSpec> fsmSpecClass, int scenarioLength) {
return new Factory<>(fsmSpecClass, scenarioLength);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy