LukeMathWalker / wiremock-rs

HTTP mocking to test Rust applications.
Apache License 2.0
631 stars 73 forks source link

Hanging requests #7

Closed exul closed 4 years ago

exul commented 4 years ago

When using a mock server, requests are "hanging" from time to time. The mock server is running, since there's no connection error from the client. I was also able to reproduce this with two different client libraries (reqwest and surf). My attempts to further debug it were not successful, since I'm just getting started with async rust. Which means that I'm also not 100% certain that this is an issue in wiremock, feel free to close this if it's not.

I've created a minimal version here: https://github.com/exul/wiremock-min. With this version I'm able to reproduce the issue on every 5th to 10th run. What is interesting is that if the requests are hanging they hang in both tests (reqwest and surf) using two different wiremock servers.

Rust version:

rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/exul/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

wasm32-unknown-unknown
x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)

OS:

uname -a
Linux xi 5.5.5-arch1-1 #1 SMP PREEMPT Thu, 20 Feb 2020 18:23:09 +0000 x86_64 GNU/Linux

While debugging I've noticed that I can reliably get the mock server hanging by changing https://github.com/LukeMathWalker/wiremock-rs/blob/master/src/mock_server.rs#L89-L95

for _ in 0..40 {
            if TcpStream::connect(mock_server.address()).await.is_ok() {
                break;
            }
            // Sleep between retries
            async_std::task::sleep(Duration::from_millis(50)).await;
        }

to

for _ in 0..40 {
            // Sleep between retries
            async_std::task::sleep(Duration::from_millis(50)).await;

            if TcpStream::connect(mock_server.address()).await.is_ok() {
                break;
            }
        }

Which could mean that something is blocking the async execution or what I did here doesn't make sense at all :-).

LukeMathWalker commented 4 years ago

This looks quite interesting :joy: Does it hang even if you use only one of the two tests in your minimal example? Or both tests are needed to trigger hanging?

exul commented 4 years ago

Using one test is enough to trigger it. I've just created two to check if it's an issue in the client.

LukeMathWalker commented 4 years ago

I managed to reproduce it, I am investigating :+1:

LukeMathWalker commented 4 years ago

If I use the #[async_std::test] on the surf test, it seems to run fine with:

repeat 100 { cargo test -- --nocapture }

with the other test commented out. It seems it's something due to the interaction between tokio and bastion.

LukeMathWalker commented 4 years ago

@o0Ignition0o gave me a huge hand and its PR should have fixed the issue - I haven't been able to replicate it locally again. Can you try it again on your machine? If all it's good I am going to cut a new patch release tomorrow morning.