test_stream_disconnect.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "testutil.hpp"
4 #include "testutil_unity.hpp"
5 
6 #include <string.h>
7 
9 
10 static const int SERVER = 0;
11 static const int CLIENT = 1;
12 
14 {
15  int turn;
16  const char *text;
17 };
18 
19 // NOTE: messages are sent without null terminator.
21  {CLIENT, "i can haz cheez burger?"},
22  {SERVER, "y u no disonnect?"},
23  {CLIENT, ""},
24 };
25 const int steps = sizeof (dialog) / sizeof (dialog[0]);
26 
27 bool has_more (void *socket_)
28 {
29  int more = 0;
30  size_t more_size = sizeof (more);
31  int rc = zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size);
32  if (rc != 0)
33  return false;
34  return more != 0;
35 }
36 
38 {
39  size_t len = MAX_SOCKET_STRING;
40  char bind_endpoint[MAX_SOCKET_STRING];
41  char connect_endpoint[MAX_SOCKET_STRING];
42  void *sockets[2];
43 
45  int enabled = 1;
47  sockets[SERVER], ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled)));
48  TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sockets[SERVER], "tcp://0.0.0.0:*"));
50  zmq_getsockopt (sockets[SERVER], ZMQ_LAST_ENDPOINT, bind_endpoint, &len));
51 
52  // Apparently Windows can't connect to 0.0.0.0. A better fix would be welcome.
53 #ifdef ZMQ_HAVE_WINDOWS
54  snprintf (connect_endpoint, MAX_SOCKET_STRING * sizeof (char),
55  "tcp://127.0.0.1:%s", strrchr (bind_endpoint, ':') + 1);
56 #else
57  strcpy (connect_endpoint, bind_endpoint);
58 #endif
59 
62  sockets[CLIENT], ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled)));
63  TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sockets[CLIENT], connect_endpoint));
64 
65  // wait for connect notification
66  // Server: Grab the 1st frame (peer routing id).
67  zmq_msg_t peer_frame;
69  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&peer_frame, sockets[SERVER], 0));
70  TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&peer_frame));
72  TEST_ASSERT_TRUE (has_more (sockets[SERVER]));
73 
74  // Server: Grab the 2nd frame (actual payload).
75  zmq_msg_t data_frame;
77  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&data_frame, sockets[SERVER], 0));
78  TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&data_frame));
80 
81  // Client: Grab the 1st frame (peer routing id).
83  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&peer_frame, sockets[CLIENT], 0));
84  TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&peer_frame));
86  TEST_ASSERT_TRUE (has_more (sockets[CLIENT]));
87 
88  // Client: Grab the 2nd frame (actual payload).
90  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&data_frame, sockets[CLIENT], 0));
91  TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&data_frame));
93 
94  // Send initial message.
95  char blob_data[256];
96  size_t blob_size = sizeof (blob_data);
98  zmq_getsockopt (sockets[CLIENT], ZMQ_ROUTING_ID, blob_data, &blob_size));
99  TEST_ASSERT_GREATER_THAN (0, blob_size);
100  zmq_msg_t msg;
101  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, blob_size));
102  memcpy (zmq_msg_data (&msg), blob_data, blob_size);
104  zmq_msg_send (&msg, sockets[dialog[0].turn], ZMQ_SNDMORE));
107  zmq_msg_init_size (&msg, strlen (dialog[0].text)));
108  memcpy (zmq_msg_data (&msg), dialog[0].text, strlen (dialog[0].text));
110  zmq_msg_send (&msg, sockets[dialog[0].turn], ZMQ_SNDMORE));
112 
113  // TODO: make sure this loop doesn't loop forever if something is wrong
114  // with the test (or the implementation).
115 
116  int step = 0;
117  while (step < steps) {
118  // Wait until something happens.
119  zmq_pollitem_t items[] = {
120  {sockets[SERVER], 0, ZMQ_POLLIN, 0},
121  {sockets[CLIENT], 0, ZMQ_POLLIN, 0},
122  };
123  TEST_ASSERT_SUCCESS_ERRNO (zmq_poll (items, 2, 100));
124 
125  // Check for data received by the server.
126  if (items[SERVER].revents & ZMQ_POLLIN) {
127  TEST_ASSERT_EQUAL_INT (CLIENT, dialog[step].turn);
128 
129  // Grab the 1st frame (peer routing id).
130  zmq_msg_t peer_frame;
131  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&peer_frame));
133  zmq_msg_recv (&peer_frame, sockets[SERVER], 0));
134  TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&peer_frame));
135  TEST_ASSERT_TRUE (has_more (sockets[SERVER]));
136 
137  // Grab the 2nd frame (actual payload).
138  zmq_msg_t data_frame;
139  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&data_frame));
141  zmq_msg_recv (&data_frame, sockets[SERVER], 0));
142 
143  // Make sure payload matches what we expect.
144  const char *const data =
145  static_cast<const char *> (zmq_msg_data (&data_frame));
146  const size_t size = zmq_msg_size (&data_frame);
147  // 0-length frame is a disconnection notification. The server
148  // should receive it as the last step in the dialogue.
149  if (size == 0) {
150  ++step;
152  } else {
153  TEST_ASSERT_EQUAL_INT (strlen (dialog[step].text), size);
155 
156  ++step;
157 
159 
160  // Prepare the response.
163  zmq_msg_init_size (&data_frame, strlen (dialog[step].text)));
164  memcpy (zmq_msg_data (&data_frame), dialog[step].text,
165  zmq_msg_size (&data_frame));
166 
167  // Send the response.
169  zmq_msg_send (&peer_frame, sockets[SERVER], ZMQ_SNDMORE));
171  zmq_msg_send (&data_frame, sockets[SERVER], ZMQ_SNDMORE));
172  }
173 
174  // Release resources.
177  }
178 
179  // Check for data received by the client.
180  if (items[CLIENT].revents & ZMQ_POLLIN) {
181  TEST_ASSERT_EQUAL_INT (SERVER, dialog[step].turn);
182 
183  // Grab the 1st frame (peer routing id).
184  zmq_msg_t peer_frame;
185  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&peer_frame));
187  zmq_msg_recv (&peer_frame, sockets[CLIENT], 0));
188  TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&peer_frame));
189  TEST_ASSERT_TRUE (has_more (sockets[CLIENT]));
190 
191  // Grab the 2nd frame (actual payload).
192  zmq_msg_t data_frame;
193  TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&data_frame));
195  zmq_msg_recv (&data_frame, sockets[CLIENT], 0));
196  TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&data_frame));
197 
198  // Make sure payload matches what we expect.
199  const char *const data =
200  static_cast<const char *> (zmq_msg_data (&data_frame));
201  const size_t size = zmq_msg_size (&data_frame);
202  TEST_ASSERT_EQUAL_INT (strlen (dialog[step].text), size);
204 
205  ++step;
206 
207  // Prepare the response (next line in the dialog).
211  zmq_msg_init_size (&data_frame, strlen (dialog[step].text)));
212  memcpy (zmq_msg_data (&data_frame), dialog[step].text,
213  zmq_msg_size (&data_frame));
214 
215  // Send the response.
217  zmq_msg_send (&peer_frame, sockets[CLIENT], ZMQ_SNDMORE));
219  zmq_msg_send (&data_frame, sockets[CLIENT], ZMQ_SNDMORE));
220 
221  // Release resources.
224  }
225  }
229 }
230 
231 int main (int, char **)
232 {
234 
235  UNITY_BEGIN ();
237  return UNITY_END ();
238 }
TEST_ASSERT_EQUAL_STRING_LEN
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)
Definition: unity.h:236
UNITY_END
return UNITY_END()
ZMQ_STREAM
#define ZMQ_STREAM
Definition: zmq.h:269
TEST_ASSERT_TRUE
#define TEST_ASSERT_TRUE(condition)
Definition: unity.h:121
zmq_msg_send
ZMQ_EXPORT int zmq_msg_send(zmq_msg_t *msg_, void *s_, int flags_)
Definition: zmq.cpp:609
zmq_poll
ZMQ_EXPORT int zmq_poll(zmq_pollitem_t *items_, int nitems_, long timeout_)
Definition: zmq.cpp:827
RUN_TEST
#define RUN_TEST(func)
Definition: unity_internals.h:615
TEST_ASSERT_GREATER_THAN
#define TEST_ASSERT_GREATER_THAN(threshold, actual)
Definition: unity.h:152
ZMQ_LAST_ENDPOINT
#define ZMQ_LAST_ENDPOINT
Definition: zmq.h:298
SETUP_TEARDOWN_TESTCONTEXT
#define SETUP_TEARDOWN_TESTCONTEXT
Definition: testutil_unity.hpp:172
ZMQ_STREAM_NOTIFY
#define ZMQ_STREAM_NOTIFY
Definition: zmq.h:334
dialog
const test_message_t dialog[]
Definition: test_stream_disconnect.cpp:20
zmq_pollitem_t
Definition: zmq.h:487
zmq_msg_data
ZMQ_EXPORT void * zmq_msg_data(zmq_msg_t *msg_)
Definition: zmq.cpp:642
zmq_connect
ZMQ_EXPORT int zmq_connect(void *s_, const char *addr_)
Definition: zmq.cpp:307
ZMQ_POLLIN
#define ZMQ_POLLIN
Definition: zmq.h:482
zmq_msg_size
ZMQ_EXPORT size_t zmq_msg_size(const zmq_msg_t *msg_)
Definition: zmq.cpp:647
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: glcorearb.h:4174
TEST_ASSERT_GREATER_THAN_INT
#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual)
Definition: unity.h:153
testutil_unity.hpp
SERVER
static const SETUP_TEARDOWN_TESTCONTEXT int SERVER
Definition: test_stream_disconnect.cpp:10
snprintf
int snprintf(char *str, size_t size, const char *format,...)
Definition: port.cc:64
main
int main(int, char **)
Definition: test_stream_disconnect.cpp:231
zmq_setsockopt
ZMQ_EXPORT int zmq_setsockopt(void *s_, int option_, const void *optval_, size_t optvallen_)
Definition: zmq.cpp:250
testutil.hpp
zmq_msg_t
Definition: zmq.h:218
test_message_t
Definition: test_stream_disconnect.cpp:13
MAX_SOCKET_STRING
#define MAX_SOCKET_STRING
Definition: libzmq/tests/testutil.hpp:35
zmq_bind
ZMQ_EXPORT int zmq_bind(void *s_, const char *addr_)
Definition: zmq.cpp:299
zmq_msg_recv
ZMQ_EXPORT int zmq_msg_recv(zmq_msg_t *msg_, void *s_, int flags_)
Definition: zmq.cpp:617
steps
const int steps
Definition: test_stream_disconnect.cpp:25
has_more
bool has_more(void *socket_)
Definition: test_stream_disconnect.cpp:27
test_context_socket
void * test_context_socket(int type_)
Definition: testutil_unity.cpp:200
test_message_t::text
const char * text
Definition: test_stream_disconnect.cpp:16
TEST_ASSERT_EQUAL_INT
#define TEST_ASSERT_EQUAL_INT(expected, actual)
Definition: unity.h:128
zmq_msg_init
ZMQ_EXPORT int zmq_msg_init(zmq_msg_t *msg_)
Definition: zmq.cpp:587
test_stream_disconnect
void test_stream_disconnect()
Definition: test_stream_disconnect.cpp:37
len
int len
Definition: php/ext/google/protobuf/map.c:206
CLIENT
static const int CLIENT
Definition: test_stream_disconnect.cpp:11
size
GLsizeiptr size
Definition: glcorearb.h:2943
setup_test_environment
void setup_test_environment(int timeout_seconds_)
Definition: testutil.cpp:201
zmq_msg_init_size
ZMQ_EXPORT int zmq_msg_init_size(zmq_msg_t *msg_, size_t size_)
Definition: zmq.cpp:592
UNITY_BEGIN
UNITY_BEGIN()
ZMQ_SNDMORE
#define ZMQ_SNDMORE
Definition: zmq.h:359
ZMQ_ROUTING_ID
#define ZMQ_ROUTING_ID
Definition: zmq.h:277
test_message_t::turn
int turn
Definition: test_stream_disconnect.cpp:15
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
TEST_ASSERT_LESS_THAN_INT
#define TEST_ASSERT_LESS_THAN_INT(threshold, actual)
Definition: unity.h:169
test_context_socket_close
void * test_context_socket_close(void *socket_)
Definition: testutil_unity.cpp:208
ZMQ_RCVMORE
#define ZMQ_RCVMORE
Definition: zmq.h:284
zmq_msg_close
ZMQ_EXPORT int zmq_msg_close(zmq_msg_t *msg_)
Definition: zmq.cpp:625
TEST_ASSERT_SUCCESS_ERRNO
#define TEST_ASSERT_SUCCESS_ERRNO(expr)
Definition: proxy_thr.cpp:47
zmq_getsockopt
ZMQ_EXPORT int zmq_getsockopt(void *s_, int option_, void *optval_, size_t *optvallen_)
Definition: zmq.cpp:261


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:59