Skip to content

Commit bc4729b

Browse files
committed
+tck timeouts now have default values as well as are ENV overrideable
1 parent 00c7a51 commit bc4729b

13 files changed

+203
-67
lines changed

.travis.yml

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ jdk:
99
env:
1010
global:
1111
- TERM=dumb
12+
- DEFAULT_TIMEOUT_MILLIS=300
13+
- GC_TIMEOUT_MILLIS=300

examples/src/test/java/org/reactivestreams/example/unicast/AsyncSubscriberTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@
1717

1818
@Test // Must be here for TestNG to find and run this, do not remove
1919
public class AsyncSubscriberTest extends SubscriberBlackboxVerification<Integer> {
20-
final static long DEFAULT_TIMEOUT_MILLIS = 100;
2120

2221
private ExecutorService e;
2322
@BeforeClass void before() { e = Executors.newFixedThreadPool(4); }
2423
@AfterClass void after() { if (e != null) e.shutdown(); }
2524

2625
public AsyncSubscriberTest() {
27-
super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS));
26+
super(new TestEnvironment());
2827
}
2928

3029
@Override public Subscriber<Integer> createSubscriber() {
@@ -53,7 +52,7 @@ public AsyncSubscriberTest() {
5352
};
5453

5554
new NumberIterablePublisher(0, 10, e).subscribe(sub);
56-
latch.await(DEFAULT_TIMEOUT_MILLIS * 10, TimeUnit.MILLISECONDS);
55+
latch.await(env.defaultTimeoutMillis() * 10, TimeUnit.MILLISECONDS);
5756
assertEquals(i.get(), 45);
5857
}
5958

