| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include <iostream> | ||
| 2 | #include <thread> | ||
| 3 | #include <chrono> | ||
| 4 | #include <signal.h> | ||
| 5 | #include <zmq.hpp> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include <atomic> | ||
| 8 | #include <cstring> // for memset | ||
| 9 | #include "data_stream_assert.h" | ||
| 10 | |||
| 11 | // Test 1: EAGAIN - Non-blocking mode was requested and no messages are available | ||
| 12 | 1 | void test_eagain(zmq::context_t& context) { | |
| 13 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n1. Test EAGAIN (no messages available in non-blocking mode):" << std::endl; |
| 14 |
1/1✓ Branch 0 (4→5) taken 1 times.
|
1 | zmq::socket_t pull_socket(context, ZMQ_PULL); |
| 15 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | pull_socket.set(zmq::sockopt::linger, -1); |
| 16 |
1/1✓ Branch 0 (6→7) taken 1 times.
|
1 | pull_socket.connect("tcp://127.0.0.1:5555"); |
| 17 | |||
| 18 | 1 | zmq::message_t msg; | |
| 19 |
1/1✓ Branch 0 (8→9) taken 1 times.
|
1 | zmq::recv_result_t result = pull_socket.recv(msg, zmq::recv_flags::dontwait); |
| 20 |
1/2✓ Branch 0 (10→11) taken 1 times.
✗ Branch 1 (10→34) not taken.
|
1 | if(!result.has_value()) { |
| 21 |
1/1✓ Branch 0 (11→12) taken 1 times.
|
1 | int zmq_errno_val = zmq_errno(); |
| 22 |
5/5✓ Branch 0 (12→13) taken 1 times.
✓ Branch 2 (13→14) taken 1 times.
✓ Branch 4 (14→15) taken 1 times.
✓ Branch 6 (15→16) taken 1 times.
✓ Branch 8 (16→17) taken 1 times.
|
1 | std::cout << " Error code caught is: " << zmq_errno_val << " and should be EAGAIN : " << EAGAIN << std::endl; |
| 23 |
4/4✓ Branch 0 (19→20) taken 1 times.
✓ Branch 2 (22→23) taken 1 times.
✓ Branch 4 (25→26) taken 1 times.
✓ Branch 6 (26→27) taken 1 times.
|
6 | data_stream_assert(zmq_errno_val == EAGAIN); |
| 24 | } | ||
| 25 | 1 | pull_socket.close(); | |
| 26 | 1 | } | |
| 27 | |||
| 28 | // Test 2: ENOTSUP - The zmq_recv() operation is not supported by this socket type | ||
| 29 | 1 | void test_enotsup(zmq::context_t& context) { | |
| 30 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n2. Test ENOTSUP (operation not supported by socket type):" << std::endl; |
| 31 | 1 | zmq::recv_result_t result; | |
| 32 | try { | ||
| 33 |
1/1✓ Branch 0 (4→5) taken 1 times.
|
1 | zmq::socket_t pub_socket(context, ZMQ_PUB); |
| 34 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | pub_socket.connect("tcp://127.0.0.1:5552"); |
| 35 | |||
| 36 | // Attempt to receive on a PUB socket (normally send-only) | ||
| 37 | 1 | zmq::message_t msg; | |
| 38 |
0/1✗ Branch 0 (7→8) not taken.
|
1 | result = pub_socket.recv(msg, zmq::recv_flags::dontwait); |
| 39 | |||
| 40 |
1/2✗ Branch 0 (34→35) not taken.
✓ Branch 1 (34→36) taken 1 times.
|
3 | } catch (const zmq::error_t& e) { |
| 41 |
7/7✓ Branch 0 (37→38) taken 1 times.
✓ Branch 2 (39→40) taken 1 times.
✓ Branch 4 (40→41) taken 1 times.
✓ Branch 6 (42→43) taken 1 times.
✓ Branch 8 (43→44) taken 1 times.
✓ Branch 10 (44→45) taken 1 times.
✓ Branch 12 (45→46) taken 1 times.
|
1 | std::cout << " Exception caught: " << e.what() << " (code: " << e.num() << ") should be ENOTSUP : " << ENOTSUP << std::endl; |
| 42 |
4/4✓ Branch 0 (48→49) taken 1 times.
✓ Branch 2 (51→52) taken 1 times.
✓ Branch 4 (54→55) taken 1 times.
✓ Branch 6 (56→57) taken 1 times.
|
5 | data_stream_assert(e.num() == ENOTSUP); |
| 43 | 1 | } | |
| 44 |
4/4✓ Branch 0 (13→14) taken 1 times.
✓ Branch 2 (16→17) taken 1 times.
✓ Branch 4 (19→20) taken 1 times.
✓ Branch 6 (21→22) taken 1 times.
|
5 | data_stream_assert(!result.has_value()); |
| 45 | 1 | } | |
| 46 | |||
| 47 | // Test 3: ETERM - The ØMQ context associated with the specified socket was terminated | ||
| 48 | 1 | void test_eterm(){ | |
| 49 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n3. Test ETERM (context was terminated):" << std::endl; |
| 50 | |||
| 51 | 1 | std::atomic<bool> recv_done{false}; | |
| 52 | 1 | std::atomic<int> error_code{0}; | |
| 53 | 1 | std::atomic<bool> recv_started{false}; | |
| 54 | 1 | std::string error_message; | |
| 55 | |||
| 56 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | zmq::context_t temp_context(1); |
| 57 | 1 | zmq::recv_result_t result; | |
| 58 | ✗ | std::thread recv_thread([&]() { | |
| 59 | try { | ||
| 60 |
1/1✓ Branch 0 (2→3) taken 1 times.
|
1 | zmq::socket_t pull_socket(temp_context, ZMQ_PULL); |
| 61 |
1/1✓ Branch 0 (3→4) taken 1 times.
|
1 | pull_socket.set(zmq::sockopt::linger, -1); |
| 62 |
1/1✓ Branch 0 (4→5) taken 1 times.
|
1 | pull_socket.bind("tcp://127.0.0.1:5557"); |
| 63 | 1 | recv_started = true; | |
| 64 | // Blocking recv - will be interrupted by context close() | ||
| 65 | 1 | zmq::message_t msg; | |
| 66 |
0/1✗ Branch 0 (7→8) not taken.
|
1 | result = pull_socket.recv(msg); // BLOCKING |
| 67 |
1/2✗ Branch 0 (18→19) not taken.
✓ Branch 1 (18→20) taken 1 times.
|
3 | } catch (const zmq::error_t& e) { |
| 68 | 1 | error_code = e.num(); | |
| 69 |
1/1✓ Branch 0 (24→25) taken 1 times.
|
1 | error_message = e.what(); |
| 70 | 1 | recv_done = true; | |
| 71 | 1 | } | |
| 72 |
1/1✓ Branch 0 (6→7) taken 1 times.
|
2 | }); |
| 73 | |||
| 74 | // Wait until recv has started | ||
| 75 |
2/2✓ Branch 0 (12→8) taken 1 times.
✓ Branch 1 (12→13) taken 1 times.
|
2 | while (!recv_started.load()) { |
| 76 |
1/1✓ Branch 0 (9→10) taken 1 times.
|
1 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); |
| 77 | } | ||
| 78 | |||
| 79 | // Then close the context to unblock recv | ||
| 80 | 1 | temp_context.close(); | |
| 81 | |||
| 82 | // Wait until recv finishes | ||
| 83 |
1/1✓ Branch 0 (14→15) taken 1 times.
|
1 | recv_thread.join(); |
| 84 | |||
| 85 |
4/4✓ Branch 0 (17→18) taken 1 times.
✓ Branch 2 (20→21) taken 1 times.
✓ Branch 4 (23→24) taken 1 times.
✓ Branch 6 (25→26) taken 1 times.
|
5 | data_stream_assert(!result.has_value()); |
| 86 |
1/2✓ Branch 0 (33→34) taken 1 times.
✗ Branch 1 (33→72) not taken.
|
1 | if(recv_done){ |
| 87 |
7/7✓ Branch 0 (34→35) taken 1 times.
✓ Branch 2 (35→36) taken 1 times.
✓ Branch 4 (36→37) taken 1 times.
✓ Branch 6 (44→45) taken 1 times.
✓ Branch 8 (45→46) taken 1 times.
✓ Branch 10 (46→47) taken 1 times.
✓ Branch 12 (47→48) taken 1 times.
|
2 | std::cout << " Error caught: " << error_message << " (code: " << error_code.load() << ") should be ETERM: " << ETERM << std::endl; |
| 88 |
4/4✓ Branch 0 (50→51) taken 1 times.
✓ Branch 2 (53→54) taken 1 times.
✓ Branch 4 (56→57) taken 1 times.
✓ Branch 6 (64→65) taken 1 times.
|
7 | data_stream_assert(error_code.load() == ETERM); |
| 89 | } | ||
| 90 | 1 | } | |
| 91 | |||
| 92 | // Test 4: ENOTSOCK - The provided socket was invalid | ||
| 93 | 1 | void test_enotsock(zmq::context_t& context) { | |
| 94 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n4. Test ENOTSOCK (socket closed/invalid):" << std::endl; |
| 95 | 1 | zmq::recv_result_t result; | |
| 96 | try { | ||
| 97 |
1/1✓ Branch 0 (4→5) taken 1 times.
|
1 | zmq::socket_t pull_socket(context, ZMQ_PULL); |
| 98 | 1 | pull_socket.close(); // Close the socket explicitly | |
| 99 | |||
| 100 | 1 | zmq::message_t msg; | |
| 101 |
0/1✗ Branch 0 (7→8) not taken.
|
1 | result = pull_socket.recv(msg, zmq::recv_flags::dontwait); |
| 102 |
1/2✗ Branch 0 (34→35) not taken.
✓ Branch 1 (34→36) taken 1 times.
|
3 | } catch (const zmq::error_t& e) { |
| 103 |
7/7✓ Branch 0 (37→38) taken 1 times.
✓ Branch 2 (39→40) taken 1 times.
✓ Branch 4 (40→41) taken 1 times.
✓ Branch 6 (42→43) taken 1 times.
✓ Branch 8 (43→44) taken 1 times.
✓ Branch 10 (44→45) taken 1 times.
✓ Branch 12 (45→46) taken 1 times.
|
1 | std::cout << " Exception caught: " << e.what() << " (code: " << e.num() << ") should be ENOTSOCK: " << ENOTSOCK << std::endl; |
| 104 |
4/4✓ Branch 0 (48→49) taken 1 times.
✓ Branch 2 (51→52) taken 1 times.
✓ Branch 4 (54→55) taken 1 times.
✓ Branch 6 (56→57) taken 1 times.
|
5 | data_stream_assert(e.num() == ENOTSOCK); |
| 105 | 1 | } | |
| 106 |
4/4✓ Branch 0 (13→14) taken 1 times.
✓ Branch 2 (16→17) taken 1 times.
✓ Branch 4 (19→20) taken 1 times.
✓ Branch 6 (21→22) taken 1 times.
|
5 | data_stream_assert(!result.has_value()); |
| 107 | 1 | } | |
| 108 | |||
| 109 | // Test 5: EFAULT - The message passed to the function was invalid | ||
| 110 | 1 | void test_efault(zmq::context_t& context) { | |
| 111 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 2 (3→4) taken 1 times.
|
1 | std::cout << "\n5. Test EFAULT (invalid message):" << std::endl; |
| 112 | |||
| 113 |
1/1✓ Branch 0 (4→5) taken 1 times.
|
1 | zmq::socket_t pull_socket(context, ZMQ_PULL); |
| 114 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | pull_socket.set(zmq::sockopt::linger, -1); |
| 115 |
1/1✓ Branch 0 (6→7) taken 1 times.
|
1 | pull_socket.connect("tcp://127.0.0.1:5559"); |
| 116 | |||
| 117 | // Get the raw socket handle | ||
| 118 | 1 | void* raw_socket = pull_socket.handle(); | |
| 119 | |||
| 120 | // Create an invalid zmq_msg_t by filling it with invalid data | ||
| 121 | zmq_msg_t invalid_msg; | ||
| 122 | 1 | memset(&invalid_msg, 0xFF, sizeof(invalid_msg)); // Fill with invalid data | |
| 123 | |||
| 124 |
1/1✓ Branch 0 (8→9) taken 1 times.
|
1 | int result = zmq_msg_recv(&invalid_msg, raw_socket, ZMQ_DONTWAIT); |
| 125 |
4/4✓ Branch 0 (11→12) taken 1 times.
✓ Branch 2 (14→15) taken 1 times.
✓ Branch 4 (17→18) taken 1 times.
✓ Branch 6 (18→19) taken 1 times.
|
5 | data_stream_assert(result == -1); |
| 126 |
1/1✓ Branch 0 (25→26) taken 1 times.
|
1 | int zmq_errno_val = zmq_errno(); |
| 127 | |||
| 128 |
5/5✓ Branch 0 (26→27) taken 1 times.
✓ Branch 2 (27→28) taken 1 times.
✓ Branch 4 (28→29) taken 1 times.
✓ Branch 6 (29→30) taken 1 times.
✓ Branch 8 (30→31) taken 1 times.
|
1 | std::cout << " Error: zmq_msg_recv returned -1, errno: " << zmq_errno_val << " should be EFAULT: " << EFAULT << std::endl; |
| 129 |
4/4✓ Branch 0 (33→34) taken 1 times.
✓ Branch 2 (36→37) taken 1 times.
✓ Branch 4 (39→40) taken 1 times.
✓ Branch 6 (40→41) taken 1 times.
|
5 | data_stream_assert(zmq_errno_val == EFAULT); |
| 130 | |||
| 131 | 1 | pull_socket.close(); | |
| 132 | 1 | } | |
| 133 | |||
| 134 | 1 | void testRecvErrors() { | |
| 135 |
1/1✓ Branch 0 (2→3) taken 1 times.
|
1 | zmq::context_t context(1); |
| 136 | |||
| 137 |
2/2✓ Branch 0 (3→4) taken 1 times.
✓ Branch 2 (4→5) taken 1 times.
|
1 | std::cout << "=== Test error cases when receiving ZMQ messages ===" << std::endl; |
| 138 | |||
| 139 |
1/1✓ Branch 0 (5→6) taken 1 times.
|
1 | test_eagain(context); |
| 140 |
1/1✓ Branch 0 (6→7) taken 1 times.
|
1 | test_enotsup(context); |
| 141 |
1/1✓ Branch 0 (7→8) taken 1 times.
|
1 | test_eterm(); |
| 142 |
1/1✓ Branch 0 (8→9) taken 1 times.
|
1 | test_enotsock(context); |
| 143 |
1/1✓ Branch 0 (9→10) taken 1 times.
|
1 | test_efault(context); |
| 144 | |||
| 145 |
2/2✓ Branch 0 (10→11) taken 1 times.
✓ Branch 2 (11→12) taken 1 times.
|
1 | std::cout << "\n✓ All receiver tests passed" << std::endl; |
| 146 | 1 | } | |
| 147 | |||
| 148 | 1 | int main() { | |
| 149 | 1 | testRecvErrors(); | |
| 150 | 1 | return 0; | |
| 151 | } | ||
| 152 |