package io.vertx.junit5;
import java.util.Objects;
import java.util.function.Consumer;
final class CountingCheckpoint implements Checkpoint {
private final Consumer<Checkpoint> satisfactionTrigger;
private final Consumer<Throwable> overuseTrigger;
private final int requiredNumberOfPasses;
private final StackTraceElement creationCallSite;
private int numberOfPasses = 0;
private boolean satisfied = false;
static CountingCheckpoint laxCountingCheckpoint(Consumer<Checkpoint> satisfactionTrigger, int requiredNumberOfPasses) {
return new CountingCheckpoint(satisfactionTrigger, null, requiredNumberOfPasses);
}
static CountingCheckpoint strictCountingCheckpoint(Consumer<Checkpoint> satisfactionTrigger, Consumer<Throwable> overuseTrigger, int requiredNumberOfPasses) {
Objects.requireNonNull(overuseTrigger);
return new CountingCheckpoint(satisfactionTrigger, overuseTrigger, requiredNumberOfPasses);
}
private CountingCheckpoint(Consumer<Checkpoint> satisfactionTrigger, Consumer<Throwable> overuseTrigger, int requiredNumberOfPasses) {
Objects.requireNonNull(satisfactionTrigger);
if (requiredNumberOfPasses <= 0) {
throw new IllegalArgumentException("A checkpoint needs at least 1 pass");
}
this.creationCallSite = findCallSite();
this.satisfactionTrigger = satisfactionTrigger;
this.overuseTrigger = overuseTrigger;
this.requiredNumberOfPasses = requiredNumberOfPasses;
}
private StackTraceElement findCallSite() {
StackTraceElement[] stackTrace = new Exception().getStackTrace();
for (int i = stackTrace.length - 1; i >= 0; i--) {
if (stackTrace[i].getClassName().equals(VertxTestContext.class.getName())) {
return stackTrace[i + 1];
}
}
return stackTrace[1];
}
@Override
public void flag() {
boolean callSatisfactionTrigger = false;
boolean callOveruseTrigger = false;
synchronized (this) {
if (satisfied) {
callOveruseTrigger = true;
} else {
numberOfPasses = numberOfPasses + 1;
if (numberOfPasses == requiredNumberOfPasses) {
callSatisfactionTrigger = true;
satisfied = true;
}
}
}
if (callSatisfactionTrigger) {
satisfactionTrigger.accept(this);
} else if (callOveruseTrigger && overuseTrigger != null) {
overuseTrigger.accept(new IllegalStateException("Strict checkpoint flagged too many times"));
}
}
public boolean satisfied() {
return this.satisfied;
}
public StackTraceElement creationCallSite() {
return creationCallSite;
}
}