this.initialRequest = initialRequest; this.logger = debugEnabled ? Loggers.getLogger(StepVerifier.class) : null; this.script = conflateScript(script, this.logger); this.taskEvents = new ConcurrentLinkedQueue<>(); Event<T> event;
Instant now = Instant.now(); DefaultVerifySubscriber<T> newVerifier = new DefaultVerifySubscriber<>( this.parent.script, this.parent.errorFormatter, newVerifier.verify(duration); return toSubscriber().verify(duration);
void waitTaskEvent() { Event<T> event; while ((event = taskEvents.poll()) != null) { try { if (event instanceof SubscriptionTaskEvent) { updateRequested(event); } ((TaskEvent<T>) event).run(this); } catch (Throwable t) { Exceptions.throwIfFatal(t); cancel(); if (t instanceof AssertionError) { throw (AssertionError) t; } throw Exceptions.propagate(t); } } }
@SuppressWarnings("unchecked") final void onExpectation(Signal<T> actualSignal) { if (monitorSignal) { setFailure(null, actualSignal, "expected no event: %s", actualSignal); return; Event<T> event = this.script.peek(); if (event == null) { waitTaskEvent(); if (isCancelled()) { return; setFailure(null, actualSignal, "did not expect: %s", actualSignal); return; if (onTaskEvent()) { event = this.script.peek(); if (consumeWhile(actualSignal, (SignalConsumeWhileEvent<T>) event)) { return; if (onSignalCount(actualSignal, (SignalCountEvent<T>) event)) { return; if (onCollect(actualSignal)) { return; if (onSignalSequence(actualSignal, (SignalSequenceEvent<T>) event)) { return;
boolean d = done; if (d && qs.isEmpty()) { if(get() == Operators.cancelledSubscription()){ return; onExpectation(Signal.complete()); if(get() == Operators.cancelledSubscription()){ return; cancel(); onError(Exceptions.unwrap(e)); return; if (!checkRequestOverflow(signal)) { onExpectation(signal); if (d && qs.isEmpty()) { if(get() == Operators.cancelledSubscription()){ return; onExpectation(Signal.complete());
setFailure(null, "expected no fusion; actual: %s", formatFusionMode(m)); setFailure(null, "expected fusion: %s; actual does not support " + "fusion", formatFusionMode(expectedFusionMode)); setFailure(null, "expected fusion mode: %s; actual: %s", formatFusionMode(expectedFusionMode), formatFusionMode(m)); T v; for (; ; ) { if(get() == Operators.cancelledSubscription()){ return; cancel(); onError(Exceptions.unwrap(e)); return; onComplete(); break; onNext(v); setFailure(null, "expected fuseable source but actual Subscription " + "is " + "not: %s",
Instant now = Instant.now(); DefaultVerifySubscriber<T> newVerifier = new DefaultVerifySubscriber<>( this.parent.script, this.parent.errorFormatter, newVerifier.verify(duration); return toSubscriber().verify(duration);
this.initialRequest = initialRequest; this.logger = debugEnabled ? Loggers.getLogger(StepVerifier.class) : null; this.script = conflateScript(script, this.logger); this.taskEvents = new ConcurrentLinkedQueue<>(); Event<T> event;
/** * Converts the {@link StepVerifier} to a {@link Subscriber}, leaving all the * lifecycle management to the user. Most notably: * <ul> * <li>no subscription is performed * <li>no {@link VirtualTimeScheduler} is registered in the Schedulers factories * </ul> * <p> * However if a {@link VirtualTimeScheduler} supplier was passed in originally * it will be invoked and the resulting scheduler will be affected by time * manipulation methods. That scheduler can be retrieved from the subscriber's * {@link DefaultVerifySubscriber#virtualTimeScheduler() virtualTimeScheduler()} * method. */ DefaultVerifySubscriber<T> toSubscriber() { VirtualTimeScheduler vts = null; if (parent.vtsLookup != null) { vts = parent.vtsLookup.get(); } return new DefaultVerifySubscriber<>( this.parent.script, this.parent.errorFormatter, this.parent.initialRequest, this.requestedFusionMode, this.expectedFusionMode, this.debugEnabled, this.parent.options.getInitialContext(), vts); }
@Override public void onSubscribe(Subscription subscription) { Objects.requireNonNull(subscription, "onSubscribe"); if (this.compareAndSet(null, subscription)) { onExpectation(Signal.subscribe(subscription)); if (requestedFusionMode >= Fuseable.NONE) { startFusion(subscription); } else if (initialRequest != 0L) { subscription.request(initialRequest); } } else { subscription.cancel(); if (isCancelled()) { setFailure(null, "an unexpected Subscription has been received: %s; actual: cancelled", subscription); } else { setFailure(null, "an unexpected Subscription has been received: %s; actual: ", subscription, this); } } }
final boolean onSignalCount(Signal<T> actualSignal, SignalCountEvent<T> event) { if (unasserted >= event.count) { this.script.poll(); unasserted -= event.count; } else { if (event.count != 0) { Optional<AssertionError> error = this.checkCountMismatch(event, actualSignal); if (error.isPresent()) { Exceptions.addThrowable(ERRORS, this, error.get()); if(actualSignal.isOnError()) { // #55 ensure the onError is added as a suppressed to the AssertionError error.get().addSuppressed(actualSignal.getThrowable()); } maybeCancel(actualSignal); this.completeLatch.countDown(); } } return true; } return false; }
boolean serializeDrainAndSubscriptionEvent() { int missed = WIP.incrementAndGet(this); if (missed != 1) { return true; } for (; ; ) { if(onSubscriptionLoop()){ return true; } if(establishedFusionMode == Fuseable.ASYNC) { drainAsyncLoop(); } missed = WIP.addAndGet(this, -missed); if (missed == 0) { break; } } return false; }
void waitTaskEvent() { Event<T> event; while ((event = taskEvents.poll()) != null) { try { if (event instanceof SubscriptionTaskEvent) { updateRequested(event); } ((TaskEvent<T>) event).run(this); } catch (Throwable t) { Exceptions.throwIfFatal(t); cancel(); if (t instanceof AssertionError) { throw (AssertionError) t; } throw Exceptions.propagate(t); } } }
@Override public void onNext(T t) { if (establishedFusionMode == Fuseable.ASYNC) { serializeDrainAndSubscriptionEvent(); } else { produced++; unasserted++; if (currentCollector != null) { currentCollector.add(t); } Signal<T> signal = Signal.next(t); if (!checkRequestOverflow(signal)) { onExpectation(signal); } } }
boolean onSubscriptionLoop(){ SubscriptionEvent<T> subscriptionEvent; if (this.script.peek() instanceof SubscriptionEvent) { subscriptionEvent = (SubscriptionEvent<T>) this.script.poll(); if (subscriptionEvent instanceof RequestEvent) { updateRequested(subscriptionEvent); } if (subscriptionEvent.isTerminal()) { doCancel(); return true; } subscriptionEvent.consume(get()); } return false; }
@Override public Assertions verifyThenAssertThat(Duration duration) { HookRecorder stepRecorder = new HookRecorder(); stepRecorder.plugHooksForSubscriber(this); try { //trigger the verify Duration time = verify(duration); //return the assertion API return new DefaultStepVerifierAssertions(stepRecorder, time, errorFormatter); } finally { stepRecorder.unplugHooks(); } }
void doCancel() { cancel(); this.completeLatch.countDown(); }
@Override public Duration verify() { return verify(defaultVerifyTimeout); }
/** Cancels this subscriber if the actual signal is null or not a complete/error */ final void maybeCancel(@Nullable Signal<T> actualSignal) { if (actualSignal == null || (!actualSignal.isOnComplete() && !actualSignal.isOnError())) { cancel(); } }