2 * tests-main.c: shared main() & friends for SVN test-suite programs
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
25 #include <apr_pools.h>
26 #include <apr_general.h>
29 #include "svn_cmdline.h"
31 #include "svn_pools.h"
32 #include "svn_error.h"
36 #include "svn_private_config.h"
39 /* Some Subversion test programs may want to parse options in the
40 argument list, so we remember it here. */
42 const char **test_argv
;
45 /* Test option: Print more output */
46 static int verbose_mode
= 0;
48 /* Test option: Print only unexpected results */
49 static int quiet_mode
= 0;
51 /* Test option: Remove test directories after success */
52 static int cleanup_mode
= 0;
54 /* Option parsing enums and structures */
56 cleanup_opt
= SVN_OPT_FIRST_LONGOPT_ID
,
63 static const apr_getopt_option_t cl_options
[] =
65 {"cleanup", cleanup_opt
, 0,
66 N_("remove test directories after success")},
67 {"fs-type", fstype_opt
, 1,
68 N_("specify a filesystem backend type ARG")},
70 N_("lists all the tests with their short description")},
71 {"verbose", verbose_opt
, 0,
72 N_("print extra information")},
73 {"quiet", quiet_opt
, 0,
74 N_("print only unexpected results")},
79 /* ================================================================= */
80 /* Stuff for cleanup processing */
82 /* When non-zero, don't remove test directories */
83 static int skip_cleanup
= 0;
85 /* All cleanup actions are registered as cleanups on this pool. */
86 static apr_pool_t
*cleanup_pool
= 0;
89 cleanup_rmtree(void *data
)
93 apr_pool_t
*pool
= svn_pool_create(NULL
);
94 const char *path
= data
;
96 /* Ignore errors here. */
97 svn_error_t
*err
= svn_io_remove_dir2(path
, FALSE
, NULL
, NULL
, pool
);
101 printf("FAILED CLEANUP: %s\n", path
);
103 printf("CLEANUP: %s\n", path
);
105 svn_pool_destroy(pool
);
112 svn_test_add_dir_cleanup(const char *path
)
117 svn_error_t
*err
= svn_path_get_absolute(&abspath
, path
, cleanup_pool
);
119 apr_pool_cleanup_register(cleanup_pool
, abspath
, cleanup_rmtree
,
120 apr_pool_cleanup_null
);
121 else if (verbose_mode
)
122 printf("FAILED ABSPATH: %s\n", path
);
127 /* ================================================================= */
128 /* Quite a few tests use random numbers. */
131 svn_test_rand(apr_uint32_t
*seed
)
133 *seed
= (*seed
* 1103515245UL + 12345UL) & 0xffffffffUL
;
138 /* ================================================================= */
141 /* Determine the array size of test_funcs[], the inelegant way. :) */
147 for (i
= 1; test_funcs
[i
].func
; i
++)
156 /* Execute a test number TEST_NUM. Pretty-print test name and dots
157 according to our test-suite spec, and return the result code. */
159 do_test_num(const char *progname
,
161 svn_boolean_t msg_only
,
162 svn_test_opts_t
*opts
,
165 svn_test_driver_t func
;
166 svn_boolean_t skip
, xfail
;
168 int array_size
= get_array_size();
170 const char *msg
= 0; /* the message this individual test prints out */
172 /* Check our array bounds! */
173 if ((test_num
> array_size
) || (test_num
<= 0))
175 printf("FAIL: %s: THERE IS NO TEST NUMBER %2d\n", progname
, test_num
);
176 return (skip_cleanup
= 1); /* BAIL, this test number doesn't exist. */
180 func
= test_funcs
[test_num
].func
;
181 skip
= (test_funcs
[test_num
].mode
== svn_test_skip
);
182 xfail
= (test_funcs
[test_num
].mode
== svn_test_xfail
);
186 err
= func(&msg
, msg_only
|| skip
, opts
, pool
);
188 /* Failure means unexpected results -- FAIL or XPASS. */
189 test_failed
= ((err
!= SVN_NO_ERROR
) != (xfail
!= 0));
191 /* If we got an error, print it out. */
194 svn_handle_error2(err
, stdout
, FALSE
, "svn_tests: ");
195 svn_error_clear(err
);
200 printf(" %2d %-5s %s\n",
202 (xfail
? "XFAIL" : (skip
? "SKIP" : "")),
203 msg
? msg
: "(test did not provide name)");
205 else if ((! quiet_mode
) || test_failed
)
207 printf("%s %s %d: %s\n",
209 ? (xfail
? "XFAIL:" : "FAIL: ")
210 : (xfail
? "XPASS:" : (skip
? "SKIP: " : "PASS: "))),
213 msg
? msg
: "(test did not provide name)");
218 int len
= strlen(msg
);
220 printf("WARNING: Test docstring exceeds 50 characters\n");
221 if (msg
[len
- 1] == '.')
222 printf("WARNING: Test docstring ends in a period (.)\n");
223 if (apr_isupper(msg
[0]))
224 printf("WARNING: Test docstring is capitalized\n");
227 skip_cleanup
= test_failed
;
233 /* Standard svn test program */
235 main(int argc
, const char *argv
[])
237 const char *prog_name
;
241 apr_pool_t
*pool
, *test_pool
;
245 apr_status_t apr_err
;
249 /* How many tests are there? */
250 int array_size
= get_array_size();
252 svn_test_opts_t opts
= { NULL
};
254 opts
.fs_type
= DEFAULT_FS_TYPE
;
256 /* Initialize APR (Apache pools) */
257 if (apr_initialize() != APR_SUCCESS
)
259 printf("apr_initialize() failed.\n");
263 /* set up the global pool */
264 pool
= svn_pool_create(NULL
);
266 /* Remember the command line */
270 err
= svn_cmdline__getopt_init(&os
, argc
, argv
, pool
);
272 /* Strip off any leading path components from the program name. */
273 prog_name
= strrchr(argv
[0], '/');
278 /* Just check if this is that weird platform that uses \ instead
279 of / for the path separator. */
280 prog_name
= strrchr(argv
[0], '\\');
288 return svn_cmdline_handle_exit_error(err
, pool
, prog_name
);
293 /* Parse the next option. */
294 apr_err
= apr_getopt_long(os
, cl_options
, &opt_id
, &opt_arg
);
295 if (APR_STATUS_IS_EOF(apr_err
))
297 else if (apr_err
&& (apr_err
!= APR_BADCH
))
299 /* Ignore invalid option error to allow passing arbitary options */
300 fprintf(stderr
,"apr_getopt_long failed : [%d] %s\n",
301 apr_err
, apr_strerror(apr_err
, errmsg
, sizeof(errmsg
)));
310 opts
.fs_type
= apr_pstrdup(pool
, opt_arg
);
324 /* You can't be both quiet and verbose. */
325 if (quiet_mode
&& verbose_mode
)
327 fprintf(stderr
, "FAIL: --verbose and --quiet are mutually exclusive\n");
331 /* Create an iteration pool for the tests */
332 cleanup_pool
= svn_pool_create(pool
);
333 test_pool
= svn_pool_create(pool
);
335 if (argc
>= 2) /* notice command-line arguments */
337 if (! strcmp(argv
[1], "list") || list_mode
)
341 /* run all tests with MSG_ONLY set to TRUE */
343 printf("Test # Mode Test Description\n"
344 "------ ----- ----------------\n");
345 for (i
= 1; i
<= array_size
; i
++)
347 if (do_test_num(prog_name
, i
, TRUE
, &opts
, test_pool
))
350 /* Clear the per-function pool */
351 svn_pool_clear(test_pool
);
352 svn_pool_clear(cleanup_pool
);
357 for (i
= 1; i
< argc
; i
++)
359 if (apr_isdigit(argv
[i
][0]))
362 test_num
= atoi(argv
[i
]);
363 if (do_test_num(prog_name
, test_num
, FALSE
, &opts
, test_pool
))
366 /* Clear the per-function pool */
367 svn_pool_clear(test_pool
);
368 svn_pool_clear(cleanup_pool
);
376 /* just run all tests */
377 for (i
= 1; i
<= array_size
; i
++)
379 if (do_test_num(prog_name
, i
, FALSE
, &opts
, test_pool
))
382 /* Clear the per-function pool */
383 svn_pool_clear(test_pool
);
384 svn_pool_clear(cleanup_pool
);
389 svn_pool_destroy(pool
); /* takes test_pool with it */