Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / Dirent_Test.cpp
blobf38fd33beaecf36ded15d3162371befbe9a9cfe9
2 //=============================================================================
3 /**
4 * @file Dirent_Test.cpp
6 * This is a test of the opendir and readdir emulation provided by the
7 * class ACE_Dirent. It is used to ensure that the emulation code
8 * works properly on platforms that don't support this capability
9 * natively. As the emulation code is not compiled in other
10 * platforms, this test also ensures that there is no impact to
11 * platforms that natively support directory scanning operations.
13 * @author Phil Mesnier <mesnier_p@ociweb.com>
14 * @author Zvika Ashani <zvika@aspectusvi.com>
15 * @author Rich Newman <RNewman@directv.com>
16 * @author and Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
18 //=============================================================================
21 #include "test_config.h"
22 #include "ace/Dirent.h"
23 #include "ace/Dirent_Selector.h"
24 #include "ace/OS_NS_sys_stat.h"
25 #include "ace/OS_NS_unistd.h"
26 #include "ace/SString.h"
28 #if defined (ACE_HAS_TCHAR_DIRENT)
29 # define TEST_ENTRY ACE_TEXT ("run_test.lst")
30 #else
31 # define TEST_ENTRY "run_test.lst"
32 #endif /* ACE_HAS_TCHAR_DIRENT */
34 // Directory to scan - we need to figure it out based on environment.
35 static ACE_TString TestDir;
36 static const int RECURSION_INDENT = 3;
38 // Number of entries in the directory.
39 static int entrycount = 0;
41 extern "C" {
42 static int
43 selector (const ACE_DIRENT *d)
45 return ACE_OS::strcmp (d->d_name, TEST_ENTRY) == 0;
48 static int
49 comparator (const ACE_DIRENT **d1, const ACE_DIRENT **d2)
51 return ACE_OS::alphasort (d1, d2);
54 } /* extern "C" */
56 static int
57 dirent_selector_test ()
59 int n;
60 int error = 0;
61 const ACE_TCHAR *test_dir = TestDir.c_str ();
62 ACE_Dirent_Selector sds;
64 // Pass in functions that'll specify the selection criteria.
65 int status = sds.open (test_dir, selector, comparator);
66 if (status == -1)
67 ACE_ERROR_RETURN ((LM_ERROR,
68 ACE_TEXT ("%s, %p\n"),
69 test_dir,
70 ACE_TEXT ("open")),
71 -1);
73 // We should only have located ourselves!
74 if (sds.length () != 1)
76 ACE_ERROR ((LM_ERROR,
77 ACE_TEXT ("selected %d entries in %s, should be 1\n"),
78 sds.length (),
79 test_dir));
80 error = 1;
83 for (n = 0; n < sds.length (); ++n)
85 #if defined (ACE_HAS_TCHAR_DIRENT)
86 ACE_DEBUG ((LM_DEBUG,
87 ACE_TEXT ("Sorted: %d: %s\n"),
89 sds[n]->d_name));
90 #else
91 ACE_DEBUG ((LM_DEBUG,
92 ACE_TEXT ("Sorted: %d: %C\n"),
94 sds[n]->d_name));
95 #endif
98 status = sds.close ();
99 if (status == -1)
101 ACE_ERROR ((LM_ERROR,
102 ACE_TEXT ("after selecting, %p\n"),
103 ACE_TEXT ("close")));
104 error = 1;
107 ACE_Dirent_Selector ds;
109 // Don't specify any selection criteria.
110 status = ds.open (test_dir);
111 if (status == -1)
113 ACE_ERROR ((LM_ERROR,
114 ACE_TEXT ("%s w/o selection criteria; %p\n"),
115 test_dir,
116 ACE_TEXT ("open")));
117 error = 1;
120 // We counted the entries earlier by hand; should be the same here.
121 if (entrycount != ds.length ())
123 ACE_ERROR ((LM_ERROR,
124 ACE_TEXT ("Counted %d entries in %s but selector says %d\n"),
125 entrycount,
126 test_dir,
127 ds.length ()));
128 error = 1;
131 for (n = 0; n < ds.length (); ++n)
133 #if defined (ACE_HAS_TCHAR_DIRENT)
134 ACE_DEBUG ((LM_DEBUG,
135 ACE_TEXT ("Entry %d: %s\n"),
137 ds[n]->d_name));
138 #else
139 ACE_DEBUG ((LM_DEBUG,
140 ACE_TEXT ("Entry %d: %C\n"),
142 ds[n]->d_name));
143 #endif
146 if (ds.close () == -1)
148 ACE_ERROR ((LM_ERROR,
149 ACE_TEXT ("w/o selection criteria; %p\n"),
150 ACE_TEXT ("close")));
151 error = 1;
154 return error ? -1 : 0;
157 static int
158 dirent_test ()
160 ACE_Dirent dir;
162 if (dir.open (TestDir.c_str ()) == -1)
163 ACE_ERROR_RETURN
164 ((LM_ERROR, ACE_TEXT ("open of dir %s failed\n"), TestDir.c_str()), -1);
166 for (ACE_DIRENT *directory = 0;
167 (directory = dir.read ()) != 0;
168 entrycount++)
170 #if defined (ACE_HAS_TCHAR_DIRENT)
171 ACE_DEBUG ((LM_DEBUG,
172 ACE_TEXT ("Entry %d: %s\n"),
173 entrycount,
174 directory->d_name));
175 #else
176 ACE_DEBUG ((LM_DEBUG,
177 ACE_TEXT ("Entry %d: %C\n"),
178 entrycount,
179 directory->d_name));
180 #endif
183 switch (entrycount)
185 case 0:
186 ACE_ERROR_RETURN
187 ((LM_ERROR, ACE_TEXT ("readdir failed to read anything\n")), -1);
188 /* NOTREACHED */
189 case 1:
190 ACE_ERROR_RETURN
191 ((LM_ERROR,
192 ACE_TEXT ("readdir failed, only matched directory name\n")),
193 -1);
194 /* NOTREACHED */
195 default:
196 ACE_DEBUG ((LM_DEBUG,
197 ACE_TEXT ("readdir succeeded, read %d entries\n"),
198 entrycount));
200 return 0;
203 static int
204 dirent_count (const ACE_TCHAR *dir_path,
205 int &dir_count,
206 int &file_count,
207 int recursion_level)
209 #if !defined (ACE_LACKS_CHDIR)
210 if (ACE_OS::chdir (dir_path) == -1)
211 ACE_ERROR_RETURN ((LM_ERROR,
212 ACE_TEXT ("chdir: %p\n"),
213 dir_path),
214 -1);
215 #else
216 ACE_UNUSED_ARG (dir_path);
217 #endif /* !ACE_LACKS_CHDIR */
219 ACE_Dirent dir;
220 if (dir.open (ACE_TEXT (".")) == -1)
221 ACE_ERROR_RETURN
222 ((LM_ERROR, ACE_TEXT ("open of dir . failed\n")), -1);
224 // Since the dir struct d_name type changes depending on the setting
225 // of ACE_LACKS_STRUCT_DIR, copy each name into a neutral format
226 // array to work on it.
227 size_t const maxnamlen = MAXNAMLEN;
228 ACE_TCHAR tname[maxnamlen + 1];
230 int entry_count = 0;
232 for (ACE_DIRENT *directory; (directory = dir.read ()) != 0;)
234 // Skip the ".." and "." files.
235 if (ACE::isdotdir(directory->d_name) == true)
236 continue;
237 ++entry_count;
239 #if defined (ACE_HAS_TCHAR_DIRENT)
240 ACE_OS::strncpy (tname, directory->d_name, maxnamlen);
241 #else
242 ACE_OS::strncpy (tname,
243 ACE_TEXT_CHAR_TO_TCHAR (directory->d_name),
244 maxnamlen);
245 #endif /* ACE_LACKS_STRUCT_DIR */
247 int local_file_count = 0;
248 int local_dir_count = 0;
249 ACE_stat stat_buf;
250 if (ACE_OS::lstat (directory->d_name, &stat_buf) == -1)
251 ACE_ERROR_RETURN ((LM_ERROR,
252 ACE_TEXT ("%p\n"),
253 tname),
254 -1);
256 switch (stat_buf.st_mode & S_IFMT)
258 case S_IFREG: // Either a regular file or an executable.
259 ++file_count;
260 break;
262 case S_IFLNK: // Either a file or directory link, so let's find out.
263 if (ACE_OS::stat (directory->d_name, &stat_buf) == -1)
264 ACE_ERROR_RETURN ((LM_ERROR,
265 ACE_TEXT ("%p\n"),
266 tname),
267 -1);
269 if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
270 // Don't recurse through symbolic directory links!
271 ++dir_count;
272 else
273 ++file_count;
274 break;
276 case S_IFDIR:
277 ACE_DEBUG ((LM_DEBUG, "%*sentering subdirectory %s\n",
278 recursion_level * RECURSION_INDENT,
279 ACE_TEXT (""),
280 tname));
281 if (dirent_count (tname,
282 local_dir_count,
283 local_file_count,
284 recursion_level + 1) != -1)
286 ACE_DEBUG
287 ((LM_DEBUG,
288 ACE_TEXT ("%*ssubdirectory %s has %d files and %d subdirectories.\n"),
289 recursion_level * RECURSION_INDENT,
290 ACE_TEXT (""),
291 tname,
292 local_file_count,
293 local_dir_count));
294 ++dir_count;
296 #if !defined (ACE_LACKS_CHDIR)
297 // Move back up a level.
298 if (ACE_OS::chdir (ACE_TEXT ("..")) == -1)
299 ACE_ERROR_RETURN ((LM_ERROR,
300 ACE_TEXT ("chdir: %p\n"),
301 dir_path),
302 -1);
303 #endif /* !ACE_LACKS_CHDIR */
305 break;
307 default: // Must be some other type of file (PIPE/FIFO/device)
308 ++file_count;
309 break;
313 return entry_count;
316 static int
317 dirent_recurse_test ()
319 int total_dirs = 0;
320 int total_files = 0;
321 const ACE_TCHAR *test_dir = TestDir.c_str ();
323 ACE_DEBUG ((LM_DEBUG,
324 ACE_TEXT ("Starting directory recursion test for %s\n"),
325 test_dir));
327 if (dirent_count (test_dir,
328 total_dirs,
329 total_files,
330 1) == -1)
331 ACE_ERROR_RETURN ((LM_ERROR,
332 ACE_TEXT ("Directory recursion test failed for %s\n"),
333 test_dir),
334 -1);
335 ACE_DEBUG ((LM_DEBUG,
336 ACE_TEXT ("Directory recursion test succeeded for %s, read %d files %d dirs\n"),
337 test_dir,
338 total_files,
339 total_dirs));
340 return 0;
344 run_main (int, ACE_TCHAR *[])
346 ACE_START_TEST (ACE_TEXT ("Dirent_Test"));
348 // First, find out where to run most of the scans. If a platform has a
349 // compiled-in setting in TEST_DIR, honor that. Else, look for:
350 // $top_srcdir/tests: The ACE_wrappers dir for autoconf builds
351 // $ACE_ROOT/tests: The ACE_wrappers dir for most other builds
352 // ../test: Last-chance try to hit the right place
353 #if defined (TEST_DIR)
354 TestDir = TEST_DIR;
355 #else
356 const char *root = ACE_OS::getenv ("top_srcdir");
357 if (root == 0)
358 root = ACE_OS::getenv ("ACE_ROOT");
359 if (root != 0)
361 TestDir = ACE_TEXT_CHAR_TO_TCHAR (root);
362 TestDir += ACE_DIRECTORY_SEPARATOR_STR;
363 TestDir += ACE_TEXT ("tests");
365 else
367 TestDir = ACE_TEXT ("../tests");
369 #endif /* TEST_DIR */
371 int status = 0;
373 if (-1 == dirent_test ())
374 status = -1;
376 if (-1 == dirent_selector_test ())
377 status = -1;
379 if (-1 == dirent_recurse_test ())
380 status = -1;
382 ACE_END_TEST;
383 return status;