pg_regress: Disable autoruns for cmd.exe on Windows
[pgsql.git] / src / test / regress / pg_regress.c
blobc894005dac06bc233896520c83c18e51af8ace9c
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-2024, 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/resource.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/wait.h>
26 #include <signal.h>
27 #include <unistd.h>
29 #include "common/logging.h"
30 #include "common/restricted_token.h"
31 #include "common/string.h"
32 #include "common/username.h"
33 #include "getopt_long.h"
34 #include "lib/stringinfo.h"
35 #include "libpq-fe.h"
36 #include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
37 #include "pg_config_paths.h"
38 #include "pg_regress.h"
39 #include "portability/instr_time.h"
41 /* for resultmap we need a list of pairs of strings */
42 typedef struct _resultmap
44 char *test;
45 char *type;
46 char *resultfile;
47 struct _resultmap *next;
48 } _resultmap;
51 * Values obtained from Makefile.
53 char *host_platform = HOST_TUPLE;
55 #ifndef WIN32 /* not used in WIN32 case */
56 static char *shellprog = SHELLPROG;
57 #endif
60 * On Windows we use -w in diff switches to avoid problems with inconsistent
61 * newline representation. The actual result files will generally have
62 * Windows-style newlines, but the comparison files might or might not.
64 #ifndef WIN32
65 const char *basic_diff_opts = "";
66 const char *pretty_diff_opts = "-U3";
67 #else
68 const char *basic_diff_opts = "-w";
69 const char *pretty_diff_opts = "-w -U3";
70 #endif
73 * The width of the testname field when printing to ensure vertical alignment
74 * of test runtimes. This number is somewhat arbitrarily chosen to match the
75 * older pre-TAP output format.
77 #define TESTNAME_WIDTH 36
80 * The number times per second that pg_regress checks to see if the test
81 * instance server has started and is available for connection.
83 #define WAIT_TICKS_PER_SECOND 20
85 typedef enum TAPtype
87 DIAG = 0,
88 BAIL,
89 NOTE,
90 NOTE_DETAIL,
91 NOTE_END,
92 TEST_STATUS,
93 PLAN,
94 NONE,
95 } TAPtype;
97 /* options settable from command line */
98 _stringlist *dblist = NULL;
99 bool debug = false;
100 char *inputdir = ".";
101 char *outputdir = ".";
102 char *expecteddir = ".";
103 char *bindir = PGBINDIR;
104 char *launcher = NULL;
105 static _stringlist *loadextension = NULL;
106 static int max_connections = 0;
107 static int max_concurrent_tests = 0;
108 static char *encoding = NULL;
109 static _stringlist *schedulelist = NULL;
110 static _stringlist *extra_tests = NULL;
111 static char *temp_instance = NULL;
112 static _stringlist *temp_configs = NULL;
113 static bool nolocale = false;
114 static bool use_existing = false;
115 static char *hostname = NULL;
116 static int port = -1;
117 static char portstr[16];
118 static bool port_specified_by_user = false;
119 static char *dlpath = PKGLIBDIR;
120 static char *user = NULL;
121 static _stringlist *extraroles = NULL;
122 static char *config_auth_datadir = NULL;
124 /* internal variables */
125 static const char *progname;
126 static char *logfilename;
127 static FILE *logfile;
128 static char *difffilename;
129 static const char *sockdir;
130 static const char *temp_sockdir;
131 static char sockself[MAXPGPATH];
132 static char socklock[MAXPGPATH];
133 static StringInfo failed_tests = NULL;
134 static bool in_note = false;
136 static _resultmap *resultmap = NULL;
138 static PID_TYPE postmaster_pid = INVALID_PID;
139 static bool postmaster_running = false;
141 static int success_count = 0;
142 static int fail_count = 0;
144 static bool directory_exists(const char *dir);
145 static void make_directory(const char *dir);
147 static void test_status_print(bool ok, const char *testname, double runtime, bool parallel);
148 static void test_status_ok(const char *testname, double runtime, bool parallel);
149 static void test_status_failed(const char *testname, double runtime, bool parallel);
150 static void bail_out(bool noatexit, const char *fmt,...) pg_attribute_printf(2, 3);
151 static void emit_tap_output(TAPtype type, const char *fmt,...) pg_attribute_printf(2, 3);
152 static void emit_tap_output_v(TAPtype type, const char *fmt, va_list argp) pg_attribute_printf(2, 0);
154 static StringInfo psql_start_command(void);
155 static void psql_add_command(StringInfo buf, const char *query,...) pg_attribute_printf(2, 3);
156 static void psql_end_command(StringInfo buf, const char *database);
159 * Convenience macros for printing TAP output with a more shorthand syntax
160 * aimed at making the code more readable.
162 #define plan(x) emit_tap_output(PLAN, "1..%i", (x))
163 #define note(...) emit_tap_output(NOTE, __VA_ARGS__)
164 #define note_detail(...) emit_tap_output(NOTE_DETAIL, __VA_ARGS__)
165 #define diag(...) emit_tap_output(DIAG, __VA_ARGS__)
166 #define note_end() emit_tap_output(NOTE_END, "\n");
167 #define bail_noatexit(...) bail_out(true, __VA_ARGS__)
168 #define bail(...) bail_out(false, __VA_ARGS__)
171 * allow core files if possible.
173 #if defined(HAVE_GETRLIMIT)
174 static void
175 unlimit_core_size(void)
177 struct rlimit lim;
179 getrlimit(RLIMIT_CORE, &lim);
180 if (lim.rlim_max == 0)
182 diag("could not set core size: disallowed by hard limit");
183 return;
185 else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
187 lim.rlim_cur = lim.rlim_max;
188 setrlimit(RLIMIT_CORE, &lim);
191 #endif
195 * Add an item at the end of a stringlist.
197 void
198 add_stringlist_item(_stringlist **listhead, const char *str)
200 _stringlist *newentry = pg_malloc(sizeof(_stringlist));
201 _stringlist *oldentry;
203 newentry->str = pg_strdup(str);
204 newentry->next = NULL;
205 if (*listhead == NULL)
206 *listhead = newentry;
207 else
209 for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
210 /* skip */ ;
211 oldentry->next = newentry;
216 * Free a stringlist.
218 static void
219 free_stringlist(_stringlist **listhead)
221 if (listhead == NULL || *listhead == NULL)
222 return;
223 if ((*listhead)->next != NULL)
224 free_stringlist(&((*listhead)->next));
225 free((*listhead)->str);
226 free(*listhead);
227 *listhead = NULL;
231 * Split a delimited string into a stringlist
233 static void
234 split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
236 char *sc = pg_strdup(s);
237 char *token = strtok(sc, delim);
239 while (token)
241 add_stringlist_item(listhead, token);
242 token = strtok(NULL, delim);
244 free(sc);
248 * Bailing out is for unrecoverable errors which prevents further testing to
249 * occur and after which the test run should be aborted. By passing noatexit
250 * as true the process will terminate with _exit(2) and skipping registered
251 * exit handlers, thus avoid any risk of bottomless recursion calls to exit.
253 static void
254 bail_out(bool noatexit, const char *fmt,...)
256 va_list ap;
258 va_start(ap, fmt);
259 emit_tap_output_v(BAIL, fmt, ap);
260 va_end(ap);
262 if (noatexit)
263 _exit(2);
265 exit(2);
269 * Print the result of a test run and associated metadata like runtime. Care
270 * is taken to align testnames and runtimes vertically to ensure the output
271 * is human readable while still TAP compliant. Tests run in parallel are
272 * prefixed with a '+' and sequential tests with a '-'. This distinction was
273 * previously indicated by 'test' prefixing sequential tests while parallel
274 * tests were indented by four leading spaces. The meson TAP parser consumes
275 * leading space however, so a non-whitespace prefix of the same length is
276 * required for both.
278 static void
279 test_status_print(bool ok, const char *testname, double runtime, bool parallel)
281 int testnumber = fail_count + success_count;
284 * Testnumbers are padded to 5 characters to ensure that testnames align
285 * vertically (assuming at most 9999 tests). Testnames are prefixed with
286 * a leading character to indicate being run in parallel or not. A leading
287 * '+' indicates a parallel test, '-' indicates a single test.
289 emit_tap_output(TEST_STATUS, "%sok %-5i%*s %c %-*s %8.0f ms",
290 (ok ? "" : "not "),
291 testnumber,
292 /* If ok, indent with four spaces matching "not " */
293 (ok ? (int) strlen("not ") : 0), "",
294 /* Prefix a parallel test '+' and a single test with '-' */
295 (parallel ? '+' : '-'),
296 /* Testnames are padded to align runtimes */
297 TESTNAME_WIDTH, testname,
298 runtime);
301 static void
302 test_status_ok(const char *testname, double runtime, bool parallel)
304 success_count++;
306 test_status_print(true, testname, runtime, parallel);
309 static void
310 test_status_failed(const char *testname, double runtime, bool parallel)
313 * Save failed tests in a buffer such that we can print a summary at the
314 * end with diag() to ensure it's shown even under test harnesses.
316 if (!failed_tests)
317 failed_tests = makeStringInfo();
318 else
319 appendStringInfoChar(failed_tests, ',');
321 appendStringInfo(failed_tests, " %s", testname);
323 fail_count++;
325 test_status_print(false, testname, runtime, parallel);
329 static void
330 emit_tap_output(TAPtype type, const char *fmt,...)
332 va_list argp;
334 va_start(argp, fmt);
335 emit_tap_output_v(type, fmt, argp);
336 va_end(argp);
339 static void
340 emit_tap_output_v(TAPtype type, const char *fmt, va_list argp)
342 va_list argp_logfile;
343 FILE *fp;
346 * Diagnostic output will be hidden by prove unless printed to stderr. The
347 * Bail message is also printed to stderr to aid debugging under a harness
348 * which might otherwise not emit such an important message.
350 if (type == DIAG || type == BAIL)
351 fp = stderr;
352 else
353 fp = stdout;
356 * If we are ending a note_detail line we can avoid further processing and
357 * immediately return following a newline.
359 if (type == NOTE_END)
361 in_note = false;
362 fprintf(fp, "\n");
363 if (logfile)
364 fprintf(logfile, "\n");
365 return;
368 /* Make a copy of the va args for printing to the logfile */
369 va_copy(argp_logfile, argp);
372 * Non-protocol output such as diagnostics or notes must be prefixed by a
373 * '#' character. We print the Bail message like this too.
375 if ((type == NOTE || type == DIAG || type == BAIL)
376 || (type == NOTE_DETAIL && !in_note))
378 fprintf(fp, "# ");
379 if (logfile)
380 fprintf(logfile, "# ");
382 vfprintf(fp, fmt, argp);
383 if (logfile)
384 vfprintf(logfile, fmt, argp_logfile);
387 * If we are entering into a note with more details to follow, register
388 * that the leading '#' has been printed such that subsequent details
389 * aren't prefixed as well.
391 if (type == NOTE_DETAIL)
392 in_note = true;
395 * If this was a Bail message, the bail protocol message must go to stdout
396 * separately.
398 if (type == BAIL)
400 fprintf(stdout, "Bail out!");
401 if (logfile)
402 fprintf(logfile, "Bail out!");
405 va_end(argp_logfile);
407 if (type != NOTE_DETAIL)
409 fprintf(fp, "\n");
410 if (logfile)
411 fprintf(logfile, "\n");
413 fflush(NULL);
417 * shut down temp postmaster
419 static void
420 stop_postmaster(void)
422 if (postmaster_running)
424 /* We use pg_ctl to issue the kill and wait for stop */
425 char buf[MAXPGPATH * 2];
426 int r;
428 snprintf(buf, sizeof(buf),
429 "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
430 bindir ? bindir : "",
431 bindir ? "/" : "",
432 temp_instance);
433 fflush(NULL);
434 r = system(buf);
435 if (r != 0)
437 /* Not using the normal bail() as we want _exit */
438 bail_noatexit(_("could not stop postmaster: exit code was %d"), r);
441 postmaster_running = false;
446 * Remove the socket temporary directory. pg_regress never waits for a
447 * postmaster exit, so it is indeterminate whether the postmaster has yet to
448 * unlink the socket and lock file. Unlink them here so we can proceed to
449 * remove the directory. Ignore errors; leaking a temporary directory is
450 * unimportant. This can run from a signal handler. The code is not
451 * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
452 * on Windows, pg_regress does not use Unix sockets by default.
454 static void
455 remove_temp(void)
457 Assert(temp_sockdir);
458 unlink(sockself);
459 unlink(socklock);
460 rmdir(temp_sockdir);
464 * Signal handler that calls remove_temp() and reraises the signal.
466 static void
467 signal_remove_temp(SIGNAL_ARGS)
469 remove_temp();
471 pqsignal(postgres_signal_arg, SIG_DFL);
472 raise(postgres_signal_arg);
476 * Create a temporary directory suitable for the server's Unix-domain socket.
477 * The directory will have mode 0700 or stricter, so no other OS user can open
478 * our socket to exploit our use of trust authentication. Most systems
479 * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
480 * place the directory under /tmp rather than relative to the possibly-deep
481 * current working directory.
483 * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
484 * testing to work in builds that relocate it to a directory not writable to
485 * the build/test user.
487 static const char *
488 make_temp_sockdir(void)
490 char *template = psprintf("%s/pg_regress-XXXXXX",
491 getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
493 temp_sockdir = mkdtemp(template);
494 if (temp_sockdir == NULL)
496 bail("could not create directory \"%s\": %s",
497 template, strerror(errno));
500 /* Stage file names for remove_temp(). Unsafe in a signal handler. */
501 UNIXSOCK_PATH(sockself, port, temp_sockdir);
502 snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
504 /* Remove the directory during clean exit. */
505 atexit(remove_temp);
508 * Remove the directory before dying to the usual signals. Omit SIGQUIT,
509 * preserving it as a quick, untidy exit.
511 pqsignal(SIGHUP, signal_remove_temp);
512 pqsignal(SIGINT, signal_remove_temp);
513 pqsignal(SIGPIPE, signal_remove_temp);
514 pqsignal(SIGTERM, signal_remove_temp);
516 return temp_sockdir;
520 * Check whether string matches pattern
522 * In the original shell script, this function was implemented using expr(1),
523 * which provides basic regular expressions restricted to match starting at
524 * the string start (in conventional regex terms, there's an implicit "^"
525 * at the start of the pattern --- but no implicit "$" at the end).
527 * For now, we only support "." and ".*" as non-literal metacharacters,
528 * because that's all that anyone has found use for in resultmap. This
529 * code could be extended if more functionality is needed.
531 static bool
532 string_matches_pattern(const char *str, const char *pattern)
534 while (*str && *pattern)
536 if (*pattern == '.' && pattern[1] == '*')
538 pattern += 2;
539 /* Trailing .* matches everything. */
540 if (*pattern == '\0')
541 return true;
544 * Otherwise, scan for a text position at which we can match the
545 * rest of the pattern.
547 while (*str)
550 * Optimization to prevent most recursion: don't recurse
551 * unless first pattern char might match this text char.
553 if (*str == *pattern || *pattern == '.')
555 if (string_matches_pattern(str, pattern))
556 return true;
559 str++;
563 * End of text with no match.
565 return false;
567 else if (*pattern != '.' && *str != *pattern)
570 * Not the single-character wildcard and no explicit match? Then
571 * time to quit...
573 return false;
576 str++;
577 pattern++;
580 if (*pattern == '\0')
581 return true; /* end of pattern, so declare match */
583 /* End of input string. Do we have matching pattern remaining? */
584 while (*pattern == '.' && pattern[1] == '*')
585 pattern += 2;
586 if (*pattern == '\0')
587 return true; /* end of pattern, so declare match */
589 return false;
593 * Scan resultmap file to find which platform-specific expected files to use.
595 * The format of each line of the file is
596 * testname/hostplatformpattern=substitutefile
597 * where the hostplatformpattern is evaluated per the rules of expr(1),
598 * namely, it is a standard regular expression with an implicit ^ at the start.
599 * (We currently support only a very limited subset of regular expressions,
600 * see string_matches_pattern() above.) What hostplatformpattern will be
601 * matched against is the config.guess output. (In the shell-script version,
602 * we also provided an indication of whether gcc or another compiler was in
603 * use, but that facility isn't used anymore.)
605 static void
606 load_resultmap(void)
608 char buf[MAXPGPATH];
609 FILE *f;
611 /* scan the file ... */
612 snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
613 f = fopen(buf, "r");
614 if (!f)
616 /* OK if it doesn't exist, else complain */
617 if (errno == ENOENT)
618 return;
619 bail("could not open file \"%s\" for reading: %s",
620 buf, strerror(errno));
623 while (fgets(buf, sizeof(buf), f))
625 char *platform;
626 char *file_type;
627 char *expected;
628 int i;
630 /* strip trailing whitespace, especially the newline */
631 i = strlen(buf);
632 while (i > 0 && isspace((unsigned char) buf[i - 1]))
633 buf[--i] = '\0';
635 /* parse out the line fields */
636 file_type = strchr(buf, ':');
637 if (!file_type)
639 bail("incorrectly formatted resultmap entry: %s", buf);
641 *file_type++ = '\0';
643 platform = strchr(file_type, ':');
644 if (!platform)
646 bail("incorrectly formatted resultmap entry: %s", buf);
648 *platform++ = '\0';
649 expected = strchr(platform, '=');
650 if (!expected)
652 bail("incorrectly formatted resultmap entry: %s", buf);
654 *expected++ = '\0';
657 * if it's for current platform, save it in resultmap list. Note: by
658 * adding at the front of the list, we ensure that in ambiguous cases,
659 * the last match in the resultmap file is used. This mimics the
660 * behavior of the old shell script.
662 if (string_matches_pattern(host_platform, platform))
664 _resultmap *entry = pg_malloc(sizeof(_resultmap));
666 entry->test = pg_strdup(buf);
667 entry->type = pg_strdup(file_type);
668 entry->resultfile = pg_strdup(expected);
669 entry->next = resultmap;
670 resultmap = entry;
673 fclose(f);
677 * Check in resultmap if we should be looking at a different file
679 static
680 const char *
681 get_expectfile(const char *testname, const char *file)
683 char *file_type;
684 _resultmap *rm;
687 * Determine the file type from the file name. This is just what is
688 * following the last dot in the file name.
690 if (!file || !(file_type = strrchr(file, '.')))
691 return NULL;
693 file_type++;
695 for (rm = resultmap; rm != NULL; rm = rm->next)
697 if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
699 return rm->resultfile;
703 return NULL;
707 * Prepare environment variables for running regression tests
709 static void
710 initialize_environment(void)
713 * Set default application_name. (The test_start_function may choose to
714 * override this, but if it doesn't, we have something useful in place.)
716 setenv("PGAPPNAME", "pg_regress", 1);
719 * Set variables that the test scripts may need to refer to.
721 setenv("PG_ABS_SRCDIR", inputdir, 1);
722 setenv("PG_ABS_BUILDDIR", outputdir, 1);
723 setenv("PG_LIBDIR", dlpath, 1);
724 setenv("PG_DLSUFFIX", DLSUFFIX, 1);
726 if (nolocale)
729 * Clear out any non-C locale settings
731 unsetenv("LC_COLLATE");
732 unsetenv("LC_CTYPE");
733 unsetenv("LC_MONETARY");
734 unsetenv("LC_NUMERIC");
735 unsetenv("LC_TIME");
736 unsetenv("LANG");
739 * Most platforms have adopted the POSIX locale as their
740 * implementation-defined default locale. Exceptions include native
741 * Windows, macOS with --enable-nls, and Cygwin with --enable-nls.
742 * (Use of --enable-nls matters because libintl replaces setlocale().)
743 * Also, PostgreSQL does not support macOS with locale environment
744 * variables unset; see PostmasterMain().
746 #if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
747 setenv("LANG", "C", 1);
748 #endif
752 * Set translation-related settings to English; otherwise psql will
753 * produce translated messages and produce diffs. (XXX If we ever support
754 * translation of pg_regress, this needs to be moved elsewhere, where psql
755 * is actually called.)
757 unsetenv("LANGUAGE");
758 unsetenv("LC_ALL");
759 setenv("LC_MESSAGES", "C", 1);
762 * Set encoding as requested
764 if (encoding)
765 setenv("PGCLIENTENCODING", encoding, 1);
766 else
767 unsetenv("PGCLIENTENCODING");
770 * Set timezone and datestyle for datetime-related tests
772 setenv("PGTZ", "PST8PDT", 1);
773 setenv("PGDATESTYLE", "Postgres, MDY", 1);
776 * Likewise set intervalstyle to ensure consistent results. This is a bit
777 * more painful because we must use PGOPTIONS, and we want to preserve the
778 * user's ability to set other variables through that.
781 const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
782 const char *old_pgoptions = getenv("PGOPTIONS");
783 char *new_pgoptions;
785 if (!old_pgoptions)
786 old_pgoptions = "";
787 new_pgoptions = psprintf("%s %s",
788 old_pgoptions, my_pgoptions);
789 setenv("PGOPTIONS", new_pgoptions, 1);
790 free(new_pgoptions);
793 if (temp_instance)
796 * Clear out any environment vars that might cause psql to connect to
797 * the wrong postmaster, or otherwise behave in nondefault ways. (Note
798 * we also use psql's -X switch consistently, so that ~/.psqlrc files
799 * won't mess things up.) Also, set PGPORT to the temp port, and set
800 * PGHOST depending on whether we are using TCP or Unix sockets.
802 * This list should be kept in sync with PostgreSQL/Test/Utils.pm.
804 unsetenv("PGCHANNELBINDING");
805 /* PGCLIENTENCODING, see above */
806 unsetenv("PGCONNECT_TIMEOUT");
807 unsetenv("PGDATA");
808 unsetenv("PGDATABASE");
809 unsetenv("PGGSSDELEGATION");
810 unsetenv("PGGSSENCMODE");
811 unsetenv("PGGSSLIB");
812 /* PGHOSTADDR, see below */
813 unsetenv("PGKRBSRVNAME");
814 unsetenv("PGPASSFILE");
815 unsetenv("PGPASSWORD");
816 unsetenv("PGREQUIREPEER");
817 unsetenv("PGREQUIRESSL");
818 unsetenv("PGSERVICE");
819 unsetenv("PGSERVICEFILE");
820 unsetenv("PGSSLCERT");
821 unsetenv("PGSSLCRL");
822 unsetenv("PGSSLCRLDIR");
823 unsetenv("PGSSLKEY");
824 unsetenv("PGSSLMAXPROTOCOLVERSION");
825 unsetenv("PGSSLMINPROTOCOLVERSION");
826 unsetenv("PGSSLMODE");
827 unsetenv("PGSSLROOTCERT");
828 unsetenv("PGSSLSNI");
829 unsetenv("PGTARGETSESSIONATTRS");
830 unsetenv("PGUSER");
831 /* PGPORT, see below */
832 /* PGHOST, see below */
834 if (hostname != NULL)
835 setenv("PGHOST", hostname, 1);
836 else
838 sockdir = getenv("PG_REGRESS_SOCK_DIR");
839 if (!sockdir)
840 sockdir = make_temp_sockdir();
841 setenv("PGHOST", sockdir, 1);
843 unsetenv("PGHOSTADDR");
844 if (port != -1)
846 char s[16];
848 snprintf(s, sizeof(s), "%d", port);
849 setenv("PGPORT", s, 1);
852 else
854 const char *pghost;
855 const char *pgport;
858 * When testing an existing install, we honor existing environment
859 * variables, except if they're overridden by command line options.
861 if (hostname != NULL)
863 setenv("PGHOST", hostname, 1);
864 unsetenv("PGHOSTADDR");
866 if (port != -1)
868 char s[16];
870 snprintf(s, sizeof(s), "%d", port);
871 setenv("PGPORT", s, 1);
873 if (user != NULL)
874 setenv("PGUSER", user, 1);
877 * However, we *don't* honor PGDATABASE, since we certainly don't wish
878 * to connect to whatever database the user might like as default.
879 * (Most tests override PGDATABASE anyway, but there are some ECPG
880 * test cases that don't.)
882 unsetenv("PGDATABASE");
885 * Report what we're connecting to
887 pghost = getenv("PGHOST");
888 pgport = getenv("PGPORT");
889 if (!pghost)
891 /* Keep this bit in sync with libpq's default host location: */
892 if (DEFAULT_PGSOCKET_DIR[0])
893 /* do nothing, we'll print "Unix socket" below */ ;
894 else
895 pghost = "localhost"; /* DefaultHost in fe-connect.c */
898 if (pghost && pgport)
899 note("using postmaster on %s, port %s", pghost, pgport);
900 if (pghost && !pgport)
901 note("using postmaster on %s, default port", pghost);
902 if (!pghost && pgport)
903 note("using postmaster on Unix socket, port %s", pgport);
904 if (!pghost && !pgport)
905 note("using postmaster on Unix socket, default port");
908 load_resultmap();
911 #ifdef ENABLE_SSPI
913 /* support for config_sspi_auth() */
914 static const char *
915 fmtHba(const char *raw)
917 static char *ret;
918 const char *rp;
919 char *wp;
921 wp = ret = pg_realloc(ret, 3 + strlen(raw) * 2);
923 *wp++ = '"';
924 for (rp = raw; *rp; rp++)
926 if (*rp == '"')
927 *wp++ = '"';
928 *wp++ = *rp;
930 *wp++ = '"';
931 *wp++ = '\0';
933 return ret;
937 * Get account and domain/realm names for the current user. This is based on
938 * pg_SSPI_recvauth(). The returned strings use static storage.
940 static void
941 current_windows_user(const char **acct, const char **dom)
943 static char accountname[MAXPGPATH];
944 static char domainname[MAXPGPATH];
945 HANDLE token;
946 TOKEN_USER *tokenuser;
947 DWORD retlen;
948 DWORD accountnamesize = sizeof(accountname);
949 DWORD domainnamesize = sizeof(domainname);
950 SID_NAME_USE accountnameuse;
952 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token))
954 bail("could not open process token: error code %lu", GetLastError());
957 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
959 bail("could not get token information buffer size: error code %lu",
960 GetLastError());
962 tokenuser = pg_malloc(retlen);
963 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
965 bail("could not get token information: error code %lu",
966 GetLastError());
969 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
970 domainname, &domainnamesize, &accountnameuse))
972 bail("could not look up account SID: error code %lu",
973 GetLastError());
976 free(tokenuser);
978 *acct = accountname;
979 *dom = domainname;
983 * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
984 * the current OS user to authenticate as the bootstrap superuser and as any
985 * user named in a --create-role option.
987 * In --config-auth mode, the --user switch can be used to specify the
988 * bootstrap superuser's name, otherwise we assume it is the default.
990 static void
991 config_sspi_auth(const char *pgdata, const char *superuser_name)
993 const char *accountname,
994 *domainname;
995 char *errstr;
996 bool have_ipv6;
997 char fname[MAXPGPATH];
998 int res;
999 FILE *hba,
1000 *ident;
1001 _stringlist *sl;
1003 /* Find out the name of the current OS user */
1004 current_windows_user(&accountname, &domainname);
1006 /* Determine the bootstrap superuser's name */
1007 if (superuser_name == NULL)
1010 * Compute the default superuser name the same way initdb does.
1012 * It's possible that this result always matches "accountname", the
1013 * value SSPI authentication discovers. But the underlying system
1014 * functions do not clearly guarantee that.
1016 superuser_name = get_user_name(&errstr);
1017 if (superuser_name == NULL)
1019 bail("%s", errstr);
1024 * Like initdb.c:setup_config(), determine whether the platform recognizes
1025 * ::1 (IPv6 loopback) as a numeric host address string.
1028 struct addrinfo *gai_result;
1029 struct addrinfo hints;
1030 WSADATA wsaData;
1032 hints.ai_flags = AI_NUMERICHOST;
1033 hints.ai_family = AF_UNSPEC;
1034 hints.ai_socktype = 0;
1035 hints.ai_protocol = 0;
1036 hints.ai_addrlen = 0;
1037 hints.ai_canonname = NULL;
1038 hints.ai_addr = NULL;
1039 hints.ai_next = NULL;
1041 have_ipv6 = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0 &&
1042 getaddrinfo("::1", NULL, &hints, &gai_result) == 0);
1045 /* Check a Write outcome and report any error. */
1046 #define CW(cond) \
1047 do { \
1048 if (!(cond)) \
1050 bail("could not write to file \"%s\": %s", \
1051 fname, strerror(errno)); \
1053 } while (0)
1055 res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
1056 if (res < 0 || res >= sizeof(fname))
1059 * Truncating this name is a fatal error, because we must not fail to
1060 * overwrite an original trust-authentication pg_hba.conf.
1062 bail("directory name too long");
1064 hba = fopen(fname, "w");
1065 if (hba == NULL)
1067 bail("could not open file \"%s\" for writing: %s",
1068 fname, strerror(errno));
1070 CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
1071 CW(fputs("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n",
1072 hba) >= 0);
1073 if (have_ipv6)
1074 CW(fputs("host all all ::1/128 sspi include_realm=1 map=regress\n",
1075 hba) >= 0);
1076 CW(fclose(hba) == 0);
1078 snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
1079 ident = fopen(fname, "w");
1080 if (ident == NULL)
1082 bail("could not open file \"%s\" for writing: %s",
1083 fname, strerror(errno));
1085 CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
1088 * Double-quote for the benefit of account names containing whitespace or
1089 * '#'. Windows forbids the double-quote character itself, so don't
1090 * bother escaping embedded double-quote characters.
1092 CW(fprintf(ident, "regress \"%s@%s\" %s\n",
1093 accountname, domainname, fmtHba(superuser_name)) >= 0);
1094 for (sl = extraroles; sl; sl = sl->next)
1095 CW(fprintf(ident, "regress \"%s@%s\" %s\n",
1096 accountname, domainname, fmtHba(sl->str)) >= 0);
1097 CW(fclose(ident) == 0);
1100 #endif /* ENABLE_SSPI */
1103 * psql_start_command, psql_add_command, psql_end_command
1105 * Issue one or more commands within one psql call.
1106 * Set up with psql_start_command, then add commands one at a time
1107 * with psql_add_command, and finally execute with psql_end_command.
1109 * Since we use system(), this doesn't return until the operation finishes
1111 static StringInfo
1112 psql_start_command(void)
1114 StringInfo buf = makeStringInfo();
1116 appendStringInfo(buf,
1117 "\"%s%spsql\" -X -q",
1118 bindir ? bindir : "",
1119 bindir ? "/" : "");
1120 return buf;
1123 static void
1124 psql_add_command(StringInfo buf, const char *query,...)
1126 StringInfoData cmdbuf;
1127 const char *cmdptr;
1129 /* Add each command as a -c argument in the psql call */
1130 appendStringInfoString(buf, " -c \"");
1132 /* Generate the query with insertion of sprintf arguments */
1133 initStringInfo(&cmdbuf);
1134 for (;;)
1136 va_list args;
1137 int needed;
1139 va_start(args, query);
1140 needed = appendStringInfoVA(&cmdbuf, query, args);
1141 va_end(args);
1142 if (needed == 0)
1143 break; /* success */
1144 enlargeStringInfo(&cmdbuf, needed);
1147 /* Now escape any shell double-quote metacharacters */
1148 for (cmdptr = cmdbuf.data; *cmdptr; cmdptr++)
1150 if (strchr("\\\"$`", *cmdptr))
1151 appendStringInfoChar(buf, '\\');
1152 appendStringInfoChar(buf, *cmdptr);
1155 appendStringInfoChar(buf, '"');
1157 pfree(cmdbuf.data);
1160 static void
1161 psql_end_command(StringInfo buf, const char *database)
1163 /* Add the database name --- assume it needs no extra escaping */
1164 appendStringInfo(buf,
1165 " \"%s\"",
1166 database);
1168 /* And now we can execute the shell command */
1169 fflush(NULL);
1170 if (system(buf->data) != 0)
1172 /* psql probably already reported the error */
1173 bail("command failed: %s", buf->data);
1176 /* Clean up */
1177 pfree(buf->data);
1178 pfree(buf);
1182 * Shorthand macro for the common case of a single command
1184 #define psql_command(database, ...) \
1185 do { \
1186 StringInfo cmdbuf = psql_start_command(); \
1187 psql_add_command(cmdbuf, __VA_ARGS__); \
1188 psql_end_command(cmdbuf, database); \
1189 } while (0)
1192 * Spawn a process to execute the given shell command; don't wait for it
1194 * Returns the process ID (or HANDLE) so we can wait for it later
1196 PID_TYPE
1197 spawn_process(const char *cmdline)
1199 #ifndef WIN32
1200 pid_t pid;
1203 * Must flush I/O buffers before fork.
1205 fflush(NULL);
1207 #ifdef EXEC_BACKEND
1208 pg_disable_aslr();
1209 #endif
1211 pid = fork();
1212 if (pid == -1)
1214 bail("could not fork: %s", strerror(errno));
1216 if (pid == 0)
1219 * In child
1221 * Instead of using system(), exec the shell directly, and tell it to
1222 * "exec" the command too. This saves two useless processes per
1223 * parallel test case.
1225 char *cmdline2;
1227 cmdline2 = psprintf("exec %s", cmdline);
1228 execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1229 /* Not using the normal bail() here as we want _exit */
1230 bail_noatexit("could not exec \"%s\": %s", shellprog, strerror(errno));
1232 /* in parent */
1233 return pid;
1234 #else
1235 PROCESS_INFORMATION pi;
1236 char *cmdline2;
1237 const char *comspec;
1239 /* Find CMD.EXE location using COMSPEC, if it's set */
1240 comspec = getenv("COMSPEC");
1241 if (comspec == NULL)
1242 comspec = "CMD";
1244 memset(&pi, 0, sizeof(pi));
1245 cmdline2 = psprintf("\"%s\" /d /c \"%s\"", comspec, cmdline);
1247 if (!CreateRestrictedProcess(cmdline2, &pi))
1248 exit(2);
1250 CloseHandle(pi.hThread);
1251 return pi.hProcess;
1252 #endif
1256 * Count bytes in file
1258 static long
1259 file_size(const char *file)
1261 long r;
1262 FILE *f = fopen(file, "r");
1264 if (!f)
1266 diag("could not open file \"%s\" for reading: %s",
1267 file, strerror(errno));
1268 return -1;
1270 fseek(f, 0, SEEK_END);
1271 r = ftell(f);
1272 fclose(f);
1273 return r;
1277 * Count lines in file
1279 static int
1280 file_line_count(const char *file)
1282 int c;
1283 int l = 0;
1284 FILE *f = fopen(file, "r");
1286 if (!f)
1288 diag("could not open file \"%s\" for reading: %s",
1289 file, strerror(errno));
1290 return -1;
1292 while ((c = fgetc(f)) != EOF)
1294 if (c == '\n')
1295 l++;
1297 fclose(f);
1298 return l;
1301 bool
1302 file_exists(const char *file)
1304 FILE *f = fopen(file, "r");
1306 if (!f)
1307 return false;
1308 fclose(f);
1309 return true;
1312 static bool
1313 directory_exists(const char *dir)
1315 struct stat st;
1317 if (stat(dir, &st) != 0)
1318 return false;
1319 if (S_ISDIR(st.st_mode))
1320 return true;
1321 return false;
1324 /* Create a directory */
1325 static void
1326 make_directory(const char *dir)
1328 if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
1330 bail("could not create directory \"%s\": %s", dir, strerror(errno));
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 fflush(NULL);
1377 r = system(cmd);
1378 if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
1380 bail("diff command failed with status %d: %s", r, cmd);
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 bail("diff command not found: %s", cmd);
1392 #endif
1394 return WEXITSTATUS(r);
1398 * Check the actual result file for the given test against expected results
1400 * Returns true if different (failure), false if correct match found.
1401 * In the true case, the diff is appended to the diffs file.
1403 static bool
1404 results_differ(const char *testname, const char *resultsfile, const char *default_expectfile)
1406 char expectfile[MAXPGPATH];
1407 char diff[MAXPGPATH];
1408 char cmd[MAXPGPATH * 3];
1409 char best_expect_file[MAXPGPATH];
1410 FILE *difffile;
1411 int best_line_count;
1412 int i;
1413 int l;
1414 const char *platform_expectfile;
1417 * We can pass either the resultsfile or the expectfile, they should have
1418 * the same type (filename.type) anyway.
1420 platform_expectfile = get_expectfile(testname, resultsfile);
1422 strlcpy(expectfile, default_expectfile, sizeof(expectfile));
1423 if (platform_expectfile)
1426 * Replace everything after the last slash in expectfile with what the
1427 * platform_expectfile contains.
1429 char *p = strrchr(expectfile, '/');
1431 if (p)
1432 strcpy(++p, platform_expectfile);
1435 /* Name to use for temporary diff file */
1436 snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
1438 /* OK, run the diff */
1439 snprintf(cmd, sizeof(cmd),
1440 "diff %s \"%s\" \"%s\" > \"%s\"",
1441 basic_diff_opts, expectfile, resultsfile, diff);
1443 /* Is the diff file empty? */
1444 if (run_diff(cmd, diff) == 0)
1446 unlink(diff);
1447 return false;
1450 /* There may be secondary comparison files that match better */
1451 best_line_count = file_line_count(diff);
1452 strcpy(best_expect_file, expectfile);
1454 for (i = 0; i <= 9; i++)
1456 char *alt_expectfile;
1458 alt_expectfile = get_alternative_expectfile(expectfile, i);
1459 if (!alt_expectfile)
1461 bail("Unable to check secondary comparison files: %s",
1462 strerror(errno));
1465 if (!file_exists(alt_expectfile))
1467 free(alt_expectfile);
1468 continue;
1471 snprintf(cmd, sizeof(cmd),
1472 "diff %s \"%s\" \"%s\" > \"%s\"",
1473 basic_diff_opts, alt_expectfile, resultsfile, diff);
1475 if (run_diff(cmd, diff) == 0)
1477 unlink(diff);
1478 free(alt_expectfile);
1479 return false;
1482 l = file_line_count(diff);
1483 if (l < best_line_count)
1485 /* This diff was a better match than the last one */
1486 best_line_count = l;
1487 strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
1489 free(alt_expectfile);
1493 * fall back on the canonical results file if we haven't tried it yet and
1494 * haven't found a complete match yet.
1497 if (platform_expectfile)
1499 snprintf(cmd, sizeof(cmd),
1500 "diff %s \"%s\" \"%s\" > \"%s\"",
1501 basic_diff_opts, default_expectfile, resultsfile, diff);
1503 if (run_diff(cmd, diff) == 0)
1505 /* No diff = no changes = good */
1506 unlink(diff);
1507 return false;
1510 l = file_line_count(diff);
1511 if (l < best_line_count)
1513 /* This diff was a better match than the last one */
1514 best_line_count = l;
1515 strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
1520 * Use the best comparison file to generate the "pretty" diff, which we
1521 * append to the diffs summary file.
1524 /* Write diff header */
1525 difffile = fopen(difffilename, "a");
1526 if (difffile)
1528 fprintf(difffile,
1529 "diff %s %s %s\n",
1530 pretty_diff_opts, best_expect_file, resultsfile);
1531 fclose(difffile);
1534 /* Run diff */
1535 snprintf(cmd, sizeof(cmd),
1536 "diff %s \"%s\" \"%s\" >> \"%s\"",
1537 pretty_diff_opts, best_expect_file, resultsfile, difffilename);
1538 run_diff(cmd, difffilename);
1540 unlink(diff);
1541 return true;
1545 * Wait for specified subprocesses to finish, and return their exit
1546 * statuses into statuses[] and stop times into stoptimes[]
1548 * If names isn't NULL, print each subprocess's name as it finishes
1550 * Note: it's OK to scribble on the pids array, but not on the names array
1552 static void
1553 wait_for_tests(PID_TYPE * pids, int *statuses, instr_time *stoptimes,
1554 char **names, int num_tests)
1556 int tests_left;
1557 int i;
1559 #ifdef WIN32
1560 PID_TYPE *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
1562 memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
1563 #endif
1565 tests_left = num_tests;
1566 while (tests_left > 0)
1568 PID_TYPE p;
1570 #ifndef WIN32
1571 int exit_status;
1573 p = wait(&exit_status);
1575 if (p == INVALID_PID)
1577 bail("failed to wait for subprocesses: %s", strerror(errno));
1579 #else
1580 DWORD exit_status;
1581 int r;
1583 r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
1584 if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
1586 bail("failed to wait for subprocesses: error code %lu",
1587 GetLastError());
1589 p = active_pids[r - WAIT_OBJECT_0];
1590 /* compact the active_pids array */
1591 active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
1592 #endif /* WIN32 */
1594 for (i = 0; i < num_tests; i++)
1596 if (p == pids[i])
1598 #ifdef WIN32
1599 GetExitCodeProcess(pids[i], &exit_status);
1600 CloseHandle(pids[i]);
1601 #endif
1602 pids[i] = INVALID_PID;
1603 statuses[i] = (int) exit_status;
1604 INSTR_TIME_SET_CURRENT(stoptimes[i]);
1605 if (names)
1606 note_detail(" %s", names[i]);
1607 tests_left--;
1608 break;
1613 #ifdef WIN32
1614 free(active_pids);
1615 #endif
1619 * report nonzero exit code from a test process
1621 static void
1622 log_child_failure(int exitstatus)
1624 if (WIFEXITED(exitstatus))
1625 diag("(test process exited with exit code %d)",
1626 WEXITSTATUS(exitstatus));
1627 else if (WIFSIGNALED(exitstatus))
1629 #if defined(WIN32)
1630 diag("(test process was terminated by exception 0x%X)",
1631 WTERMSIG(exitstatus));
1632 #else
1633 diag("(test process was terminated by signal %d: %s)",
1634 WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
1635 #endif
1637 else
1638 diag("(test process exited with unrecognized status %d)", exitstatus);
1642 * Run all the tests specified in one schedule file
1644 static void
1645 run_schedule(const char *schedule, test_start_function startfunc,
1646 postprocess_result_function postfunc)
1648 #define MAX_PARALLEL_TESTS 100
1649 char *tests[MAX_PARALLEL_TESTS];
1650 _stringlist *resultfiles[MAX_PARALLEL_TESTS];
1651 _stringlist *expectfiles[MAX_PARALLEL_TESTS];
1652 _stringlist *tags[MAX_PARALLEL_TESTS];
1653 PID_TYPE pids[MAX_PARALLEL_TESTS];
1654 instr_time starttimes[MAX_PARALLEL_TESTS];
1655 instr_time stoptimes[MAX_PARALLEL_TESTS];
1656 int statuses[MAX_PARALLEL_TESTS];
1657 char scbuf[1024];
1658 FILE *scf;
1659 int line_num = 0;
1661 memset(tests, 0, sizeof(tests));
1662 memset(resultfiles, 0, sizeof(resultfiles));
1663 memset(expectfiles, 0, sizeof(expectfiles));
1664 memset(tags, 0, sizeof(tags));
1666 scf = fopen(schedule, "r");
1667 if (!scf)
1669 bail("could not open file \"%s\" for reading: %s",
1670 schedule, strerror(errno));
1673 while (fgets(scbuf, sizeof(scbuf), scf))
1675 char *test = NULL;
1676 char *c;
1677 int num_tests;
1678 bool inword;
1679 int i;
1681 line_num++;
1683 /* strip trailing whitespace, especially the newline */
1684 i = strlen(scbuf);
1685 while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
1686 scbuf[--i] = '\0';
1688 if (scbuf[0] == '\0' || scbuf[0] == '#')
1689 continue;
1690 if (strncmp(scbuf, "test: ", 6) == 0)
1691 test = scbuf + 6;
1692 else
1694 bail("syntax error in schedule file \"%s\" line %d: %s",
1695 schedule, line_num, scbuf);
1698 num_tests = 0;
1699 inword = false;
1700 for (c = test;; c++)
1702 if (*c == '\0' || isspace((unsigned char) *c))
1704 if (inword)
1706 /* Reached end of a test name */
1707 char sav;
1709 if (num_tests >= MAX_PARALLEL_TESTS)
1711 bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
1712 MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
1714 sav = *c;
1715 *c = '\0';
1716 tests[num_tests] = pg_strdup(test);
1717 num_tests++;
1718 *c = sav;
1719 inword = false;
1721 if (*c == '\0')
1722 break; /* loop exit is here */
1724 else if (!inword)
1726 /* Start of a test name */
1727 test = c;
1728 inword = true;
1732 if (num_tests == 0)
1734 bail("syntax error in schedule file \"%s\" line %d: %s",
1735 schedule, line_num, scbuf);
1738 if (num_tests == 1)
1740 pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
1741 INSTR_TIME_SET_CURRENT(starttimes[0]);
1742 wait_for_tests(pids, statuses, stoptimes, NULL, 1);
1743 /* status line is finished below */
1745 else if (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
1747 bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
1748 max_concurrent_tests, schedule, line_num, scbuf);
1750 else if (max_connections > 0 && max_connections < num_tests)
1752 int oldest = 0;
1754 note_detail("parallel group (%d tests, in groups of %d): ",
1755 num_tests, max_connections);
1756 for (i = 0; i < num_tests; i++)
1758 if (i - oldest >= max_connections)
1760 wait_for_tests(pids + oldest, statuses + oldest,
1761 stoptimes + oldest,
1762 tests + oldest, i - oldest);
1763 oldest = i;
1765 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1766 INSTR_TIME_SET_CURRENT(starttimes[i]);
1768 wait_for_tests(pids + oldest, statuses + oldest,
1769 stoptimes + oldest,
1770 tests + oldest, i - oldest);
1771 note_end();
1773 else
1775 note_detail("parallel group (%d tests): ", num_tests);
1776 for (i = 0; i < num_tests; i++)
1778 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1779 INSTR_TIME_SET_CURRENT(starttimes[i]);
1781 wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
1782 note_end();
1785 /* Check results for all tests */
1786 for (i = 0; i < num_tests; i++)
1788 _stringlist *rl,
1789 *el,
1790 *tl;
1791 bool differ = false;
1793 INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
1796 * Advance over all three lists simultaneously.
1798 * Compare resultfiles[j] with expectfiles[j] always. Tags are
1799 * optional but if there are tags, the tag list has the same
1800 * length as the other two lists.
1802 for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
1803 rl != NULL; /* rl and el have the same length */
1804 rl = rl->next, el = el->next,
1805 tl = tl ? tl->next : NULL)
1807 bool newdiff;
1809 if (postfunc)
1810 (*postfunc) (rl->str);
1811 newdiff = results_differ(tests[i], rl->str, el->str);
1812 if (newdiff && tl)
1814 diag("tag: %s", tl->str);
1816 differ |= newdiff;
1819 if (statuses[i] != 0)
1821 test_status_failed(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
1822 log_child_failure(statuses[i]);
1824 else
1826 if (differ)
1828 test_status_failed(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
1830 else
1832 test_status_ok(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
1837 for (i = 0; i < num_tests; i++)
1839 pg_free(tests[i]);
1840 tests[i] = NULL;
1841 free_stringlist(&resultfiles[i]);
1842 free_stringlist(&expectfiles[i]);
1843 free_stringlist(&tags[i]);
1847 fclose(scf);
1851 * Run a single test
1853 static void
1854 run_single_test(const char *test, test_start_function startfunc,
1855 postprocess_result_function postfunc)
1857 PID_TYPE pid;
1858 instr_time starttime;
1859 instr_time stoptime;
1860 int exit_status;
1861 _stringlist *resultfiles = NULL;
1862 _stringlist *expectfiles = NULL;
1863 _stringlist *tags = NULL;
1864 _stringlist *rl,
1865 *el,
1866 *tl;
1867 bool differ = false;
1869 pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
1870 INSTR_TIME_SET_CURRENT(starttime);
1871 wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
1874 * Advance over all three lists simultaneously.
1876 * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
1877 * but if there are tags, the tag list has the same length as the other
1878 * two lists.
1880 for (rl = resultfiles, el = expectfiles, tl = tags;
1881 rl != NULL; /* rl and el have the same length */
1882 rl = rl->next, el = el->next,
1883 tl = tl ? tl->next : NULL)
1885 bool newdiff;
1887 if (postfunc)
1888 (*postfunc) (rl->str);
1889 newdiff = results_differ(test, rl->str, el->str);
1890 if (newdiff && tl)
1892 diag("tag: %s", tl->str);
1894 differ |= newdiff;
1897 INSTR_TIME_SUBTRACT(stoptime, starttime);
1899 if (exit_status != 0)
1901 test_status_failed(test, INSTR_TIME_GET_MILLISEC(stoptime), false);
1902 log_child_failure(exit_status);
1904 else
1906 if (differ)
1908 test_status_failed(test, INSTR_TIME_GET_MILLISEC(stoptime), false);
1910 else
1912 test_status_ok(test, INSTR_TIME_GET_MILLISEC(stoptime), false);
1918 * Create the summary-output files (making them empty if already existing)
1920 static void
1921 open_result_files(void)
1923 char file[MAXPGPATH];
1924 FILE *difffile;
1926 /* create outputdir directory if not present */
1927 if (!directory_exists(outputdir))
1928 make_directory(outputdir);
1930 /* create the log file (copy of running status output) */
1931 snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1932 logfilename = pg_strdup(file);
1933 logfile = fopen(logfilename, "w");
1934 if (!logfile)
1936 bail("could not open file \"%s\" for writing: %s",
1937 logfilename, strerror(errno));
1940 /* create the diffs file as empty */
1941 snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1942 difffilename = pg_strdup(file);
1943 difffile = fopen(difffilename, "w");
1944 if (!difffile)
1946 bail("could not open file \"%s\" for writing: %s",
1947 difffilename, strerror(errno));
1949 /* we don't keep the diffs file open continuously */
1950 fclose(difffile);
1952 /* also create the results directory if not present */
1953 snprintf(file, sizeof(file), "%s/results", outputdir);
1954 if (!directory_exists(file))
1955 make_directory(file);
1958 static void
1959 drop_database_if_exists(const char *dbname)
1961 StringInfo buf = psql_start_command();
1963 /* Set warning level so we don't see chatter about nonexistent DB */
1964 psql_add_command(buf, "SET client_min_messages = warning");
1965 psql_add_command(buf, "DROP DATABASE IF EXISTS \"%s\"", dbname);
1966 psql_end_command(buf, "postgres");
1969 static void
1970 create_database(const char *dbname)
1972 StringInfo buf = psql_start_command();
1973 _stringlist *sl;
1976 * We use template0 so that any installation-local cruft in template1 will
1977 * not mess up the tests.
1979 if (encoding)
1980 psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
1981 (nolocale) ? " LOCALE='C'" : "");
1982 else
1983 psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
1984 (nolocale) ? " LOCALE='C'" : "");
1985 psql_add_command(buf,
1986 "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
1987 "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
1988 "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
1989 "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
1990 "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
1991 "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
1992 dbname, dbname, dbname, dbname, dbname, dbname);
1993 psql_end_command(buf, "postgres");
1996 * Install any requested extensions. We use CREATE IF NOT EXISTS so that
1997 * this will work whether or not the extension is preinstalled.
1999 for (sl = loadextension; sl != NULL; sl = sl->next)
2000 psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
2003 static void
2004 drop_role_if_exists(const char *rolename)
2006 StringInfo buf = psql_start_command();
2008 /* Set warning level so we don't see chatter about nonexistent role */
2009 psql_add_command(buf, "SET client_min_messages = warning");
2010 psql_add_command(buf, "DROP ROLE IF EXISTS \"%s\"", rolename);
2011 psql_end_command(buf, "postgres");
2014 static void
2015 create_role(const char *rolename, const _stringlist *granted_dbs)
2017 StringInfo buf = psql_start_command();
2019 psql_add_command(buf, "CREATE ROLE \"%s\" WITH LOGIN", rolename);
2020 for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
2022 psql_add_command(buf, "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
2023 granted_dbs->str, rolename);
2025 psql_end_command(buf, "postgres");
2028 static void
2029 help(void)
2031 printf(_("PostgreSQL regression test driver\n"));
2032 printf(_("\n"));
2033 printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
2034 printf(_("\n"));
2035 printf(_("Options:\n"));
2036 printf(_(" --bindir=BINPATH use BINPATH for programs that are run;\n"));
2037 printf(_(" if empty, use PATH from the environment\n"));
2038 printf(_(" --config-auth=DATADIR update authentication settings for DATADIR\n"));
2039 printf(_(" --create-role=ROLE create the specified role before testing\n"));
2040 printf(_(" --dbname=DB use database DB (default \"regression\")\n"));
2041 printf(_(" --debug turn on debug mode in programs that are run\n"));
2042 printf(_(" --dlpath=DIR look for dynamic libraries in DIR\n"));
2043 printf(_(" --encoding=ENCODING use ENCODING as the encoding\n"));
2044 printf(_(" --expecteddir=DIR take expected files from DIR (default \".\")\n"));
2045 printf(_(" -h, --help show this help, then exit\n"));
2046 printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n"));
2047 printf(_(" --launcher=CMD use CMD as launcher of psql\n"));
2048 printf(_(" --load-extension=EXT load the named extension before running the\n"));
2049 printf(_(" tests; can appear multiple times\n"));
2050 printf(_(" --max-connections=N maximum number of concurrent connections\n"));
2051 printf(_(" (default is 0, meaning unlimited)\n"));
2052 printf(_(" --max-concurrent-tests=N maximum number of concurrent tests in schedule\n"));
2053 printf(_(" (default is 0, meaning unlimited)\n"));
2054 printf(_(" --outputdir=DIR place output files in DIR (default \".\")\n"));
2055 printf(_(" --schedule=FILE use test ordering schedule from FILE\n"));
2056 printf(_(" (can be used multiple times to concatenate)\n"));
2057 printf(_(" --temp-instance=DIR create a temporary instance in DIR\n"));
2058 printf(_(" --use-existing use an existing installation\n"));
2059 printf(_(" -V, --version output version information, then exit\n"));
2060 printf(_("\n"));
2061 printf(_("Options for \"temp-instance\" mode:\n"));
2062 printf(_(" --no-locale use C locale\n"));
2063 printf(_(" --port=PORT start postmaster on PORT\n"));
2064 printf(_(" --temp-config=FILE append contents of FILE to temporary config\n"));
2065 printf(_("\n"));
2066 printf(_("Options for using an existing installation:\n"));
2067 printf(_(" --host=HOST use postmaster running on HOST\n"));
2068 printf(_(" --port=PORT use postmaster running at PORT\n"));
2069 printf(_(" --user=USER connect as USER\n"));
2070 printf(_("\n"));
2071 printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
2072 printf(_("if the tests could not be run for some reason.\n"));
2073 printf(_("\n"));
2074 printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2075 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
2079 regression_main(int argc, char *argv[],
2080 init_function ifunc,
2081 test_start_function startfunc,
2082 postprocess_result_function postfunc)
2084 static struct option long_options[] = {
2085 {"help", no_argument, NULL, 'h'},
2086 {"version", no_argument, NULL, 'V'},
2087 {"dbname", required_argument, NULL, 1},
2088 {"debug", no_argument, NULL, 2},
2089 {"inputdir", required_argument, NULL, 3},
2090 {"max-connections", required_argument, NULL, 5},
2091 {"encoding", required_argument, NULL, 6},
2092 {"outputdir", required_argument, NULL, 7},
2093 {"schedule", required_argument, NULL, 8},
2094 {"temp-instance", required_argument, NULL, 9},
2095 {"no-locale", no_argument, NULL, 10},
2096 {"host", required_argument, NULL, 13},
2097 {"port", required_argument, NULL, 14},
2098 {"user", required_argument, NULL, 15},
2099 {"bindir", required_argument, NULL, 16},
2100 {"dlpath", required_argument, NULL, 17},
2101 {"create-role", required_argument, NULL, 18},
2102 {"temp-config", required_argument, NULL, 19},
2103 {"use-existing", no_argument, NULL, 20},
2104 {"launcher", required_argument, NULL, 21},
2105 {"load-extension", required_argument, NULL, 22},
2106 {"config-auth", required_argument, NULL, 24},
2107 {"max-concurrent-tests", required_argument, NULL, 25},
2108 {"expecteddir", required_argument, NULL, 26},
2109 {NULL, 0, NULL, 0}
2112 bool use_unix_sockets;
2113 _stringlist *sl;
2114 int c;
2115 int i;
2116 int option_index;
2117 char buf[MAXPGPATH * 4];
2119 pg_logging_init(argv[0]);
2120 progname = get_progname(argv[0]);
2121 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
2123 get_restricted_token();
2125 atexit(stop_postmaster);
2127 #if defined(WIN32)
2130 * We don't use Unix-domain sockets on Windows by default (see comment at
2131 * remove_temp() for a reason). Override at your own risk.
2133 use_unix_sockets = getenv("PG_TEST_USE_UNIX_SOCKETS") ? true : false;
2134 #else
2135 use_unix_sockets = true;
2136 #endif
2138 if (!use_unix_sockets)
2139 hostname = "localhost";
2142 * We call the initialization function here because that way we can set
2143 * default parameters and let them be overwritten by the commandline.
2145 ifunc(argc, argv);
2147 if (getenv("PG_REGRESS_DIFF_OPTS"))
2148 pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
2150 while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
2152 switch (c)
2154 case 'h':
2155 help();
2156 exit(0);
2157 case 'V':
2158 puts("pg_regress (PostgreSQL) " PG_VERSION);
2159 exit(0);
2160 case 1:
2163 * If a default database was specified, we need to remove it
2164 * before we add the specified one.
2166 free_stringlist(&dblist);
2167 split_to_stringlist(optarg, ",", &dblist);
2168 break;
2169 case 2:
2170 debug = true;
2171 break;
2172 case 3:
2173 inputdir = pg_strdup(optarg);
2174 break;
2175 case 5:
2176 max_connections = atoi(optarg);
2177 break;
2178 case 6:
2179 encoding = pg_strdup(optarg);
2180 break;
2181 case 7:
2182 outputdir = pg_strdup(optarg);
2183 break;
2184 case 8:
2185 add_stringlist_item(&schedulelist, optarg);
2186 break;
2187 case 9:
2188 temp_instance = make_absolute_path(optarg);
2189 break;
2190 case 10:
2191 nolocale = true;
2192 break;
2193 case 13:
2194 hostname = pg_strdup(optarg);
2195 break;
2196 case 14:
2197 port = atoi(optarg);
2198 port_specified_by_user = true;
2199 break;
2200 case 15:
2201 user = pg_strdup(optarg);
2202 break;
2203 case 16:
2204 /* "--bindir=" means to use PATH */
2205 if (strlen(optarg))
2206 bindir = pg_strdup(optarg);
2207 else
2208 bindir = NULL;
2209 break;
2210 case 17:
2211 dlpath = pg_strdup(optarg);
2212 break;
2213 case 18:
2214 split_to_stringlist(optarg, ",", &extraroles);
2215 break;
2216 case 19:
2217 add_stringlist_item(&temp_configs, optarg);
2218 break;
2219 case 20:
2220 use_existing = true;
2221 break;
2222 case 21:
2223 launcher = pg_strdup(optarg);
2224 break;
2225 case 22:
2226 add_stringlist_item(&loadextension, optarg);
2227 break;
2228 case 24:
2229 config_auth_datadir = pg_strdup(optarg);
2230 break;
2231 case 25:
2232 max_concurrent_tests = atoi(optarg);
2233 break;
2234 case 26:
2235 expecteddir = pg_strdup(optarg);
2236 break;
2237 default:
2238 /* getopt_long already emitted a complaint */
2239 pg_log_error_hint("Try \"%s --help\" for more information.",
2240 progname);
2241 exit(2);
2246 * if we still have arguments, they are extra tests to run
2248 while (argc - optind >= 1)
2250 add_stringlist_item(&extra_tests, argv[optind]);
2251 optind++;
2255 * We must have a database to run the tests in; either a default name, or
2256 * one supplied by the --dbname switch.
2258 if (!(dblist && dblist->str && dblist->str[0]))
2260 bail("no database name was specified");
2263 if (config_auth_datadir)
2265 #ifdef ENABLE_SSPI
2266 if (!use_unix_sockets)
2267 config_sspi_auth(config_auth_datadir, user);
2268 #endif
2269 exit(0);
2272 if (temp_instance && !port_specified_by_user)
2275 * To reduce chances of interference with parallel installations, use
2276 * a port number starting in the private range (49152-65535)
2277 * calculated from the version number. This aids non-Unix socket mode
2278 * systems; elsewhere, the use of a private socket directory already
2279 * prevents interference.
2281 port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
2283 inputdir = make_absolute_path(inputdir);
2284 outputdir = make_absolute_path(outputdir);
2285 expecteddir = make_absolute_path(expecteddir);
2286 dlpath = make_absolute_path(dlpath);
2289 * Initialization
2291 open_result_files();
2293 initialize_environment();
2295 #if defined(HAVE_GETRLIMIT)
2296 unlimit_core_size();
2297 #endif
2299 if (temp_instance)
2301 StringInfoData cmd;
2302 FILE *pg_conf;
2303 const char *env_wait;
2304 int wait_seconds;
2305 const char *initdb_template_dir;
2306 const char *keywords[4];
2307 const char *values[4];
2308 PGPing rv;
2311 * Prepare the temp instance
2314 if (directory_exists(temp_instance))
2316 if (!rmtree(temp_instance, true))
2318 bail("could not remove temp instance \"%s\"", temp_instance);
2322 /* make the temp instance top directory */
2323 make_directory(temp_instance);
2325 /* and a directory for log files */
2326 snprintf(buf, sizeof(buf), "%s/log", outputdir);
2327 if (!directory_exists(buf))
2328 make_directory(buf);
2330 initStringInfo(&cmd);
2333 * Create data directory.
2335 * If available, use a previously initdb'd cluster as a template by
2336 * copying it. For a lot of tests, that's substantially cheaper.
2338 * There's very similar code in Cluster.pm, but we can't easily de
2339 * duplicate it until we require perl at build time.
2341 initdb_template_dir = getenv("INITDB_TEMPLATE");
2342 if (initdb_template_dir == NULL || nolocale || debug)
2344 note("initializing database system by running initdb");
2346 appendStringInfo(&cmd,
2347 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync",
2348 bindir ? bindir : "",
2349 bindir ? "/" : "",
2350 temp_instance);
2351 if (debug)
2352 appendStringInfoString(&cmd, " --debug");
2353 if (nolocale)
2354 appendStringInfoString(&cmd, " --no-locale");
2355 appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
2356 fflush(NULL);
2357 if (system(cmd.data))
2359 bail("initdb failed\n"
2360 "# Examine \"%s/log/initdb.log\" for the reason.\n"
2361 "# Command was: %s",
2362 outputdir, cmd.data);
2365 else
2367 #ifndef WIN32
2368 const char *copycmd = "cp -RPp \"%s\" \"%s/data\"";
2369 int expected_exitcode = 0;
2370 #else
2371 const char *copycmd = "robocopy /E /NJS /NJH /NFL /NDL /NP \"%s\" \"%s/data\"";
2372 int expected_exitcode = 1; /* 1 denotes files were copied */
2373 #endif
2375 note("initializing database system by copying initdb template");
2377 appendStringInfo(&cmd,
2378 copycmd,
2379 initdb_template_dir,
2380 temp_instance);
2381 appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
2382 fflush(NULL);
2383 if (system(cmd.data) != expected_exitcode)
2385 bail("copying of initdb template failed\n"
2386 "# Examine \"%s/log/initdb.log\" for the reason.\n"
2387 "# Command was: %s",
2388 outputdir, cmd.data);
2392 pfree(cmd.data);
2395 * Adjust the default postgresql.conf for regression testing. The user
2396 * can specify a file to be appended; in any case we expand logging
2397 * and set max_prepared_transactions to enable testing of prepared
2398 * xacts. (Note: to reduce the probability of unexpected shmmax
2399 * failures, don't set max_prepared_transactions any higher than
2400 * actually needed by the prepared_xacts regression test.)
2402 snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
2403 pg_conf = fopen(buf, "a");
2404 if (pg_conf == NULL)
2406 bail("could not open \"%s\" for adding extra config: %s",
2407 buf, strerror(errno));
2409 fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
2410 fputs("log_autovacuum_min_duration = 0\n", pg_conf);
2411 fputs("log_checkpoints = on\n", pg_conf);
2412 fputs("log_line_prefix = '%m %b[%p] %q%a '\n", pg_conf);
2413 fputs("log_lock_waits = on\n", pg_conf);
2414 fputs("log_temp_files = 128kB\n", pg_conf);
2415 fputs("max_prepared_transactions = 2\n", pg_conf);
2417 for (sl = temp_configs; sl != NULL; sl = sl->next)
2419 char *temp_config = sl->str;
2420 FILE *extra_conf;
2421 char line_buf[1024];
2423 extra_conf = fopen(temp_config, "r");
2424 if (extra_conf == NULL)
2426 bail("could not open \"%s\" to read extra config: %s",
2427 temp_config, strerror(errno));
2429 while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
2430 fputs(line_buf, pg_conf);
2431 fclose(extra_conf);
2434 fclose(pg_conf);
2436 #ifdef ENABLE_SSPI
2437 if (!use_unix_sockets)
2440 * Since we successfully used the same buffer for the much-longer
2441 * "initdb" command, this can't truncate.
2443 snprintf(buf, sizeof(buf), "%s/data", temp_instance);
2444 config_sspi_auth(buf, NULL);
2446 #endif
2449 * Prepare the connection params for checking the state of the server
2450 * before starting the tests.
2452 sprintf(portstr, "%d", port);
2453 keywords[0] = "dbname";
2454 values[0] = "postgres";
2455 keywords[1] = "port";
2456 values[1] = portstr;
2457 keywords[2] = "host";
2458 values[2] = hostname ? hostname : sockdir;
2459 keywords[3] = NULL;
2460 values[3] = NULL;
2463 * Check if there is a postmaster running already.
2465 for (i = 0; i < 16; i++)
2467 rv = PQpingParams(keywords, values, 1);
2469 if (rv == PQPING_OK)
2471 if (port_specified_by_user || i == 15)
2473 note("port %d apparently in use", port);
2474 if (!port_specified_by_user)
2475 note("could not determine an available port");
2476 bail("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.");
2479 note("port %d apparently in use, trying %d", port, port + 1);
2480 port++;
2481 sprintf(portstr, "%d", port);
2482 setenv("PGPORT", portstr, 1);
2484 else
2485 break;
2489 * Start the temp postmaster
2491 snprintf(buf, sizeof(buf),
2492 "\"%s%spostgres\" -D \"%s/data\" -F%s "
2493 "-c \"listen_addresses=%s\" -k \"%s\" "
2494 "> \"%s/log/postmaster.log\" 2>&1",
2495 bindir ? bindir : "",
2496 bindir ? "/" : "",
2497 temp_instance, debug ? " -d 5" : "",
2498 hostname ? hostname : "", sockdir ? sockdir : "",
2499 outputdir);
2500 postmaster_pid = spawn_process(buf);
2501 if (postmaster_pid == INVALID_PID)
2502 bail("could not spawn postmaster: %s", strerror(errno));
2505 * Wait till postmaster is able to accept connections; normally takes
2506 * only a fraction of a second or so, but Cygwin is reportedly *much*
2507 * slower, and test builds using Valgrind or similar tools might be
2508 * too. Hence, allow the default timeout of 60 seconds to be
2509 * overridden from the PGCTLTIMEOUT environment variable.
2511 env_wait = getenv("PGCTLTIMEOUT");
2512 if (env_wait != NULL)
2514 wait_seconds = atoi(env_wait);
2515 if (wait_seconds <= 0)
2516 wait_seconds = 60;
2518 else
2519 wait_seconds = 60;
2521 for (i = 0; i < wait_seconds * WAIT_TICKS_PER_SECOND; i++)
2524 * It's fairly unlikely that the server is responding immediately
2525 * so we start with sleeping before checking instead of the other
2526 * way around.
2528 pg_usleep(1000000L / WAIT_TICKS_PER_SECOND);
2530 rv = PQpingParams(keywords, values, 1);
2532 /* Done if the server is running and accepts connections */
2533 if (rv == PQPING_OK)
2534 break;
2536 if (rv == PQPING_NO_ATTEMPT)
2537 bail("attempting to connect to postmaster failed");
2540 * Fail immediately if postmaster has exited
2542 #ifndef WIN32
2543 if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
2544 #else
2545 if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
2546 #endif
2548 bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason",
2549 outputdir);
2552 if (i >= wait_seconds * WAIT_TICKS_PER_SECOND)
2554 diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason",
2555 wait_seconds, outputdir);
2558 * If we get here, the postmaster is probably wedged somewhere in
2559 * startup. Try to kill it ungracefully rather than leaving a
2560 * stuck postmaster that might interfere with subsequent test
2561 * attempts.
2563 #ifndef WIN32
2564 if (kill(postmaster_pid, SIGKILL) != 0 && errno != ESRCH)
2565 bail("could not kill failed postmaster: %s", strerror(errno));
2566 #else
2567 if (TerminateProcess(postmaster_pid, 255) == 0)
2568 bail("could not kill failed postmaster: error code %lu",
2569 GetLastError());
2570 #endif
2571 bail("postmaster failed");
2574 postmaster_running = true;
2576 #ifdef _WIN64
2577 /* need a series of two casts to convert HANDLE without compiler warning */
2578 #define ULONGPID(x) (unsigned long) (unsigned long long) (x)
2579 #else
2580 #define ULONGPID(x) (unsigned long) (x)
2581 #endif
2582 note("using temp instance on port %d with PID %lu",
2583 port, ULONGPID(postmaster_pid));
2585 else
2588 * Using an existing installation, so may need to get rid of
2589 * pre-existing database(s) and role(s)
2591 if (!use_existing)
2593 for (sl = dblist; sl; sl = sl->next)
2594 drop_database_if_exists(sl->str);
2595 for (sl = extraroles; sl; sl = sl->next)
2596 drop_role_if_exists(sl->str);
2601 * Create the test database(s) and role(s)
2603 if (!use_existing)
2605 for (sl = dblist; sl; sl = sl->next)
2606 create_database(sl->str);
2607 for (sl = extraroles; sl; sl = sl->next)
2608 create_role(sl->str, dblist);
2612 * Ready to run the tests
2614 for (sl = schedulelist; sl != NULL; sl = sl->next)
2616 run_schedule(sl->str, startfunc, postfunc);
2619 for (sl = extra_tests; sl != NULL; sl = sl->next)
2621 run_single_test(sl->str, startfunc, postfunc);
2625 * Shut down temp installation's postmaster
2627 if (temp_instance)
2629 stop_postmaster();
2633 * If there were no errors, remove the temp instance immediately to
2634 * conserve disk space. (If there were errors, we leave the instance in
2635 * place for possible manual investigation.)
2637 if (temp_instance && fail_count == 0)
2639 if (!rmtree(temp_instance, true))
2640 diag("could not remove temp instance \"%s\"",
2641 temp_instance);
2645 * Emit a TAP compliant Plan
2647 plan(fail_count + success_count);
2650 * Emit nice-looking summary message
2652 if (fail_count == 0)
2653 note("All %d tests passed.", success_count);
2654 else
2655 diag("%d of %d tests failed.", fail_count, success_count + fail_count);
2657 if (file_size(difffilename) > 0)
2659 diag("The differences that caused some tests to fail can be viewed in the file \"%s\".",
2660 difffilename);
2661 diag("A copy of the test summary that you see above is saved in the file \"%s\".",
2662 logfilename);
2664 else
2666 unlink(difffilename);
2667 unlink(logfilename);
2670 fclose(logfile);
2671 logfile = NULL;
2673 if (fail_count != 0)
2674 exit(1);
2676 return 0;