Index: src/interfaces/ecpg/test/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v retrieving revision 1.67 diff -c -r1.67 Makefile *** src/interfaces/ecpg/test/Makefile 29 Mar 2007 12:02:24 -0000 1.67 --- src/interfaces/ecpg/test/Makefile 9 Jun 2007 13:12:35 -0000 *************** *** 8,13 **** --- 8,16 ---- # this is also defined in test/connect/Makefile TEMP_PORT = 5$(DEF_PGPORT) + # where to find psql for testing an existing installation + PSQLDIR = $(bindir) + # default encoding MULTIBYTE = SQL_ASCII *************** *** 26,31 **** --- 29,43 ---- abs_builddir := $(shell pwd -W) endif + # stuff to pass into build of pg_regress + EXTRADEFS = '-DHOST_TUPLE="$(host_tuple)"' \ + '-DMAKEPROG="$(MAKE)"' \ + '-DSHELLPROG="$(SHELL)"' \ + '-DDLSUFFIX="$(DLSUFFIX)"' + + REGRESSINCLUDES = "-I$(top_builddir)/src/test/regress" + REGRESSDRIVER = "$(top_builddir)/src/test/regress/pg_regress.o" + all install installdirs uninstall distprep: $(MAKE) -C connect $@ $(MAKE) -C expected $@ *************** *** 45,64 **** $(MAKE) -C compat_informix $@ $(MAKE) -C thread $@ rm -rf tmp_check results log ! rm -f pg_regress regression.diffs ! all: pg_regress ! pg_regress: pg_regress.sh $(top_builddir)/src/Makefile.global ! sed -e 's,@bindir@,$(bindir),g' \ ! -e 's,@libdir@,$(libdir),g' \ ! -e 's,@pkglibdir@,$(pkglibdir),g' \ ! -e 's,@datadir@,$(datadir),g' \ ! -e 's/@VERSION@/$(VERSION)/g' \ ! -e 's/@host_tuple@/$(host_tuple)/g' \ ! -e 's,@GMAKE@,$(MAKE),g' \ ! -e 's/@enable_shared@/$(enable_shared)/g' \ ! $< >$@ # When doing a VPATH build, copy over the .pgc, .stdout and .stderr # files so that the driver script can find them. We have to use an --- 57,77 ---- $(MAKE) -C compat_informix $@ $(MAKE) -C thread $@ rm -rf tmp_check results log ! rm -f pg_regress regression.diffs pg_regress_ecpg.o ! ! # Build regression test driver ! ! all: pg_regress$(X) ! ! pg_regress$(X): pg_regress_ecpg.o ! $(CC) $(CFLAGS) $^ $(REGRESSDRIVER) $(LDFLAGS) $(LIBS) -o $@ ! # dependencies ensure that path changes propagate ! pg_regress_ecpg.o: pg_regress_ecpg.c $(top_builddir)/src/port/pg_config_paths.h ! $(CC) $(CFLAGS) $(CPPFLAGS) -I$(top_builddir)/src/port $(REGRESSINCLUDES) $(EXTRADEFS) -c -o $@ $< ! $(top_builddir)/src/port/pg_config_paths.h: $(top_builddir)/src/Makefile.global ! $(MAKE) -C $(top_builddir)/src/port pg_config_paths.h # When doing a VPATH build, copy over the .pgc, .stdout and .stderr # files so that the driver script can find them. We have to use an *************** *** 78,88 **** check: all ! sh ./pg_regress --dbname=regress1 --temp-install --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) # the same options, but with --listen-on-tcp checktcp: all ! sh ./pg_regress --dbname=regress1 --temp-install --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) --listen-on-tcp $(THREAD) installcheck: all ! sh ./pg_regress --dbname=regress1 --top-builddir=$(top_builddir) --load-language=plpgsql $(NOLOCALE) --- 91,101 ---- check: all ! ./pg_regress --dbname=regress1,connectdb --top-builddir=$(top_builddir) --temp-install=./tmp_check --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule --create-role=connectuser,connectdb # the same options, but with --listen-on-tcp checktcp: all ! ./pg_regress --dbname=regress1,connectdb --top-builddir=$(top_builddir) --temp-install=./tmp_check --temp-port=$(TEMP_PORT) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule_tcp --create-role=connectuser,connectdb --host=localhost installcheck: all ! ./pg_regress --psqldir=$(PSQLDIR) --dbname=regress1,connectdb --top-builddir=$(top_builddir) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) $(THREAD) --schedule=$(srcdir)/ecpg_schedule --create-role=connectuser,connectdb Index: src/test/regress/GNUmakefile =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/GNUmakefile,v retrieving revision 1.67 diff -c -r1.67 GNUmakefile *** src/test/regress/GNUmakefile 13 Mar 2007 22:56:48 -0000 1.67 --- src/test/regress/GNUmakefile 9 Jun 2007 11:36:13 -0000 *************** *** 51,57 **** all: submake-libpgport pg_regress$(X) ! pg_regress$(X): pg_regress.o $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@ # dependencies ensure that path changes propagate --- 51,57 ---- all: submake-libpgport pg_regress$(X) ! pg_regress$(X): pg_regress.o pg_regress_main.o $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LIBS) -o $@ # dependencies ensure that path changes propagate *************** *** 165,171 **** # things built by `all' target rm -f $(NAME)$(DLSUFFIX) $(OBJS) $(MAKE) -C $(contribdir)/spi clean ! rm -f $(output_files) $(input_files) pg_regress.o pg_regress$(X) # things created by various check targets rm -rf testtablespace rm -rf results tmp_check log --- 165,171 ---- # things built by `all' target rm -f $(NAME)$(DLSUFFIX) $(OBJS) $(MAKE) -C $(contribdir)/spi clean ! rm -f $(output_files) $(input_files) pg_regress_main.o pg_regress.o pg_regress$(X) # things created by various check targets rm -rf testtablespace rm -rf results tmp_check log Index: src/test/regress/pg_regress.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/pg_regress.c,v retrieving revision 1.32 diff -c -r1.32 pg_regress.c *** src/test/regress/pg_regress.c 31 May 2007 15:13:06 -0000 1.32 --- src/test/regress/pg_regress.c 9 Jun 2007 17:58:10 -0000 *************** *** 16,22 **** *------------------------------------------------------------------------- */ ! #include "postgres_fe.h" #include #include --- 16,22 ---- *------------------------------------------------------------------------- */ ! #include "pg_regress.h" #include #include *************** *** 32,57 **** #include "getopt_long.h" #include "pg_config_paths.h" - #ifndef WIN32 - #define PID_TYPE pid_t - #define INVALID_PID (-1) - #else - #define PID_TYPE HANDLE - #define INVALID_PID INVALID_HANDLE_VALUE - #endif - - - /* simple list of strings */ - typedef struct _stringlist - { - char *str; - struct _stringlist *next; - } _stringlist; - /* for resultmap we need a list of pairs of strings */ typedef struct _resultmap { char *test; char *resultfile; struct _resultmap *next; } _resultmap; --- 32,42 ---- #include "getopt_long.h" #include "pg_config_paths.h" /* for resultmap we need a list of pairs of strings */ typedef struct _resultmap { char *test; + char *type; char *resultfile; struct _resultmap *next; } _resultmap; *************** *** 63,72 **** * In non-temp_install mode, the only thing we need is the location of psql, * which we expect to find in psqldir, or in the PATH if psqldir isn't given. */ ! static char *bindir = PGBINDIR; ! static char *libdir = LIBDIR; ! static char *datadir = PGSHAREDIR; ! static char *host_platform = HOST_TUPLE; #ifndef WIN32_ONLY_COMPILER static char *makeprog = MAKEPROG; #endif --- 48,57 ---- * In non-temp_install mode, the only thing we need is the location of psql, * which we expect to find in psqldir, or in the PATH if psqldir isn't given. */ ! char *bindir = PGBINDIR; ! char *libdir = LIBDIR; ! char *datadir = PGSHAREDIR; ! char *host_platform = HOST_TUPLE; #ifndef WIN32_ONLY_COMPILER static char *makeprog = MAKEPROG; #endif *************** *** 76,89 **** #endif /* currently we can use the same diff switches on all platforms */ ! static const char *basic_diff_opts = "-w"; ! static const char *pretty_diff_opts = "-w -C3"; /* options settable from command line */ ! static char *dbname = "regression"; ! static bool debug = false; ! static char *inputdir = "."; ! static char *outputdir = "."; static _stringlist *loadlanguage = NULL; static int max_connections = 0; static char *encoding = NULL; --- 61,76 ---- #endif /* currently we can use the same diff switches on all platforms */ ! const char *basic_diff_opts = "-w"; ! const char *pretty_diff_opts = "-w -C3"; /* options settable from command line */ ! _stringlist *dblist = NULL; ! bool debug = false; ! char *inputdir = "."; ! char *outputdir = "."; ! char *psqldir = NULL; ! char *ecpgdir = NULL; static _stringlist *loadlanguage = NULL; static int max_connections = 0; static char *encoding = NULL; *************** *** 93,103 **** static char *top_builddir = NULL; static int temp_port = 65432; static bool nolocale = false; - static char *psqldir = NULL; static char *hostname = NULL; static int port = -1; static char *user = NULL; static char *srcdir = NULL; /* internal variables */ static const char *progname; --- 80,90 ---- static char *top_builddir = NULL; static int temp_port = 65432; static bool nolocale = false; static char *hostname = NULL; static int port = -1; static char *user = NULL; static char *srcdir = NULL; + static _stringlist *extraroles = NULL; /* internal variables */ static const char *progname; *************** *** 170,176 **** /* * Add an item at the end of a stringlist. */ ! static void add_stringlist_item(_stringlist ** listhead, const char *str) { _stringlist *newentry = malloc(sizeof(_stringlist)); --- 157,163 ---- /* * Add an item at the end of a stringlist. */ ! void add_stringlist_item(_stringlist ** listhead, const char *str) { _stringlist *newentry = malloc(sizeof(_stringlist)); *************** *** 189,194 **** --- 176,212 ---- } /* + * Free a stringlist. + */ + static void + free_stringlist(_stringlist **listhead) + { + if (listhead == NULL || *listhead == NULL) + return; + if ((*listhead)->next != NULL) + free_stringlist(&((*listhead)->next)); + free((*listhead)->str); + free(*listhead); + *listhead = NULL; + } + + /* + * Split a delimited string into a stringlist + */ + static void + split_to_stringlist(const char *s, const char *delim, _stringlist **listhead) + { + char *sc = strdup(s); + char *token = strtok(sc, delim); + while (token) + { + add_stringlist_item(listhead, token); + token = strtok(NULL, delim); + } + free(sc); + } + + /* * Print a progress banner on stdout. */ static void *************** *** 265,271 **** * Always exit through here, not through plain exit(), to ensure we make * an effort to shut down a temp postmaster */ ! static void exit_nicely(int code) { stop_postmaster(); --- 283,289 ---- * Always exit through here, not through plain exit(), to ensure we make * an effort to shut down a temp postmaster */ ! void exit_nicely(int code) { stop_postmaster(); *************** *** 349,355 **** * Replace all occurances of a string in a string with a different string. * NOTE: Assumes there is enough room in the target buffer! */ ! static void replace_string(char *string, char *replace, char *replacement) { char *ptr; --- 367,373 ---- * Replace all occurances of a string in a string with a different string. * NOTE: Assumes there is enough room in the target buffer! */ ! void replace_string(char *string, char *replace, char *replacement) { char *ptr; *************** *** 537,542 **** --- 555,561 ---- while (fgets(buf, sizeof(buf), f)) { char *platform; + char *file_type; char *expected; int i; *************** *** 546,552 **** buf[--i] = '\0'; /* parse out the line fields */ ! platform = strchr(buf, '/'); if (!platform) { fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"), --- 565,580 ---- buf[--i] = '\0'; /* parse out the line fields */ ! file_type = strchr(buf, ':'); ! if (!file_type) ! { ! fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"), ! buf); ! exit_nicely(2); ! } ! *file_type++ = '\0'; ! ! platform = strchr(file_type, ':'); if (!platform) { fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"), *************** *** 574,579 **** --- 602,608 ---- _resultmap *entry = malloc(sizeof(_resultmap)); entry->test = strdup(buf); + entry->type = strdup(file_type); entry->resultfile = strdup(expected); entry->next = resultmap; resultmap = entry; *************** *** 583,588 **** --- 612,646 ---- } /* + * Check in resultmap if we should be looking at a different file + */ + static + const char *get_expectfile(const char *testname, const char *file) + { + char *file_type; + _resultmap *rm; + + /* + * Determine the file type from the file name. This is just what is + * following the last dot in the file name. + */ + if (!file || !(file_type = strrchr(file, '.'))) + return NULL; + + file_type++; + + for (rm = resultmap; rm != NULL; rm = rm->next) + { + if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0) + { + return rm->resultfile; + } + } + + return NULL; + } + + /* * Handy subroutine for setting an environment variable "var" to "val" */ static void *************** *** 704,709 **** --- 762,770 ---- /* psql will be installed into temp-install bindir */ psqldir = bindir; + + /* ecpg will be installed into temp-install bindir */ + ecpgdir = bindir; /* * Set up shared library paths to include the temp install. *************** *** 820,826 **** * * Returns the process ID (or HANDLE) so we can wait for it later */ ! static PID_TYPE spawn_process(const char *cmdline) { #ifndef WIN32 --- 881,887 ---- * * Returns the process ID (or HANDLE) so we can wait for it later */ ! PID_TYPE spawn_process(const char *cmdline) { #ifndef WIN32 *************** *** 944,986 **** } /* - * start a psql test process for specified file (including redirection), - * and return process ID - */ - static PID_TYPE - psql_start_test(const char *testname) - { - PID_TYPE pid; - char infile[MAXPGPATH]; - char outfile[MAXPGPATH]; - char psql_cmd[MAXPGPATH * 3]; - - snprintf(infile, sizeof(infile), "%s/sql/%s.sql", - inputdir, testname); - snprintf(outfile, sizeof(outfile), "%s/results/%s.out", - outputdir, testname); - - snprintf(psql_cmd, sizeof(psql_cmd), - SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE, - psqldir ? psqldir : "", - psqldir ? "/" : "", - dbname, - infile, - outfile); - - pid = spawn_process(psql_cmd); - - if (pid == INVALID_PID) - { - fprintf(stderr, _("could not start process for test %s\n"), - testname); - exit_nicely(2); - } - - return pid; - } - - /* * Count bytes in file */ static long --- 1005,1010 ---- *************** *** 1062,1067 **** --- 1086,1111 ---- } /* + * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9 + */ + static char * + get_alternative_expectfile(const char *expectfile, int i) + { + char *last_dot; + int ssize = strlen(expectfile) + 2 + 1; + char *tmp = (char *)malloc(ssize); + char *s = (char *)malloc(ssize); + strcpy(tmp, expectfile); + last_dot = strrchr(tmp,'.'); + if (!last_dot) + return NULL; + *last_dot = '\0'; + snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot+1); + free(tmp); + return s; + } + + /* * Run a "diff" command and also check that it didn't crash */ static int *************** *** 1098,1139 **** * In the true case, the diff is appended to the diffs file. */ static bool ! results_differ(const char *testname) { - const char *expectname; - char resultsfile[MAXPGPATH]; char expectfile[MAXPGPATH]; char diff[MAXPGPATH]; char cmd[MAXPGPATH * 3]; char best_expect_file[MAXPGPATH]; - _resultmap *rm; FILE *difffile; int best_line_count; int i; int l; ! /* Check in resultmap if we should be looking at a different file */ ! expectname = testname; ! for (rm = resultmap; rm != NULL; rm = rm->next) { ! if (strcmp(testname, rm->test) == 0) ! { ! expectname = rm->resultfile; ! break; ! } } - /* Name of test results file */ - snprintf(resultsfile, sizeof(resultsfile), "%s/results/%s.out", - outputdir, testname); - - /* Name of expected-results file */ - snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out", - inputdir, expectname); - /* Name to use for temporary diff file */ ! snprintf(diff, sizeof(diff), "%s/results/%s.diff", ! outputdir, testname); /* OK, run the diff */ snprintf(cmd, sizeof(cmd), --- 1142,1179 ---- * In the true case, the diff is appended to the diffs file. */ static bool ! results_differ(const char *testname, const char *resultsfile, const char *default_expectfile) { char expectfile[MAXPGPATH]; char diff[MAXPGPATH]; char cmd[MAXPGPATH * 3]; char best_expect_file[MAXPGPATH]; FILE *difffile; int best_line_count; int i; int l; + const char *platform_expectfile; ! /* ! * We can pass either the resultsfile or the expectfile, they should ! * have the same type (filename.type) anyway. ! */ ! platform_expectfile = get_expectfile(testname, resultsfile); ! ! strcpy(expectfile, default_expectfile); ! if (platform_expectfile) { ! /* ! * Replace everything afer the last slash in expectfile with what the ! * platform_expectfile contains. XXX SEPARATOR ! */ ! char *p = strrchr(expectfile, '/'); ! if (p) ! strcpy(++p, platform_expectfile); } /* Name to use for temporary diff file */ ! snprintf(diff, sizeof(diff), "%s.diff", resultsfile); /* OK, run the diff */ snprintf(cmd, sizeof(cmd), *************** *** 1153,1166 **** for (i = 0; i <= 9; i++) { ! snprintf(expectfile, sizeof(expectfile), "%s/expected/%s_%d.out", ! inputdir, expectname, i); ! if (!file_exists(expectfile)) continue; snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, ! basic_diff_opts, expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { --- 1193,1207 ---- for (i = 0; i <= 9; i++) { ! char *alt_expectfile; ! ! alt_expectfile = get_alternative_expectfile(expectfile, i); ! if (!file_exists(alt_expectfile)) continue; snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, ! basic_diff_opts, alt_expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { *************** *** 1173,1180 **** { /* This diff was a better match than the last one */ best_line_count = l; ! strcpy(best_expect_file, expectfile); } } /* --- 1214,1222 ---- { /* This diff was a better match than the last one */ best_line_count = l; ! strcpy(best_expect_file, alt_expectfile); } + free(alt_expectfile); } /* *************** *** 1182,1195 **** * haven't found a complete match yet. */ ! if (strcmp(expectname, testname) != 0) { - snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out", - inputdir, testname); - snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, ! basic_diff_opts, expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { --- 1224,1234 ---- * haven't found a complete match yet. */ ! if (platform_expectfile) { snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE, ! basic_diff_opts, default_expectfile, resultsfile, diff); if (run_diff(cmd, diff) == 0) { *************** *** 1203,1209 **** { /* This diff was a better match than the last one */ best_line_count = l; ! strcpy(best_expect_file, expectfile); } } --- 1242,1248 ---- { /* This diff was a better match than the last one */ best_line_count = l; ! strcpy(best_expect_file, default_expectfile); } } *************** *** 1302,1317 **** * Run all the tests specified in one schedule file */ static void ! run_schedule(const char *schedule) { #define MAX_PARALLEL_TESTS 100 char *tests[MAX_PARALLEL_TESTS]; PID_TYPE pids[MAX_PARALLEL_TESTS]; _stringlist *ignorelist = NULL; char scbuf[1024]; FILE *scf; int line_num = 0; scf = fopen(schedule, "r"); if (!scf) { --- 1341,1363 ---- * Run all the tests specified in one schedule file */ static void ! run_schedule(const char *schedule, test_function tfunc) { #define MAX_PARALLEL_TESTS 100 char *tests[MAX_PARALLEL_TESTS]; + _stringlist *resultfiles[MAX_PARALLEL_TESTS]; + _stringlist *expectfiles[MAX_PARALLEL_TESTS]; + _stringlist *tags[MAX_PARALLEL_TESTS]; PID_TYPE pids[MAX_PARALLEL_TESTS]; _stringlist *ignorelist = NULL; char scbuf[1024]; FILE *scf; int line_num = 0; + memset(resultfiles,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + memset(expectfiles,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + memset(tags,0,sizeof(_stringlist *) * MAX_PARALLEL_TESTS); + scf = fopen(schedule, "r"); if (!scf) { *************** *** 1330,1335 **** --- 1376,1390 ---- line_num++; + for (i = 0; i < MAX_PARALLEL_TESTS; i++) + { + if (resultfiles[i] == NULL) + break; + free_stringlist(&resultfiles[i]); + free_stringlist(&expectfiles[i]); + free_stringlist(&tags[i]); + } + /* strip trailing whitespace, especially the newline */ i = strlen(scbuf); while (i > 0 && isspace((unsigned char) scbuf[i - 1])) *************** *** 1394,1400 **** if (num_tests == 1) { status(_("test %-20s ... "), tests[0]); ! pids[0] = psql_start_test(tests[0]); wait_for_tests(pids, NULL, 1); /* status line is finished below */ } --- 1449,1455 ---- if (num_tests == 1) { status(_("test %-20s ... "), tests[0]); ! pids[0] = (*tfunc)(tests[0], &resultfiles[0], &expectfiles[0], &tags[0]); wait_for_tests(pids, NULL, 1); /* status line is finished below */ } *************** *** 1411,1417 **** wait_for_tests(pids + oldest, tests + oldest, i - oldest); oldest = i; } ! pids[i] = psql_start_test(tests[i]); } wait_for_tests(pids + oldest, tests + oldest, i - oldest); status_end(); --- 1466,1472 ---- wait_for_tests(pids + oldest, tests + oldest, i - oldest); oldest = i; } ! pids[i] = (tfunc)(tests[i], &resultfiles[i], &expectfiles[i], &tags[i]); } wait_for_tests(pids + oldest, tests + oldest, i - oldest); status_end(); *************** *** 1421,1427 **** status(_("parallel group (%d tests): "), num_tests); for (i = 0; i < num_tests; i++) { ! pids[i] = psql_start_test(tests[i]); } wait_for_tests(pids, tests, num_tests); status_end(); --- 1476,1482 ---- status(_("parallel group (%d tests): "), num_tests); for (i = 0; i < num_tests; i++) { ! pids[i] = (tfunc)(tests[i], &resultfiles[i], &expectfiles[i], &tags[i]); } wait_for_tests(pids, tests, num_tests); status_end(); *************** *** 1430,1439 **** /* Check results for all tests */ for (i = 0; i < num_tests; i++) { if (num_tests > 1) status(_(" %-20s ... "), tests[i]); ! if (results_differ(tests[i])) { bool ignore = false; _stringlist *sl; --- 1485,1520 ---- /* Check results for all tests */ for (i = 0; i < num_tests; i++) { + _stringlist *rl, *el, *tl; + bool differ = false; + if (num_tests > 1) status(_(" %-20s ... "), tests[i]); ! /* ! * Advance over all three lists simultaneously. ! * ! * Compare resultfiles[j] with expectfiles[j] always. ! * Tags are optional but if there are tags, the tag list has the ! * same length as the other two lists. ! */ ! for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i]; ! rl != NULL; /* rl and el have the same length */ ! rl = rl->next, el = el->next) ! { ! bool newdiff; ! if (tl) ! tl = tl->next; /* tl has the same lengt has rl and el if it exists */ ! ! newdiff = results_differ(tests[i], rl->str, el->str); ! if (newdiff && tl) ! { ! printf("%s ", tl->str); ! } ! differ |= newdiff; ! } ! ! if (differ) { bool ignore = false; _stringlist *sl; *************** *** 1474,1488 **** * Run a single test */ static void ! run_single_test(const char *test) { PID_TYPE pid; status(_("test %-20s ... "), test); ! pid = psql_start_test(test); wait_for_tests(&pid, NULL, 1); ! if (results_differ(test)) { status(_("FAILED")); fail_count++; --- 1555,1598 ---- * Run a single test */ static void ! run_single_test(const char *test, test_function tfunc) { PID_TYPE pid; + _stringlist *resultfiles; + _stringlist *expectfiles; + _stringlist *tags; + _stringlist *rl, *el, *tl; + bool differ; status(_("test %-20s ... "), test); ! /* XXX: Initialize varialbes? */ ! pid = (tfunc)(test, &resultfiles, &expectfiles, &tags); wait_for_tests(&pid, NULL, 1); ! /* ! * Advance over all three lists simultaneously. ! * ! * Compare resultfiles[j] with expectfiles[j] always. ! * Tags are optional but if there are tags, the tag list has the ! * same length as the other two lists. ! */ ! for (rl = resultfiles, el = expectfiles, tl = tags; ! rl != NULL; /* rl and el have the same length */ ! rl = rl->next, el = el->next) ! { ! bool newdiff; ! if (tl) ! tl = tl->next; /* tl has the same lengt has rl and el if it exists */ ! ! newdiff = results_differ(test, rl->str, el->str); ! if (newdiff && tl) ! { ! printf("%s ", tl->str); ! } ! differ |= newdiff; ! } ! ! if (differ) { status(_("FAILED")); fail_count++; *************** *** 1535,1540 **** --- 1645,1707 ---- } static void + drop_database_if_exists(const char *dbname) + { + header(_("dropping database \"%s\""), dbname); + psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname); + } + + static void + create_database(const char *dbname) + { + _stringlist *sl; + /* + * We use template0 so that any installation-local cruft in template1 will + * not mess up the tests. + */ + header(_("creating database \"%s\""), dbname); + if (encoding) + psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'", dbname, encoding); + else + psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0", dbname); + psql_command(dbname, + "ALTER DATABASE \"%s\" SET lc_messages TO 'C';" + "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';" + "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';" + "ALTER DATABASE \"%s\" SET lc_time TO 'C';" + "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';", + dbname, dbname, dbname, dbname, dbname); + + /* + * Install any requested procedural languages + */ + for (sl = loadlanguage; sl != NULL; sl = sl->next) + { + header(_("installing %s"), sl->str); + psql_command(dbname, "CREATE LANGUAGE \"%s\"", sl->str); + } + } + + static void + drop_role_if_exists(const char *rolename) + { + header(_("dropping role \"%s\""), rolename); + psql_command("postgres", "DROP ROLE IF EXISTS \"%s\"", rolename); + } + + static void + create_role(const char *rolename, const _stringlist *granted_dbs) + { + header(_("creating role \"%s\""), rolename); + psql_command("postgres", "CREATE ROLE \"%s\" WITH LOGIN", rolename); + for (; granted_dbs != NULL; granted_dbs = granted_dbs->next) + { + psql_command("postgres", "GRANT ALL ON DATABASE \"%s\" TO \"%s\"", + granted_dbs->str, rolename); + } + } + + static void help(void) { printf(_("PostgreSQL regression test driver\n")); *************** *** 1547,1552 **** --- 1714,1720 ---- printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n")); printf(_(" --load-language=lang load the named language before running the\n")); printf(_(" tests; can appear multiple times\n")); + printf(_(" --create-role=ROLE create the specified role before testing\n")); printf(_(" --max-connections=N maximum number of concurrent connections\n")); printf(_(" (default is 0 meaning unlimited)\n")); printf(_(" --multibyte=ENCODING use ENCODING as the multibyte encoding\n")); *************** *** 1566,1571 **** --- 1734,1740 ---- printf(_(" --port=PORT use postmaster running at PORT\n")); printf(_(" --user=USER connect as USER\n")); printf(_(" --psqldir=DIR use psql in DIR (default: find in PATH)\n")); + printf(_(" --ecpgdir=DIR use ecpg in DIR (default: find in PATH)\n")); printf(_("\n")); printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n")); printf(_("if the tests could not be run for some reason.\n")); *************** *** 1574,1580 **** } int ! main(int argc, char *argv[]) { _stringlist *sl; int c; --- 1743,1749 ---- } int ! regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc) { _stringlist *sl; int c; *************** *** 1602,1607 **** --- 1771,1778 ---- {"user", required_argument, NULL, 15}, {"psqldir", required_argument, NULL, 16}, {"srcdir", required_argument, NULL, 17}, + {"create-role", required_argument, NULL, 18}, + {"ecpgdir", required_argument, NULL, 19}, {NULL, 0, NULL, 0} }; *************** *** 1613,1618 **** --- 1784,1795 ---- hostname = "localhost"; #endif + /* + * We call the initialization function here because that way we can set + * default parameters and let them be overwritten by the commandline. + */ + ifunc(); + while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1) { switch (c) *************** *** 1624,1630 **** printf("pg_regress (PostgreSQL %s)\n", PG_VERSION); exit_nicely(0); case 1: ! dbname = strdup(optarg); break; case 2: debug = true; --- 1801,1807 ---- printf("pg_regress (PostgreSQL %s)\n", PG_VERSION); exit_nicely(0); case 1: ! split_to_stringlist(strdup(optarg), ", ", &dblist); break; case 2: debug = true; *************** *** 1697,1702 **** --- 1874,1887 ---- case 17: srcdir = strdup(optarg); break; + case 18: + split_to_stringlist(strdup(optarg), ", ", &extraroles); + break; + case 19: + /* "--ecpgdir=" should mean to use PATH */ + if (strlen(optarg)) + ecpgdir = strdup(optarg); + break; default: /* getopt_long already emitted a complaint */ fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"), *************** *** 1865,1909 **** { /* * Using an existing installation, so may need to get rid of ! * pre-existing database. */ ! header(_("dropping database \"%s\""), dbname); ! psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname); } /* ! * Create the test database ! * ! * We use template0 so that any installation-local cruft in template1 will ! * not mess up the tests. */ ! header(_("creating database \"%s\""), dbname); ! if (encoding) ! psql_command("postgres", ! "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'", ! dbname, encoding); ! else ! /* use installation default */ ! psql_command("postgres", ! "CREATE DATABASE \"%s\" TEMPLATE=template0", ! dbname); ! ! psql_command(dbname, ! "ALTER DATABASE \"%s\" SET lc_messages TO 'C';" ! "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';" ! "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';" ! "ALTER DATABASE \"%s\" SET lc_time TO 'C';" ! "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';", ! dbname, dbname, dbname, dbname, dbname); ! ! /* ! * Install any requested PL languages ! */ ! for (sl = loadlanguage; sl != NULL; sl = sl->next) ! { ! header(_("installing %s"), sl->str); ! psql_command(dbname, "CREATE LANGUAGE \"%s\"", sl->str); ! } /* * Ready to run the tests --- 2050,2070 ---- { /* * Using an existing installation, so may need to get rid of ! * pre-existing database(s) and role(s) */ ! for (sl = dblist; sl; sl = sl->next) ! drop_database_if_exists(sl->str); ! for (sl = extraroles; sl; sl = sl->next) ! drop_role_if_exists(sl->str); } /* ! * Create the test database(s) and role(s) */ ! for (sl = dblist; sl; sl = sl->next) ! create_database(sl->str); ! for (sl = extraroles; sl; sl = sl->next) ! create_role(sl->str, dblist); /* * Ready to run the tests *************** *** 1912,1923 **** for (sl = schedulelist; sl != NULL; sl = sl->next) { ! run_schedule(sl->str); } for (sl = extra_tests; sl != NULL; sl = sl->next) { ! run_single_test(sl->str); } /* --- 2073,2084 ---- for (sl = schedulelist; sl != NULL; sl = sl->next) { ! run_schedule(sl->str, tfunc); } for (sl = extra_tests; sl != NULL; sl = sl->next) { ! run_single_test(sl->str, tfunc); } /* Index: src/test/regress/resultmap =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/resultmap,v retrieving revision 1.84 diff -c -r1.84 resultmap *** src/test/regress/resultmap 8 Feb 2007 15:28:58 -0000 1.84 --- src/test/regress/resultmap 9 Jun 2007 11:14:35 -0000 *************** *** 1,11 **** ! float4/i.86-pc-mingw32=float4-exp-three-digits ! float4/i.86-pc-win32vc=float4-exp-three-digits ! float8/i.86-.*-freebsd=float8-small-is-zero ! float8/i.86-.*-openbsd=float8-small-is-zero ! float8/i.86-.*-netbsd=float8-small-is-zero ! float8/m68k-.*-netbsd=float8-small-is-zero ! float8/i.86-pc-mingw32=float8-exp-three-digits-win32 ! float8/i.86-pc-win32vc=float8-exp-three-digits-win32 ! float8/i.86-pc-cygwin=float8-small-is-zero ! int8/i.86-pc-mingw32=int8-exp-three-digits ! int8/i.86-pc-win32vc=int8-exp-three-digits \ No newline at end of file --- 1,11 ---- ! float4:out:i.86-pc-mingw32=float4-exp-three-digits.out ! float4:out:i.86-pc-win32vc=float4-exp-three-digits.out ! float8:out:i.86-.*-freebsd=float8-small-is-zero.out ! float8:out:i.86-.*-openbsd=float8-small-is-zero.out ! float8:out:i.86-.*-netbsd=float8-small-is-zero.out ! float8:out:m68k-.*-netbsd=float8-small-is-zero.out ! float8:out:i.86-pc-mingw32=float8-exp-three-digits-win32.out ! float8:out:i.86-pc-win32vc=float8-exp-three-digits-win32.out ! float8:out:i.86-pc-cygwin=float8-small-is-zero.out ! int8:out:i.86-pc-mingw32=int8-exp-three-digits.out ! int8:out:i.86-pc-win32vc=int8-exp-three-digits.out Index: src/tools/msvc/Install.pm =================================================================== RCS file: /projects/cvsroot/pgsql/src/tools/msvc/Install.pm,v retrieving revision 1.15 diff -c -r1.15 Install.pm *** src/tools/msvc/Install.pm 13 May 2007 15:33:07 -0000 1.15 --- src/tools/msvc/Install.pm 9 Jun 2007 11:14:36 -0000 *************** *** 25,30 **** --- 25,31 ---- require 'config.pl'; chdir("../../..") if (-f "../../../configure"); + chdir("../../../..") if (-f "../../../../configure"); my $conf = ""; if (-d "debug") { *************** *** 115,120 **** --- 116,122 ---- { chomp; next if /regress/; # Skip temporary install in regression subdir + next if /ecpg.test/; # Skip temporary install in regression subdir my $tgt = $target . basename($_); print "."; my $src = $norecurse?(dirname($spec) . '/' . $_):$_; Index: src/tools/msvc/Mkvcbuild.pm =================================================================== RCS file: /projects/cvsroot/pgsql/src/tools/msvc/Mkvcbuild.pm,v retrieving revision 1.11 diff -c -r1.11 Mkvcbuild.pm *** src/tools/msvc/Mkvcbuild.pm 27 Apr 2007 16:45:54 -0000 1.11 --- src/tools/msvc/Mkvcbuild.pm 9 Jun 2007 13:02:38 -0000 *************** *** 154,159 **** --- 154,168 ---- $ecpg->AddDefine('PATCHLEVEL=1'); $ecpg->AddReference($libpgport); + my $pgregress_ecpg = $solution->AddProject('pg_regress_ecpg','exe','misc'); + $pgregress_ecpg->AddFile('src\interfaces\ecpg\test\pg_regress_ecpg.c'); + $pgregress_ecpg->AddFile('src\test\regress\pg_regress.c'); + $pgregress_ecpg->AddIncludeDir('src\port'); + $pgregress_ecpg->AddIncludeDir('src\test\regress'); + $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); + $pgregress_ecpg->AddDefine('FRONTEND'); + $pgregress_ecpg->AddReference($libpgport); + # src/bin my $initdb = AddSimpleFrontend('initdb', 1); $initdb->AddLibrary('wsock32.lib ws2_32.lib'); *************** *** 315,320 **** --- 324,330 ---- my $pgregress = $solution->AddProject('pg_regress','exe','misc'); $pgregress->AddFile('src\test\regress\pg_regress.c'); + $pgregress->AddFile('src\test\regress\pg_regress_main.c'); $pgregress->AddIncludeDir('src\port'); $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); $pgregress->AddDefine('FRONTEND'); Index: src/tools/msvc/vcregress.bat =================================================================== RCS file: /projects/cvsroot/pgsql/src/tools/msvc/vcregress.bat,v retrieving revision 1.11 diff -c -r1.11 vcregress.bat *** src/tools/msvc/vcregress.bat 21 Apr 2007 20:58:05 -0000 1.11 --- src/tools/msvc/vcregress.bat 9 Jun 2007 13:01:10 -0000 *************** *** 11,16 **** --- 11,17 ---- if /I "%1"=="installcheck" SET what=INSTALLCHECK if /I "%1"=="plcheck" SET what=PLCHECK if /I "%1"=="contribcheck" SET what=CONTRIBCHECK + if /I "%1"=="ecpgcheck" SET what=ECPGCHECK if "%what%"=="" goto usage SET CONFIG=Debug *************** *** 28,37 **** SET TEMPPORT=54321 IF NOT "%2"=="" SET SCHEDULE=%2 ! SET PERL5LIB=..\..\tools\msvc if "%what%"=="INSTALLCHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale if "%what%"=="CHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale --temp-install=./tmp_check --top-builddir="%TOPDIR%" --temp-port=%TEMPPORT% if "%what%"=="PLCHECK" call :plcheck if "%what%"=="CONTRIBCHECK" call :contribcheck SET E=%ERRORLEVEL% --- 29,45 ---- SET TEMPPORT=54321 IF NOT "%2"=="" SET SCHEDULE=%2 ! IF "%what%"=="ECPGCHECK" ( ! cd "%TOPDIR%" ! cd src\interfaces\ecpg\test ! SET SCHEDULE=ecpg ! ) ! ! SET PERL5LIB=%TOPDIR%\src\tools\msvc if "%what%"=="INSTALLCHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale if "%what%"=="CHECK" ..\..\..\%CONFIG%\pg_regress\pg_regress --psqldir="..\..\..\%CONFIG%\psql" --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale --temp-install=./tmp_check --top-builddir="%TOPDIR%" --temp-port=%TEMPPORT% + if "%what%"=="ECPGCHECK" ..\..\..\..\%CONFIG%\pg_regress_ecpg\pg_regress_ecpg --psqldir="..\..\..\%CONFIG%\psql" --dbname=regress1,connectdb --create-role=connectuser,connectdb --schedule=%SCHEDULE%_schedule --multibyte=SQL_ASCII --load-language=plpgsql --no-locale --temp-install=./tmp_check --top-builddir="%TOPDIR%" --temp-port=%TEMPPORT% if "%what%"=="PLCHECK" call :plcheck if "%what%"=="CONTRIBCHECK" call :contribcheck SET E=%ERRORLEVEL% *************** *** 40,46 **** exit /b %E% :usage ! echo "Usage: vcregress [schedule]" goto :eof --- 48,54 ---- exit /b %E% :usage ! echo "Usage: vcregress [schedule]" goto :eof