com.github.dakusui.jcunit8.factorspace.fsm.Scenario Maven / Gradle / Ivy
package com.github.dakusui.jcunit8.factorspace.fsm;
import com.github.dakusui.jcunit.exceptions.InvalidTestException;
import com.github.dakusui.jcunit.fsm.Action;
import com.github.dakusui.jcunit.fsm.Args;
import com.github.dakusui.jcunit.fsm.FiniteStateMachine;
import com.github.dakusui.jcunit.fsm.State;
import com.github.dakusui.jcunit.fsm.spec.FsmSpec;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static java.util.stream.Collectors.toList;
public interface Scenario extends Stimulus {
Sequence setUp();
Sequence main();
static > Scenario.Builder builder(String name, Class specClass) {
return new Builder<>(name, specClass);
}
String name();
class Impl implements Scenario {
private final Sequence setUp;
private final Sequence main;
private final String name;
public Impl(String name, Sequence setUp, Sequence main) {
this.setUp = setUp;
this.main = main;
this.name = Objects.requireNonNull(name);
}
@Override
public Sequence setUp() {
return this.setUp;
}
@Override
public Sequence main() {
return this.main;
}
@Override
public String name() {
return this.name;
}
@Override
public void accept(Player player) {
player.visit(this);
}
@Override
public String toString() {
return String.format("setUp:%s; main:%s", setUp, main);
}
}
class Builder> {
private final Class spec;
private final FiniteStateMachine fsm;
private final String name;
private SPEC startFrom;
private final List> edges = new LinkedList<>();
public Builder(String name, Class spec) {
this.name = name;
this.spec = Objects.requireNonNull(spec);
this.fsm = FiniteStateMachine.create(name, spec);
this.startFrom(this.fsm.initialState().spec());
}
public Builder startFrom(SPEC state) {
this.startFrom = Objects.requireNonNull(state);
return this;
}
public Builder doAction(String name, Object... args) {
Objects.requireNonNull(name);
return this.doAction(
findAction(name),
new Args(args)
);
}
public Scenario build() {
Sequence setup = new FsmComposer<>(
this.name,
this.fsm,
-1
).composeScenarioToBringUpFsmTo(
findState(
this.startFrom
)
);
//noinspection Convert2MethodRef
Sequence main = this.edges.stream().collect(
() -> new Sequence.Builder<>(),
Sequence.Builder::add,
(Sequence.Builder builder1, Sequence.Builder builder2) -> {
builder1.addAll(builder2.edges);
builder2.addAll(builder1.edges);
}
).build();
return new Impl<>(this.name, setup, main);
}
private Action findAction(String name) {
return this.fsm.actions().stream(
).filter(
action -> action.id().startsWith(name)
).findFirst(
).orElseThrow(
() -> new InvalidTestException(
String.format(
"No action matching '%s' was found in '%s': [%s]",
name,
this.spec.getCanonicalName(),
this.fsm.actions().stream(
).map(
Action::id
).collect(
toList()
)
)
)
);
}
private Builder doAction(Action action, Args args) {
this.edges.add(new Edge.Builder<>(currentState())
.with(action, args)
.to(currentState().expectation(action, args).state)
.build());
return this;
}
private State findState(SPEC stateSpec) {
return this.fsm.states().stream(
).filter(
eachState -> eachState.spec().equals(stateSpec)
).findFirst(
).orElseThrow(
() -> new InvalidTestException(
String.format(
"No state matching '%s' was found in '%s': [%s]",
stateSpec,
this.spec.getCanonicalName(),
this.fsm.states().stream(
).map(
eachState -> eachState == this.fsm.initialState() ?
String.format("*%s*", eachState.spec()) :
eachState.spec().toString()
).collect(
toList()
)
)
)
);
}
private State currentState() {
return this.edges.isEmpty() ?
findState(this.startFrom) :
this.edges.get(this.edges.size() - 1).to;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy