1 /* $NetBSD: dirent-test.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */ 2 3 /*********************************************************************** 4 * Copyright (c) 2009, Secure Endpoints Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * - Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 * OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 **********************************************************************/ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stdarg.h> 37 #include <direct.h> 38 #include <errno.h> 39 #include <io.h> 40 #include <fcntl.h> 41 #include <sys/stat.h> 42 #include <string.h> 43 #include "dirent.h" 44 45 /* Note that we create a known directory structure in a subdirectory 46 of the current directory to run our tests. */ 47 48 #define TESTDIR "dirent-test-dir" 49 50 const char * dir_entries[] = { 51 "A", 52 "B", 53 "C", 54 "CAA", 55 "CAAA", 56 "CABBBB", 57 "CAABBB.txt", 58 "A filename with spaces" 59 }; 60 61 const char * entries_begin_with_C[] = { 62 "C", 63 "CAA", 64 "CAAA", 65 "CABBBB", 66 "CAABBB.txt" 67 }; 68 69 const char * entries_end_with_A[] = { 70 "A", 71 "CAA", 72 "CAAA" 73 }; 74 75 const int n_dir_entries = sizeof(dir_entries)/sizeof(dir_entries[0]); 76 77 int teardown_test(void); 78 79 void fail_test(const char * reason, ...) 80 { 81 va_list args; 82 83 va_start(args, reason); 84 vfprintf(stderr, reason, args); 85 va_end(args); 86 87 fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno)); 88 teardown_test(); 89 abort(); 90 } 91 92 void fail_test_nf(const char * format, ...) 93 { 94 va_list args; 95 96 fprintf(stderr, "FAIL:"); 97 98 va_start(args, format); 99 vfprintf(stderr, format, args); 100 va_end(args); 101 102 fprintf(stderr, " : errno = %d (%s)\n", errno, strerror(errno)); 103 } 104 105 int touch(const char * filename) 106 { 107 int fd; 108 109 fd = _open(filename, _O_CREAT, _S_IREAD| _S_IWRITE); 110 111 if (fd == -1) 112 return -1; 113 114 return _close(fd); 115 } 116 117 int setup_test(void) 118 { 119 int i; 120 121 fprintf(stderr, "Creating test directory %s ...\n", TESTDIR); 122 123 if (_mkdir(TESTDIR)) 124 fail_test("Can't create test directory \"" TESTDIR "\""); 125 126 if (_chdir(TESTDIR)) 127 fail_test("Can't change to test directory"); 128 129 for (i=0; i < n_dir_entries; i++) { 130 if (touch(dir_entries[i])) 131 fail_test("Can't create test file '%s'", dir_entries[i]); 132 } 133 134 fprintf(stderr, "Done with test setup.\n"); 135 136 return 0; 137 } 138 139 int teardown_test(void) 140 { 141 char dirname[_MAX_PATH]; 142 size_t len; 143 int i; 144 145 printf ("Begin cleanup...\n"); 146 147 if (_getcwd(dirname, sizeof(dirname)/sizeof(char)) != NULL && 148 149 (len = strlen(dirname)) > sizeof(TESTDIR)/sizeof(char) && 150 151 !strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR)) { 152 153 /* fallthrough */ 154 155 } else { 156 /* did we create the directory? */ 157 158 if (!_rmdir( TESTDIR )) { 159 fprintf(stderr, "Removed test directory\n"); 160 return 0; 161 } else { 162 if (errno == ENOTEMPTY) { 163 if (_chdir(TESTDIR)) { 164 fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n"); 165 return -1; 166 } else { 167 /* fallthrough */ 168 } 169 } else { 170 return -1; 171 } 172 } 173 } 174 175 fprintf(stderr, "Cleaning up test directory %s ...\n", TESTDIR); 176 177 for (i=0; i < n_dir_entries; i++) { 178 if (_unlink(dir_entries[i])) { 179 /* if the test setup failed, we expect this to happen for 180 at least some files */ 181 } 182 } 183 184 if (_chdir("..")) { 185 fprintf(stderr, "Can't escape test directory. Giving in.\n"); 186 return -1; 187 } 188 189 if (_rmdir( TESTDIR )) { 190 fprintf(stderr, "Can't remove test directory.\n"); 191 return -1; 192 } 193 194 printf("Cleaned up test directory\n"); 195 return 0; 196 } 197 198 int check_list(const char * filespec, const char ** list, int n, int expect_dot_and_dotdot) 199 { 200 DIR * d; 201 struct dirent * e; 202 int n_found = 0; 203 int i; 204 int rv = 0; 205 int retry = 1; 206 207 d = opendir(filespec); 208 if (d == NULL) { 209 fail_test_nf("opendir failed for [%s]", filespec); 210 return -1; 211 } 212 213 printf("Checking filespec [%s]... ", filespec); 214 215 retry: 216 while ((e = readdir(d)) != NULL) { 217 n_found ++; 218 219 if (expect_dot_and_dotdot && 220 (!strcmp(e->d_name, ".") || 221 !strcmp(e->d_name, ".."))) 222 continue; 223 224 for (i=0; i < n; i++) { 225 if (!strcmp(list[i], e->d_name)) 226 break; 227 } 228 229 if (i == n) { 230 fail_test_nf("Found unexpected entry [%s]", e->d_name); 231 rv = -1; 232 } 233 } 234 235 if (n_found != n) { 236 fail_test_nf("Unexpected number of entries [%d]. Expected %d", n_found, n); 237 rv = -1; 238 } 239 240 if (retry) { 241 retry = 0; 242 n_found = 0; 243 244 rewinddir(d); 245 goto retry; 246 } 247 248 if (closedir(d)) { 249 fail_test_nf("closedir() failed"); 250 } 251 252 printf("done\n"); 253 254 return rv; 255 } 256 257 int run_tests() 258 { 259 /* assumes that the test directory has been set up and we have 260 changed into the test directory. */ 261 262 check_list("*", dir_entries, n_dir_entries + 2, 1); 263 check_list("*.*", dir_entries, n_dir_entries + 2, 1); 264 check_list("C*", entries_begin_with_C, sizeof(entries_begin_with_C)/sizeof(entries_begin_with_C[0]), 0); 265 check_list("*A", entries_end_with_A, sizeof(entries_end_with_A)/sizeof(entries_end_with_A[0]), 0); 266 267 return 0; 268 } 269 270 int main(int argc, char ** argv) 271 { 272 if (setup_test()) 273 return 1; 274 275 run_tests(); 276 277 teardown_test(); 278 279 return 0; 280 } 281