Mark many merge tests as skip-against-old-server.
[svn.git] / subversion / tests / svn_test_main.c
blob943f8575f78f17006cc5b9afe179b8b4df4d4fe3
1 /*
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 * ====================================================================
21 #include <string.h>
22 #include <stdio.h>
23 #include <stdlib.h>
25 #include <apr_pools.h>
26 #include <apr_general.h>
27 #include <apr_lib.h>
29 #include "svn_cmdline.h"
30 #include "svn_opt.h"
31 #include "svn_pools.h"
32 #include "svn_error.h"
33 #include "svn_test.h"
34 #include "svn_io.h"
35 #include "svn_path.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. */
41 int test_argc;
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 */
55 enum {
56 cleanup_opt = SVN_OPT_FIRST_LONGOPT_ID,
57 fstype_opt,
58 list_opt,
59 verbose_opt,
60 quiet_opt
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")},
69 {"list", list_opt, 0,
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")},
75 {0, 0, 0, 0}
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;
88 static apr_status_t
89 cleanup_rmtree(void *data)
91 if (!skip_cleanup)
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);
98 if (verbose_mode)
100 if (err)
101 printf("FAILED CLEANUP: %s\n", path);
102 else
103 printf("CLEANUP: %s\n", path);
105 svn_pool_destroy(pool);
107 return APR_SUCCESS;
111 void
112 svn_test_add_dir_cleanup(const char *path)
114 if (cleanup_mode)
116 const char *abspath;
117 svn_error_t *err = svn_path_get_absolute(&abspath, path, cleanup_pool);
118 if (!err)
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. */
130 apr_uint32_t
131 svn_test_rand(apr_uint32_t *seed)
133 *seed = (*seed * 1103515245UL + 12345UL) & 0xffffffffUL;
134 return *seed;
138 /* ================================================================= */
141 /* Determine the array size of test_funcs[], the inelegant way. :) */
142 static int
143 get_array_size(void)
145 int i;
147 for (i = 1; test_funcs[i].func; i++)
151 return (i - 1);
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. */
158 static int
159 do_test_num(const char *progname,
160 int test_num,
161 svn_boolean_t msg_only,
162 svn_test_opts_t *opts,
163 apr_pool_t *pool)
165 svn_test_driver_t func;
166 svn_boolean_t skip, xfail;
167 svn_error_t *err;
168 int array_size = get_array_size();
169 int test_failed = 0;
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. */
178 else
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);
185 /* Do test */
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. */
192 if (err)
194 svn_handle_error2(err, stdout, FALSE, "svn_tests: ");
195 svn_error_clear(err);
198 if (msg_only)
200 printf(" %2d %-5s %s\n",
201 test_num,
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",
208 (err
209 ? (xfail ? "XFAIL:" : "FAIL: ")
210 : (xfail ? "XPASS:" : (skip ? "SKIP: " : "PASS: "))),
211 progname,
212 test_num,
213 msg ? msg : "(test did not provide name)");
216 if (msg)
218 int len = strlen(msg);
219 if (len > 50)
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;
229 return test_failed;
233 /* Standard svn test program */
235 main(int argc, const char *argv[])
237 const char *prog_name;
238 int test_num;
239 int i;
240 int got_error = 0;
241 apr_pool_t *pool, *test_pool;
242 int ran_a_test = 0;
243 int list_mode = 0;
244 int opt_id;
245 apr_status_t apr_err;
246 apr_getopt_t *os;
247 svn_error_t *err;
248 char errmsg[200];
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");
260 exit(1);
263 /* set up the global pool */
264 pool = svn_pool_create(NULL);
266 /* Remember the command line */
267 test_argc = argc;
268 test_argv = argv;
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], '/');
274 if (prog_name)
275 prog_name++;
276 else
278 /* Just check if this is that weird platform that uses \ instead
279 of / for the path separator. */
280 prog_name = strrchr(argv[0], '\\');
281 if (prog_name)
282 prog_name++;
283 else
284 prog_name = argv[0];
287 if (err)
288 return svn_cmdline_handle_exit_error(err, pool, prog_name);
289 while (1)
291 const char *opt_arg;
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))
296 break;
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)));
302 exit(1);
305 switch (opt_id) {
306 case cleanup_opt:
307 cleanup_mode = 1;
308 break;
309 case fstype_opt:
310 opts.fs_type = apr_pstrdup(pool, opt_arg);
311 break;
312 case list_opt:
313 list_mode = 1;
314 break;
315 case verbose_opt:
316 verbose_mode = 1;
317 break;
318 case quiet_opt:
319 quiet_mode = 1;
320 break;
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");
328 exit(1);
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)
339 ran_a_test = 1;
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))
348 got_error = 1;
350 /* Clear the per-function pool */
351 svn_pool_clear(test_pool);
352 svn_pool_clear(cleanup_pool);
355 else
357 for (i = 1; i < argc; i++)
359 if (apr_isdigit(argv[i][0]))
361 ran_a_test = 1;
362 test_num = atoi(argv[i]);
363 if (do_test_num(prog_name, test_num, FALSE, &opts, test_pool))
364 got_error = 1;
366 /* Clear the per-function pool */
367 svn_pool_clear(test_pool);
368 svn_pool_clear(cleanup_pool);
374 if (! ran_a_test)
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))
380 got_error = 1;
382 /* Clear the per-function pool */
383 svn_pool_clear(test_pool);
384 svn_pool_clear(cleanup_pool);
388 /* Clean up APR */
389 svn_pool_destroy(pool); /* takes test_pool with it */
390 apr_terminate();
392 exit(got_error);
393 return got_error;