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