@@ -203,31 +203,35 @@ public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterReciev
203
203
204
204
// Verifies rule: https://github.com/reactive-streams/reactive-streams#2.5
205
205
@ Override @ Test
206
- public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal () throws Exception {
207
- new WhiteboxTestStage (env ) {{
208
- // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail
209
- final Latch secondSubscriptionCancelled = new Latch (env );
210
- sub ().onSubscribe (
211
- new Subscription () {
212
- @ Override
213
- public void request (long elements ) {
214
- env .flop (String .format ("Subscriber %s illegally called `subscription.request(%s)`" , sub (), elements ));
215
- }
206
+ public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal () throws Throwable {
207
+ subscriberTest (new TestStageTestRun () {
208
+ @ Override
209
+ public void run (WhiteboxTestStage stage ) throws Throwable {
210
+ // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail
211
+ final Latch secondSubscriptionCancelled = new Latch (env );
212
+ final Subscriber <? super T > sub = stage .sub ();
213
+ final Subscription subscription = new Subscription () {
214
+ @ Override
215
+ public void request (long elements ) {
216
+ // ignore...
217
+ }
216
218
217
- @ Override
218
- public void cancel () {
219
- secondSubscriptionCancelled .close ();
220
- }
219
+ @ Override
220
+ public void cancel () {
221
+ secondSubscriptionCancelled .close ();
222
+ }
221
223
222
- @ Override
223
- public String toString () {
224
- return "SecondSubscription(should get cancelled)" ;
225
- }
226
- });
224
+ @ Override
225
+ public String toString () {
226
+ return "SecondSubscription(should get cancelled)" ;
227
+ }
228
+ };
229
+ sub .onSubscribe (subscription );
227
230
228
- secondSubscriptionCancelled .expectClose ("Expected 2nd Subscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called." );
229
- env .verifyNoAsyncErrors ();
230
- }};
231
+ secondSubscriptionCancelled .expectClose ("Expected 2nd Subscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called" );
232
+ env .verifyNoAsyncErrors ();
233
+ }
234
+ });
231
235
}
232
236
233
237
// Verifies rule: https://github.com/reactive-streams/reactive-streams#2.6
@@ -348,50 +352,38 @@ public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParame
348
352
@ Override
349
353
public void run (WhiteboxTestStage stage ) throws Throwable {
350
354
351
- {
352
- final Subscriber <? super T > sub = stage .sub ();
353
- boolean gotNPE = false ;
354
- try {
355
- sub .onSubscribe (null );
356
- } catch (final NullPointerException expected ) {
357
- gotNPE = true ;
358
- }
359
- assertTrue (gotNPE , "onSubscribe(null) did not throw NullPointerException" );
355
+ final Subscriber <? super T > sub = stage .sub ();
356
+ boolean gotNPE = false ;
357
+ try {
358
+ sub .onSubscribe (null );
359
+ } catch (final NullPointerException expected ) {
360
+ gotNPE = true ;
360
361
}
362
+ assertTrue (gotNPE , "onSubscribe(null) did not throw NullPointerException" );
361
363
362
- env .verifyNoAsyncErrors ();
364
+ env .verifyNoAsyncErrors (env . defaultTimeoutMillis () );
363
365
}
364
366
});
365
- }// Verifies rule: https://github.com/reactive-streams/reactive-streams#2.13
367
+ }
368
+
369
+ // Verifies rule: https://github.com/reactive-streams/reactive-streams#2.13
366
370
@ Override @ Test
367
371
public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull () throws Throwable {
368
372
subscriberTest (new TestStageTestRun () {
369
373
@ Override
370
374
public void run (WhiteboxTestStage stage ) throws Throwable {
371
375
372
- final Subscription subscription = new Subscription () {
373
- @ Override
374
- public void request (final long elements ) {
375
- }
376
-
377
- @ Override
378
- public void cancel () {
379
- }
380
- };
381
-
382
- {
383
- final Subscriber <? super T > sub = stage .sub ();
384
- boolean gotNPE = false ;
385
- sub .onSubscribe (subscription );
386
- try {
387
- sub .onNext (null );
388
- } catch (final NullPointerException expected ) {
389
- gotNPE = true ;
390
- }
376
+ final Subscriber <? super T > sub = stage .sub ();
377
+ boolean gotNPE = false ;
378
+ try {
379
+ sub .onNext (null );
380
+ } catch (final NullPointerException expected ) {
381
+ gotNPE = true ;
382
+ } finally {
391
383
assertTrue (gotNPE , "onNext(null) did not throw NullPointerException" );
392
384
}
393
385
394
- env .verifyNoAsyncErrors ();
386
+ env .verifyNoAsyncErrors (env . defaultTimeoutMillis () );
395
387
}
396
388
});
397
389
}
@@ -403,29 +395,17 @@ public void required_spec213_onError_mustThrowNullPointerExceptionWhenParameters
403
395
@ Override
404
396
public void run (WhiteboxTestStage stage ) throws Throwable {
405
397
406
- final Subscription subscription = new Subscription () {
407
- @ Override
408
- public void request (final long elements ) {
409
- }
410
-
411
- @ Override
412
- public void cancel () {
413
- }
414
- };
415
-
416
- {
417
398
final Subscriber <? super T > sub = stage .sub ();
418
399
boolean gotNPE = false ;
419
- sub .onSubscribe (subscription );
420
400
try {
421
401
sub .onError (null );
422
402
} catch (final NullPointerException expected ) {
423
403
gotNPE = true ;
404
+ } finally {
405
+ assertTrue (gotNPE , "onError(null) did not throw NullPointerException" );
424
406
}
425
- assertTrue (gotNPE , "onError(null) did not throw NullPointerException" );
426
- }
427
407
428
- env .verifyNoAsyncErrors ();
408
+ env .verifyNoAsyncErrors (env . defaultTimeoutMillis () );
429
409
}
430
410
});
431
411
}
@@ -495,11 +475,24 @@ abstract class TestStageTestRun {
495
475
public abstract void run (WhiteboxTestStage stage ) throws Throwable ;
496
476
}
497
477
478
+ /**
479
+ * Prepares subscriber and publisher pair (by subscribing the first to the latter),
480
+ * and then hands over the tests {@link WhiteboxTestStage} over to the test.
481
+ *
482
+ * The test stage is, like in a puppet show, used to orchestrate what each participant should do.
483
+ * Since this is a whitebox test, this allows the stage to completely control when and how to signal / expect signals.
484
+ */
498
485
public void subscriberTest (TestStageTestRun body ) throws Throwable {
499
486
WhiteboxTestStage stage = new WhiteboxTestStage (env , true );
500
487
body .run (stage );
501
488
}
502
489
490
+ /**
491
+ * Provides a {@link WhiteboxTestStage} without performing any additional setup,
492
+ * like the {@link org.reactivestreams.tck.SubscriberWhiteboxVerification#subscriberTest(TestStageTestRun)} would.
493
+ *
494
+ * Use this method to write tests in which you need full control over when and how the initial {@code subscribe} is signalled.
495
+ */
503
496
public void subscriberTestWithoutSetup (TestStageTestRun body ) throws Throwable {
504
497
WhiteboxTestStage stage = new WhiteboxTestStage (env , false );
505
498
body .run (stage );
@@ -559,7 +552,10 @@ public WhiteboxSubscriberProbe<T> createWhiteboxSubscriberProbe(TestEnvironment
559
552
}
560
553
561
554
public T signalNext () throws InterruptedException {
562
- T element = nextT ();
555
+ return signalNext (nextT ());
556
+ }
557
+
558
+ private T signalNext (T element ) throws InterruptedException {
563
559
sendNext (element );
564
560
return element ;
565
561
}
@@ -577,7 +573,7 @@ public void verifyNoAsyncErrors() {
577
573
/**
578
574
* This class is intented to be used as {@code Subscriber} decorator and should be used in {@code pub.subscriber(...)} calls,
579
575
* in order to allow intercepting calls on the underlying {@code Subscriber}.
580
- * This delegation allows the proxy to implement {@link org.reactivestreams.tck.SubscriberWhiteboxVerification. BlackboxProbe} assertions.
576
+ * This delegation allows the proxy to implement {@link BlackboxProbe} assertions.
581
577
*/
582
578
public static class BlackboxSubscriberProxy <T > extends BlackboxProbe <T > implements Subscriber <T > {
583
579
@@ -741,8 +737,6 @@ private SubscriberPuppet puppet() {
741
737
public void registerOnSubscribe (SubscriberPuppet p ) {
742
738
if (!puppet .isCompleted ()) {
743
739
puppet .complete (p );
744
- } else {
745
- env .flop (String .format ("Subscriber %s illegally accepted a second Subscription" , sub ()));
746
740
}
747
741
}
748
742
0 commit comments