001/*************************************************** 002 * Licensed under MIT No Attribution (SPDX: MIT-0) * 003 ***************************************************/ 004 005package org.reactivestreams.tck.flow.support; 006 007import org.reactivestreams.tck.SubscriberBlackboxVerification; 008 009/** 010 * Internal TCK use only. 011 * Add / Remove tests for SubscriberBlackboxVerification here to make sure that they arre added/removed in the other places. 012 */ 013public interface SubscriberBlackboxVerificationRules { 014 /** 015 * Asks for a {@code Subscriber} instance, expects it to call {@code request()} in 016 * a timely manner and signals as many {@code onNext} items as the very first request 017 * amount specified by the {@code Subscriber}. 018 * <p> 019 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.1'>2.1</a> 020 * <p> 021 * Notes: 022 * <ul> 023 * <li>This test emits the number of items requested thus the {@code Subscriber} implementation 024 * should not request too much.</li> 025 * <li>Only the very first {@code request} amount is considered.</li> 026 * <li>This test doesn't signal {@code onComplete} after the first set of {@code onNext} signals 027 * has been emitted and may cause resource leak in 028 * {@code Subscriber}s that expect a finite {@code Publisher}.</li> 029 * <li>The test ignores cancellation from the {@code Subscriber} and emits the requested amount regardless.</li> 030 * </ul> 031 * <p> 032 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 033 * <ul> 034 * <li>if the {@code Subscriber} requires external stimulus to begin requesting; override the 035 * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method 036 * in this case,</li> 037 * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Subscriber} has some time-delay behavior,</li> 038 * <li>if the {@code Subscriber} requests zero or a negative value in some circumstances,</li> 039 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 040 * {@code onNext} methods. 041 * </ul> 042 */ 043 void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable; 044 /** 045 * Currently, this test is skipped because there is no agreed upon approach how 046 * to detect if the {@code Subscriber} really goes async or just responds in 047 * a timely manner. 048 * <p> 049 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.2'>2.2</a> 050 */ 051 void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception; 052 /** 053 * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onComplete} synchronously, 054 * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s 055 * {@code onComplete} implementation. 056 * <p> 057 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.3'>2.3</a> 058 * <p> 059 * Notes: 060 * <ul> 061 * <li>The test checks for the presensce of method named "onComplete" in the current stacktrace when handling 062 * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. 063 * </ul> 064 * <p> 065 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 066 * <ul> 067 * <li>no calls happen to {@code request} or {@code cancel} in response to an {@code onComplete} 068 * directly or indirectly,</li> 069 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 070 * {@code onComplete} methods. 071 * </ul> 072 */ 073 void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable; 074 /** 075 * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onError} synchronously, 076 * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s 077 * {@code onComplete} implementation. 078 * <p> 079 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.3'>2.3</a> 080 * <p> 081 * Notes: 082 * <ul> 083 * <li>The test checks for the presensce of method named "onError" in the current stacktrace when handling 084 * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. 085 * </ul> 086 * <p> 087 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 088 * <ul> 089 * <li>no calls happen to {@code request} or {@code cancel} in response to an {@code onError} 090 * directly or indirectly,</li> 091 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 092 * {@code onError} methods. 093 * </ul> 094 */ 095 void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable; 096 /** 097 * Currently, this test is skipped because there is no way to check what the {@code Subscriber} "considers" 098 * since rule §2.3 forbids interaction from within the {@code onError} and {@code onComplete} methods. 099 * <p> 100 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.4'>2.4</a> 101 * <p> 102 * Notes: 103 * <ul> 104 * <li>It would be possible to check if there was an async interaction with the test's {@code Subscription} 105 * within a grace period but such check is still not generally decisive.</li> 106 * </ul> 107 */ 108 void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception; 109 /** 110 * Asks for a {@code Subscriber}, signals {@code onSubscribe} twice synchronously and expects the second {@code Subscription} gets 111 * cancelled in a timely manner and without any calls to its {@code request} method. 112 * <p> 113 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.5'>2.5</a> 114 * <p> 115 * Notes: 116 * <ul> 117 * <li>The test doesn't signal any other events than {@code onSubscribe} and may cause resource leak in 118 * {@code Subscriber}s that expect a finite {@code Publisher}. 119 * </ul> 120 * <p> 121 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 122 * <ul> 123 * <li>if the {@code Subscribe.onSubscribe} implementation actually tries to detect multiple calls to it,</li> 124 * <li>if the second {@code Subscription} is cancelled asynchronously and that takes longer time than 125 * the {@code TestEnvironment}'s timeout permits.</li> 126 * </ul> 127 */ 128 void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception; 129 130 /** 131 * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation 132 * to make it cancel the {@code Subscription} for some external condition. 133 * <p> 134 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.6'>2.6</a> 135 */ 136 void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception; 137 /** 138 * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation 139 * to issue requests based on external stimulus. 140 * <p> 141 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.7'>2.7</a> 142 */ 143 void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception; 144 /** 145 * Currently, this test is skipped because there is no way to make the {@code Subscriber} implementation 146 * cancel the test's {@code Subscription} and check the outcome of sending {@code onNext}s after such 147 * cancel. 148 * <p> 149 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.8'>2.8</a> 150 */ 151 void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable; 152 /** 153 * Asks for a {@code Subscriber}, expects it to request some amount and in turn be able to receive an {@code onComplete} 154 * synchronously from the {@code request} call without any {@code onNext} signals before that. 155 * <p> 156 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.9'>2.9</a> 157 * <p> 158 * Notes: 159 * <ul> 160 * <li>The test ignores cancellation from the {@code Subscriber}.</li> 161 * <li>Invalid request amounts are ignored by this test.</li> 162 * <li>Concurrent calls to the test's {@code Subscription.request()} must be externally synchronized, otherwise 163 * such case results probabilistically in multiple {@code onComplete} calls by the test.</li> 164 * </ul> 165 * <p> 166 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 167 * <ul> 168 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 169 * {@code onComplete} methods. 170 * <li>if the {@code Subscriber} requires external stimulus to begin requesting; override the 171 * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method 172 * in this case,</li> 173 * </ul> 174 */ 175 void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable; 176 /** 177 * Asks for a {@code Subscriber} and expects it to handle {@code onComplete} independent of whether the {@code Subscriber} 178 * requests items or not. 179 * <p> 180 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.9'>2.9</a> 181 * <p> 182 * Notes: 183 * <ul> 184 * <li>Currently, the test doesn't call {@code onSubscribe} on the {@code Subscriber} which violates §1.9. 185 * </ul> 186 * <p> 187 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 188 * <ul> 189 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 190 * {@code onComplete} methods. 191 * </ul> 192 */ 193 void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable; 194 /** 195 * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. 196 * <p> 197 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.10'>2.10</a> 198 * <p> 199 * Notes: 200 * <ul> 201 * <li>Despite the method name, the test doesn't expect a request signal from {@code Subscriber} and emits the 202 * {@code onError} signal anyway. 203 * </ul> 204 * <p> 205 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 206 * <ul> 207 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 208 * {@code onError} methods. 209 * </ul> 210 */ 211 void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable; 212 213 /** 214 * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. 215 * <p> 216 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.10'>2.10</a> 217 * <p> 218 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 219 * <ul> 220 * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or 221 * {@code onError} methods. 222 * </ul> 223 */ 224 void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable; 225 226 /** 227 * Currently, this test is skipped because it would require analyzing what the {@code Subscriber} implementation 228 * does. 229 * <p> 230 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.11'>2.11</a> 231 */ 232 void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception; 233 /** 234 * Currently, this test is skipped because the test for 235 * {@link #required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal §2.5} 236 * is in a better position to test for handling the reuse of the same {@code Subscriber}. 237 * <p> 238 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.12'>2.12</a> 239 * <p> 240 * Notes: 241 * <ul> 242 * <li>In addition to §2.5, this rule could be better verified when testing a {@code Publisher}'s subscription behavior. 243 * </ul> 244 */ 245 void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable; 246 /** 247 * Currently, this test is skipped because it would require more control over the {@code Subscriber} to 248 * fail internally in response to a set of legal event emissions, not throw any exception from the {@code Subscriber} 249 * methods and have it cancel the {@code Subscription}. 250 * <p> 251 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a> 252 */ 253 void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception; 254 /** 255 * Asks for a {@code Subscriber} and signals an {@code onSubscribe} event with {@code null} as a parameter and 256 * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onSubscribe} method. 257 * <p> 258 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a> 259 * <p> 260 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 261 * <ul> 262 * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onSubscribe} method 263 * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. 264 * </ul> 265 */ 266 void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; 267 /** 268 * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a 269 * {@code onNext} with {@code null} as a parameter and 270 * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onNext} method. 271 * <p> 272 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a> 273 * <p> 274 * Notes: 275 * <ul> 276 * <li>The test ignores cancellation and requests from the {@code Subscriber} and emits the {@code onNext} 277 * signal with a {@code null} parameter anyway.</li> 278 * </ul> 279 * <p> 280 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 281 * <ul> 282 * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method 283 * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. 284 * </ul> 285 */ 286 void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; 287 /** 288 * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a 289 * {@code onError} with {@code null} as a parameter and 290 * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onError} method. 291 * <p> 292 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a> 293 * <p> 294 * Notes: 295 * <ul> 296 * <li>The test ignores cancellation from the {@code Subscriber} and emits the {@code onError} 297 * signal with a {@code null} parameter anyway.</li> 298 * </ul> 299 * <p> 300 * If this test fails, the following could be checked within the {@code Subscriber} implementation: 301 * <ul> 302 * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method 303 * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. 304 * </ul> 305 */ 306 void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; 307 /** 308 * Currently, this test is skipped because there is no agreed upon way for specifying, enforcing and testing 309 * a {@code Subscriber} with an arbitrary context. 310 * <p> 311 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.1'>3.1</a> 312 */ 313 void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception; 314 /** 315 * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and 316 * a {@code Subscription} is not expected to be the active element in an established subscription. 317 * <p> 318 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.8'>3.8</a> 319 */ 320 void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable; 321 /** 322 * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and 323 * a {@code Subscription} is not expected to be the active element in an established subscription. 324 * <p> 325 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.10'>3.10</a> 326 * <p> 327 * Notes: 328 * <ul> 329 * <li>This could be tested with a synchronous source currently not available within the TCK.</li> 330 * </ul> 331 */ 332 void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception; 333 /** 334 * Currently, this test is skipped because signal production is the responsibility of the {@code Publisher} and 335 * a {@code Subscription} is not expected to be the active element in an established subscription. 336 * <p> 337 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.11'>3.11</a> 338 * <p> 339 * Notes: 340 * <ul> 341 * <li>Tests {@link #required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() §2.9} 342 * and {@link #required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() §2.10} are 343 * supposed to cover this case from the {@code Subscriber's} perspective.</li> 344 * </ul> 345 */ 346 void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception; 347 /** 348 * Currently, this test is skipped because it is the responsibility of the {@code Publisher} deal with the case 349 * that all subscribers have cancelled their subscription. 350 * <p> 351 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.14'>3.14</a> 352 * <p> 353 * Notes: 354 * <ul> 355 * <li>The specification lists this as an optional behavior because only some {@code Publisher} implementations 356 * (most likely {@code Processor}s) would coordinate with multiple {@code Subscriber}s.</li> 357 * </ul> 358 */ 359 void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception; 360 /** 361 * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation 362 * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response 363 * to an exception thrown from {@code Subscription.cancel}. 364 * <p> 365 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.15'>3.15</a> 366 */ 367 void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception; 368 /** 369 * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation 370 * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response 371 * to an exception thrown from {@code Subscription.request}. 372 * <p> 373 * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.16'>3.16</a> 374 */ 375 void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception; 376}