use of reactor.test.ParameterizedTestWithName in project reactor-core by reactor.
the class BoundedElasticSchedulerTest method whenCapReachedPicksLeastBusyExecutorWithContention.
@ParameterizedTestWithName
@CsvSource(value = { "4, 1", "4, 100", "4, 1000", "100, 1", "100, 100", "100, 1000", "1000, 1", "1000, 100", "1000, 1000", "10000, 1", "10000, 100", "10000, 1000" })
void whenCapReachedPicksLeastBusyExecutorWithContention(int maxThreads, int contention) throws InterruptedException {
BoundedElasticScheduler s = scheduler(maxThreads);
HashSet<BoundedElasticScheduler.BoundedState> boundedStates = new HashSet<>();
// reach the cap of workers and keep track of boundedStates
for (int i = 0; i < maxThreads; i++) {
boundedStates.add(afterTest.autoDispose(s.boundedServices.pick()));
}
assertThat(boundedStates).as("all distinct").hasSize(maxThreads);
CountDownLatch latch = new CountDownLatch(1);
AtomicInteger countDown = new AtomicInteger(contention);
AtomicInteger errors = new AtomicInteger();
ExecutorService executorService = Executors.newFixedThreadPool(contention);
AtomicIntegerArray busyPattern = new AtomicIntegerArray(Math.max(5, contention));
for (int i = 0; i < contention; i++) {
executorService.submit(() -> {
if (countDown.get() <= 0) {
return;
}
try {
BoundedElasticScheduler.BoundedState bs = s.boundedServices.pick();
assertThat(boundedStates).as("picked a busy one").contains(bs);
assertThat(bs.markPicked()).isTrue();
int business = bs.markCount;
busyPattern.incrementAndGet(business);
} catch (Throwable t) {
errors.incrementAndGet();
t.printStackTrace();
countDown.set(0);
latch.countDown();
} finally {
if (countDown.decrementAndGet() <= 0) {
latch.countDown();
}
}
});
}
assertThat(latch.await(10, TimeUnit.SECONDS)).as("latch").isTrue();
executorService.shutdownNow();
assertThat(errors).as("errors").hasValue(0);
int maxPicks = 0;
for (int businessFactor = 0; businessFactor < busyPattern.length(); businessFactor++) {
int pickCount = busyPattern.get(businessFactor);
if (pickCount == 0)
continue;
if (pickCount > maxPicks)
maxPicks = pickCount;
LOGGER.trace("Picked {} times at business level {}", pickCount, businessFactor);
}
final int expectedMaxPick = Math.min(contention, maxThreads);
Offset<Integer> offset;
if (expectedMaxPick < 10) {
offset = Offset.offset(1);
} else if (expectedMaxPick < 1000) {
offset = Offset.offset(10);
} else {
offset = Offset.offset(50);
}
assertThat(maxPicks).as("maxPicks").isCloseTo(expectedMaxPick, offset);
LOGGER.info("Max picks {} ", maxPicks);
}
use of reactor.test.ParameterizedTestWithName in project reactor-core by reactor.
the class FluxDoOnEachTest method errorCallbackError.
@ParameterizedTestWithName
@MethodSource("sourcesError")
void errorCallbackError(Flux<Integer> source) {
AssertSubscriber<Integer> ts = AssertSubscriber.create();
LongAdder state = new LongAdder();
IllegalStateException err = new IllegalStateException("test");
source.doOnEach(s -> {
if (s.isOnError()) {
state.increment();
throw Exceptions.propagate(err);
}
}).filter(t -> true).subscribe(ts);
ts.assertNoValues();
ts.assertError(IllegalStateException.class);
ts.assertErrorWith(e -> e.getSuppressed()[0].getMessage().equals(sourceErrorMessage));
ts.assertErrorWith(e -> e.getMessage().equals("test"));
assertThat(state.intValue()).isEqualTo(1);
}
use of reactor.test.ParameterizedTestWithName in project reactor-core by reactor.
the class FluxCreateTest method secondOnDisposeHandlerIsDisposedImmediately.
@ParameterizedTestWithName
@EnumSource(OverflowStrategy.class)
void secondOnDisposeHandlerIsDisposedImmediately(OverflowStrategy overflowStrategy) {
AtomicInteger firstDisposed = new AtomicInteger();
AtomicInteger secondDisposed = new AtomicInteger();
Flux.create(sink -> sink.onDispose(firstDisposed::incrementAndGet).onDispose(secondDisposed::incrementAndGet), overflowStrategy).subscribe();
assertThat(firstDisposed).as("first handler for %s", overflowStrategy).hasValue(0);
assertThat(secondDisposed).as("second handler for %s", overflowStrategy).hasValue(1);
}
use of reactor.test.ParameterizedTestWithName in project reactor-core by reactor.
the class FluxDoOnEachTest method error.
@ParameterizedTestWithName
@MethodSource("sourcesError")
void error(Flux<Integer> source) {
AssertSubscriber<Integer> ts = AssertSubscriber.create();
AtomicReference<Integer> onNext = new AtomicReference<>();
AtomicReference<Throwable> onError = new AtomicReference<>();
AtomicBoolean onComplete = new AtomicBoolean();
LongAdder state = new LongAdder();
source.doOnEach(s -> {
if (s.isOnNext()) {
onNext.set(s.get());
state.increment();
} else if (s.isOnError()) {
onError.set(s.getThrowable());
} else if (s.isOnComplete()) {
onComplete.set(true);
}
}).filter(t -> true).subscribe(ts);
assertThat(onNext).hasValue(null);
assertThat(onError.get()).isInstanceOf(IllegalStateException.class).hasMessage(sourceErrorMessage);
assertThat(onComplete).isFalse();
assertThat(state.intValue()).isZero();
}
use of reactor.test.ParameterizedTestWithName in project reactor-core by reactor.
the class FluxOnAssemblyTest method checkpointDescriptionAndForceStackForParallel.
@ParameterizedTestWithName
@ValueSource(booleans = { false, true })
void checkpointDescriptionAndForceStackForParallel(boolean debugModeOn) {
if (debugModeOn) {
Hooks.onOperatorDebug();
}
StringWriter sw = new StringWriter();
Flux<Integer> tested = Flux.range(1, 10).parallel(2).transformGroups(g -> g.map(i -> (Integer) null)).checkpoint("heavy", true).sequential().doOnError(t -> t.printStackTrace(new PrintWriter(sw)));
StepVerifier.create(tested).verifyError();
String debugStack = sw.toString();
if (debugModeOn) {
// the traceback "error has been observed" contains both individual ops and checkpoint with description,
// assembly points to map, with no description
assertThat(debugStack).contains("Assembly trace from producer [reactor.core.publisher.FluxMap] :").contains("*__ParallelFlux.transformGroups ⇢ at reactor.core.publisher.FluxOnAssemblyTest.checkpointDescriptionAndForceStackForParallel(").contains("checkpoint(heavy) ⇢ at reactor.core.publisher.FluxOnAssemblyTest.checkpointDescriptionAndForceStackForParallel(");
} else {
// the traceback "error has been observed" only contains the checkpoint, with callsite and description,
// assembly points to parallelSource and reflects description
assertThat(debugStack).contains("Assembly trace from producer [reactor.core.publisher.ParallelSource], described as [heavy] :").contains("checkpoint(heavy) ⇢ at reactor.core.publisher.FluxOnAssemblyTest.checkpointDescriptionAndForceStackForParallel(").doesNotContain("ParallelFlux.transformGroups ⇢ at");
}
}
Aggregations