GCC Code Coverage Report


Directory: ./
File: TESTS/TEST_ZMQ_ERRORS/main_receiver_errors.cpp
Date: 2026-01-23 17:10:06
Exec Total Coverage
Lines: 95 96 99.0%
Functions: 8 8 100.0%
Branches: 115 123 93.5%

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