Skip to content

Commit 042d895

Browse files
committed
!TCK clarify what error publisher is
+ add better readme on what this method is + add better javadoc on this method - removes reference to old style spec annotation from readme + proposing to change method name to "createFailed..." as it is the wording used in the spec and reactive manifesto (footnote 1.1) Resolves reactive-streams#237, reactive-streams#235
1 parent b33420a commit 042d895

File tree

10 files changed

+54
-28
lines changed

10 files changed

+54
-28
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public interface Subscriber<T> {
120120
| <a name="2.8">8</a> | A `Subscriber` MUST be prepared to receive one or more `onNext` signals after having called `Subscription.cancel()` if there are still requested elements pending [see [3.12](#3.12)]. `Subscription.cancel()` does not guarantee to perform the underlying cleaning operations immediately. |
121121
| <a name="2.9">9</a> | A `Subscriber` MUST be prepared to receive an `onComplete` signal with or without a preceding `Subscription.request(long n)` call. |
122122
| <a name="2.10">10</a> | A `Subscriber` MUST be prepared to receive an `onError` signal with or without a preceding `Subscription.request(long n)` call. |
123-
| <a name="2.11">11</a> | A `Subscriber` MUST make sure that all calls on its `onXXX` methods happen-before [[1]](#footnote-2-1) the processing of the respective signals. I.e. the Subscriber must take care of properly publishing the signal to its processing logic. |
123+
| <a name="2.11">11</a> | A `Subscriber` MUST make sure that all calls on its `onXXX` metfaihods happen-before [[1]](#footnote-2-1) the processing of the respective signals. I.e. the Subscriber must take care of properly publishing the signal to its processing logic. |
124124
| <a name="2.12">12</a> | `Subscriber.onSubscribe` MUST be called at most once for a given `Subscriber` (based on object equality). |
125125
| <a name="2.13">13</a> | Calling `onSubscribe`, `onNext`, `onError` or `onComplete` MUST return normally except when any provided parameter is `null` in which case it MUST throw a `java.lang.NullPointerException` to the caller, for all other situations the only legal way for a `Subscriber` to signal failure is by cancelling its `Subscription`. In the case that this rule is violated, any associated `Subscription` to the `Subscriber` MUST be considered as cancelled, and the caller MUST raise this error condition in a fashion that is adequate for the runtime environment. |
126126

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public IterablePublisherTest() {
3030
return new NumberIterablePublisher(0, (int)elements, e);
3131
}
3232

33-
@Override public Publisher<Integer> createErrorStatePublisher() {
33+
@Override public Publisher<Integer> createFailedPublisher() {
3434
return new AsyncIterablePublisher<Integer>(new Iterable<Integer>() {
3535
@Override public Iterator<Integer> iterator() {
3636
throw new RuntimeException("Error state signal!");

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public UnboundedIntegerIncrementPublisherTest() {
2525
return new InfiniteIncrementNumberPublisher(e);
2626
}
2727

28-
@Override public Publisher<Integer> createErrorStatePublisher() {
28+
@Override public Publisher<Integer> createFailedPublisher() {
2929
return new AsyncIterablePublisher<Integer>(new Iterable<Integer>() {
3030
@Override public Iterator<Integer> iterator() {
3131
throw new RuntimeException("Error state signal!");

tck/README.md

+23-5
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Explanations:
6666
@Test public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable
6767
```
6868

69-
... means that this test case is optional, it covers a *MAY* or *SHOULD* Rule of the Specification. This prefix is also used if more configuration is needed in order to run it, e.g. `@Additional(implement = "createErrorStatePublisher") @Test` signals the implementer that in order to include this test case in his test runs, (s)he must implement the `Publisher<T> createErrorStatePublisher()` method.
69+
... means that this test case is optional, it covers a *MAY* or *SHOULD* Rule of the Specification.
7070

7171
```java
7272
@Test public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable
@@ -116,6 +116,25 @@ In order to inform the TCK that your Publiher is not able to signal completion,
116116
}
117117
```
118118

119+
### Testing a "failed" Publisher
120+
The Reactive Streams spec mandates certain behaviours for Publishers which are "failed",
121+
e.g. it was unable to initialize a connection it needs to emit elements.
122+
It may be useful to specifically such known to be failed Publisher using the TCK.
123+
124+
In order to run additional tests on your failed publisher you can implement the `createFailedPublisher` method.
125+
The expected behaviour from the returned implementation is to follow Rule 1.4 and Rule 1.9 - which are concerned
126+
with the order of emiting the Subscription and signaling the failure.
127+
128+
```java
129+
@Override public Publisher<T> createFailedPublisher() {
130+
final String invalidData = "this input string is known it to be failed";
131+
return new MyPublisher(invalidData);
132+
}
133+
```
134+
135+
In case you don't really have a known up-front error state you can put your Publisher into,
136+
you can easily ignore these tests by returning `null` from the `createFailedPublisher` method.
137+
119138
## Publisher Verification
120139

121140
`PublisherVerification` tests verify Publisher as well as some Subscription Rules of the Specification.
@@ -142,7 +161,7 @@ public class RangePublisherTest extends PublisherVerification<Integer> {
142161
}
143162

144163
@Override
145-
public Publisher<Integer> createErrorStatePublisher() {
164+
public Publisher<Integer> createFailedPublisher() {
146165
return new Publisher<Integer>() {
147166
@Override
148167
public void subscribe(Subscriber<Integer> s) {
@@ -427,8 +446,7 @@ public class MyIdentityProcessorVerificationTest extends IdentityProcessorVerifi
427446
// ENABLE ADDITIONAL TESTS
428447

429448
@Override
430-
public Publisher<Integer> createErrorStatePublisher() {
431-
// return error state Publisher instead of null to run additional tests
449+
public Publisher<Integer> createFailedPublisher() {
432450
return null;
433451
}
434452

@@ -504,7 +522,7 @@ class IterablePublisherTest(env: TestEnvironment, publisherShutdownTimeout: Long
504522
def createPublisher(elements: Long): Publisher[Int] = ???
505523

506524
// example error state publisher implementation
507-
override def createErrorStatePublisher(): Publisher[Int] =
525+
override def createFailedPublisher(): Publisher[Int] =
508526
new Publisher[Int] {
509527
override def subscribe(s: Subscriber[Int]): Unit = {
510528
s.onError(new Exception("Unable to serve subscribers right now!"))

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

+9-5
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ public Publisher<T> createPublisher(long elements) {
9494
}
9595

9696
@Override
97-
public Publisher<T> createErrorStatePublisher() {
98-
return IdentityProcessorVerification.this.createErrorStatePublisher();
97+
public Publisher<T> createFailedPublisher() {
98+
return IdentityProcessorVerification.this.createFailedPublisher();
9999
}
100100

101101
@Override
@@ -125,10 +125,14 @@ public boolean skipStochasticTests() {
125125
public abstract Processor<T, T> createIdentityProcessor(int bufferSize);
126126

127127
/**
128-
* Return a Publisher that immediately signals {@code onError} to incoming subscriptions,
129-
* or {@code null} in order to skip them.
128+
* By implementing this method, additional TCK tests concerning a "failed" publishers will be run.
129+
*
130+
* The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription,
131+
* followed by signalling {@code onError} on it, as specified by Rule 1.9.
132+
*
133+
* If you ignore these additional tests, return {@code null} from this method.
130134
*/
131-
public abstract Publisher<T> createErrorStatePublisher();
135+
public abstract Publisher<T> createFailedPublisher();
132136

133137
/**
134138
* Override and return lower value if your Publisher is only able to produce a known number of elements.

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

+9-5
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,14 @@ public static long envPublisherReferenceGCTimeoutMillis() {
8686
public abstract Publisher<T> createPublisher(long elements);
8787

8888
/**
89-
* Return a Publisher in {@code error} state in order to run additional tests on it,
90-
* or {@code null} in order to skip them.
89+
* By implementing this method, additional TCK tests concerning a "failed" publishers will be run.
90+
*
91+
* The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription,
92+
* followed by signalling {@code onError} on it, as specified by Rule 1.9.
93+
*
94+
* If you ignore these additional tests, return {@code null} from this method.
9195
*/
92-
public abstract Publisher<T> createErrorStatePublisher();
96+
public abstract Publisher<T> createFailedPublisher();
9397

9498

9599
/**
@@ -1121,15 +1125,15 @@ public void optionalActivePublisherTest(long elements, boolean completionSignalR
11211125

11221126
public static final String SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE =
11231127
"Skipping because no error state Publisher provided, and the test requires it. " +
1124-
"Please implement PublisherVerification#createErrorStatePublisher to run this test.";
1128+
"Please implement PublisherVerification#createFailedPublisher to run this test.";
11251129

11261130
public static final String SKIPPING_OPTIONAL_TEST_FAILED =
11271131
"Skipping, because provided Publisher does not pass this *additional* verification.";
11281132
/**
11291133
* Additional test for Publisher in error state
11301134
*/
11311135
public void whenHasErrorPublisherTest(PublisherTestRun<T> body) throws Throwable {
1132-
potentiallyPendingTest(createErrorStatePublisher(), body, SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE);
1136+
potentiallyPendingTest(createFailedPublisher(), body, SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE);
11331137
}
11341138

11351139
public void potentiallyPendingTest(Publisher<T> pub, PublisherTestRun<T> body) throws Throwable {

tck/src/test/java/org/reactivestreams/tck/EmptyLazyPublisherTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Publisher<Integer> createPublisher(long elements) {
3131
}
3232

3333
@Override
34-
public Publisher<Integer> createErrorStatePublisher() {
34+
public Publisher<Integer> createFailedPublisher() {
3535
return null;
3636
}
3737

tck/src/test/java/org/reactivestreams/tck/IdentityProcessorVerificationTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANo
4141
return SKIP;
4242
}
4343

44-
@Override public Publisher<Integer> createErrorStatePublisher() {
44+
@Override public Publisher<Integer> createFailedPublisher() {
4545
return SKIP;
4646
}
4747

@@ -107,7 +107,7 @@ public void required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANo
107107
};
108108
}
109109

110-
@Override public Publisher<Integer> createErrorStatePublisher() {
110+
@Override public Publisher<Integer> createFailedPublisher() {
111111
return SKIP;
112112
}
113113
}.required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANonRecoverableError();

tck/src/test/java/org/reactivestreams/tck/PublisherVerificationTest.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete_shou
203203
return 0; // it is an "empty" Publisher
204204
}
205205

206-
@Override public Publisher<Integer> createErrorStatePublisher() {
206+
@Override public Publisher<Integer> createFailedPublisher() {
207207
return null;
208208
}
209209
};
@@ -618,7 +618,7 @@ final PublisherVerification<Integer> noopPublisherVerification() {
618618

619619
}
620620

621-
@Override public Publisher<Integer> createErrorStatePublisher() {
621+
@Override public Publisher<Integer> createFailedPublisher() {
622622
return SKIP;
623623
}
624624
};
@@ -643,7 +643,7 @@ final PublisherVerification<Integer> onErroringPublisherVerification() {
643643

644644
}
645645

646-
@Override public Publisher<Integer> createErrorStatePublisher() {
646+
@Override public Publisher<Integer> createFailedPublisher() {
647647
return SKIP;
648648
}
649649
};
@@ -665,7 +665,7 @@ final PublisherVerification<Integer> customPublisherVerification(final Publisher
665665
return pub;
666666
}
667667

668-
@Override public Publisher<Integer> createErrorStatePublisher() {
668+
@Override public Publisher<Integer> createFailedPublisher() {
669669
return errorPub;
670670
}
671671
};
@@ -694,7 +694,7 @@ final PublisherVerification<Integer> demandIgnoringSynchronousPublisherVerificat
694694

695695
}
696696

697-
@Override public Publisher<Integer> createErrorStatePublisher() {
697+
@Override public Publisher<Integer> createFailedPublisher() {
698698
return SKIP;
699699
}
700700
};
@@ -782,7 +782,7 @@ final PublisherVerification<Integer> demandIgnoringAsynchronousPublisherVerifica
782782

783783
}
784784

785-
@Override public Publisher<Integer> createErrorStatePublisher() {
785+
@Override public Publisher<Integer> createFailedPublisher() {
786786
return SKIP;
787787
}
788788
};

tck/src/test/java/org/reactivestreams/tck/SingleElementPublisherTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Publisher<Integer> createPublisher(long elements) {
3131
}
3232

3333
@Override
34-
public Publisher<Integer> createErrorStatePublisher() {
34+
public Publisher<Integer> createFailedPublisher() {
3535
return null;
3636
}
3737

0 commit comments

Comments
 (0)