Consistently use "superuser" instead of "super user"
[pgsql.git] / src / test / regress / pg_regress.c
blob05296f7ee1db9bc6c923908f051c698e43227240
1 /*-------------------------------------------------------------------------
3 * pg_regress --- regression test driver
5 * This is a C implementation of the previous shell script for running
6 * the regression tests, and should be mostly compatible with it.
7 * Initial author of C translation: Magnus Hagander
9 * This code is released under the terms of the PostgreSQL License.
11 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
14 * src/test/regress/pg_regress.c
16 *-------------------------------------------------------------------------
19 #include "postgres_fe.h"
21 #include <ctype.h>
22 #include <sys/stat.h>
23 #include <sys/wait.h>
24 #include <signal.h>
25 #include <unistd.h>
27 #ifdef HAVE_SYS_RESOURCE_H
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #endif
32 #include "common/logging.h"
33 #include "common/restricted_token.h"
34 #include "common/string.h"
35 #include "common/username.h"
36 #include "getopt_long.h"
37 #include "lib/stringinfo.h"
38 #include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
39 #include "pg_config_paths.h"
40 #include "pg_regress.h"
41 #include "portability/instr_time.h"
43 /* for resultmap we need a list of pairs of strings */
44 typedef struct _resultmap
46 char *test;
47 char *type;
48 char *resultfile;
49 struct _resultmap *next;
50 } _resultmap;
53 * Values obtained from Makefile.
55 char *host_platform = HOST_TUPLE;
57 #ifndef WIN32 /* not used in WIN32 case */
58 static char *shellprog = SHELLPROG;
59 #endif
62 * On Windows we use -w in diff switches to avoid problems with inconsistent
63 * newline representation. The actual result files will generally have
64 * Windows-style newlines, but the comparison files might or might not.
66 #ifndef WIN32
67 const char *basic_diff_opts = "";
68 const char *pretty_diff_opts = "-U3";
69 #else
70 const char *basic_diff_opts = "-w";
71 const char *pretty_diff_opts = "-w -U3";
72 #endif
74 /* options settable from command line */
75 _stringlist *dblist = NULL;
76 bool debug = false;
77 char *inputdir = ".";
78 char *outputdir = ".";
79 char *bindir = PGBINDIR;
80 char *launcher = NULL;
81 static _stringlist *loadextension = NULL;
82 static int max_connections = 0;
83 static int max_concurrent_tests = 0;
84 static char *encoding = NULL;
85 static _stringlist *schedulelist = NULL;
86 static _stringlist *extra_tests = NULL;
87 static char *temp_instance = NULL;
88 static _stringlist *temp_configs = NULL;
89 static bool nolocale = false;
90 static bool use_existing = false;
91 static char *hostname = NULL;
92 static int port = -1;
93 static bool port_specified_by_user = false;
94 static char *dlpath = PKGLIBDIR;
95 static char *user = NULL;
96 static _stringlist *extraroles = NULL;
97 static char *config_auth_datadir = NULL;
99 /* internal variables */
100 static const char *progname;
101 static char *logfilename;
102 static FILE *logfile;
103 static char *difffilename;
104 static const char *sockdir;
105 #ifdef HAVE_UNIX_SOCKETS
106 static const char *temp_sockdir;
107 static char sockself[MAXPGPATH];
108 static char socklock[MAXPGPATH];
109 #endif
111 static _resultmap *resultmap = NULL;
113 static PID_TYPE postmaster_pid = INVALID_PID;
114 static bool postmaster_running = false;
116 static int success_count = 0;
117 static int fail_count = 0;
118 static int fail_ignore_count = 0;
120 static bool directory_exists(const char *dir);
121 static void make_directory(const char *dir);
123 static void header(const char *fmt,...) pg_attribute_printf(1, 2);
124 static void status(const char *fmt,...) pg_attribute_printf(1, 2);
125 static void psql_command(const char *database, const char *query,...) pg_attribute_printf(2, 3);
128 * allow core files if possible.
130 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
131 static void
132 unlimit_core_size(void)
134 struct rlimit lim;
136 getrlimit(RLIMIT_CORE, &lim);
137 if (lim.rlim_max == 0)
139 fprintf(stderr,
140 _("%s: could not set core size: disallowed by hard limit\n"),
141 progname);
142 return;
144 else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
146 lim.rlim_cur = lim.rlim_max;
147 setrlimit(RLIMIT_CORE, &lim);
150 #endif
154 * Add an item at the end of a stringlist.
156 void
157 add_stringlist_item(_stringlist **listhead, const char *str)
159 _stringlist *newentry = pg_malloc(sizeof(_stringlist));
160 _stringlist *oldentry;
162 newentry->str = pg_strdup(str);
163 newentry->next = NULL;
164 if (*listhead == NULL)
165 *listhead = newentry;
166 else
168 for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
169 /* skip */ ;
170 oldentry->next = newentry;
175 * Free a stringlist.
177 static void
178 free_stringlist(_stringlist **listhead)
180 if (listhead == NULL || *listhead == NULL)
181 return;
182 if ((*listhead)->next != NULL)
183 free_stringlist(&((*listhead)->next));
184 free((*listhead)->str);
185 free(*listhead);
186 *listhead = NULL;
190 * Split a delimited string into a stringlist
192 static void
193 split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
195 char *sc = pg_strdup(s);
196 char *token = strtok(sc, delim);
198 while (token)
200 add_stringlist_item(listhead, token);
201 token = strtok(NULL, delim);
203 free(sc);
207 * Print a progress banner on stdout.
209 static void
210 header(const char *fmt,...)
212 char tmp[64];
213 va_list ap;
215 va_start(ap, fmt);
216 vsnprintf(tmp, sizeof(tmp), fmt, ap);
217 va_end(ap);
219 fprintf(stdout, "============== %-38s ==============\n", tmp);
220 fflush(stdout);
224 * Print "doing something ..." --- supplied text should not end with newline
226 static void
227 status(const char *fmt,...)
229 va_list ap;
231 va_start(ap, fmt);
232 vfprintf(stdout, fmt, ap);
233 fflush(stdout);
234 va_end(ap);
236 if (logfile)
238 va_start(ap, fmt);
239 vfprintf(logfile, fmt, ap);
240 va_end(ap);
245 * Done "doing something ..."
247 static void
248 status_end(void)
250 fprintf(stdout, "\n");
251 fflush(stdout);
252 if (logfile)
253 fprintf(logfile, "\n");
257 * shut down temp postmaster
259 static void
260 stop_postmaster(void)
262 if (postmaster_running)
264 /* We use pg_ctl to issue the kill and wait for stop */
265 char buf[MAXPGPATH * 2];
266 int r;
268 /* On Windows, system() seems not to force fflush, so... */
269 fflush(stdout);
270 fflush(stderr);
272 snprintf(buf, sizeof(buf),
273 "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
274 bindir ? bindir : "",
275 bindir ? "/" : "",
276 temp_instance);
277 r = system(buf);
278 if (r != 0)
280 fprintf(stderr, _("\n%s: could not stop postmaster: exit code was %d\n"),
281 progname, r);
282 _exit(2); /* not exit(), that could be recursive */
285 postmaster_running = false;
289 #ifdef HAVE_UNIX_SOCKETS
291 * Remove the socket temporary directory. pg_regress never waits for a
292 * postmaster exit, so it is indeterminate whether the postmaster has yet to
293 * unlink the socket and lock file. Unlink them here so we can proceed to
294 * remove the directory. Ignore errors; leaking a temporary directory is
295 * unimportant. This can run from a signal handler. The code is not
296 * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
297 * on Windows, pg_regress does not use Unix sockets by default.
299 static void
300 remove_temp(void)
302 Assert(temp_sockdir);
303 unlink(sockself);
304 unlink(socklock);
305 rmdir(temp_sockdir);
309 * Signal handler that calls remove_temp() and reraises the signal.
311 static void
312 signal_remove_temp(int signum)
314 remove_temp();
316 pqsignal(signum, SIG_DFL);
317 raise(signum);
321 * Create a temporary directory suitable for the server's Unix-domain socket.
322 * The directory will have mode 0700 or stricter, so no other OS user can open
323 * our socket to exploit our use of trust authentication. Most systems
324 * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
325 * place the directory under /tmp rather than relative to the possibly-deep
326 * current working directory.
328 * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
329 * testing to work in builds that relocate it to a directory not writable to
330 * the build/test user.
332 static const char *
333 make_temp_sockdir(void)
335 char *template = psprintf("%s/pg_regress-XXXXXX",
336 getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
338 temp_sockdir = mkdtemp(template);
339 if (temp_sockdir == NULL)
341 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
342 progname, template, strerror(errno));
343 exit(2);
346 /* Stage file names for remove_temp(). Unsafe in a signal handler. */
347 UNIXSOCK_PATH(sockself, port, temp_sockdir);
348 snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
350 /* Remove the directory during clean exit. */
351 atexit(remove_temp);
354 * Remove the directory before dying to the usual signals. Omit SIGQUIT,
355 * preserving it as a quick, untidy exit.
357 pqsignal(SIGHUP, signal_remove_temp);
358 pqsignal(SIGINT, signal_remove_temp);
359 pqsignal(SIGPIPE, signal_remove_temp);
360 pqsignal(SIGTERM, signal_remove_temp);
362 return temp_sockdir;
364 #endif /* HAVE_UNIX_SOCKETS */
367 * Check whether string matches pattern
369 * In the original shell script, this function was implemented using expr(1),
370 * which provides basic regular expressions restricted to match starting at
371 * the string start (in conventional regex terms, there's an implicit "^"
372 * at the start of the pattern --- but no implicit "$" at the end).
374 * For now, we only support "." and ".*" as non-literal metacharacters,
375 * because that's all that anyone has found use for in resultmap. This
376 * code could be extended if more functionality is needed.
378 static bool
379 string_matches_pattern(const char *str, const char *pattern)
381 while (*str && *pattern)
383 if (*pattern == '.' && pattern[1] == '*')
385 pattern += 2;
386 /* Trailing .* matches everything. */
387 if (*pattern == '\0')
388 return true;
391 * Otherwise, scan for a text position at which we can match the
392 * rest of the pattern.
394 while (*str)
397 * Optimization to prevent most recursion: don't recurse
398 * unless first pattern char might match this text char.
400 if (*str == *pattern || *pattern == '.')
402 if (string_matches_pattern(str, pattern))
403 return true;
406 str++;
410 * End of text with no match.
412 return false;
414 else if (*pattern != '.' && *str != *pattern)
417 * Not the single-character wildcard and no explicit match? Then
418 * time to quit...
420 return false;
423 str++;
424 pattern++;
427 if (*pattern == '\0')
428 return true; /* end of pattern, so declare match */
430 /* End of input string. Do we have matching pattern remaining? */
431 while (*pattern == '.' && pattern[1] == '*')
432 pattern += 2;
433 if (*pattern == '\0')
434 return true; /* end of pattern, so declare match */
436 return false;
440 * Replace all occurrences of "replace" in "string" with "replacement".
441 * The StringInfo will be suitably enlarged if necessary.
443 * Note: this is optimized on the assumption that most calls will find
444 * no more than one occurrence of "replace", and quite likely none.
446 void
447 replace_string(StringInfo string, const char *replace, const char *replacement)
449 int pos = 0;
450 char *ptr;
452 while ((ptr = strstr(string->data + pos, replace)) != NULL)
454 /* Must copy the remainder of the string out of the StringInfo */
455 char *suffix = pg_strdup(ptr + strlen(replace));
457 /* Truncate StringInfo at start of found string ... */
458 string->len = ptr - string->data;
459 /* ... and append the replacement (this restores the trailing '\0') */
460 appendStringInfoString(string, replacement);
461 /* Next search should start after the replacement */
462 pos = string->len;
463 /* Put back the remainder of the string */
464 appendStringInfoString(string, suffix);
465 free(suffix);
470 * Convert *.source found in the "source" directory, replacing certain tokens
471 * in the file contents with their intended values, and put the resulting files
472 * in the "dest" directory, replacing the ".source" prefix in their names with
473 * the given suffix.
475 static void
476 convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const char *dest_subdir, const char *suffix)
478 char testtablespace[MAXPGPATH];
479 char indir[MAXPGPATH];
480 char outdir_sub[MAXPGPATH];
481 char **name;
482 char **names;
483 int count = 0;
485 snprintf(indir, MAXPGPATH, "%s/%s", inputdir, source_subdir);
487 /* Check that indir actually exists and is a directory */
488 if (!directory_exists(indir))
491 * No warning, to avoid noise in tests that do not have these
492 * directories; for example, ecpg, contrib and src/pl.
494 return;
497 names = pgfnames(indir);
498 if (!names)
499 /* Error logged in pgfnames */
500 exit(2);
502 /* Create the "dest" subdirectory if not present */
503 snprintf(outdir_sub, MAXPGPATH, "%s/%s", dest_dir, dest_subdir);
504 if (!directory_exists(outdir_sub))
505 make_directory(outdir_sub);
507 /* We might need to replace @testtablespace@ */
508 snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
510 /* finally loop on each file and do the replacement */
511 for (name = names; *name; name++)
513 char srcfile[MAXPGPATH];
514 char destfile[MAXPGPATH];
515 char prefix[MAXPGPATH];
516 FILE *infile,
517 *outfile;
518 StringInfoData line;
520 /* reject filenames not finishing in ".source" */
521 if (strlen(*name) < 8)
522 continue;
523 if (strcmp(*name + strlen(*name) - 7, ".source") != 0)
524 continue;
526 count++;
528 /* build the full actual paths to open */
529 snprintf(prefix, strlen(*name) - 6, "%s", *name);
530 snprintf(srcfile, MAXPGPATH, "%s/%s", indir, *name);
531 snprintf(destfile, MAXPGPATH, "%s/%s/%s.%s", dest_dir, dest_subdir,
532 prefix, suffix);
534 infile = fopen(srcfile, "r");
535 if (!infile)
537 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
538 progname, srcfile, strerror(errno));
539 exit(2);
541 outfile = fopen(destfile, "w");
542 if (!outfile)
544 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
545 progname, destfile, strerror(errno));
546 exit(2);
549 initStringInfo(&line);
551 while (pg_get_line_buf(infile, &line))
553 replace_string(&line, "@abs_srcdir@", inputdir);
554 replace_string(&line, "@abs_builddir@", outputdir);
555 replace_string(&line, "@testtablespace@", testtablespace);
556 replace_string(&line, "@libdir@", dlpath);
557 replace_string(&line, "@DLSUFFIX@", DLSUFFIX);
558 fputs(line.data, outfile);
561 pfree(line.data);
562 fclose(infile);
563 fclose(outfile);
567 * If we didn't process any files, complain because it probably means
568 * somebody neglected to pass the needed --inputdir argument.
570 if (count <= 0)
572 fprintf(stderr, _("%s: no *.source files found in \"%s\"\n"),
573 progname, indir);
574 exit(2);
577 pgfnames_cleanup(names);
580 /* Create the .sql and .out files from the .source files, if any */
581 static void
582 convert_sourcefiles(void)
584 convert_sourcefiles_in("input", outputdir, "sql", "sql");
585 convert_sourcefiles_in("output", outputdir, "expected", "out");
589 * Clean out the test tablespace dir, or create it if it doesn't exist.
591 * On Windows, doing this cleanup here makes it possible to run the
592 * regression tests under a Windows administrative user account with the
593 * restricted token obtained when starting pg_regress.
595 static void
596 prepare_testtablespace_dir(void)
598 char testtablespace[MAXPGPATH];
600 snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
602 if (directory_exists(testtablespace))
604 if (!rmtree(testtablespace, true))
606 fprintf(stderr, _("\n%s: could not remove test tablespace \"%s\"\n"),
607 progname, testtablespace);
608 exit(2);
611 make_directory(testtablespace);
615 * Scan resultmap file to find which platform-specific expected files to use.
617 * The format of each line of the file is
618 * testname/hostplatformpattern=substitutefile
619 * where the hostplatformpattern is evaluated per the rules of expr(1),
620 * namely, it is a standard regular expression with an implicit ^ at the start.
621 * (We currently support only a very limited subset of regular expressions,
622 * see string_matches_pattern() above.) What hostplatformpattern will be
623 * matched against is the config.guess output. (In the shell-script version,
624 * we also provided an indication of whether gcc or another compiler was in
625 * use, but that facility isn't used anymore.)
627 static void
628 load_resultmap(void)
630 char buf[MAXPGPATH];
631 FILE *f;
633 /* scan the file ... */
634 snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
635 f = fopen(buf, "r");
636 if (!f)
638 /* OK if it doesn't exist, else complain */
639 if (errno == ENOENT)
640 return;
641 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
642 progname, buf, strerror(errno));
643 exit(2);
646 while (fgets(buf, sizeof(buf), f))
648 char *platform;
649 char *file_type;
650 char *expected;
651 int i;
653 /* strip trailing whitespace, especially the newline */
654 i = strlen(buf);
655 while (i > 0 && isspace((unsigned char) buf[i - 1]))
656 buf[--i] = '\0';
658 /* parse out the line fields */
659 file_type = strchr(buf, ':');
660 if (!file_type)
662 fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
663 buf);
664 exit(2);
666 *file_type++ = '\0';
668 platform = strchr(file_type, ':');
669 if (!platform)
671 fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
672 buf);
673 exit(2);
675 *platform++ = '\0';
676 expected = strchr(platform, '=');
677 if (!expected)
679 fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
680 buf);
681 exit(2);
683 *expected++ = '\0';
686 * if it's for current platform, save it in resultmap list. Note: by
687 * adding at the front of the list, we ensure that in ambiguous cases,
688 * the last match in the resultmap file is used. This mimics the
689 * behavior of the old shell script.
691 if (string_matches_pattern(host_platform, platform))
693 _resultmap *entry = pg_malloc(sizeof(_resultmap));
695 entry->test = pg_strdup(buf);
696 entry->type = pg_strdup(file_type);
697 entry->resultfile = pg_strdup(expected);
698 entry->next = resultmap;
699 resultmap = entry;
702 fclose(f);
706 * Check in resultmap if we should be looking at a different file
708 static
709 const char *
710 get_expectfile(const char *testname, const char *file)
712 char *file_type;
713 _resultmap *rm;
716 * Determine the file type from the file name. This is just what is
717 * following the last dot in the file name.
719 if (!file || !(file_type = strrchr(file, '.')))
720 return NULL;
722 file_type++;
724 for (rm = resultmap; rm != NULL; rm = rm->next)
726 if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
728 return rm->resultfile;
732 return NULL;
736 * Prepare environment variables for running regression tests
738 static void
739 initialize_environment(void)
742 * Set default application_name. (The test_start_function may choose to
743 * override this, but if it doesn't, we have something useful in place.)
745 setenv("PGAPPNAME", "pg_regress", 1);
747 if (nolocale)
750 * Clear out any non-C locale settings
752 unsetenv("LC_COLLATE");
753 unsetenv("LC_CTYPE");
754 unsetenv("LC_MONETARY");
755 unsetenv("LC_NUMERIC");
756 unsetenv("LC_TIME");
757 unsetenv("LANG");
760 * Most platforms have adopted the POSIX locale as their
761 * implementation-defined default locale. Exceptions include native
762 * Windows, macOS with --enable-nls, and Cygwin with --enable-nls.
763 * (Use of --enable-nls matters because libintl replaces setlocale().)
764 * Also, PostgreSQL does not support macOS with locale environment
765 * variables unset; see PostmasterMain().
767 #if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
768 setenv("LANG", "C", 1);
769 #endif
773 * Set translation-related settings to English; otherwise psql will
774 * produce translated messages and produce diffs. (XXX If we ever support
775 * translation of pg_regress, this needs to be moved elsewhere, where psql
776 * is actually called.)
778 unsetenv("LANGUAGE");
779 unsetenv("LC_ALL");
780 setenv("LC_MESSAGES", "C", 1);
783 * Set encoding as requested
785 if (encoding)
786 setenv("PGCLIENTENCODING", encoding, 1);
787 else
788 unsetenv("PGCLIENTENCODING");
791 * Set timezone and datestyle for datetime-related tests
793 setenv("PGTZ", "PST8PDT", 1);
794 setenv("PGDATESTYLE", "Postgres, MDY", 1);
797 * Likewise set intervalstyle to ensure consistent results. This is a bit
798 * more painful because we must use PGOPTIONS, and we want to preserve the
799 * user's ability to set other variables through that.
802 const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
803 const char *old_pgoptions = getenv("PGOPTIONS");
804 char *new_pgoptions;
806 if (!old_pgoptions)
807 old_pgoptions = "";
808 new_pgoptions = psprintf("%s %s",
809 old_pgoptions, my_pgoptions);
810 setenv("PGOPTIONS", new_pgoptions, 1);
811 free(new_pgoptions);
814 if (temp_instance)
817 * Clear out any environment vars that might cause psql to connect to
818 * the wrong postmaster, or otherwise behave in nondefault ways. (Note
819 * we also use psql's -X switch consistently, so that ~/.psqlrc files
820 * won't mess things up.) Also, set PGPORT to the temp port, and set
821 * PGHOST depending on whether we are using TCP or Unix sockets.
823 * This list should be kept in sync with TestLib.pm.
825 unsetenv("PGCHANNELBINDING");
826 /* PGCLIENTENCODING, see above */
827 unsetenv("PGCONNECT_TIMEOUT");
828 unsetenv("PGDATA");
829 unsetenv("PGDATABASE");
830 unsetenv("PGGSSENCMODE");
831 unsetenv("PGGSSLIB");
832 /* PGHOSTADDR, see below */
833 unsetenv("PGKRBSRVNAME");
834 unsetenv("PGPASSFILE");
835 unsetenv("PGPASSWORD");
836 unsetenv("PGREQUIREPEER");
837 unsetenv("PGREQUIRESSL");
838 unsetenv("PGSERVICE");
839 unsetenv("PGSERVICEFILE");
840 unsetenv("PGSSLCERT");
841 unsetenv("PGSSLCRL");
842 unsetenv("PGSSLCRLDIR");
843 unsetenv("PGSSLKEY");
844 unsetenv("PGSSLMAXPROTOCOLVERSION");
845 unsetenv("PGSSLMINPROTOCOLVERSION");
846 unsetenv("PGSSLMODE");
847 unsetenv("PGSSLROOTCERT");
848 unsetenv("PGSSLSNI");
849 unsetenv("PGTARGETSESSIONATTRS");
850 unsetenv("PGUSER");
851 /* PGPORT, see below */
852 /* PGHOST, see below */
854 #ifdef HAVE_UNIX_SOCKETS
855 if (hostname != NULL)
856 setenv("PGHOST", hostname, 1);
857 else
859 sockdir = getenv("PG_REGRESS_SOCK_DIR");
860 if (!sockdir)
861 sockdir = make_temp_sockdir();
862 setenv("PGHOST", sockdir, 1);
864 #else
865 Assert(hostname != NULL);
866 setenv("PGHOST", hostname, 1);
867 #endif
868 unsetenv("PGHOSTADDR");
869 if (port != -1)
871 char s[16];
873 sprintf(s, "%d", port);
874 setenv("PGPORT", s, 1);
877 else
879 const char *pghost;
880 const char *pgport;
883 * When testing an existing install, we honor existing environment
884 * variables, except if they're overridden by command line options.
886 if (hostname != NULL)
888 setenv("PGHOST", hostname, 1);
889 unsetenv("PGHOSTADDR");
891 if (port != -1)
893 char s[16];
895 sprintf(s, "%d", port);
896 setenv("PGPORT", s, 1);
898 if (user != NULL)
899 setenv("PGUSER", user, 1);
902 * However, we *don't* honor PGDATABASE, since we certainly don't wish
903 * to connect to whatever database the user might like as default.
904 * (Most tests override PGDATABASE anyway, but there are some ECPG
905 * test cases that don't.)
907 unsetenv("PGDATABASE");
910 * Report what we're connecting to
912 pghost = getenv("PGHOST");
913 pgport = getenv("PGPORT");
914 #ifndef HAVE_UNIX_SOCKETS
915 if (!pghost)
916 pghost = "localhost";
917 #endif
919 if (pghost && pgport)
920 printf(_("(using postmaster on %s, port %s)\n"), pghost, pgport);
921 if (pghost && !pgport)
922 printf(_("(using postmaster on %s, default port)\n"), pghost);
923 if (!pghost && pgport)
924 printf(_("(using postmaster on Unix socket, port %s)\n"), pgport);
925 if (!pghost && !pgport)
926 printf(_("(using postmaster on Unix socket, default port)\n"));
929 convert_sourcefiles();
930 load_resultmap();
933 #ifdef ENABLE_SSPI
935 /* support for config_sspi_auth() */
936 static const char *
937 fmtHba(const char *raw)
939 static char *ret;
940 const char *rp;
941 char *wp;
943 wp = ret = realloc(ret, 3 + strlen(raw) * 2);
945 *wp++ = '"';
946 for (rp = raw; *rp; rp++)
948 if (*rp == '"')
949 *wp++ = '"';
950 *wp++ = *rp;
952 *wp++ = '"';
953 *wp++ = '\0';
955 return ret;
959 * Get account and domain/realm names for the current user. This is based on
960 * pg_SSPI_recvauth(). The returned strings use static storage.
962 static void
963 current_windows_user(const char **acct, const char **dom)
965 static char accountname[MAXPGPATH];
966 static char domainname[MAXPGPATH];
967 HANDLE token;
968 TOKEN_USER *tokenuser;
969 DWORD retlen;
970 DWORD accountnamesize = sizeof(accountname);
971 DWORD domainnamesize = sizeof(domainname);
972 SID_NAME_USE accountnameuse;
974 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token))
976 fprintf(stderr,
977 _("%s: could not open process token: error code %lu\n"),
978 progname, GetLastError());
979 exit(2);
982 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
984 fprintf(stderr,
985 _("%s: could not get token information buffer size: error code %lu\n"),
986 progname, GetLastError());
987 exit(2);
989 tokenuser = pg_malloc(retlen);
990 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
992 fprintf(stderr,
993 _("%s: could not get token information: error code %lu\n"),
994 progname, GetLastError());
995 exit(2);
998 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
999 domainname, &domainnamesize, &accountnameuse))
1001 fprintf(stderr,
1002 _("%s: could not look up account SID: error code %lu\n"),
1003 progname, GetLastError());
1004 exit(2);
1007 free(tokenuser);
1009 *acct = accountname;
1010 *dom = domainname;
1014 * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
1015 * the current OS user to authenticate as the bootstrap superuser and as any
1016 * user named in a --create-role option.
1018 * In --config-auth mode, the --user switch can be used to specify the
1019 * bootstrap superuser's name, otherwise we assume it is the default.
1021 static void
1022 config_sspi_auth(const char *pgdata, const char *superuser_name)
1024 const char *accountname,
1025 *domainname;
1026 char *errstr;
1027 bool have_ipv6;
1028 char fname[MAXPGPATH];
1029 int res;
1030 FILE *hba,
1031 *ident;
1032 _stringlist *sl;
1034 /* Find out the name of the current OS user */
1035 current_windows_user(&accountname, &domainname);
1037 /* Determine the bootstrap superuser's name */
1038 if (superuser_name == NULL)
1041 * Compute the default superuser name the same way initdb does.
1043 * It's possible that this result always matches "accountname", the
1044 * value SSPI authentication discovers. But the underlying system
1045 * functions do not clearly guarantee that.
1047 superuser_name = get_user_name(&errstr);
1048 if (superuser_name == NULL)
1050 fprintf(stderr, "%s: %s\n", progname, errstr);
1051 exit(2);
1056 * Like initdb.c:setup_config(), determine whether the platform recognizes
1057 * ::1 (IPv6 loopback) as a numeric host address string.
1060 struct addrinfo *gai_result;
1061 struct addrinfo hints;
1062 WSADATA wsaData;
1064 hints.ai_flags = AI_NUMERICHOST;
1065 hints.ai_family = AF_UNSPEC;
1066 hints.ai_socktype = 0;
1067 hints.ai_protocol = 0;
1068 hints.ai_addrlen = 0;
1069 hints.ai_canonname = NULL;
1070 hints.ai_addr = NULL;
1071 hints.ai_next = NULL;
1073 have_ipv6 = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0 &&
1074 getaddrinfo("::1", NULL, &hints, &gai_result) == 0);
1077 /* Check a Write outcome and report any error. */
1078 #define CW(cond) \
1079 do { \
1080 if (!(cond)) \
1082 fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
1083 progname, fname, strerror(errno)); \
1084 exit(2); \
1086 } while (0)
1088 res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
1089 if (res < 0 || res >= sizeof(fname))
1092 * Truncating this name is a fatal error, because we must not fail to
1093 * overwrite an original trust-authentication pg_hba.conf.
1095 fprintf(stderr, _("%s: directory name too long\n"), progname);
1096 exit(2);
1098 hba = fopen(fname, "w");
1099 if (hba == NULL)
1101 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1102 progname, fname, strerror(errno));
1103 exit(2);
1105 CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
1106 CW(fputs("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n",
1107 hba) >= 0);
1108 if (have_ipv6)
1109 CW(fputs("host all all ::1/128 sspi include_realm=1 map=regress\n",
1110 hba) >= 0);
1111 CW(fclose(hba) == 0);
1113 snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
1114 ident = fopen(fname, "w");
1115 if (ident == NULL)
1117 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1118 progname, fname, strerror(errno));
1119 exit(2);
1121 CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
1124 * Double-quote for the benefit of account names containing whitespace or
1125 * '#'. Windows forbids the double-quote character itself, so don't
1126 * bother escaping embedded double-quote characters.
1128 CW(fprintf(ident, "regress \"%s@%s\" %s\n",
1129 accountname, domainname, fmtHba(superuser_name)) >= 0);
1130 for (sl = extraroles; sl; sl = sl->next)
1131 CW(fprintf(ident, "regress \"%s@%s\" %s\n",
1132 accountname, domainname, fmtHba(sl->str)) >= 0);
1133 CW(fclose(ident) == 0);
1136 #endif /* ENABLE_SSPI */
1139 * Issue a command via psql, connecting to the specified database
1141 * Since we use system(), this doesn't return until the operation finishes
1143 static void
1144 psql_command(const char *database, const char *query,...)
1146 char query_formatted[1024];
1147 char query_escaped[2048];
1148 char psql_cmd[MAXPGPATH + 2048];
1149 va_list args;
1150 char *s;
1151 char *d;
1153 /* Generate the query with insertion of sprintf arguments */
1154 va_start(args, query);
1155 vsnprintf(query_formatted, sizeof(query_formatted), query, args);
1156 va_end(args);
1158 /* Now escape any shell double-quote metacharacters */
1159 d = query_escaped;
1160 for (s = query_formatted; *s; s++)
1162 if (strchr("\\\"$`", *s))
1163 *d++ = '\\';
1164 *d++ = *s;
1166 *d = '\0';
1168 /* And now we can build and execute the shell command */
1169 snprintf(psql_cmd, sizeof(psql_cmd),
1170 "\"%s%spsql\" -X -c \"%s\" \"%s\"",
1171 bindir ? bindir : "",
1172 bindir ? "/" : "",
1173 query_escaped,
1174 database);
1176 if (system(psql_cmd) != 0)
1178 /* psql probably already reported the error */
1179 fprintf(stderr, _("command failed: %s\n"), psql_cmd);
1180 exit(2);
1185 * Spawn a process to execute the given shell command; don't wait for it
1187 * Returns the process ID (or HANDLE) so we can wait for it later
1189 PID_TYPE
1190 spawn_process(const char *cmdline)
1192 #ifndef WIN32
1193 pid_t pid;
1196 * Must flush I/O buffers before fork. Ideally we'd use fflush(NULL) here
1197 * ... does anyone still care about systems where that doesn't work?
1199 fflush(stdout);
1200 fflush(stderr);
1201 if (logfile)
1202 fflush(logfile);
1204 pid = fork();
1205 if (pid == -1)
1207 fprintf(stderr, _("%s: could not fork: %s\n"),
1208 progname, strerror(errno));
1209 exit(2);
1211 if (pid == 0)
1214 * In child
1216 * Instead of using system(), exec the shell directly, and tell it to
1217 * "exec" the command too. This saves two useless processes per
1218 * parallel test case.
1220 char *cmdline2;
1222 cmdline2 = psprintf("exec %s", cmdline);
1223 execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1224 fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
1225 progname, shellprog, strerror(errno));
1226 _exit(1); /* not exit() here... */
1228 /* in parent */
1229 return pid;
1230 #else
1231 PROCESS_INFORMATION pi;
1232 char *cmdline2;
1233 HANDLE restrictedToken;
1234 const char *comspec;
1236 /* Find CMD.EXE location using COMSPEC, if it's set */
1237 comspec = getenv("COMSPEC");
1238 if (comspec == NULL)
1239 comspec = "CMD";
1241 memset(&pi, 0, sizeof(pi));
1242 cmdline2 = psprintf("\"%s\" /c \"%s\"", comspec, cmdline);
1244 if ((restrictedToken =
1245 CreateRestrictedProcess(cmdline2, &pi)) == 0)
1246 exit(2);
1248 CloseHandle(pi.hThread);
1249 return pi.hProcess;
1250 #endif
1254 * Count bytes in file
1256 static long
1257 file_size(const char *file)
1259 long r;
1260 FILE *f = fopen(file, "r");
1262 if (!f)
1264 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1265 progname, file, strerror(errno));
1266 return -1;
1268 fseek(f, 0, SEEK_END);
1269 r = ftell(f);
1270 fclose(f);
1271 return r;
1275 * Count lines in file
1277 static int
1278 file_line_count(const char *file)
1280 int c;
1281 int l = 0;
1282 FILE *f = fopen(file, "r");
1284 if (!f)
1286 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1287 progname, file, strerror(errno));
1288 return -1;
1290 while ((c = fgetc(f)) != EOF)
1292 if (c == '\n')
1293 l++;
1295 fclose(f);
1296 return l;
1299 bool
1300 file_exists(const char *file)
1302 FILE *f = fopen(file, "r");
1304 if (!f)
1305 return false;
1306 fclose(f);
1307 return true;
1310 static bool
1311 directory_exists(const char *dir)
1313 struct stat st;
1315 if (stat(dir, &st) != 0)
1316 return false;
1317 if (S_ISDIR(st.st_mode))
1318 return true;
1319 return false;
1322 /* Create a directory */
1323 static void
1324 make_directory(const char *dir)
1326 if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
1328 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
1329 progname, dir, strerror(errno));
1330 exit(2);
1335 * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9
1337 static char *
1338 get_alternative_expectfile(const char *expectfile, int i)
1340 char *last_dot;
1341 int ssize = strlen(expectfile) + 2 + 1;
1342 char *tmp;
1343 char *s;
1345 if (!(tmp = (char *) malloc(ssize)))
1346 return NULL;
1348 if (!(s = (char *) malloc(ssize)))
1350 free(tmp);
1351 return NULL;
1354 strcpy(tmp, expectfile);
1355 last_dot = strrchr(tmp, '.');
1356 if (!last_dot)
1358 free(tmp);
1359 free(s);
1360 return NULL;
1362 *last_dot = '\0';
1363 snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
1364 free(tmp);
1365 return s;
1369 * Run a "diff" command and also check that it didn't crash
1371 static int
1372 run_diff(const char *cmd, const char *filename)
1374 int r;
1376 r = system(cmd);
1377 if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
1379 fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
1380 exit(2);
1382 #ifdef WIN32
1385 * On WIN32, if the 'diff' command cannot be found, system() returns 1,
1386 * but produces nothing to stdout, so we check for that here.
1388 if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
1390 fprintf(stderr, _("diff command not found: %s\n"), cmd);
1391 exit(2);
1393 #endif
1395 return WEXITSTATUS(r);
1399 * Check the actual result file for the given test against expected results
1401 * Returns true if different (failure), false if correct match found.
1402 * In the true case, the diff is appended to the diffs file.
1404 static bool
1405 results_differ(const char *testname, const char *resultsfile, const char *default_expectfile)
1407 char expectfile[MAXPGPATH];
1408 char diff[MAXPGPATH];
1409 char cmd[MAXPGPATH * 3];
1410 char best_expect_file[MAXPGPATH];
1411 FILE *difffile;
1412 int best_line_count;
1413 int i;
1414 int l;
1415 const char *platform_expectfile;
1418 * We can pass either the resultsfile or the expectfile, they should have
1419 * the same type (filename.type) anyway.
1421 platform_expectfile = get_expectfile(testname, resultsfile);
1423 strlcpy(expectfile, default_expectfile, sizeof(expectfile));
1424 if (platform_expectfile)
1427 * Replace everything after the last slash in expectfile with what the
1428 * platform_expectfile contains.
1430 char *p = strrchr(expectfile, '/');
1432 if (p)
1433 strcpy(++p, platform_expectfile);
1436 /* Name to use for temporary diff file */
1437 snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
1439 /* OK, run the diff */
1440 snprintf(cmd, sizeof(cmd),
1441 "diff %s \"%s\" \"%s\" > \"%s\"",
1442 basic_diff_opts, expectfile, resultsfile, diff);
1444 /* Is the diff file empty? */
1445 if (run_diff(cmd, diff) == 0)
1447 unlink(diff);
1448 return false;
1451 /* There may be secondary comparison files that match better */
1452 best_line_count = file_line_count(diff);
1453 strcpy(best_expect_file, expectfile);
1455 for (i = 0; i <= 9; i++)
1457 char *alt_expectfile;
1459 alt_expectfile = get_alternative_expectfile(expectfile, i);
1460 if (!alt_expectfile)
1462 fprintf(stderr, _("Unable to check secondary comparison files: %s\n"),
1463 strerror(errno));
1464 exit(2);
1467 if (!file_exists(alt_expectfile))
1469 free(alt_expectfile);
1470 continue;
1473 snprintf(cmd, sizeof(cmd),
1474 "diff %s \"%s\" \"%s\" > \"%s\"",
1475 basic_diff_opts, alt_expectfile, resultsfile, diff);
1477 if (run_diff(cmd, diff) == 0)
1479 unlink(diff);
1480 free(alt_expectfile);
1481 return false;
1484 l = file_line_count(diff);
1485 if (l < best_line_count)
1487 /* This diff was a better match than the last one */
1488 best_line_count = l;
1489 strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
1491 free(alt_expectfile);
1495 * fall back on the canonical results file if we haven't tried it yet and
1496 * haven't found a complete match yet.
1499 if (platform_expectfile)
1501 snprintf(cmd, sizeof(cmd),
1502 "diff %s \"%s\" \"%s\" > \"%s\"",
1503 basic_diff_opts, default_expectfile, resultsfile, diff);
1505 if (run_diff(cmd, diff) == 0)
1507 /* No diff = no changes = good */
1508 unlink(diff);
1509 return false;
1512 l = file_line_count(diff);
1513 if (l < best_line_count)
1515 /* This diff was a better match than the last one */
1516 best_line_count = l;
1517 strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
1522 * Use the best comparison file to generate the "pretty" diff, which we
1523 * append to the diffs summary file.
1526 /* Write diff header */
1527 difffile = fopen(difffilename, "a");
1528 if (difffile)
1530 fprintf(difffile,
1531 "diff %s %s %s\n",
1532 pretty_diff_opts, best_expect_file, resultsfile);
1533 fclose(difffile);
1536 /* Run diff */
1537 snprintf(cmd, sizeof(cmd),
1538 "diff %s \"%s\" \"%s\" >> \"%s\"",
1539 pretty_diff_opts, best_expect_file, resultsfile, difffilename);
1540 run_diff(cmd, difffilename);
1542 unlink(diff);
1543 return true;
1547 * Wait for specified subprocesses to finish, and return their exit
1548 * statuses into statuses[] and stop times into stoptimes[]
1550 * If names isn't NULL, print each subprocess's name as it finishes
1552 * Note: it's OK to scribble on the pids array, but not on the names array
1554 static void
1555 wait_for_tests(PID_TYPE * pids, int *statuses, instr_time *stoptimes,
1556 char **names, int num_tests)
1558 int tests_left;
1559 int i;
1561 #ifdef WIN32
1562 PID_TYPE *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
1564 memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
1565 #endif
1567 tests_left = num_tests;
1568 while (tests_left > 0)
1570 PID_TYPE p;
1572 #ifndef WIN32
1573 int exit_status;
1575 p = wait(&exit_status);
1577 if (p == INVALID_PID)
1579 fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
1580 strerror(errno));
1581 exit(2);
1583 #else
1584 DWORD exit_status;
1585 int r;
1587 r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
1588 if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
1590 fprintf(stderr, _("failed to wait for subprocesses: error code %lu\n"),
1591 GetLastError());
1592 exit(2);
1594 p = active_pids[r - WAIT_OBJECT_0];
1595 /* compact the active_pids array */
1596 active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
1597 #endif /* WIN32 */
1599 for (i = 0; i < num_tests; i++)
1601 if (p == pids[i])
1603 #ifdef WIN32
1604 GetExitCodeProcess(pids[i], &exit_status);
1605 CloseHandle(pids[i]);
1606 #endif
1607 pids[i] = INVALID_PID;
1608 statuses[i] = (int) exit_status;
1609 INSTR_TIME_SET_CURRENT(stoptimes[i]);
1610 if (names)
1611 status(" %s", names[i]);
1612 tests_left--;
1613 break;
1618 #ifdef WIN32
1619 free(active_pids);
1620 #endif
1624 * report nonzero exit code from a test process
1626 static void
1627 log_child_failure(int exitstatus)
1629 if (WIFEXITED(exitstatus))
1630 status(_(" (test process exited with exit code %d)"),
1631 WEXITSTATUS(exitstatus));
1632 else if (WIFSIGNALED(exitstatus))
1634 #if defined(WIN32)
1635 status(_(" (test process was terminated by exception 0x%X)"),
1636 WTERMSIG(exitstatus));
1637 #else
1638 status(_(" (test process was terminated by signal %d: %s)"),
1639 WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
1640 #endif
1642 else
1643 status(_(" (test process exited with unrecognized status %d)"),
1644 exitstatus);
1648 * Run all the tests specified in one schedule file
1650 static void
1651 run_schedule(const char *schedule, test_start_function startfunc,
1652 postprocess_result_function postfunc)
1654 #define MAX_PARALLEL_TESTS 100
1655 char *tests[MAX_PARALLEL_TESTS];
1656 _stringlist *resultfiles[MAX_PARALLEL_TESTS];
1657 _stringlist *expectfiles[MAX_PARALLEL_TESTS];
1658 _stringlist *tags[MAX_PARALLEL_TESTS];
1659 PID_TYPE pids[MAX_PARALLEL_TESTS];
1660 instr_time starttimes[MAX_PARALLEL_TESTS];
1661 instr_time stoptimes[MAX_PARALLEL_TESTS];
1662 int statuses[MAX_PARALLEL_TESTS];
1663 _stringlist *ignorelist = NULL;
1664 char scbuf[1024];
1665 FILE *scf;
1666 int line_num = 0;
1668 memset(tests, 0, sizeof(tests));
1669 memset(resultfiles, 0, sizeof(resultfiles));
1670 memset(expectfiles, 0, sizeof(expectfiles));
1671 memset(tags, 0, sizeof(tags));
1673 scf = fopen(schedule, "r");
1674 if (!scf)
1676 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1677 progname, schedule, strerror(errno));
1678 exit(2);
1681 while (fgets(scbuf, sizeof(scbuf), scf))
1683 char *test = NULL;
1684 char *c;
1685 int num_tests;
1686 bool inword;
1687 int i;
1689 line_num++;
1691 /* strip trailing whitespace, especially the newline */
1692 i = strlen(scbuf);
1693 while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
1694 scbuf[--i] = '\0';
1696 if (scbuf[0] == '\0' || scbuf[0] == '#')
1697 continue;
1698 if (strncmp(scbuf, "test: ", 6) == 0)
1699 test = scbuf + 6;
1700 else if (strncmp(scbuf, "ignore: ", 8) == 0)
1702 c = scbuf + 8;
1703 while (*c && isspace((unsigned char) *c))
1704 c++;
1705 add_stringlist_item(&ignorelist, c);
1708 * Note: ignore: lines do not run the test, they just say that
1709 * failure of this test when run later on is to be ignored. A bit
1710 * odd but that's how the shell-script version did it.
1712 continue;
1714 else
1716 fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1717 schedule, line_num, scbuf);
1718 exit(2);
1721 num_tests = 0;
1722 inword = false;
1723 for (c = test;; c++)
1725 if (*c == '\0' || isspace((unsigned char) *c))
1727 if (inword)
1729 /* Reached end of a test name */
1730 char sav;
1732 if (num_tests >= MAX_PARALLEL_TESTS)
1734 fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1735 MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
1736 exit(2);
1738 sav = *c;
1739 *c = '\0';
1740 tests[num_tests] = pg_strdup(test);
1741 num_tests++;
1742 *c = sav;
1743 inword = false;
1745 if (*c == '\0')
1746 break; /* loop exit is here */
1748 else if (!inword)
1750 /* Start of a test name */
1751 test = c;
1752 inword = true;
1756 if (num_tests == 0)
1758 fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1759 schedule, line_num, scbuf);
1760 exit(2);
1763 if (num_tests == 1)
1765 status(_("test %-28s ... "), tests[0]);
1766 pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
1767 INSTR_TIME_SET_CURRENT(starttimes[0]);
1768 wait_for_tests(pids, statuses, stoptimes, NULL, 1);
1769 /* status line is finished below */
1771 else if (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
1773 fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1774 max_concurrent_tests, schedule, line_num, scbuf);
1775 exit(2);
1777 else if (max_connections > 0 && max_connections < num_tests)
1779 int oldest = 0;
1781 status(_("parallel group (%d tests, in groups of %d): "),
1782 num_tests, max_connections);
1783 for (i = 0; i < num_tests; i++)
1785 if (i - oldest >= max_connections)
1787 wait_for_tests(pids + oldest, statuses + oldest,
1788 stoptimes + oldest,
1789 tests + oldest, i - oldest);
1790 oldest = i;
1792 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1793 INSTR_TIME_SET_CURRENT(starttimes[i]);
1795 wait_for_tests(pids + oldest, statuses + oldest,
1796 stoptimes + oldest,
1797 tests + oldest, i - oldest);
1798 status_end();
1800 else
1802 status(_("parallel group (%d tests): "), num_tests);
1803 for (i = 0; i < num_tests; i++)
1805 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1806 INSTR_TIME_SET_CURRENT(starttimes[i]);
1808 wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
1809 status_end();
1812 /* Check results for all tests */
1813 for (i = 0; i < num_tests; i++)
1815 _stringlist *rl,
1816 *el,
1817 *tl;
1818 bool differ = false;
1820 if (num_tests > 1)
1821 status(_(" %-28s ... "), tests[i]);
1824 * Advance over all three lists simultaneously.
1826 * Compare resultfiles[j] with expectfiles[j] always. Tags are
1827 * optional but if there are tags, the tag list has the same
1828 * length as the other two lists.
1830 for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
1831 rl != NULL; /* rl and el have the same length */
1832 rl = rl->next, el = el->next,
1833 tl = tl ? tl->next : NULL)
1835 bool newdiff;
1837 if (postfunc)
1838 (*postfunc) (rl->str);
1839 newdiff = results_differ(tests[i], rl->str, el->str);
1840 if (newdiff && tl)
1842 printf("%s ", tl->str);
1844 differ |= newdiff;
1847 if (differ)
1849 bool ignore = false;
1850 _stringlist *sl;
1852 for (sl = ignorelist; sl != NULL; sl = sl->next)
1854 if (strcmp(tests[i], sl->str) == 0)
1856 ignore = true;
1857 break;
1860 if (ignore)
1862 status(_("failed (ignored)"));
1863 fail_ignore_count++;
1865 else
1867 status(_("FAILED"));
1868 fail_count++;
1871 else
1873 status(_("ok ")); /* align with FAILED */
1874 success_count++;
1877 if (statuses[i] != 0)
1878 log_child_failure(statuses[i]);
1880 INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
1881 status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptimes[i]));
1883 status_end();
1886 for (i = 0; i < num_tests; i++)
1888 pg_free(tests[i]);
1889 tests[i] = NULL;
1890 free_stringlist(&resultfiles[i]);
1891 free_stringlist(&expectfiles[i]);
1892 free_stringlist(&tags[i]);
1896 free_stringlist(&ignorelist);
1898 fclose(scf);
1902 * Run a single test
1904 static void
1905 run_single_test(const char *test, test_start_function startfunc,
1906 postprocess_result_function postfunc)
1908 PID_TYPE pid;
1909 instr_time starttime;
1910 instr_time stoptime;
1911 int exit_status;
1912 _stringlist *resultfiles = NULL;
1913 _stringlist *expectfiles = NULL;
1914 _stringlist *tags = NULL;
1915 _stringlist *rl,
1916 *el,
1917 *tl;
1918 bool differ = false;
1920 status(_("test %-28s ... "), test);
1921 pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
1922 INSTR_TIME_SET_CURRENT(starttime);
1923 wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
1926 * Advance over all three lists simultaneously.
1928 * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
1929 * but if there are tags, the tag list has the same length as the other
1930 * two lists.
1932 for (rl = resultfiles, el = expectfiles, tl = tags;
1933 rl != NULL; /* rl and el have the same length */
1934 rl = rl->next, el = el->next,
1935 tl = tl ? tl->next : NULL)
1937 bool newdiff;
1939 if (postfunc)
1940 (*postfunc) (rl->str);
1941 newdiff = results_differ(test, rl->str, el->str);
1942 if (newdiff && tl)
1944 printf("%s ", tl->str);
1946 differ |= newdiff;
1949 if (differ)
1951 status(_("FAILED"));
1952 fail_count++;
1954 else
1956 status(_("ok ")); /* align with FAILED */
1957 success_count++;
1960 if (exit_status != 0)
1961 log_child_failure(exit_status);
1963 INSTR_TIME_SUBTRACT(stoptime, starttime);
1964 status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptime));
1966 status_end();
1970 * Create the summary-output files (making them empty if already existing)
1972 static void
1973 open_result_files(void)
1975 char file[MAXPGPATH];
1976 FILE *difffile;
1978 /* create outputdir directory if not present */
1979 if (!directory_exists(outputdir))
1980 make_directory(outputdir);
1982 /* create the log file (copy of running status output) */
1983 snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1984 logfilename = pg_strdup(file);
1985 logfile = fopen(logfilename, "w");
1986 if (!logfile)
1988 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1989 progname, logfilename, strerror(errno));
1990 exit(2);
1993 /* create the diffs file as empty */
1994 snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1995 difffilename = pg_strdup(file);
1996 difffile = fopen(difffilename, "w");
1997 if (!difffile)
1999 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
2000 progname, difffilename, strerror(errno));
2001 exit(2);
2003 /* we don't keep the diffs file open continuously */
2004 fclose(difffile);
2006 /* also create the results directory if not present */
2007 snprintf(file, sizeof(file), "%s/results", outputdir);
2008 if (!directory_exists(file))
2009 make_directory(file);
2012 static void
2013 drop_database_if_exists(const char *dbname)
2015 header(_("dropping database \"%s\""), dbname);
2016 psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname);
2019 static void
2020 create_database(const char *dbname)
2022 _stringlist *sl;
2025 * We use template0 so that any installation-local cruft in template1 will
2026 * not mess up the tests.
2028 header(_("creating database \"%s\""), dbname);
2029 if (encoding)
2030 psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
2031 (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
2032 else
2033 psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
2034 (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
2035 psql_command(dbname,
2036 "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
2037 "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
2038 "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
2039 "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
2040 "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
2041 "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
2042 dbname, dbname, dbname, dbname, dbname, dbname);
2045 * Install any requested extensions. We use CREATE IF NOT EXISTS so that
2046 * this will work whether or not the extension is preinstalled.
2048 for (sl = loadextension; sl != NULL; sl = sl->next)
2050 header(_("installing %s"), sl->str);
2051 psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
2055 static void
2056 drop_role_if_exists(const char *rolename)
2058 header(_("dropping role \"%s\""), rolename);
2059 psql_command("postgres", "DROP ROLE IF EXISTS \"%s\"", rolename);
2062 static void
2063 create_role(const char *rolename, const _stringlist *granted_dbs)
2065 header(_("creating role \"%s\""), rolename);
2066 psql_command("postgres", "CREATE ROLE \"%s\" WITH LOGIN", rolename);
2067 for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
2069 psql_command("postgres", "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
2070 granted_dbs->str, rolename);
2074 static void
2075 help(void)
2077 printf(_("PostgreSQL regression test driver\n"));
2078 printf(_("\n"));
2079 printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
2080 printf(_("\n"));
2081 printf(_("Options:\n"));
2082 printf(_(" --bindir=BINPATH use BINPATH for programs that are run;\n"));
2083 printf(_(" if empty, use PATH from the environment\n"));
2084 printf(_(" --config-auth=DATADIR update authentication settings for DATADIR\n"));
2085 printf(_(" --create-role=ROLE create the specified role before testing\n"));
2086 printf(_(" --dbname=DB use database DB (default \"regression\")\n"));
2087 printf(_(" --debug turn on debug mode in programs that are run\n"));
2088 printf(_(" --dlpath=DIR look for dynamic libraries in DIR\n"));
2089 printf(_(" --encoding=ENCODING use ENCODING as the encoding\n"));
2090 printf(_(" -h, --help show this help, then exit\n"));
2091 printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n"));
2092 printf(_(" --launcher=CMD use CMD as launcher of psql\n"));
2093 printf(_(" --load-extension=EXT load the named extension before running the\n"));
2094 printf(_(" tests; can appear multiple times\n"));
2095 printf(_(" --make-testtablespace-dir create testtablespace directory\n"));
2096 printf(_(" --max-connections=N maximum number of concurrent connections\n"));
2097 printf(_(" (default is 0, meaning unlimited)\n"));
2098 printf(_(" --max-concurrent-tests=N maximum number of concurrent tests in schedule\n"));
2099 printf(_(" (default is 0, meaning unlimited)\n"));
2100 printf(_(" --outputdir=DIR place output files in DIR (default \".\")\n"));
2101 printf(_(" --schedule=FILE use test ordering schedule from FILE\n"));
2102 printf(_(" (can be used multiple times to concatenate)\n"));
2103 printf(_(" --temp-instance=DIR create a temporary instance in DIR\n"));
2104 printf(_(" --use-existing use an existing installation\n"));
2105 printf(_(" -V, --version output version information, then exit\n"));
2106 printf(_("\n"));
2107 printf(_("Options for \"temp-instance\" mode:\n"));
2108 printf(_(" --no-locale use C locale\n"));
2109 printf(_(" --port=PORT start postmaster on PORT\n"));
2110 printf(_(" --temp-config=FILE append contents of FILE to temporary config\n"));
2111 printf(_("\n"));
2112 printf(_("Options for using an existing installation:\n"));
2113 printf(_(" --host=HOST use postmaster running on HOST\n"));
2114 printf(_(" --port=PORT use postmaster running at PORT\n"));
2115 printf(_(" --user=USER connect as USER\n"));
2116 printf(_("\n"));
2117 printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
2118 printf(_("if the tests could not be run for some reason.\n"));
2119 printf(_("\n"));
2120 printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2121 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
2125 regression_main(int argc, char *argv[],
2126 init_function ifunc,
2127 test_start_function startfunc,
2128 postprocess_result_function postfunc)
2130 static struct option long_options[] = {
2131 {"help", no_argument, NULL, 'h'},
2132 {"version", no_argument, NULL, 'V'},
2133 {"dbname", required_argument, NULL, 1},
2134 {"debug", no_argument, NULL, 2},
2135 {"inputdir", required_argument, NULL, 3},
2136 {"max-connections", required_argument, NULL, 5},
2137 {"encoding", required_argument, NULL, 6},
2138 {"outputdir", required_argument, NULL, 7},
2139 {"schedule", required_argument, NULL, 8},
2140 {"temp-instance", required_argument, NULL, 9},
2141 {"no-locale", no_argument, NULL, 10},
2142 {"host", required_argument, NULL, 13},
2143 {"port", required_argument, NULL, 14},
2144 {"user", required_argument, NULL, 15},
2145 {"bindir", required_argument, NULL, 16},
2146 {"dlpath", required_argument, NULL, 17},
2147 {"create-role", required_argument, NULL, 18},
2148 {"temp-config", required_argument, NULL, 19},
2149 {"use-existing", no_argument, NULL, 20},
2150 {"launcher", required_argument, NULL, 21},
2151 {"load-extension", required_argument, NULL, 22},
2152 {"config-auth", required_argument, NULL, 24},
2153 {"max-concurrent-tests", required_argument, NULL, 25},
2154 {"make-testtablespace-dir", no_argument, NULL, 26},
2155 {NULL, 0, NULL, 0}
2158 bool use_unix_sockets;
2159 bool make_testtablespace_dir = false;
2160 _stringlist *sl;
2161 int c;
2162 int i;
2163 int option_index;
2164 char buf[MAXPGPATH * 4];
2165 char buf2[MAXPGPATH * 4];
2167 pg_logging_init(argv[0]);
2168 progname = get_progname(argv[0]);
2169 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
2171 get_restricted_token();
2173 atexit(stop_postmaster);
2175 #if !defined(HAVE_UNIX_SOCKETS)
2176 use_unix_sockets = false;
2177 #elif defined(WIN32)
2180 * We don't use Unix-domain sockets on Windows by default, even if the
2181 * build supports them. (See comment at remove_temp() for a reason.)
2182 * Override at your own risk.
2184 use_unix_sockets = getenv("PG_TEST_USE_UNIX_SOCKETS") ? true : false;
2185 #else
2186 use_unix_sockets = true;
2187 #endif
2189 if (!use_unix_sockets)
2190 hostname = "localhost";
2193 * We call the initialization function here because that way we can set
2194 * default parameters and let them be overwritten by the commandline.
2196 ifunc(argc, argv);
2198 if (getenv("PG_REGRESS_DIFF_OPTS"))
2199 pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
2201 while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
2203 switch (c)
2205 case 'h':
2206 help();
2207 exit(0);
2208 case 'V':
2209 puts("pg_regress (PostgreSQL) " PG_VERSION);
2210 exit(0);
2211 case 1:
2214 * If a default database was specified, we need to remove it
2215 * before we add the specified one.
2217 free_stringlist(&dblist);
2218 split_to_stringlist(optarg, ",", &dblist);
2219 break;
2220 case 2:
2221 debug = true;
2222 break;
2223 case 3:
2224 inputdir = pg_strdup(optarg);
2225 break;
2226 case 5:
2227 max_connections = atoi(optarg);
2228 break;
2229 case 6:
2230 encoding = pg_strdup(optarg);
2231 break;
2232 case 7:
2233 outputdir = pg_strdup(optarg);
2234 break;
2235 case 8:
2236 add_stringlist_item(&schedulelist, optarg);
2237 break;
2238 case 9:
2239 temp_instance = make_absolute_path(optarg);
2240 break;
2241 case 10:
2242 nolocale = true;
2243 break;
2244 case 13:
2245 hostname = pg_strdup(optarg);
2246 break;
2247 case 14:
2248 port = atoi(optarg);
2249 port_specified_by_user = true;
2250 break;
2251 case 15:
2252 user = pg_strdup(optarg);
2253 break;
2254 case 16:
2255 /* "--bindir=" means to use PATH */
2256 if (strlen(optarg))
2257 bindir = pg_strdup(optarg);
2258 else
2259 bindir = NULL;
2260 break;
2261 case 17:
2262 dlpath = pg_strdup(optarg);
2263 break;
2264 case 18:
2265 split_to_stringlist(optarg, ",", &extraroles);
2266 break;
2267 case 19:
2268 add_stringlist_item(&temp_configs, optarg);
2269 break;
2270 case 20:
2271 use_existing = true;
2272 break;
2273 case 21:
2274 launcher = pg_strdup(optarg);
2275 break;
2276 case 22:
2277 add_stringlist_item(&loadextension, optarg);
2278 break;
2279 case 24:
2280 config_auth_datadir = pg_strdup(optarg);
2281 break;
2282 case 25:
2283 max_concurrent_tests = atoi(optarg);
2284 break;
2285 case 26:
2286 make_testtablespace_dir = true;
2287 break;
2288 default:
2289 /* getopt_long already emitted a complaint */
2290 fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
2291 progname);
2292 exit(2);
2297 * if we still have arguments, they are extra tests to run
2299 while (argc - optind >= 1)
2301 add_stringlist_item(&extra_tests, argv[optind]);
2302 optind++;
2305 if (config_auth_datadir)
2307 #ifdef ENABLE_SSPI
2308 if (!use_unix_sockets)
2309 config_sspi_auth(config_auth_datadir, user);
2310 #endif
2311 exit(0);
2314 if (temp_instance && !port_specified_by_user)
2317 * To reduce chances of interference with parallel installations, use
2318 * a port number starting in the private range (49152-65535)
2319 * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
2320 * systems; elsewhere, the use of a private socket directory already
2321 * prevents interference.
2323 port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
2325 inputdir = make_absolute_path(inputdir);
2326 outputdir = make_absolute_path(outputdir);
2327 dlpath = make_absolute_path(dlpath);
2330 * Initialization
2332 open_result_files();
2334 initialize_environment();
2336 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
2337 unlimit_core_size();
2338 #endif
2340 if (make_testtablespace_dir)
2341 prepare_testtablespace_dir();
2343 if (temp_instance)
2345 FILE *pg_conf;
2346 const char *env_wait;
2347 int wait_seconds;
2350 * Prepare the temp instance
2353 if (directory_exists(temp_instance))
2355 header(_("removing existing temp instance"));
2356 if (!rmtree(temp_instance, true))
2358 fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2359 progname, temp_instance);
2360 exit(2);
2364 header(_("creating temporary instance"));
2366 /* make the temp instance top directory */
2367 make_directory(temp_instance);
2369 /* and a directory for log files */
2370 snprintf(buf, sizeof(buf), "%s/log", outputdir);
2371 if (!directory_exists(buf))
2372 make_directory(buf);
2374 /* initdb */
2375 header(_("initializing database system"));
2376 snprintf(buf, sizeof(buf),
2377 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync%s%s > \"%s/log/initdb.log\" 2>&1",
2378 bindir ? bindir : "",
2379 bindir ? "/" : "",
2380 temp_instance,
2381 debug ? " --debug" : "",
2382 nolocale ? " --no-locale" : "",
2383 outputdir);
2384 if (system(buf))
2386 fprintf(stderr, _("\n%s: initdb failed\nExamine %s/log/initdb.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
2387 exit(2);
2391 * Adjust the default postgresql.conf for regression testing. The user
2392 * can specify a file to be appended; in any case we expand logging
2393 * and set max_prepared_transactions to enable testing of prepared
2394 * xacts. (Note: to reduce the probability of unexpected shmmax
2395 * failures, don't set max_prepared_transactions any higher than
2396 * actually needed by the prepared_xacts regression test.)
2398 snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
2399 pg_conf = fopen(buf, "a");
2400 if (pg_conf == NULL)
2402 fprintf(stderr, _("\n%s: could not open \"%s\" for adding extra config: %s\n"), progname, buf, strerror(errno));
2403 exit(2);
2405 fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
2406 fputs("log_autovacuum_min_duration = 0\n", pg_conf);
2407 fputs("log_checkpoints = on\n", pg_conf);
2408 fputs("log_line_prefix = '%m %b[%p] %q%a '\n", pg_conf);
2409 fputs("log_lock_waits = on\n", pg_conf);
2410 fputs("log_temp_files = 128kB\n", pg_conf);
2411 fputs("max_prepared_transactions = 2\n", pg_conf);
2413 for (sl = temp_configs; sl != NULL; sl = sl->next)
2415 char *temp_config = sl->str;
2416 FILE *extra_conf;
2417 char line_buf[1024];
2419 extra_conf = fopen(temp_config, "r");
2420 if (extra_conf == NULL)
2422 fprintf(stderr, _("\n%s: could not open \"%s\" to read extra config: %s\n"), progname, temp_config, strerror(errno));
2423 exit(2);
2425 while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
2426 fputs(line_buf, pg_conf);
2427 fclose(extra_conf);
2430 fclose(pg_conf);
2432 #ifdef ENABLE_SSPI
2433 if (!use_unix_sockets)
2436 * Since we successfully used the same buffer for the much-longer
2437 * "initdb" command, this can't truncate.
2439 snprintf(buf, sizeof(buf), "%s/data", temp_instance);
2440 config_sspi_auth(buf, NULL);
2442 #elif !defined(HAVE_UNIX_SOCKETS)
2443 #error Platform has no means to secure the test installation.
2444 #endif
2447 * Check if there is a postmaster running already.
2449 snprintf(buf2, sizeof(buf2),
2450 "\"%s%spsql\" -X postgres <%s 2>%s",
2451 bindir ? bindir : "",
2452 bindir ? "/" : "",
2453 DEVNULL, DEVNULL);
2455 for (i = 0; i < 16; i++)
2457 if (system(buf2) == 0)
2459 char s[16];
2461 if (port_specified_by_user || i == 15)
2463 fprintf(stderr, _("port %d apparently in use\n"), port);
2464 if (!port_specified_by_user)
2465 fprintf(stderr, _("%s: could not determine an available port\n"), progname);
2466 fprintf(stderr, _("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.\n"));
2467 exit(2);
2470 fprintf(stderr, _("port %d apparently in use, trying %d\n"), port, port + 1);
2471 port++;
2472 sprintf(s, "%d", port);
2473 setenv("PGPORT", s, 1);
2475 else
2476 break;
2480 * Start the temp postmaster
2482 header(_("starting postmaster"));
2483 snprintf(buf, sizeof(buf),
2484 "\"%s%spostgres\" -D \"%s/data\" -F%s "
2485 "-c \"listen_addresses=%s\" -k \"%s\" "
2486 "> \"%s/log/postmaster.log\" 2>&1",
2487 bindir ? bindir : "",
2488 bindir ? "/" : "",
2489 temp_instance, debug ? " -d 5" : "",
2490 hostname ? hostname : "", sockdir ? sockdir : "",
2491 outputdir);
2492 postmaster_pid = spawn_process(buf);
2493 if (postmaster_pid == INVALID_PID)
2495 fprintf(stderr, _("\n%s: could not spawn postmaster: %s\n"),
2496 progname, strerror(errno));
2497 exit(2);
2501 * Wait till postmaster is able to accept connections; normally this
2502 * is only a second or so, but Cygwin is reportedly *much* slower, and
2503 * test builds using Valgrind or similar tools might be too. Hence,
2504 * allow the default timeout of 60 seconds to be overridden from the
2505 * PGCTLTIMEOUT environment variable.
2507 env_wait = getenv("PGCTLTIMEOUT");
2508 if (env_wait != NULL)
2510 wait_seconds = atoi(env_wait);
2511 if (wait_seconds <= 0)
2512 wait_seconds = 60;
2514 else
2515 wait_seconds = 60;
2517 for (i = 0; i < wait_seconds; i++)
2519 /* Done if psql succeeds */
2520 if (system(buf2) == 0)
2521 break;
2524 * Fail immediately if postmaster has exited
2526 #ifndef WIN32
2527 if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
2528 #else
2529 if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
2530 #endif
2532 fprintf(stderr, _("\n%s: postmaster failed\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
2533 exit(2);
2536 pg_usleep(1000000L);
2538 if (i >= wait_seconds)
2540 fprintf(stderr, _("\n%s: postmaster did not respond within %d seconds\nExamine %s/log/postmaster.log for the reason\n"),
2541 progname, wait_seconds, outputdir);
2544 * If we get here, the postmaster is probably wedged somewhere in
2545 * startup. Try to kill it ungracefully rather than leaving a
2546 * stuck postmaster that might interfere with subsequent test
2547 * attempts.
2549 #ifndef WIN32
2550 if (kill(postmaster_pid, SIGKILL) != 0 &&
2551 errno != ESRCH)
2552 fprintf(stderr, _("\n%s: could not kill failed postmaster: %s\n"),
2553 progname, strerror(errno));
2554 #else
2555 if (TerminateProcess(postmaster_pid, 255) == 0)
2556 fprintf(stderr, _("\n%s: could not kill failed postmaster: error code %lu\n"),
2557 progname, GetLastError());
2558 #endif
2560 exit(2);
2563 postmaster_running = true;
2565 #ifdef _WIN64
2566 /* need a series of two casts to convert HANDLE without compiler warning */
2567 #define ULONGPID(x) (unsigned long) (unsigned long long) (x)
2568 #else
2569 #define ULONGPID(x) (unsigned long) (x)
2570 #endif
2571 printf(_("running on port %d with PID %lu\n"),
2572 port, ULONGPID(postmaster_pid));
2574 else
2577 * Using an existing installation, so may need to get rid of
2578 * pre-existing database(s) and role(s)
2580 if (!use_existing)
2582 for (sl = dblist; sl; sl = sl->next)
2583 drop_database_if_exists(sl->str);
2584 for (sl = extraroles; sl; sl = sl->next)
2585 drop_role_if_exists(sl->str);
2590 * Create the test database(s) and role(s)
2592 if (!use_existing)
2594 for (sl = dblist; sl; sl = sl->next)
2595 create_database(sl->str);
2596 for (sl = extraroles; sl; sl = sl->next)
2597 create_role(sl->str, dblist);
2601 * Ready to run the tests
2603 header(_("running regression test queries"));
2605 for (sl = schedulelist; sl != NULL; sl = sl->next)
2607 run_schedule(sl->str, startfunc, postfunc);
2610 for (sl = extra_tests; sl != NULL; sl = sl->next)
2612 run_single_test(sl->str, startfunc, postfunc);
2616 * Shut down temp installation's postmaster
2618 if (temp_instance)
2620 header(_("shutting down postmaster"));
2621 stop_postmaster();
2625 * If there were no errors, remove the temp instance immediately to
2626 * conserve disk space. (If there were errors, we leave the instance in
2627 * place for possible manual investigation.)
2629 if (temp_instance && fail_count == 0 && fail_ignore_count == 0)
2631 header(_("removing temporary instance"));
2632 if (!rmtree(temp_instance, true))
2633 fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2634 progname, temp_instance);
2637 fclose(logfile);
2640 * Emit nice-looking summary message
2642 if (fail_count == 0 && fail_ignore_count == 0)
2643 snprintf(buf, sizeof(buf),
2644 _(" All %d tests passed. "),
2645 success_count);
2646 else if (fail_count == 0) /* fail_count=0, fail_ignore_count>0 */
2647 snprintf(buf, sizeof(buf),
2648 _(" %d of %d tests passed, %d failed test(s) ignored. "),
2649 success_count,
2650 success_count + fail_ignore_count,
2651 fail_ignore_count);
2652 else if (fail_ignore_count == 0) /* fail_count>0 && fail_ignore_count=0 */
2653 snprintf(buf, sizeof(buf),
2654 _(" %d of %d tests failed. "),
2655 fail_count,
2656 success_count + fail_count);
2657 else
2658 /* fail_count>0 && fail_ignore_count>0 */
2659 snprintf(buf, sizeof(buf),
2660 _(" %d of %d tests failed, %d of these failures ignored. "),
2661 fail_count + fail_ignore_count,
2662 success_count + fail_count + fail_ignore_count,
2663 fail_ignore_count);
2665 putchar('\n');
2666 for (i = strlen(buf); i > 0; i--)
2667 putchar('=');
2668 printf("\n%s\n", buf);
2669 for (i = strlen(buf); i > 0; i--)
2670 putchar('=');
2671 putchar('\n');
2672 putchar('\n');
2674 if (file_size(difffilename) > 0)
2676 printf(_("The differences that caused some tests to fail can be viewed in the\n"
2677 "file \"%s\". A copy of the test summary that you see\n"
2678 "above is saved in the file \"%s\".\n\n"),
2679 difffilename, logfilename);
2681 else
2683 unlink(difffilename);
2684 unlink(logfilename);
2687 if (fail_count != 0)
2688 exit(1);
2690 return 0;