Compile fixes
[ACE_TAO.git] / ACE / tests / SOCK_Send_Recv_Test.cpp
blob544bf8a6641b26a3a295ca75420e2d8a97967565
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"
32 // Change to non-zero if test fails
33 static int Test_Result = 0;
35 #if !defined (ACE_LACKS_FORK) || defined (ACE_HAS_THREADS)
37 // In test 3, a large amount of data is sent. The purpose is to overflow the
38 // TCP send window, causing the sender to block (it's a send_n). This value
39 // is the amount to send. The assumption is that no implementation has a
40 // receive window larger than 128K bytes. If one is found, this is the place
41 // to change it.
42 // For some odd reason, NT will try to send a single large buffer, but not
43 // multiple smaller ones that add up to the large size.
44 const size_t Test3_Send_Size = 4*1024;
45 const size_t Test3_Loops = 10;
46 const size_t Test3_Total_Size = Test3_Send_Size * Test3_Loops;
49 void *
50 client (void *arg)
52 ACE_INET_Addr *remote_addr = reinterpret_cast<ACE_INET_Addr *> (arg);
53 ACE_INET_Addr server_addr (remote_addr->get_port_number (),
54 ACE_LOCALHOST);
55 ACE_SOCK_Stream cli_stream;
56 ACE_SOCK_Connector con;
57 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
59 ACE_DEBUG ((LM_DEBUG,
60 ACE_TEXT ("(%P|%t) Connecting to port %d\n"),
61 server_addr.get_port_number()));
63 // Initiate connection with server; don't wait forever
64 if (con.connect (cli_stream,
65 server_addr,
66 &timeout) == -1)
68 ACE_ERROR ((LM_ERROR,
69 ACE_TEXT ("(%P|%t) %p\n"),
70 ACE_TEXT ("connection failed")));
71 Test_Result = 1;
72 return 0;
75 ACE_DEBUG ((LM_DEBUG,
76 ACE_TEXT ("(%P|%t) connected to %C\n"),
77 server_addr.get_host_name ()));
79 //******************* TEST 0 ******************************
81 // First make sure that non-blocking receive works as intended.
82 // Set the socket to non-blocking and do a recv() - the server side
83 // will send a short piece of data after sleeping for a few seconds.
84 // This means we should get a EWOULDBLOCK first; then change to
85 // blocking for the rest of the tests.
87 u_char buffer[255];
88 size_t i;
89 ssize_t len;
91 if (-1 == cli_stream.enable (ACE_NONBLOCK))
92 ACE_ERROR ((LM_ERROR,
93 ACE_TEXT ("(%P|%t) %p\n"),
94 ACE_TEXT ("Can't enable test 0 nonblocking")));
96 len = cli_stream.recv (buffer, sizeof (buffer));
97 cli_stream.disable (ACE_NONBLOCK);
98 if (len == -1)
100 if (errno == EWOULDBLOCK)
101 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Nonblocking recv ok!\n")));
102 else
104 ACE_ERROR ((LM_ERROR,
105 ACE_TEXT ("(%P|%t) %p\n"),
106 ACE_TEXT ("Nonblocking recv")));
107 Test_Result = 1;
109 cli_stream.recv (buffer, sizeof (buffer)); // Drain the sent data
111 else
113 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) Nonblocking recv blocked\n")));
114 Test_Result = 1;
117 //******************* TEST 1 ******************************
119 // Do a iovec sendv - send the 255 byte buffer in 5 chunks. The
120 // server will verify that the correct data is sent, and that there
121 // is no more and no less.
123 // The server will verify that this data pattern gets there intact.
125 for (i = 0; i < sizeof buffer; ++i)
126 buffer[i] = static_cast<u_char> (i);
128 iovec iov[5];
130 iov[0].iov_base = reinterpret_cast<char *> (&buffer[0]);
131 iov[0].iov_len = 50;
133 iov[1].iov_base = reinterpret_cast<char *> (&buffer[50]);
134 iov[1].iov_len = 25;
136 iov[2].iov_base = reinterpret_cast<char *> (&buffer[75]);
137 iov[2].iov_len = 150;
139 iov[3].iov_base = reinterpret_cast<char *> (&buffer[225]);
140 iov[3].iov_len = 29;
142 iov[4].iov_base = reinterpret_cast<char *> (&buffer[254]);
143 iov[4].iov_len = 1;
145 len = cli_stream.sendv (iov, 5);
146 if (len == -1)
148 ACE_ERROR ((LM_ERROR,
149 ACE_TEXT ("(%P|%t) %p\n"),
150 ACE_TEXT ("Test 1, sendv failed")));
151 Test_Result = 1;
153 else if (len != 255)
154 ACE_ERROR ((LM_ERROR,
155 ACE_TEXT ("(%P|%t) test 1 recvd %d; should be 255\n"),
156 static_cast<int> (len)));
158 //******************* TEST 2 ******************************
160 // The same data is coming back - receive it using recv (size_t n,
161 // ...) and compare it to the original data.
163 u_char buffer2[255];
164 // Give it a chance to get here
165 ACE_OS::sleep (2);
166 #ifndef ACE_LACKS_VA_FUNCTIONS
167 len = cli_stream.recv (4,
168 buffer2,
169 150,
170 &buffer2[150],
171 105);
172 #endif
173 if (len != 255)
175 ACE_ERROR ((LM_ERROR,
176 ACE_TEXT ("(%P|%t) %m; len is %d, but should be 255!\n"),
177 len));
180 for (i = 0; i < 255; i++)
181 if (buffer2[i] != buffer[i])
183 ACE_ERROR ((LM_ERROR,
184 ACE_TEXT ("(%P|%t) Test 2, rcvd byte %d is %d, not %d\n"),
185 i, buffer2[i], buffer[i]));
186 Test_Result = 1;
189 //******************* TEST 3 ******************************
191 // Do a send_n of a large size. The receive should sleep some to
192 // cause the data reception to be delayed, which will fill up the
193 // TCP window and cause send_n to block at some point. The particular
194 // case this tests only needs to be exercised if the socket is
195 // non-blocking, so set that first.
197 char buff[Test3_Send_Size];
198 if (-1 == cli_stream.enable (ACE_NONBLOCK))
199 ACE_ERROR ((LM_ERROR,
200 ACE_TEXT ("(%P|%t) %p\n"),
201 ACE_TEXT ("Can't enable test 3 nonblocking")));
202 for (i = 0; i < Test3_Loops; ++i)
204 errno = 0;
205 ssize_t sent = cli_stream.send_n (buff, sizeof (buff));
206 if (sent != (ssize_t) sizeof (buff) && errno != 0)
208 ACE_ERROR ((LM_ERROR,
209 ACE_TEXT ("(%P|%t) Test 3, pass %d, sent %d, %p\n"),
210 i, sent, ACE_TEXT ("error")));
211 Test_Result = 1; // Fail
215 cli_stream.close ();
217 return 0;
220 void *
221 server (void *arg)
223 ACE_SOCK_Acceptor *peer_acceptor = (ACE_SOCK_Acceptor *) arg;
224 ACE_SOCK_Stream sock_str;
225 ACE_INET_Addr cli_addr;
226 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
228 // Accept the connection over which the stream tests will run.
229 // Don't lock up if client doesn't connect
230 if (peer_acceptor->accept (sock_str,
231 &cli_addr,
232 &timeout) == -1)
234 ACE_ERROR ((LM_ERROR,
235 ACE_TEXT ("(%P|%t) %p\n"),
236 ACE_TEXT ("accept")));
237 Test_Result = 1;
238 return 0;
241 ACE_DEBUG ((LM_DEBUG,
242 ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
243 cli_addr.get_host_name (),
244 cli_addr.get_port_number ()));
246 //******************* TEST 1 ******************************
248 // The client will be expecting to not see data for a few seconds.
249 // Wait a bit then send a short blurb to complete the client's recv.
251 ACE_OS::sleep (3);
252 sock_str.send ("abc", 3);
254 //******************* TEST 1 ******************************
256 // Do a iovec recvv - the client should send 255 bytes, which we
257 // will be detected and read into a ACE-allocated buffer. Use a 5
258 // second timeout to give the client a chance to send it all.
260 ACE_OS::sleep (5);
262 iovec iov[3];
263 u_char buffer[255];
264 ssize_t len;
265 int i;
267 iov[0].iov_base = reinterpret_cast<char *> (&buffer[0]);
268 iov[0].iov_len = 75;
270 iov[1].iov_base = reinterpret_cast<char *> (&buffer[75]);
271 iov[1].iov_len = 100;
273 iov[2].iov_base = reinterpret_cast<char *> (&buffer[175]);
274 iov[2].iov_len = 80;
276 len = sock_str.recvv_n (iov, 3);
277 if (len == -1)
279 ACE_ERROR ((LM_ERROR,
280 ACE_TEXT ("(%P|%t) %p\n"),
281 ACE_TEXT ("Test 1, recvv failed")));
282 Test_Result = 1;
285 if (len != 255)
287 ACE_ERROR ((LM_ERROR,
288 ACE_TEXT ("(%P|%t) Test 1 recvd %d; should be 255\n"),
289 static_cast<int> (len)));
290 Test_Result = 1;
292 for (i = 0; i < 255; i++)
293 if (buffer[i] != i)
295 ACE_ERROR ((LM_ERROR,
296 ACE_TEXT ("(%P|%t) Test 1, rcvd byte %d is %d, not %d\n"),
298 buffer[i],
299 i));
300 Test_Result = 1;
303 //******************* TEST 2 ******************************
305 // Send the buffer back, using send (size_t n, ...) in 3 pieces.
307 #ifndef ACE_LACKS_VA_FUNCTIONS
308 len = sock_str.send (6,
309 buffer,
311 &buffer[42],
312 189,
313 &buffer[231],
314 24);
315 #endif
317 if (len != 255)
319 ACE_ERROR ((LM_ERROR,
320 ACE_TEXT ("(%P|%t) Test 2 sent %d; should be 255\n"),
321 static_cast<int> (len)));
322 Test_Result = 1;
325 //******************* TEST 3 ******************************
327 // The sender is testing send_n to make sure it blocks if the TCP
328 // window fills. So sleep here for a bit to avoid getting the data
329 // yet. Then just read and empty out the received data.
330 ACE_OS::sleep (8);
331 // Keep reading until the peer closes.
332 sock_str.disable (ACE_NONBLOCK);
333 ssize_t got = 1;
334 size_t total_recv = 0;
335 while (got != 0)
337 errno = 0;
338 got = sock_str.recv (buffer, sizeof (buffer));
339 if (got < 0)
340 break;
341 total_recv += got;
344 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) Test 3 received %d bytes\n"),
345 total_recv));
347 if (total_recv == Test3_Total_Size)
349 if (got != 0 || errno != 0)
351 ACE_ERROR ((LM_ERROR,
352 ACE_TEXT ("(%P|%t) Test 3 final recv status %d, expected 0\n"),
353 got));
354 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"),
355 ACE_TEXT ("expected errno == 0, instead")));
356 Test_Result = 1; // Fail
359 else
361 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) Test 3 expected %d %p\n"),
362 Test3_Total_Size, ACE_TEXT ("bytes")));
363 Test_Result = 1;
366 sock_str.close();
368 return 0;
371 #endif /* !ACE_LACKS_FORK || ACE_HAS_THREADS */
373 void
374 spawn ()
376 // Acceptor
377 ACE_SOCK_Acceptor peer_acceptor;
379 // Create a server address.
380 ACE_INET_Addr server_addr;
382 // Bind listener to any port and then find out what the port was.
383 if (peer_acceptor.open (ACE_Addr::sap_any) == -1
384 || peer_acceptor.get_local_addr (server_addr) == -1)
385 ACE_ERROR ((LM_ERROR,
386 ACE_TEXT ("(%P|%t) %p\n"),
387 ACE_TEXT ("open")));
388 else
390 ACE_DEBUG ((LM_DEBUG,
391 ACE_TEXT ("(%P|%t) starting server at port %d\n"),
392 server_addr.get_port_number ()));
394 #if !defined (ACE_LACKS_FORK)
395 switch (ACE_OS::fork (ACE_TEXT ("child")))
397 case -1:
398 ACE_ERROR ((LM_ERROR,
399 ACE_TEXT ("(%P|%t) %p\n"),
400 ACE_TEXT ("fork failed"),
401 1));
402 ACE_OS::abort ();
403 case 0:
404 ACE_LOG_MSG->sync (ACE_TEXT ("SOCK_Send_Recv_Test-child"));
405 client (&server_addr);
406 ACE_OS::exit (0);
407 /* NOTREACHED */
408 default:
409 server (reinterpret_cast<void *> (&peer_acceptor));
410 ACE_OS::waitpid (0, 0, 0);
412 #elif defined (ACE_HAS_THREADS)
413 if (ACE_Thread_Manager::instance ()->spawn
414 (ACE_THR_FUNC (server),
415 reinterpret_cast<void *> (&peer_acceptor),
416 THR_NEW_LWP | THR_DETACHED) == -1)
417 ACE_ERROR ((LM_ERROR,
418 ACE_TEXT ("(%P|%t) %p\n%a"),
419 ACE_TEXT ("thread create failed"),
420 1));
422 if (ACE_Thread_Manager::instance ()->spawn
423 (ACE_THR_FUNC (client),
424 reinterpret_cast<void *> (&server_addr),
425 THR_NEW_LWP | THR_DETACHED) == -1)
426 ACE_ERROR ((LM_ERROR,
427 ACE_TEXT ("(%P|%t) %p\n%a"),
428 ACE_TEXT ("thread create failed"),
429 1));
431 // Wait for the threads to exit.
432 ACE_Thread_Manager::instance ()->wait ();
433 #else
434 ACE_ERROR ((LM_INFO,
435 ACE_TEXT ("(%P|%t) ")
436 ACE_TEXT ("only one thread may be run ")
437 ACE_TEXT ("in a process on this platform\n")));
438 #endif /* ACE_HAS_THREADS */
440 peer_acceptor.close ();
445 run_main (int, ACE_TCHAR *[])
447 ACE_START_TEST (ACE_TEXT ("SOCK_Send_Recv_Test"));
449 #ifndef ACE_LACKS_ACCEPT
450 spawn ();
451 #endif
453 ACE_END_TEST;
454 return Test_Result;