Doxygen changes
[ACE_TAO.git] / ACE / tests / FIFO_Test.cpp
blobfa0cd5e7dba0accdd686c4818cf3ac608291b6f6
2 //=============================================================================
3 /**
4 * @file FIFO_Test.cpp
6 * This is a test of basic ACE_FIFO_* class functionality.
7 * The test forks two processes or spawns two threads (depending
8 * upon the platform) and then tests various data exchange
9 * scenarios.
11 * @author Steve Huston <shuston@riverace.com>
13 //=============================================================================
16 #include "test_config.h"
17 #include "ace/OS_NS_string.h"
18 #include "ace/OS_NS_sys_stat.h"
19 #include "ace/OS_NS_sys_wait.h"
20 #include "ace/OS_NS_unistd.h"
21 #include "ace/ACE.h"
22 #include "ace/FIFO_Send_Msg.h"
23 #include "ace/FIFO_Recv_Msg.h"
24 #include "ace/Handle_Set.h"
25 #include "ace/Lib_Find.h"
26 #include "ace/Thread.h"
27 #include "ace/Thread_Manager.h"
31 #if !defined (ACE_LACKS_MKFIFO)
33 static const char ACE_ALPHABET[] = "abcdefghijklmnopqrstuvwxyz";
35 // This length is used for the "big buffer" send/receive.
36 static const size_t big_size = (BUFSIZ * 4);
38 static void *
39 client (void *arg)
41 ACE_TCHAR *fifo_path = reinterpret_cast <ACE_TCHAR *> (arg);
42 ACE_FIFO_Send_Msg fifo;
43 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) client opening %s\n"), fifo_path));
44 if (fifo.open (fifo_path) == -1)
45 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), fifo_path), 0);
47 // Try some transfers - the server part is expecting this data.
48 // First, try a nice, easy send.
49 ssize_t send_count;
50 ssize_t expect = static_cast <ssize_t> (ACE_OS::strlen (ACE_ALPHABET));
51 send_count = fifo.send (ACE_ALPHABET, ACE_OS::strlen (ACE_ALPHABET));
52 if (send_count == expect)
54 // Ok, so far so good. Now try one that will overflow the reader
55 // side to be sure it properly tosses the overflow. Then send another
56 // to be sure it finds the start of the next message ok.
57 char big[big_size];
58 for (size_t i = 0; i < big_size; ++i)
59 big[i] = (i % 2) ? 0x05 : 0x0A; // Make nice pattern in blown stack
60 expect = static_cast <ssize_t> (big_size);
61 send_count = fifo.send (big, big_size);
62 if (send_count == expect)
64 expect = static_cast <ssize_t> (ACE_OS::strlen (ACE_ALPHABET));
65 send_count = fifo.send (ACE_ALPHABET, ACE_OS::strlen (ACE_ALPHABET));
66 if (send_count != expect)
67 ACE_ERROR ((LM_ERROR,
68 ACE_TEXT ("(%P|%t) Final send; sent %d, expected %d")
69 ACE_TEXT ("%p\n"),
70 send_count, expect, ACE_TEXT ("send")));
71 else
72 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) All sends ok\n")));
74 else
76 ACE_ERROR
77 ((LM_ERROR,
78 ACE_TEXT ("(%P|%t) Second send expected %d; sent %d. %p\n"),
79 expect, send_count, ACE_TEXT ("send")));
82 else
84 ACE_ERROR ((LM_ERROR,
85 ACE_TEXT ("(%P|%t) First send expected %d; sent %d. %p\n"),
86 expect, send_count, ACE_TEXT ("send")));
89 if (fifo.close () != 0)
90 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("fifo close")));
92 return 0;
95 static void *
96 server (void *arg)
98 ACE_FIFO_Recv_Msg *fifo = reinterpret_cast <ACE_FIFO_Recv_Msg *> (arg);
100 // Wait for the client to get going and open the FIFO.
101 errno = 0;
102 ACE_Handle_Set h;
103 ACE_Time_Value delay (10);
104 h.set_bit (fifo->get_handle ());
105 if (ACE::select (h.max_set () + 1, h, &delay) == -1)
106 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) server %p\n"),
107 ACE_TEXT ("select")),
110 // On AIX, select() always seems to select a fifo handle as a normal file,
111 // always readable. Just wait a second...
112 # if defined (AIX) || defined (HPUX) || defined (__osf__)
113 ACE_OS::sleep (1);
114 # endif /* AIX || HPUX */
116 // Read the things the client is sending; alphabet, huge overflow, then
117 // alphabet.
119 char buf[BUFSIZ];
120 ssize_t recv_count;
121 ssize_t expect = static_cast <ssize_t> (ACE_OS::strlen (ACE_ALPHABET));
122 recv_count = fifo->recv (buf, sizeof (buf));
123 if (recv_count != expect)
124 ACE_ERROR_RETURN ((LM_ERROR,
125 ACE_TEXT ("(%P|%t) Recv 1 expected %d, got %d. %p\n"),
126 expect, recv_count, ACE_TEXT ("recv")),
128 buf[recv_count] = '\0';
129 if (ACE_OS::strcmp (buf, ACE_ALPHABET) != 0)
130 ACE_ERROR ((LM_ERROR,
131 ACE_TEXT ("(%P|%t) Recv 1 expected alphabet; got %s\n"),
132 buf));
134 // See documented return values for ACE_FIFO_Recv_Msg...
135 // We are being sent a message much longer than BUFSIZ.
136 // If this platform has STREAM pipes, the entire message will come
137 // through and we can grab it all. If not, then ACE_FIFO_Recv_Msg ditches
138 // the part of the message we don't read. This is rather a pain in the
139 // neck, but the API doesn't return info that more data is in the message
140 // (for STREAM pipes). When non-ACE_HAS_STREAM_PIPES discards data, the
141 // returned length will be larger than requested, though only the requested
142 // number of bytes are written to the buffer.
143 #if defined (ACE_HAS_STREAM_PIPES)
144 for (size_t remaining = big_size;
145 remaining > 0;
146 remaining -= recv_count)
148 #endif /* ACE_HAS_STREAM_PIPES */
150 // recv_count is sizeof(buf) on ACE_HAS_STREAM_PIPES; big_size on others.
151 #if defined (ACE_HAS_STREAM_PIPES)
152 expect = static_cast <ssize_t> (sizeof (buf));
153 #else
154 expect = static_cast <ssize_t> (big_size);
155 #endif /* ACE_HAS_STREAM_PIPES */
156 recv_count = fifo->recv (buf, sizeof (buf));
157 if (recv_count != expect)
158 ACE_ERROR_RETURN ((LM_ERROR,
159 ACE_TEXT ("(%P|%t) Recv 2 expected %d, ")
160 ACE_TEXT ("got %d. %p\n"),
161 expect, recv_count, ACE_TEXT ("recv")),
163 #if defined (ACE_HAS_STREAM_PIPES)
165 #endif /* ACE_HAS_STREAM_PIPES */
167 expect = static_cast <ssize_t> (ACE_OS::strlen (ACE_ALPHABET));
168 recv_count = fifo->recv (buf, sizeof (buf));
169 if (recv_count != expect)
170 ACE_ERROR_RETURN ((LM_ERROR,
171 ACE_TEXT ("(%P|%t) Recv 3 expected %d, got %d. %p\n"),
172 expect, recv_count, ACE_TEXT ("recv")),
174 buf[recv_count] = '\0';
175 if (ACE_OS::strcmp (buf, ACE_ALPHABET) != 0)
176 ACE_ERROR ((LM_ERROR,
177 ACE_TEXT ("(%P|%t) Recv 3 expected alphabet; got %s\n"),
178 buf));
179 else
180 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) All receives ok\n")));
181 return 0;
184 static int
185 test_fifo_msg (void)
187 // Reader side opens first - it may fail if fifo not supported on this
188 // platform.
189 ACE_TCHAR fifo_path[MAXPATHLEN];
190 if (ACE::get_temp_dir (fifo_path, MAXPATHLEN) == -1)
191 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
192 ACE_TEXT ("get_temp_dir")), 1);
193 ACE_OS::strcat (fifo_path, ACE_TEXT ("FIFO_Test"));
194 ACE_FIFO_Recv_Msg read_side;
195 // Open read only, not persistent (4th arg is 0)
196 if (-1 == read_side.open (fifo_path,
197 O_CREAT | O_RDONLY,
198 ACE_DEFAULT_FILE_PERMS,
201 #if defined (ACE_WIN32)
202 if (errno == ENOTSUP)
204 ACE_DEBUG ((LM_DEBUG,
205 ACE_TEXT ("FIFO not supported on Win32; ")
206 ACE_TEXT ("this is correct.\n")));
207 return 0;
209 #endif /* ACE_WIN32 */
210 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
211 ACE_TEXT ("ACE_FIFO_Recv_Msg::open")),
215 // Ok, the FIFO opened clean for read. Now it's safe to spawn a
216 // process/thread and test some transfers.
218 int status = 0; // Test status; innocent until proven guilty.
220 #if !defined (ACE_LACKS_FORK)
221 switch (ACE_OS::fork (ACE_TEXT ("child")))
223 case -1:
224 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("fork failed")));
225 status = 1;
226 break;
227 case 0:
228 client (fifo_path);
229 ACE_OS::exit (0);
230 /* NOTREACHED */
231 default:
232 server (&read_side);
233 ACE_OS::wait ();
235 #elif defined (ACE_HAS_THREADS)
236 if (ACE_Thread_Manager::instance ()->spawn
237 (ACE_THR_FUNC (server),
238 &read_side,
239 THR_NEW_LWP | THR_DETACHED) == -1)
241 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("server spawn")));
242 ++status;
245 if (ACE_Thread_Manager::instance ()->spawn
246 (ACE_THR_FUNC (client),
247 fifo_path,
248 THR_NEW_LWP | THR_DETACHED) == -1)
250 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("client spawn")));
251 ++status;
254 // Wait for the threads to exit.
255 ACE_Thread_Manager::instance ()->wait ();
256 #else
257 ACE_ERROR ((LM_INFO,
258 ACE_TEXT ("This test requires multiple threads ")
259 ACE_TEXT ("or processes.\n")));
260 #endif /* ACE_HAS_THREADS */
262 if (read_side.remove () != 0)
264 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("fifo remove")));
265 ++status;
268 ACE_stat fifo_stat;
269 if (ACE_OS::stat (fifo_path, &fifo_stat) == 0)
271 ACE_ERROR ((LM_ERROR, ACE_TEXT ("FIFO %s should be gone but isn't\n"),
272 fifo_path));
273 ++status;
274 ACE_OS::unlink (fifo_path); // Try to get rid of it.
277 return status;
281 run_main (int, ACE_TCHAR *[])
283 ACE_START_TEST (ACE_TEXT ("FIFO_Test"));
285 int errors = 0;
286 errors += test_fifo_msg ();
288 ACE_END_TEST;
289 return errors;
292 #else
295 run_main (int, ACE_TCHAR *[])
297 ACE_START_TEST (ACE_TEXT ("FIFO_Test"));
299 ACE_ERROR ((LM_INFO, ACE_TEXT ("FIFOs are not supported on this platform\n")));
301 ACE_END_TEST;
302 return 0;
305 #endif /* !ACE_LACKS_MKFIFO */