Skip to content

(TCK) SubscriberBlackboxVerification.required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete (onError) #460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pavelrappo opened this issue Jun 5, 2019 · 1 comment · Fixed by #483

Comments

@pavelrappo
Copy link

pavelrappo commented Jun 5, 2019

There are two tests in SubscriberBlackboxVerification that verify conformance to Rule 2.3:

Subscriber.onComplete() and Subscriber.onError(Throwable t) MUST NOT call any methods on the Subscription or the Publisher.

I can see that this is done by examining the call stack, looking for the specific methods' names:

        final Subscription subs = new Subscription() {
          @Override
          public void request(long n) {
            Throwable thr = new Throwable();
            for (StackTraceElement stackElem : thr.getStackTrace()) {
              if (stackElem.getMethodName().equals("onError")) {
                env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
              }
            }
          }

          @Override
          public void cancel() {
            Throwable thr = new Throwable();
            for (StackTraceElement stackElem : thr.getStackTrace()) {
              if (stackElem.getMethodName().equals("onError")) {
                env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
              }
            }
          }
        };

It seems to do the job, however, the approach might be brittle. The reason is that approach is not specific enough. It might produce false positives as it disregards the objects on which onError and onComplete are called. A method can be similarly named, but otherwise unrelated. Or the method can be called on a different Subscriber (i.e. calling subscription1.cancel() from subscriber2.onComplete()).

Could a ThreadLocal<Boolean> flag solution be any better? Before calling onError on onComplete on Subscriber the test sets that flag. Upon exit from those methods the flag is cleared. Inside Subscription's cancel and request(long) the flag is being checked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants