Skip to content

Remove (Web|Rest)ClientIntegrationTests#invalidDomain flaky tests #31119

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
hunjipo opened this issue Aug 27, 2023 · 8 comments
Closed

Remove (Web|Rest)ClientIntegrationTests#invalidDomain flaky tests #31119

hunjipo opened this issue Aug 27, 2023 · 8 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: task A general task
Milestone

Comments

@hunjipo
Copy link
Contributor

hunjipo commented Aug 27, 2023

Affects: 6.1.0-SNAPSHOT


  • Spring Version: 6.1.0-SNAPSHOT
  • JDK Version: Java 17

When I tried to run the test case, it reported this error, The stack:

Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
	at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
	at reactor.core.publisher.Mono.block(Mono.java:1738)
	at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
	...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
java.lang.AssertionError: 
Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
	at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
	at reactor.core.publisher.Mono.block(Mono.java:1738)
	at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
	...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
	at org.springframework.web.client.RestClientIntegrationTests.invalidDomain(RestClientIntegrationTests.java:709)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)



RestClientIntegrationTests > invalidDomain(ClientHttpRequestFactory) > [6] Reactor Netty FAILED
    java.lang.AssertionError at RestClientIntegrationTests.java:709
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Aug 27, 2023
@sbrannen
Copy link
Member

Please attempt to run it again.

That sounds like one of our flaky reactive tests.

In light of that, I'm closing this issue.

However, if you find that it fails repeatedly for you, please report back here with further details on your environment.

@sbrannen sbrannen closed this as not planned Won't fix, can't repro, duplicate, stale Aug 27, 2023
@sbrannen sbrannen added in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 27, 2023
@hunjipo
Copy link
Contributor Author

hunjipo commented Aug 27, 2023

In my environment, it always fails.

  • OS: Windows 11 22H2 22621.2134
  • Java: Java 17.0.7
  • CPU: AMD Ryzen 9 7945HX
  • IDEA: 2023.1.2

@sbrannen sbrannen changed the title Test Case RestClientIntegrationTests#invalidDomain failed Test case RestClientIntegrationTests#invalidDomain fails repeatedly Aug 27, 2023
@sbrannen
Copy link
Member

Thanks for the feedback, @hunjipo.

It could potentially be an issue when running on MS Windows.

Someone from the team will investigate it.

@sbrannen sbrannen reopened this Aug 27, 2023
@sbrannen sbrannen added status: waiting-for-triage An issue we've not yet triaged or decided on and removed status: declined A suggestion or change that we don't feel we should currently apply labels Aug 27, 2023
@quaff
Copy link
Contributor

quaff commented Aug 28, 2023

It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:

Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"

@hunjipo
Copy link
Contributor Author

hunjipo commented Aug 28, 2023

It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:

Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"

@quaff Thanks, this is a good direction, and I did indeed have proxy enabled at that time. However, I didn't enable the proxy today, and I also turned off the HTTP proxy in the IDEA settings. Despite this, the test case still failed. Another noteworthy point is that we are throwing a different exception.

@sdeleuze sdeleuze self-assigned this Aug 28, 2023
@sdeleuze
Copy link
Contributor

sdeleuze commented Aug 29, 2023

I can reproduce time to time without a proxy the original exception reported (IllegalStateException). I am wondering if we should use blockOptional() with Optional.orElseThrow(Supplier) to throw a ResourceAccessException for the empty use case.

@rstoyanchev
Copy link
Contributor

It depends if we want to treat the timeout as a ResourceAccessException, essentially an I/O error. In this case the exchangeTimeout is configured at the level of the ReactorNettyClientRequestFactory, but a timeout can also occur at a lower level. So if we decide to handle it this way, then we should also handle the Reactor Netty TimeoutException for consistency.

If we simply increase the default exchangeTimeout, then the test expectations should be met.

Also note that for HTTP Interface Client we have a similar case with two levels of timeout settings, and if you configure timeouts at the HTTP client level, which are more fine-grained, then the exchangeTimeout can get in the way, and it can create confusion as described in #30248. This is why currently the HTTP Interface client does not impose a timeout by default, and instead relies on underlying client timeout values. It occurs to me that when used with RestClient users will once again hit an additional timeout. Perhaps it's worth considering leaving the exchangeTimeout not set at all by default.

@sdeleuze sdeleuze changed the title Test case RestClientIntegrationTests#invalidDomain fails repeatedly Test case (Web|Rest)ClientIntegrationTests#invalidDomain fails repeatedly Oct 24, 2023
@sdeleuze sdeleuze added type: task A general task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 24, 2023
@sdeleuze sdeleuze added this to the 6.0.14 milestone Oct 24, 2023
@sdeleuze sdeleuze changed the title Test case (Web|Rest)ClientIntegrationTests#invalidDomain fails repeatedly Remove (Web|Rest)ClientIntegrationTests#invalidDomain flaky tests Oct 24, 2023
@sdeleuze
Copy link
Contributor

After a related team discussion, we agreed that the wide range of possible different behaviors (dozens of milliseconds to dozens of seconds timeouts, some proxies and security software returning various HTTP code with different bodies, DNS behavior different across OSes) do not allow to have a reliable integration test for invalid domain, so we will just remove those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: task A general task
Projects
None yet
Development

No branches or pull requests

6 participants