io.hyperfoil.api.config.ScenarioBuilder Maven / Gradle / Ivy
/*
* Copyright 2018 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 io.hyperfoil.api.config;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Ståle Pedersen
*/
public class ScenarioBuilder {
private final PhaseBuilder> phaseBuilder;
private final PhaseForkBuilder forkBuilder;
private List initialSequences = new ArrayList<>();
private List sequences = new ArrayList<>();
private Scenario scenario;
private int maxRequests = 16;
// We don't use sum of concurrency because that could be excessively high
private int maxSequences = 16;
ScenarioBuilder(PhaseBuilder> phaseBuilder, PhaseForkBuilder forkBuilder) {
this.phaseBuilder = phaseBuilder;
this.forkBuilder = forkBuilder;
}
public PhaseForkBuilder fork() {
return forkBuilder;
}
public PhaseBuilder> endScenario() {
return phaseBuilder;
}
private void initialSequence(SequenceBuilder sequence) {
initialSequences.add(sequence);
sequence(sequence);
}
public List resetInitialSequences() {
List prev = this.initialSequences;
initialSequences = new ArrayList<>();
return prev;
}
public SequenceBuilder initialSequence(String name, SequenceBuilder copyFrom) {
SequenceBuilder sequenceBuilder = copyFrom == null ? new SequenceBuilder(this) : copyFrom.copy(this);
sequenceBuilder.nextSequence(null);
initialSequence(sequenceBuilder.name(name));
return sequenceBuilder;
}
public SequenceBuilder initialSequence(String name) {
SequenceBuilder builder = new SequenceBuilder(this).name(name);
initialSequence(builder);
return builder;
}
private void sequence(SequenceBuilder sequence) {
sequence.id(sequences.size());
sequences.add(sequence);
}
public SequenceBuilder sequence(String name, SequenceBuilder copyFrom) {
SequenceBuilder sequenceBuilder = copyFrom == null ? new SequenceBuilder(this) : copyFrom.copy(this);
sequenceBuilder.nextSequence(null);
sequence(sequenceBuilder.name(name));
return sequenceBuilder;
}
public SequenceBuilder sequence(String name) {
SequenceBuilder builder = new SequenceBuilder(this).name(name);
sequence(builder);
return builder;
}
public boolean hasSequence(String name) {
return sequences.stream().anyMatch(sb -> name.equals(sb.name()));
}
public SequenceBuilder findSequence(String name) {
return sequences.stream().filter(sb -> name.equals(sb.name())).findFirst()
.orElseThrow(() -> new BenchmarkDefinitionException("No sequence " + name + " in phase " + endScenario().name()));
}
public ScenarioBuilder maxRequests(int maxRequests) {
this.maxRequests = maxRequests;
return this;
}
public ScenarioBuilder maxSequences(int maxSequences) {
this.maxSequences = maxSequences;
return this;
}
public void prepareBuild() {
new ArrayList<>(sequences).forEach(SequenceBuilder::prepareBuild);
}
public Scenario build() {
Locator.push(this);
try {
if (scenario != null) {
return scenario;
}
if (initialSequences.isEmpty()) {
throw new BenchmarkDefinitionException("No initial sequences in phase " + endScenario().name());
}
Sequence[] initialSequences = new Sequence[this.initialSequences.size()];
int offset = 0;
for (int i = 0; i < this.initialSequences.size(); i++) {
Sequence sequence = this.initialSequences.get(i).build(offset);
initialSequences[i] = sequence;
offset += sequence.concurrency() > 0 ? sequence.concurrency() : 1;
}
Sequence[] sequences = new Sequence[this.sequences.size()];
for (int i = 0; i < this.sequences.size(); i++) {
Sequence sequence = this.sequences.get(i).build(offset);
sequences[i] = sequence;
offset += sequence.concurrency() > 0 ? sequence.concurrency() : 1;
}
int maxSequences = Math.max(Stream.of(sequences).mapToInt(sequence -> {
boolean isInitial = Stream.of(initialSequences).anyMatch(s -> s == sequence);
return isInitial ? sequence.concurrency() : sequence.concurrency() + 1;
}).max().orElse(1), this.maxSequences);
return scenario = new Scenario(
initialSequences,
sequences,
maxRequests,
maxSequences);
} finally {
Locator.pop();
}
}
public void readFrom(ScenarioBuilder other) {
this.sequences = other.sequences.stream()
.map(seq -> seq.copy(this)).collect(Collectors.toList());
this.initialSequences = other.initialSequences.stream()
.map(seq -> findMatchingSequence(seq.name())).collect(Collectors.toList());
}
private SequenceBuilder findMatchingSequence(String name) {
return this.sequences.stream().filter(s2 -> s2.name().equals(name)).findFirst().orElseThrow(IllegalStateException::new);
}
}