|
35 | 35 | #include "../src/Client/LibevNetProvider.hpp" |
36 | 36 | #include "../src/Client/Connector.hpp" |
37 | 37 |
|
| 38 | +#include <thread> |
| 39 | + |
38 | 40 | const char *localhost = "127.0.0.1"; |
39 | 41 | int port = 3301; |
40 | 42 | int dummy_server_port = 3302; |
@@ -1144,6 +1146,47 @@ response_decoding(Connector<BUFFER, NetProvider> &client) |
1144 | 1146 | client.close(conn); |
1145 | 1147 | } |
1146 | 1148 |
|
| 1149 | +#ifdef __linux__ |
| 1150 | +/** Sleep time for internal wait failure test. */ |
| 1151 | +static constexpr double INTERNAL_WAIT_FAILURE_SLEEP_TIME = 1e5; |
| 1152 | + |
| 1153 | +/** No-op signal handler for internal wait failure test. */ |
| 1154 | +void |
| 1155 | +sigusr_handler(int signo) |
| 1156 | +{ |
| 1157 | + fail_unless(signo != SIGINT); |
| 1158 | +} |
| 1159 | + |
| 1160 | +/** |
| 1161 | + * Helper for setting up an internal wait failure test case. Creates a request and spawns a thread that will send |
| 1162 | + * a signal to the request processing thread to interrupt its wait method. |
| 1163 | + */ |
| 1164 | +void |
| 1165 | +setup_internal_wait_failure_test_case(Connection<Buf_t, NetProvider> &conn, rid_t *f, std::thread *signal_thread) |
| 1166 | +{ |
| 1167 | + *f = conn.call("remote_sleep", std::forward_as_tuple(INTERNAL_WAIT_FAILURE_SLEEP_TIME / 1e6)); |
| 1168 | + fail_unless(!conn.futureIsReady(*f)); |
| 1169 | + pthread_t tid = pthread_self(); |
| 1170 | + *signal_thread = std::thread([tid] { |
| 1171 | + usleep(INTERNAL_WAIT_FAILURE_SLEEP_TIME / 2); |
| 1172 | + pthread_kill(tid, SIGUSR1); |
| 1173 | + }); |
| 1174 | +} |
| 1175 | + |
| 1176 | +/** |
| 1177 | + * Helper for tearing down an internal wait failure test case. Gets the response for the future and joins the |
| 1178 | + * signalling thread. |
| 1179 | + */ |
| 1180 | +void |
| 1181 | +teardown_internal_wait_failure_test_case(Connection<Buf_t, NetProvider> &conn, rid_t f, std::thread &signal_thread) |
| 1182 | +{ |
| 1183 | + fail_unless(conn.futureIsReady(f)); |
| 1184 | + std::optional<Response<Buf_t>> response = conn.getResponse(f); |
| 1185 | + fail_unless(response.has_value()); |
| 1186 | + signal_thread.join(); |
| 1187 | +} |
| 1188 | +#endif /* __linux__ */ |
| 1189 | + |
1147 | 1190 | /** Checks all available `wait` methods of connector. */ |
1148 | 1191 | template <class BUFFER, class NetProvider> |
1149 | 1192 | void |
@@ -1346,6 +1389,41 @@ test_wait(Connector<BUFFER, NetProvider> &client) |
1346 | 1389 | conn.getResponse(f); |
1347 | 1390 | #endif |
1348 | 1391 |
|
| 1392 | +#ifdef __linux__ |
| 1393 | + TEST_CASE("wait methods internal wait failure (gh-121)"); |
| 1394 | + struct sigaction act; |
| 1395 | + act.sa_handler = sigusr_handler; |
| 1396 | + act.sa_flags = 0; |
| 1397 | + sigemptyset(&act.sa_mask); |
| 1398 | + sigaction(SIGUSR1, &act, nullptr); |
| 1399 | + std::thread signal_thread; |
| 1400 | + |
| 1401 | + setup_internal_wait_failure_test_case(conn, &f, &signal_thread); |
| 1402 | + fail_unless(client.wait(conn, f) != 0); |
| 1403 | + conn.reset(); |
| 1404 | + fail_unless(client.wait(conn, f) == 0); |
| 1405 | + teardown_internal_wait_failure_test_case(conn, f, signal_thread); |
| 1406 | + |
| 1407 | + setup_internal_wait_failure_test_case(conn, &f, &signal_thread); |
| 1408 | + fail_unless(client.waitAll(conn, {f}) != 0); |
| 1409 | + conn.reset(); |
| 1410 | + fail_unless(client.waitAll(conn, {f}) == 0); |
| 1411 | + teardown_internal_wait_failure_test_case(conn, f, signal_thread); |
| 1412 | + |
| 1413 | + setup_internal_wait_failure_test_case(conn, &f, &signal_thread); |
| 1414 | + fail_unless(client.waitCount(conn, 1) != 0); |
| 1415 | + conn.reset(); |
| 1416 | + fail_unless(client.waitCount(conn, 1) == 0); |
| 1417 | + teardown_internal_wait_failure_test_case(conn, f, signal_thread); |
| 1418 | + |
| 1419 | + setup_internal_wait_failure_test_case(conn, &f, &signal_thread); |
| 1420 | + fail_unless(!client.waitAny().has_value()); |
| 1421 | + fail_unless(client.waitAny().has_value()); |
| 1422 | + teardown_internal_wait_failure_test_case(conn, f, signal_thread); |
| 1423 | + |
| 1424 | + sigaction(SIGUSR1, nullptr, nullptr); |
| 1425 | +#endif /* __linux__ */ |
| 1426 | + |
1349 | 1427 | client.close(conn); |
1350 | 1428 | } |
1351 | 1429 |
|
|
0 commit comments