|
27 | 27 | #include "cpprest/http_listener.h"
|
28 | 28 | #endif
|
29 | 29 |
|
| 30 | +#include <chrono> |
| 31 | +#include <thread> |
| 32 | + |
30 | 33 | using namespace web;
|
31 | 34 | using namespace utility;
|
32 | 35 | using namespace concurrency;
|
@@ -400,6 +403,36 @@ TEST_FIXTURE(uri_address, cancel_while_downloading_data)
|
400 | 403 | }
|
401 | 404 | #endif
|
402 | 405 |
|
| 406 | +// Try to connect to a server on a closed port and cancel the operation. |
| 407 | +TEST_FIXTURE(uri_address, cancel_bad_port) |
| 408 | +{ |
| 409 | + // http_client_asio had a bug where, when canceled, it would cancel only the |
| 410 | + // current connection but then go and try the next address from the list of |
| 411 | + // resolved addresses, i.e., it wouldn't actually cancel as long as there |
| 412 | + // are more addresses to try. Consequently, it would not report the task as |
| 413 | + // being canceled. This was easiest to observe when trying to connect to a |
| 414 | + // server that does not respond on a certain port, otherwise the timing |
| 415 | + // might be tricky. |
| 416 | + |
| 417 | + // We need to connect to a URI for which there are multiple addresses |
| 418 | + // associated (i.e., multiple A records). |
| 419 | + web::http::uri uri(U("https://microsoft.com:442/")); |
| 420 | + |
| 421 | + // Send request. |
| 422 | + http_client c(uri); |
| 423 | + web::http::http_request r; |
| 424 | + auto cts = pplx::cancellation_token_source(); |
| 425 | + auto ct = cts.get_token(); |
| 426 | + auto t = c.request(r, ct); |
| 427 | + |
| 428 | + // Make sure that the client already finished resolving before canceling, |
| 429 | + // otherwise the bug might not be triggered. |
| 430 | + std::this_thread::sleep_for(std::chrono::seconds(1)); |
| 431 | + cts.cancel(); |
| 432 | + |
| 433 | + VERIFY_THROWS_HTTP_ERROR_CODE(t.get(), std::errc::operation_canceled); |
| 434 | +} |
| 435 | + |
403 | 436 | } // SUITE(connections_and_errors)
|
404 | 437 |
|
405 | 438 | }}}}
|
0 commit comments