Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / tests / SOCK_Send_Recv_Test.cpp
blobeeb406cb1cfcfd26d62223c6ec957436a66e5853
2 //=============================================================================
3 /**
4 * @file SOCK_Send_Recv_Test.cpp
6 * This is a test of the <ACE_SOCK>'s various send and receive
7 * methods. The test forks two processes or spawns two threads
8 * (depending upon the platform) and then executes client and
9 * server allowing them to connect and exchange data in ways
10 * designed to exercise the send and recv functions.
12 * Right now, it primarily tests the iov-like send and recv
13 * functions, but others should be added to completely cover the
14 * possible scenarios.
16 * @author Steve Huston <shuston@riverace.com>
18 //=============================================================================
21 #include "test_config.h"
22 #include "ace/OS_NS_sys_wait.h"
23 #include "ace/OS_NS_unistd.h"
24 #include "ace/Thread.h"
25 #include "ace/Thread_Manager.h"
26 #include "ace/Time_Value.h"
27 #include "ace/SOCK_Connector.h"
28 #include "ace/SOCK_Acceptor.h"
29 #include "ace/SOCK_Stream.h"
33 // Change to non-zero if test fails
34 static int Test_Result = 0;
36 #if !defined (ACE_LACKS_FORK) || defined (ACE_HAS_THREADS)
38 // In test 3, a large amount of data is sent. The purpose is to overflow the
39 // TCP send window, causing the sender to block (it's a send_n). This value
40 // is the amount to send. The assumption is that no implementation has a
41 // receive window larger than 128K bytes. If one is found, this is the place
42 // to change it.
43 // For some odd reason, NT will try to send a single large buffer, but not
44 // multiple smaller ones that add up to the large size.
45 const size_t Test3_Send_Size = 4*1024;
46 const size_t Test3_Loops = 10;
47 const size_t Test3_Total_Size = Test3_Send_Size * Test3_Loops;
50 void *
51 client (void *arg)
53 ACE_INET_Addr *remote_addr = reinterpret_cast<ACE_INET_Addr *> (arg);
54 ACE_INET_Addr server_addr (remote_addr->get_port_number (),
55 ACE_LOCALHOST);
56 ACE_SOCK_Stream cli_stream;
57 ACE_SOCK_Connector con;
58 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
60 ACE_DEBUG ((LM_DEBUG,
61 ACE_TEXT ("(%P|%t) Connecting to port %d\n"),
62 server_addr.get_port_number()));
64 // Initiate connection with server; don't wait forever
65 if (con.connect (cli_stream,
66 server_addr,
67 &timeout) == -1)
69 ACE_ERROR ((LM_ERROR,
70 ACE_TEXT ("(%P|%t) %p\n"),
71 ACE_TEXT ("connection failed")));
72 Test_Result = 1;
73 return 0;
76 ACE_DEBUG ((LM_DEBUG,
77 ACE_TEXT ("(%P|%t) connected to %C\n"),
78 server_addr.get_host_name ()));
80 //******************* TEST 0 ******************************
82 // First make sure that non-blocking receive works as intended.
83 // Set the socket to non-blocking and do a recv() - the server side
84 // will send a short piece of data after sleeping for a few seconds.
85 // This means we should get a EWOULDBLOCK first; then change to
86 // blocking for the rest of the tests.
88 u_char buffer[255];
89 size_t i;
90 ssize_t len;
92 if (-1 == cli_stream.enable (ACE_NONBLOCK))
93 ACE_ERROR ((LM_ERROR,
94 ACE_TEXT ("(%P|%t) %p\n"),
95 ACE_TEXT ("Can't enable test 0 nonblocking")));
97 len = cli_stream.recv (buffer, sizeof (buffer));
98 cli_stream.disable (ACE_NONBLOCK);
99 if (len == -1)
101 if (errno == EWOULDBLOCK)
102 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Nonblocking recv ok!\n")));
103 else
105 ACE_ERROR ((LM_ERROR,
106 ACE_TEXT ("(%P|%t) %p\n"),
107 ACE_TEXT ("Nonblocking recv")));
108 Test_Result = 1;
110 cli_stream.recv (buffer, sizeof (buffer)); // Drain the sent data
112 else
114 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) Nonblocking recv blocked\n")));
115 Test_Result = 1;
118 //******************* TEST 1 ******************************
120 // Do a iovec sendv - send the 255 byte buffer in 5 chunks. The
121 // server will verify that the correct data is sent, and that there
122 // is no more and no less.
124 // The server will verify that this data pattern gets there intact.
126 for (i = 0; i < sizeof buffer; ++i)
127 buffer[i] = static_cast<u_char> (i);
129 iovec iov[5];
131 iov[0].iov_base = reinterpret_cast<char *> (&buffer[0]);
132 iov[0].iov_len = 50;
134 iov[1].iov_base = reinterpret_cast<char *> (&buffer[50]);
135 iov[1].iov_len = 25;
137 iov[2].iov_base = reinterpret_cast<char *> (&buffer[75]);
138 iov[2].iov_len = 150;
140 iov[3].iov_base = reinterpret_cast<char *> (&buffer[225]);
141 iov[3].iov_len = 29;
143 iov[4].iov_base = reinterpret_cast<char *> (&buffer[254]);
144 iov[4].iov_len = 1;
146 len = cli_stream.sendv (iov, 5);
147 if (len == -1)
149 ACE_ERROR ((LM_ERROR,
150 ACE_TEXT ("(%P|%t) %p\n"),
151 ACE_TEXT ("Test 1, sendv failed")));
152 Test_Result = 1;
154 else if (len != 255)
155 ACE_ERROR ((LM_ERROR,
156 ACE_TEXT ("(%P|%t) test 1 recvd %d; should be 255\n"),
157 static_cast<int> (len)));
159 //******************* TEST 2 ******************************
161 // The same data is coming back - receive it using recv (size_t n,
162 // ...) and compare it to the original data.
164 u_char buffer2[255];
165 // Give it a chance to get here
166 ACE_OS::sleep (2);
167 #ifndef ACE_LACKS_VA_FUNCTIONS
168 len = cli_stream.recv (4,
169 buffer2,
170 150,
171 &buffer2[150],
172 105);
173 #endif
174 if (len != 255)
176 ACE_ERROR ((LM_ERROR,
177 ACE_TEXT ("(%P|%t) %m; len is %d, but should be 255!\n"),
178 len));
181 for (i = 0; i < 255; i++)
182 if (buffer2[i] != buffer[i])
184 ACE_ERROR ((LM_ERROR,
185 ACE_TEXT ("(%P|%t) Test 2, rcvd byte %d is %d, not %d\n"),
186 i, buffer2[i], buffer[i]));
187 Test_Result = 1;
190 //******************* TEST 3 ******************************
192 // Do a send_n of a large size. The receive should sleep some to
193 // cause the data reception to be delayed, which will fill up the
194 // TCP window and cause send_n to block at some point. The particular
195 // case this tests only needs to be exercised if the socket is
196 // non-blocking, so set that first.
198 char buff[Test3_Send_Size];
199 if (-1 == cli_stream.enable (ACE_NONBLOCK))
200 ACE_ERROR ((LM_ERROR,
201 ACE_TEXT ("(%P|%t) %p\n"),
202 ACE_TEXT ("Can't enable test 3 nonblocking")));
203 for (i = 0; i < Test3_Loops; ++i)
205 errno = 0;
206 ssize_t sent = cli_stream.send_n (buff, sizeof (buff));
207 if (sent != (ssize_t) sizeof (buff) && errno != 0)
209 ACE_ERROR ((LM_ERROR,
210 ACE_TEXT ("(%P|%t) Test 3, pass %d, sent %d, %p\n"),
211 i, sent, ACE_TEXT ("error")));
212 Test_Result = 1; // Fail
216 cli_stream.close ();
218 return 0;
221 void *
222 server (void *arg)
224 ACE_SOCK_Acceptor *peer_acceptor = (ACE_SOCK_Acceptor *) arg;
225 ACE_SOCK_Stream sock_str;
226 ACE_INET_Addr cli_addr;
227 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
229 // Accept the connection over which the stream tests will run.
230 // Don't lock up if client doesn't connect
231 if (peer_acceptor->accept (sock_str,
232 &cli_addr,
233 &timeout) == -1)
235 ACE_ERROR ((LM_ERROR,
236 ACE_TEXT ("(%P|%t) %p\n"),
237 ACE_TEXT ("accept")));
238 Test_Result = 1;
239 return 0;
242 ACE_DEBUG ((LM_DEBUG,
243 ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
244 cli_addr.get_host_name (),
245 cli_addr.get_port_number ()));
247 //******************* TEST 1 ******************************
249 // The client will be expecting to not see data for a few seconds.
250 // Wait a bit then send a short blurb to complete the client's recv.
252 ACE_OS::sleep (3);
253 sock_str.send ("abc", 3);
255 //******************* TEST 1 ******************************
257 // Do a iovec recvv - the client should send 255 bytes, which we
258 // will be detected and read into a ACE-allocated buffer. Use a 5
259 // second timeout to give the client a chance to send it all.
261 ACE_OS::sleep (5);
263 iovec iov[3];
264 u_char buffer[255];
265 ssize_t len;
266 int i;
268 iov[0].iov_base = reinterpret_cast<char *> (&buffer[0]);
269 iov[0].iov_len = 75;
271 iov[1].iov_base = reinterpret_cast<char *> (&buffer[75]);
272 iov[1].iov_len = 100;
274 iov[2].iov_base = reinterpret_cast<char *> (&buffer[175]);
275 iov[2].iov_len = 80;
277 len = sock_str.recvv_n (iov, 3);
278 if (len == -1)
280 ACE_ERROR ((LM_ERROR,
281 ACE_TEXT ("(%P|%t) %p\n"),
282 ACE_TEXT ("Test 1, recvv failed")));
283 Test_Result = 1;
286 if (len != 255)
288 ACE_ERROR ((LM_ERROR,
289 ACE_TEXT ("(%P|%t) Test 1 recvd %d; should be 255\n"),
290 static_cast<int> (len)));
291 Test_Result = 1;
293 for (i = 0; i < 255; i++)
294 if (buffer[i] != i)
296 ACE_ERROR ((LM_ERROR,
297 ACE_TEXT ("(%P|%t) Test 1, rcvd byte %d is %d, not %d\n"),
299 buffer[i],
300 i));
301 Test_Result = 1;
304 //******************* TEST 2 ******************************
306 // Send the buffer back, using send (size_t n, ...) in 3 pieces.
308 #ifndef ACE_LACKS_VA_FUNCTIONS
309 len = sock_str.send (6,
310 buffer,
312 &buffer[42],
313 189,
314 &buffer[231],
315 24);
316 #endif
318 if (len != 255)
320 ACE_ERROR ((LM_ERROR,
321 ACE_TEXT ("(%P|%t) Test 2 sent %d; should be 255\n"),
322 static_cast<int> (len)));
323 Test_Result = 1;
326 //******************* TEST 3 ******************************
328 // The sender is testing send_n to make sure it blocks if the TCP
329 // window fills. So sleep here for a bit to avoid getting the data
330 // yet. Then just read and empty out the received data.
331 ACE_OS::sleep (8);
332 // Keep reading until the peer closes.
333 sock_str.disable (ACE_NONBLOCK);
334 ssize_t got = 1;
335 size_t total_recv = 0;
336 while (got != 0)
338 errno = 0;
339 got = sock_str.recv (buffer, sizeof (buffer));
340 if (got < 0)
341 break;
342 total_recv += got;
345 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Test 3 received %d bytes\n"),
346 total_recv));
348 if (total_recv == Test3_Total_Size)
350 if (got != 0 || errno != 0)
352 ACE_ERROR ((LM_ERROR,
353 ACE_TEXT ("(%P|%t) Test 3 final recv status %d, expected 0\n"),
354 got));
355 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"),
356 ACE_TEXT ("expected errno == 0, instead")));
357 Test_Result = 1; // Fail
360 else
362 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) Test 3 expected %d %p\n"),
363 Test3_Total_Size, ACE_TEXT ("bytes")));
364 Test_Result = 1;
367 sock_str.close();
369 return 0;
372 #endif /* !ACE_LACKS_FORK || ACE_HAS_THREADS */
374 void
375 spawn (void)
377 // Acceptor
378 ACE_SOCK_Acceptor peer_acceptor;
380 // Create a server address.
381 ACE_INET_Addr server_addr;
383 // Bind listener to any port and then find out what the port was.
384 if (peer_acceptor.open (ACE_Addr::sap_any) == -1
385 || peer_acceptor.get_local_addr (server_addr) == -1)
386 ACE_ERROR ((LM_ERROR,
387 ACE_TEXT ("(%P|%t) %p\n"),
388 ACE_TEXT ("open")));
389 else
391 ACE_DEBUG ((LM_DEBUG,
392 ACE_TEXT ("(%P|%t) starting server at port %d\n"),
393 server_addr.get_port_number ()));
395 #if !defined (ACE_LACKS_FORK)
396 switch (ACE_OS::fork (ACE_TEXT ("child")))
398 case -1:
399 ACE_ERROR ((LM_ERROR,
400 ACE_TEXT ("(%P|%t) %p\n%a"),
401 ACE_TEXT ("fork failed"),
402 1));
403 /* NOTREACHED */
404 case 0:
405 ACE_LOG_MSG->sync (ACE_TEXT ("SOCK_Send_Recv_Test-child"));
406 client (&server_addr);
407 ACE_OS::exit (0);
408 /* NOTREACHED */
409 default:
410 server (reinterpret_cast<void *> (&peer_acceptor));
411 ACE_OS::waitpid (0, 0, 0);
413 #elif defined (ACE_HAS_THREADS)
414 if (ACE_Thread_Manager::instance ()->spawn
415 (ACE_THR_FUNC (server),
416 reinterpret_cast<void *> (&peer_acceptor),
417 THR_NEW_LWP | THR_DETACHED) == -1)
418 ACE_ERROR ((LM_ERROR,
419 ACE_TEXT ("(%P|%t) %p\n%a"),
420 ACE_TEXT ("thread create failed"),
421 1));
423 if (ACE_Thread_Manager::instance ()->spawn
424 (ACE_THR_FUNC (client),
425 reinterpret_cast<void *> (&server_addr),
426 THR_NEW_LWP | THR_DETACHED) == -1)
427 ACE_ERROR ((LM_ERROR,
428 ACE_TEXT ("(%P|%t) %p\n%a"),
429 ACE_TEXT ("thread create failed"),
430 1));
432 // Wait for the threads to exit.
433 ACE_Thread_Manager::instance ()->wait ();
434 #else
435 ACE_ERROR ((LM_INFO,
436 ACE_TEXT ("(%P|%t) ")
437 ACE_TEXT ("only one thread may be run ")
438 ACE_TEXT ("in a process on this platform\n")));
439 #endif /* ACE_HAS_THREADS */
441 peer_acceptor.close ();
446 run_main (int, ACE_TCHAR *[])
448 ACE_START_TEST (ACE_TEXT ("SOCK_Send_Recv_Test"));
450 #ifndef ACE_LACKS_ACCEPT
451 spawn ();
452 #endif
454 ACE_END_TEST;
455 return Test_Result;