examples/src/test/java/org/reactivestreams/example/unicast/IterablePublisherTest.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,12 @@
1515
@Test // Must be here for TestNG to find and run this, do not remove
1616
public class IterablePublisherTest extends PublisherVerification<Integer> {
1717

18-
final static long DefaultTimeoutMillis = 100;
19-
final static long PublisherReferenceGCTimeoutMillis = 300;
20-
2118
private ExecutorService e;
2219
@BeforeClass void before() { e = Executors.newFixedThreadPool(4); }
2320
@AfterClass void after() { if (e != null) e.shutdown(); }
2421

2522
public IterablePublisherTest() {
26-
super(new TestEnvironment(DefaultTimeoutMillis), PublisherReferenceGCTimeoutMillis);
23+
super(new TestEnvironment());
2724
}
2825

2926
@SuppressWarnings("unchecked")

examples/src/test/java/org/reactivestreams/example/unicast/SyncSubscriberTest.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@
1313
@Test // Must be here for TestNG to find and run this, do not remove
1414
public class SyncSubscriberTest extends SubscriberBlackboxVerification<Integer> {
1515

16-
final static long DefaultTimeoutMillis = 100;
17-
1816
private ExecutorService e;
1917
@BeforeClass void before() { e = Executors.newFixedThreadPool(4); }
2018
@AfterClass void after() { if (e != null) e.shutdown(); }
2119

2220
public SyncSubscriberTest() {
23-
super(new TestEnvironment(DefaultTimeoutMillis));
21+
super(new TestEnvironment());
2422
}
2523

2624
@Override public Subscriber<Integer> createSubscriber() {

examples/src/test/java/org/reactivestreams/example/unicast/UnboundedIntegerIncrementPublisherTest.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,13 @@
1111

1212
@Test // Must be here for TestNG to find and run this, do not remove
1313
public class UnboundedIntegerIncrementPublisherTest extends PublisherVerification<Integer> {
14-
final static long DefaultTimeoutMillis = 200;
15-
final static long PublisherReferenceGCTimeoutMillis = 500;
1614

1715
private ExecutorService e;
1816
@BeforeClass void before() { e = Executors.newFixedThreadPool(4); }
1917
@AfterClass void after() { if (e != null) e.shutdown(); }
2018

2119
public UnboundedIntegerIncrementPublisherTest() {
22-
super(new TestEnvironment(DefaultTimeoutMillis), PublisherReferenceGCTimeoutMillis);
20+
super(new TestEnvironment());
2321
}
2422

2523
@Override public Publisher<Integer> createPublisher(long elements) {

tck/README.md

+64-10
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,8 @@ import org.reactivestreams.tck.TestEnvironment;
132132

133133
public class RangePublisherTest extends PublisherVerification<Integer> {
134134

135-
public static final long DEFAULT_TIMEOUT_MILLIS = 300L;
136-
public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 1000L;
137-
138135
public RangePublisherTest() {
139-
super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS);
136+
super(new TestEnvironment());
140137
}
141138

142139
@Override
@@ -174,6 +171,39 @@ Notable configuration options include:
174171
* `boundedDepthOfOnNextAndRequestRecursion` – which should only be overridden in case of synchronous Publishers. This number will be used to validate if a
175172
`Subscription` actually solves the "unbounded recursion" problem (Rule 3.3).
176173

174+
### Timeout configuration
175+
Publisher tests make use of two kinds of timeouts, one is the `defaultTimeoutMillis` which corresponds to all methods used
176+
within the TCK which await for something to happen. The other timeout is `publisherReferenceGCTimeoutMillis` which is only used in order to verify
177+
[Rule 3.13](https://github.com/reactive-streams/reactive-streams#3.13) which defines that subscriber references MUST be dropped
178+
by the Publisher.
179+
180+
In order to configure these timeouts (for example when running on a slow continious integtation machine), you can either:
181+
182+
**Use env variables** to set these timeouts, in which case the you can just:
183+
184+
```bash
185+
export DEFAULT_TIMEOUT_MILLIS=300
186+
export PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS=500
187+
```
188+
189+
Or **define the timeouts explicitly in code**:
190+
191+
```java
192+
public class RangePublisherTest extends PublisherVerification<Integer> {
193+
194+
public static final long DEFAULT_TIMEOUT_MILLIS = 300L;
195+
public static final long PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS = 500L;
196+
197+
public RangePublisherTest() {
198+
super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS), PUBLISHER_REFERENCE_CLEANUP_TIMEOUT_MILLIS);
199+
}
200+
201+
// ...
202+
}
203+
```
204+
205+
Note that hard-coded values *take precedence* over environment set values (!).
206+
177207
## Subscriber Verification
178208

179209
Subscriber rules Verification is split up into two files (styles) of tests.
@@ -233,10 +263,8 @@ import org.reactivestreams.tck.TestEnvironment;
233263

234264
public class MySubscriberBlackboxVerificationTest extends SubscriberBlackboxVerification<Integer> {
235265

236-
public static final long DEFAULT_TIMEOUT_MILLIS = 300L;
237-
238266
public MySubscriberBlackboxVerificationTest() {
239-
super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS));
267+
super(new TestEnvironment());
240268
}
241269

242270
@Override
@@ -273,10 +301,8 @@ import org.reactivestreams.tck.TestEnvironment;
273301

274302
public class MySubscriberWhiteboxVerificationTest extends SubscriberWhiteboxVerification<Integer> {
275303

276-
public static final long DEFAULT_TIMEOUT_MILLIS = 300L;
277-
278304
public MySubscriberWhiteboxVerificationTest() {
279-
super(new TestEnvironment(DEFAULT_TIMEOUT_MILLIS));
305+
super(new TestEnvironment());
280306
}
281307

282308
@Override
@@ -331,6 +357,34 @@ public class MySubscriberWhiteboxVerificationTest extends SubscriberWhiteboxVeri
331357
}
332358
```
333359

360+
### Timeout configuration
361+
Similarily to `PublisherVerification`, it is possible to set the timeouts used by the TCK to validate subscriber behaviour.
362+
This can be set either by using env variables or hardcoded explicitly.
363+
364+
**Use env variables** to set the timeout value to be used by the TCK:
365+
366+
```bash
367+
export DEFAULT_TIMEOUT_MILLIS=300
368+
```
369+
370+
Or **define the timeout explicitly in code**:
371+
372+
```java
373+
public class MySubscriberTest extends BlackboxSubscriberVerification<Integer> {
374+
375+
public static final long DEFAULT_TIMEOUT_MILLIS = 300L;
376+
377+
public RangePublisherTest() {
378+
super(new MySubscriberTest(DEFAULT_TIMEOUT_MILLIS));
379+
}
380+
381+
// ...
382+
}
383+
```
384+
385+
Note that hard-coded values *take precedence* over environment set values (!).
386+
387+
334388
## Subscription Verification
335389

336390
Please note that while `Subscription` does **not** have it's own test class, it's rules are validated inside of the `Publisher` and `Subscriber` tests – depending if the Rule demands specific action to be taken by the publishing, or subscribing side of the subscription contract.

tck/src/main/java/org/reactivestreams/tck/PublisherVerification.java

+73-29
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,50 @@
3333
*/
3434
public abstract class PublisherVerification<T> implements PublisherVerificationRules {
3535

36+
private static final String PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV = "PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS";
37+
private static final long DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS = 300L;
38+
3639
private final TestEnvironment env;
3740
private final long publisherReferenceGCTimeoutMillis;
3841

42+
/**
43+
* Constructs a new verification class using the given env and configuration.
44+
*
45+
* @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
46+
*/
3947
public PublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) {
4048
this.env = env;
4149
this.publisherReferenceGCTimeoutMillis = publisherReferenceGCTimeoutMillis;
4250
}
4351

52+
/**
53+
* Constructs a new verification class using the given env and configuration.
54+
*
55+
* The value for {@code publisherReferenceGCTimeoutMillis} will be obtained by using {@link PublisherVerification#envPublisherReferenceGCTimeoutMillis()}.
56+
*/
57+
public PublisherVerification(TestEnvironment env) {
58+
this.env = env;
59+
this.publisherReferenceGCTimeoutMillis = envPublisherReferenceGCTimeoutMillis();
60+
}
61+
62+
/**
63+
* Tries to parse the env variable {@code PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS} as long and returns the value if present,
64+
* OR its default value ({@link PublisherVerification#DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS}).
65+
*
66+
* This value is used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
67+
*
68+
* @throws java.lang.IllegalArgumentException when unable to parse the env variable
69+
*/
70+
public static long envPublisherReferenceGCTimeoutMillis() {
71+
final String envMillis = System.getenv(PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV);
72+
if (envMillis == null) return DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS;
73+
else try {
74+
return Long.parseLong(envMillis);
75+
} catch(NumberFormatException ex) {
76+
throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV, envMillis), ex);
77+
}
78+
}
79+
4480
/**
4581
* This is the main method you must implement in your test incarnation.
4682
* It must create a Publisher for a stream with exactly the given number of elements.
@@ -88,6 +124,14 @@ public long boundedDepthOfOnNextAndRequestRecursion() {
88124
return 1;
89125
}
90126

127+
/**
128+
* The amount of time after which a cancelled Subscriber reference should be dropped.
129+
* See Rule 3.13 for details.
130+
*/
131+
final public long publisherReferenceGCTimeoutMillis() {
132+
return publisherReferenceGCTimeoutMillis;
133+
}
134+
91135
////////////////////// TEST ENV CLEANUP /////////////////////////////////////
92136

93137
@BeforeMethod
@@ -298,20 +342,20 @@ public void onComplete() {
298342
public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable {
299343
try {
300344
whenHasErrorPublisherTest(new PublisherTestRun<T>() {
301-
@Override
302-
public void run(final Publisher<T> pub) throws InterruptedException {
303-
final Latch latch = new Latch(env);
304-
pub.subscribe(new TestEnvironment.TestSubscriber<T>(env) {
305-
@Override
306-
public void onError(Throwable cause) {
307-
latch.assertOpen(String.format("Error-state Publisher %s called `onError` twice on new Subscriber", pub));
308-
latch.close();
309-
}
310-
});
345+
@Override
346+
public void run(final Publisher<T> pub) throws InterruptedException {
347+
final Latch latch = new Latch(env);
348+
pub.subscribe(new TestEnvironment.TestSubscriber<T>(env) {
349+
@Override
350+
public void onError(Throwable cause) {
351+
latch.assertOpen(String.format("Error-state Publisher %s called `onError` twice on new Subscriber", pub));
352+
latch.close();
353+
}
354+
});
311355

312-
latch.expectClose(String.format("Error-state Publisher %s did not call `onError` on new Subscriber", pub));
356+
latch.expectClose(String.format("Error-state Publisher %s did not call `onError` on new Subscriber", pub));
313357

314-
env.verifyNoAsyncErrors(env.defaultTimeoutMillis());
358+
env.verifyNoAsyncErrors(env.defaultTimeoutMillis());
315359
}
316360
});
317361
} catch (SkipException se) {
@@ -404,25 +448,25 @@ public void run(Publisher<T> pub) throws Throwable {
404448
@Override @Test
405449
public void required_spec112_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorInsteadOfOnSubscribe() throws Throwable {
406450
whenHasErrorPublisherTest(new PublisherTestRun<T>() {
407-
@Override
408-
public void run(Publisher<T> pub) throws Throwable {
409-
final Latch onErrorLatch = new Latch(env);
410-
ManualSubscriberWithSubscriptionSupport<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(env) {
411-
@Override
412-
public void onError(Throwable cause) {
413-
onErrorLatch.assertOpen("Only one onError call expected");
414-
onErrorLatch.close();
415-
}
451+
@Override
452+
public void run(Publisher<T> pub) throws Throwable {
453+
final Latch onErrorLatch = new Latch(env);
454+
ManualSubscriberWithSubscriptionSupport<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(env) {
455+
@Override
456+
public void onError(Throwable cause) {
457+
onErrorLatch.assertOpen("Only one onError call expected");
458+
onErrorLatch.close();
459+
}
416460

417-
@Override
418-
public void onSubscribe(Subscription subs) {
419-
env.flop("onSubscribe should not be called if Publisher is unable to subscribe a Subscriber");
420-
}
421-
};
422-
pub.subscribe(sub);
423-
onErrorLatch.assertClosed("Should have received onError");
461+
@Override
462+
public void onSubscribe(Subscription subs) {
463+
env.flop("onSubscribe should not be called if Publisher is unable to subscribe a Subscriber");
464+
}
465+
};
466+
pub.subscribe(sub);
467+
onErrorLatch.assertClosed("Should have received onError");
424468

425-
env.verifyNoAsyncErrors();
469+
env.verifyNoAsyncErrors();
426470
}
427471
});
428472
}

tck/src/main/java/org/reactivestreams/tck/SubscriberBlackboxVerification.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import org.reactivestreams.tck.TestEnvironment.ManualPublisher;
77
import org.reactivestreams.tck.TestEnvironment.ManualSubscriber;
88
import org.reactivestreams.tck.support.Optional;
9-
import org.reactivestreams.tck.support.TestException;
109
import org.reactivestreams.tck.support.SubscriberBlackboxVerificationRules;
10+
import org.reactivestreams.tck.support.TestException;
1111
import org.testng.SkipException;
1212
import org.testng.annotations.AfterClass;
1313
import org.testng.annotations.BeforeClass;
@@ -16,7 +16,6 @@
1616

1717
import java.util.concurrent.ExecutorService;
1818
import java.util.concurrent.Executors;
19-
import java.util.concurrent.atomic.AtomicBoolean;
2019

2120
import static org.reactivestreams.tck.SubscriberWhiteboxVerification.BlackboxSubscriberProxy;
2221

@@ -34,7 +33,7 @@
3433
public abstract class SubscriberBlackboxVerification<T> extends WithHelperPublisher<T>
3534
implements SubscriberBlackboxVerificationRules {
3635

37-
private final TestEnvironment env;
36+
protected final TestEnvironment env;
3837

3938
protected SubscriberBlackboxVerification(TestEnvironment env) {
4039
this.env = env;

0 commit comments

Comments
 (0)