]> granicus.if.org Git - postgresql/blob - src/test/regress/pg_regress.c
Align timestamps in pg_regress output
[postgresql] / src / test / regress / pg_regress.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_regress --- regression test driver
4  *
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
8  *
9  * This code is released under the terms of the PostgreSQL License.
10  *
11  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
12  * Portions Copyright (c) 1994, Regents of the University of California
13  *
14  * src/test/regress/pg_regress.c
15  *
16  *-------------------------------------------------------------------------
17  */
18
19 #include "postgres_fe.h"
20
21 #include <ctype.h>
22 #include <sys/stat.h>
23 #include <sys/wait.h>
24 #include <signal.h>
25 #include <unistd.h>
26
27 #ifdef HAVE_SYS_RESOURCE_H
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #endif
31
32 #include "pg_regress.h"
33
34 #include "common/restricted_token.h"
35 #include "common/username.h"
36 #include "getopt_long.h"
37 #include "libpq/pqcomm.h"               /* needed for UNIXSOCK_PATH() */
38 #include "pg_config_paths.h"
39 #include "portability/instr_time.h"
40
41 /* for resultmap we need a list of pairs of strings */
42 typedef struct _resultmap
43 {
44         char       *test;
45         char       *type;
46         char       *resultfile;
47         struct _resultmap *next;
48 } _resultmap;
49
50 /*
51  * Values obtained from Makefile.
52  */
53 char       *host_platform = HOST_TUPLE;
54
55 #ifndef WIN32                                   /* not used in WIN32 case */
56 static char *shellprog = SHELLPROG;
57 #endif
58
59 /*
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.
63  */
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
71
72 /* options settable from command line */
73 _stringlist *dblist = NULL;
74 bool            debug = false;
75 char       *inputdir = ".";
76 char       *outputdir = ".";
77 char       *bindir = PGBINDIR;
78 char       *launcher = NULL;
79 static _stringlist *loadlanguage = NULL;
80 static _stringlist *loadextension = NULL;
81 static int      max_connections = 0;
82 static int      max_concurrent_tests = 0;
83 static char *encoding = NULL;
84 static _stringlist *schedulelist = NULL;
85 static _stringlist *extra_tests = NULL;
86 static char *temp_instance = NULL;
87 static _stringlist *temp_configs = NULL;
88 static bool nolocale = false;
89 static bool use_existing = false;
90 static char *hostname = NULL;
91 static int      port = -1;
92 static bool port_specified_by_user = false;
93 static char *dlpath = PKGLIBDIR;
94 static char *user = NULL;
95 static _stringlist *extraroles = NULL;
96 static char *config_auth_datadir = NULL;
97
98 /* internal variables */
99 static const char *progname;
100 static char *logfilename;
101 static FILE *logfile;
102 static char *difffilename;
103 static const char *sockdir;
104 #ifdef HAVE_UNIX_SOCKETS
105 static const char *temp_sockdir;
106 static char sockself[MAXPGPATH];
107 static char socklock[MAXPGPATH];
108 #endif
109
110 static _resultmap *resultmap = NULL;
111
112 static PID_TYPE postmaster_pid = INVALID_PID;
113 static bool postmaster_running = false;
114
115 static int      success_count = 0;
116 static int      fail_count = 0;
117 static int      fail_ignore_count = 0;
118
119 static bool directory_exists(const char *dir);
120 static void make_directory(const char *dir);
121
122 static void header(const char *fmt,...) pg_attribute_printf(1, 2);
123 static void status(const char *fmt,...) pg_attribute_printf(1, 2);
124 static void psql_command(const char *database, const char *query,...) pg_attribute_printf(2, 3);
125
126 /*
127  * allow core files if possible.
128  */
129 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
130 static void
131 unlimit_core_size(void)
132 {
133         struct rlimit lim;
134
135         getrlimit(RLIMIT_CORE, &lim);
136         if (lim.rlim_max == 0)
137         {
138                 fprintf(stderr,
139                                 _("%s: could not set core size: disallowed by hard limit\n"),
140                                 progname);
141                 return;
142         }
143         else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
144         {
145                 lim.rlim_cur = lim.rlim_max;
146                 setrlimit(RLIMIT_CORE, &lim);
147         }
148 }
149 #endif
150
151
152 /*
153  * Add an item at the end of a stringlist.
154  */
155 void
156 add_stringlist_item(_stringlist **listhead, const char *str)
157 {
158         _stringlist *newentry = pg_malloc(sizeof(_stringlist));
159         _stringlist *oldentry;
160
161         newentry->str = pg_strdup(str);
162         newentry->next = NULL;
163         if (*listhead == NULL)
164                 *listhead = newentry;
165         else
166         {
167                 for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
168                          /* skip */ ;
169                 oldentry->next = newentry;
170         }
171 }
172
173 /*
174  * Free a stringlist.
175  */
176 static void
177 free_stringlist(_stringlist **listhead)
178 {
179         if (listhead == NULL || *listhead == NULL)
180                 return;
181         if ((*listhead)->next != NULL)
182                 free_stringlist(&((*listhead)->next));
183         free((*listhead)->str);
184         free(*listhead);
185         *listhead = NULL;
186 }
187
188 /*
189  * Split a delimited string into a stringlist
190  */
191 static void
192 split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
193 {
194         char       *sc = pg_strdup(s);
195         char       *token = strtok(sc, delim);
196
197         while (token)
198         {
199                 add_stringlist_item(listhead, token);
200                 token = strtok(NULL, delim);
201         }
202         free(sc);
203 }
204
205 /*
206  * Print a progress banner on stdout.
207  */
208 static void
209 header(const char *fmt,...)
210 {
211         char            tmp[64];
212         va_list         ap;
213
214         va_start(ap, fmt);
215         vsnprintf(tmp, sizeof(tmp), fmt, ap);
216         va_end(ap);
217
218         fprintf(stdout, "============== %-38s ==============\n", tmp);
219         fflush(stdout);
220 }
221
222 /*
223  * Print "doing something ..." --- supplied text should not end with newline
224  */
225 static void
226 status(const char *fmt,...)
227 {
228         va_list         ap;
229
230         va_start(ap, fmt);
231         vfprintf(stdout, fmt, ap);
232         fflush(stdout);
233         va_end(ap);
234
235         if (logfile)
236         {
237                 va_start(ap, fmt);
238                 vfprintf(logfile, fmt, ap);
239                 va_end(ap);
240         }
241 }
242
243 /*
244  * Done "doing something ..."
245  */
246 static void
247 status_end(void)
248 {
249         fprintf(stdout, "\n");
250         fflush(stdout);
251         if (logfile)
252                 fprintf(logfile, "\n");
253 }
254
255 /*
256  * shut down temp postmaster
257  */
258 static void
259 stop_postmaster(void)
260 {
261         if (postmaster_running)
262         {
263                 /* We use pg_ctl to issue the kill and wait for stop */
264                 char            buf[MAXPGPATH * 2];
265                 int                     r;
266
267                 /* On Windows, system() seems not to force fflush, so... */
268                 fflush(stdout);
269                 fflush(stderr);
270
271                 snprintf(buf, sizeof(buf),
272                                  "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
273                                  bindir ? bindir : "",
274                                  bindir ? "/" : "",
275                                  temp_instance);
276                 r = system(buf);
277                 if (r != 0)
278                 {
279                         fprintf(stderr, _("\n%s: could not stop postmaster: exit code was %d\n"),
280                                         progname, r);
281                         _exit(2);                       /* not exit(), that could be recursive */
282                 }
283
284                 postmaster_running = false;
285         }
286 }
287
288 #ifdef HAVE_UNIX_SOCKETS
289 /*
290  * Remove the socket temporary directory.  pg_regress never waits for a
291  * postmaster exit, so it is indeterminate whether the postmaster has yet to
292  * unlink the socket and lock file.  Unlink them here so we can proceed to
293  * remove the directory.  Ignore errors; leaking a temporary directory is
294  * unimportant.  This can run from a signal handler.  The code is not
295  * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
296  * Windows is not a HAVE_UNIX_SOCKETS platform.
297  */
298 static void
299 remove_temp(void)
300 {
301         Assert(temp_sockdir);
302         unlink(sockself);
303         unlink(socklock);
304         rmdir(temp_sockdir);
305 }
306
307 /*
308  * Signal handler that calls remove_temp() and reraises the signal.
309  */
310 static void
311 signal_remove_temp(int signum)
312 {
313         remove_temp();
314
315         pqsignal(signum, SIG_DFL);
316         raise(signum);
317 }
318
319 /*
320  * Create a temporary directory suitable for the server's Unix-domain socket.
321  * The directory will have mode 0700 or stricter, so no other OS user can open
322  * our socket to exploit our use of trust authentication.  Most systems
323  * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
324  * place the directory under /tmp rather than relative to the possibly-deep
325  * current working directory.
326  *
327  * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
328  * testing to work in builds that relocate it to a directory not writable to
329  * the build/test user.
330  */
331 static const char *
332 make_temp_sockdir(void)
333 {
334         char       *template = pg_strdup("/tmp/pg_regress-XXXXXX");
335
336         temp_sockdir = mkdtemp(template);
337         if (temp_sockdir == NULL)
338         {
339                 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
340                                 progname, template, strerror(errno));
341                 exit(2);
342         }
343
344         /* Stage file names for remove_temp().  Unsafe in a signal handler. */
345         UNIXSOCK_PATH(sockself, port, temp_sockdir);
346         snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
347
348         /* Remove the directory during clean exit. */
349         atexit(remove_temp);
350
351         /*
352          * Remove the directory before dying to the usual signals.  Omit SIGQUIT,
353          * preserving it as a quick, untidy exit.
354          */
355         pqsignal(SIGHUP, signal_remove_temp);
356         pqsignal(SIGINT, signal_remove_temp);
357         pqsignal(SIGPIPE, signal_remove_temp);
358         pqsignal(SIGTERM, signal_remove_temp);
359
360         return temp_sockdir;
361 }
362 #endif                                                  /* HAVE_UNIX_SOCKETS */
363
364 /*
365  * Check whether string matches pattern
366  *
367  * In the original shell script, this function was implemented using expr(1),
368  * which provides basic regular expressions restricted to match starting at
369  * the string start (in conventional regex terms, there's an implicit "^"
370  * at the start of the pattern --- but no implicit "$" at the end).
371  *
372  * For now, we only support "." and ".*" as non-literal metacharacters,
373  * because that's all that anyone has found use for in resultmap.  This
374  * code could be extended if more functionality is needed.
375  */
376 static bool
377 string_matches_pattern(const char *str, const char *pattern)
378 {
379         while (*str && *pattern)
380         {
381                 if (*pattern == '.' && pattern[1] == '*')
382                 {
383                         pattern += 2;
384                         /* Trailing .* matches everything. */
385                         if (*pattern == '\0')
386                                 return true;
387
388                         /*
389                          * Otherwise, scan for a text position at which we can match the
390                          * rest of the pattern.
391                          */
392                         while (*str)
393                         {
394                                 /*
395                                  * Optimization to prevent most recursion: don't recurse
396                                  * unless first pattern char might match this text char.
397                                  */
398                                 if (*str == *pattern || *pattern == '.')
399                                 {
400                                         if (string_matches_pattern(str, pattern))
401                                                 return true;
402                                 }
403
404                                 str++;
405                         }
406
407                         /*
408                          * End of text with no match.
409                          */
410                         return false;
411                 }
412                 else if (*pattern != '.' && *str != *pattern)
413                 {
414                         /*
415                          * Not the single-character wildcard and no explicit match? Then
416                          * time to quit...
417                          */
418                         return false;
419                 }
420
421                 str++;
422                 pattern++;
423         }
424
425         if (*pattern == '\0')
426                 return true;                    /* end of pattern, so declare match */
427
428         /* End of input string.  Do we have matching pattern remaining? */
429         while (*pattern == '.' && pattern[1] == '*')
430                 pattern += 2;
431         if (*pattern == '\0')
432                 return true;                    /* end of pattern, so declare match */
433
434         return false;
435 }
436
437 /*
438  * Replace all occurrences of a string in a string with a different string.
439  * NOTE: Assumes there is enough room in the target buffer!
440  */
441 void
442 replace_string(char *string, const char *replace, const char *replacement)
443 {
444         char       *ptr;
445
446         while ((ptr = strstr(string, replace)) != NULL)
447         {
448                 char       *dup = pg_strdup(string);
449
450                 strlcpy(string, dup, ptr - string + 1);
451                 strcat(string, replacement);
452                 strcat(string, dup + (ptr - string) + strlen(replace));
453                 free(dup);
454         }
455 }
456
457 /*
458  * Convert *.source found in the "source" directory, replacing certain tokens
459  * in the file contents with their intended values, and put the resulting files
460  * in the "dest" directory, replacing the ".source" prefix in their names with
461  * the given suffix.
462  */
463 static void
464 convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const char *dest_subdir, const char *suffix)
465 {
466         char            testtablespace[MAXPGPATH];
467         char            indir[MAXPGPATH];
468         struct stat st;
469         int                     ret;
470         char      **name;
471         char      **names;
472         int                     count = 0;
473
474         snprintf(indir, MAXPGPATH, "%s/%s", inputdir, source_subdir);
475
476         /* Check that indir actually exists and is a directory */
477         ret = stat(indir, &st);
478         if (ret != 0 || !S_ISDIR(st.st_mode))
479         {
480                 /*
481                  * No warning, to avoid noise in tests that do not have these
482                  * directories; for example, ecpg, contrib and src/pl.
483                  */
484                 return;
485         }
486
487         names = pgfnames(indir);
488         if (!names)
489                 /* Error logged in pgfnames */
490                 exit(2);
491
492         snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
493
494 #ifdef WIN32
495
496         /*
497          * On Windows only, clean out the test tablespace dir, or create it if it
498          * doesn't exist.  On other platforms we expect the Makefile to take care
499          * of that.  (We don't migrate that functionality in here because it'd be
500          * harder to cope with platform-specific issues such as SELinux.)
501          *
502          * XXX it would be better if pg_regress.c had nothing at all to do with
503          * testtablespace, and this were handled by a .BAT file or similar on
504          * Windows.  See pgsql-hackers discussion of 2008-01-18.
505          */
506         if (directory_exists(testtablespace))
507                 if (!rmtree(testtablespace, true))
508                 {
509                         fprintf(stderr, _("\n%s: could not remove test tablespace \"%s\"\n"),
510                                         progname, testtablespace);
511                         exit(2);
512                 }
513         make_directory(testtablespace);
514 #endif
515
516         /* finally loop on each file and do the replacement */
517         for (name = names; *name; name++)
518         {
519                 char            srcfile[MAXPGPATH];
520                 char            destfile[MAXPGPATH];
521                 char            prefix[MAXPGPATH];
522                 FILE       *infile,
523                                    *outfile;
524                 char            line[1024];
525
526                 /* reject filenames not finishing in ".source" */
527                 if (strlen(*name) < 8)
528                         continue;
529                 if (strcmp(*name + strlen(*name) - 7, ".source") != 0)
530                         continue;
531
532                 count++;
533
534                 /* build the full actual paths to open */
535                 snprintf(prefix, strlen(*name) - 6, "%s", *name);
536                 snprintf(srcfile, MAXPGPATH, "%s/%s", indir, *name);
537                 snprintf(destfile, MAXPGPATH, "%s/%s/%s.%s", dest_dir, dest_subdir,
538                                  prefix, suffix);
539
540                 infile = fopen(srcfile, "r");
541                 if (!infile)
542                 {
543                         fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
544                                         progname, srcfile, strerror(errno));
545                         exit(2);
546                 }
547                 outfile = fopen(destfile, "w");
548                 if (!outfile)
549                 {
550                         fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
551                                         progname, destfile, strerror(errno));
552                         exit(2);
553                 }
554                 while (fgets(line, sizeof(line), infile))
555                 {
556                         replace_string(line, "@abs_srcdir@", inputdir);
557                         replace_string(line, "@abs_builddir@", outputdir);
558                         replace_string(line, "@testtablespace@", testtablespace);
559                         replace_string(line, "@libdir@", dlpath);
560                         replace_string(line, "@DLSUFFIX@", DLSUFFIX);
561                         fputs(line, outfile);
562                 }
563                 fclose(infile);
564                 fclose(outfile);
565         }
566
567         /*
568          * If we didn't process any files, complain because it probably means
569          * somebody neglected to pass the needed --inputdir argument.
570          */
571         if (count <= 0)
572         {
573                 fprintf(stderr, _("%s: no *.source files found in \"%s\"\n"),
574                                 progname, indir);
575                 exit(2);
576         }
577
578         pgfnames_cleanup(names);
579 }
580
581 /* Create the .sql and .out files from the .source files, if any */
582 static void
583 convert_sourcefiles(void)
584 {
585         convert_sourcefiles_in("input", outputdir, "sql", "sql");
586         convert_sourcefiles_in("output", outputdir, "expected", "out");
587 }
588
589 /*
590  * Scan resultmap file to find which platform-specific expected files to use.
591  *
592  * The format of each line of the file is
593  *                 testname/hostplatformpattern=substitutefile
594  * where the hostplatformpattern is evaluated per the rules of expr(1),
595  * namely, it is a standard regular expression with an implicit ^ at the start.
596  * (We currently support only a very limited subset of regular expressions,
597  * see string_matches_pattern() above.)  What hostplatformpattern will be
598  * matched against is the config.guess output.  (In the shell-script version,
599  * we also provided an indication of whether gcc or another compiler was in
600  * use, but that facility isn't used anymore.)
601  */
602 static void
603 load_resultmap(void)
604 {
605         char            buf[MAXPGPATH];
606         FILE       *f;
607
608         /* scan the file ... */
609         snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
610         f = fopen(buf, "r");
611         if (!f)
612         {
613                 /* OK if it doesn't exist, else complain */
614                 if (errno == ENOENT)
615                         return;
616                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
617                                 progname, buf, strerror(errno));
618                 exit(2);
619         }
620
621         while (fgets(buf, sizeof(buf), f))
622         {
623                 char       *platform;
624                 char       *file_type;
625                 char       *expected;
626                 int                     i;
627
628                 /* strip trailing whitespace, especially the newline */
629                 i = strlen(buf);
630                 while (i > 0 && isspace((unsigned char) buf[i - 1]))
631                         buf[--i] = '\0';
632
633                 /* parse out the line fields */
634                 file_type = strchr(buf, ':');
635                 if (!file_type)
636                 {
637                         fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
638                                         buf);
639                         exit(2);
640                 }
641                 *file_type++ = '\0';
642
643                 platform = strchr(file_type, ':');
644                 if (!platform)
645                 {
646                         fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
647                                         buf);
648                         exit(2);
649                 }
650                 *platform++ = '\0';
651                 expected = strchr(platform, '=');
652                 if (!expected)
653                 {
654                         fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
655                                         buf);
656                         exit(2);
657                 }
658                 *expected++ = '\0';
659
660                 /*
661                  * if it's for current platform, save it in resultmap list. Note: by
662                  * adding at the front of the list, we ensure that in ambiguous cases,
663                  * the last match in the resultmap file is used. This mimics the
664                  * behavior of the old shell script.
665                  */
666                 if (string_matches_pattern(host_platform, platform))
667                 {
668                         _resultmap *entry = pg_malloc(sizeof(_resultmap));
669
670                         entry->test = pg_strdup(buf);
671                         entry->type = pg_strdup(file_type);
672                         entry->resultfile = pg_strdup(expected);
673                         entry->next = resultmap;
674                         resultmap = entry;
675                 }
676         }
677         fclose(f);
678 }
679
680 /*
681  * Check in resultmap if we should be looking at a different file
682  */
683 static
684 const char *
685 get_expectfile(const char *testname, const char *file)
686 {
687         char       *file_type;
688         _resultmap *rm;
689
690         /*
691          * Determine the file type from the file name. This is just what is
692          * following the last dot in the file name.
693          */
694         if (!file || !(file_type = strrchr(file, '.')))
695                 return NULL;
696
697         file_type++;
698
699         for (rm = resultmap; rm != NULL; rm = rm->next)
700         {
701                 if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
702                 {
703                         return rm->resultfile;
704                 }
705         }
706
707         return NULL;
708 }
709
710 /*
711  * Handy subroutine for setting an environment variable "var" to "val"
712  */
713 static void
714 doputenv(const char *var, const char *val)
715 {
716         char       *s;
717
718         s = psprintf("%s=%s", var, val);
719         putenv(s);
720 }
721
722 /*
723  * Prepare environment variables for running regression tests
724  */
725 static void
726 initialize_environment(void)
727 {
728         putenv("PGAPPNAME=pg_regress");
729
730         if (nolocale)
731         {
732                 /*
733                  * Clear out any non-C locale settings
734                  */
735                 unsetenv("LC_COLLATE");
736                 unsetenv("LC_CTYPE");
737                 unsetenv("LC_MONETARY");
738                 unsetenv("LC_NUMERIC");
739                 unsetenv("LC_TIME");
740                 unsetenv("LANG");
741
742                 /*
743                  * Most platforms have adopted the POSIX locale as their
744                  * implementation-defined default locale.  Exceptions include native
745                  * Windows, macOS with --enable-nls, and Cygwin with --enable-nls.
746                  * (Use of --enable-nls matters because libintl replaces setlocale().)
747                  * Also, PostgreSQL does not support macOS with locale environment
748                  * variables unset; see PostmasterMain().
749                  */
750 #if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
751                 putenv("LANG=C");
752 #endif
753         }
754
755         /*
756          * Set translation-related settings to English; otherwise psql will
757          * produce translated messages and produce diffs.  (XXX If we ever support
758          * translation of pg_regress, this needs to be moved elsewhere, where psql
759          * is actually called.)
760          */
761         unsetenv("LANGUAGE");
762         unsetenv("LC_ALL");
763         putenv("LC_MESSAGES=C");
764
765         /*
766          * Set encoding as requested
767          */
768         if (encoding)
769                 doputenv("PGCLIENTENCODING", encoding);
770         else
771                 unsetenv("PGCLIENTENCODING");
772
773         /*
774          * Set timezone and datestyle for datetime-related tests
775          */
776         putenv("PGTZ=PST8PDT");
777         putenv("PGDATESTYLE=Postgres, MDY");
778
779         /*
780          * Likewise set intervalstyle to ensure consistent results.  This is a bit
781          * more painful because we must use PGOPTIONS, and we want to preserve the
782          * user's ability to set other variables through that.
783          */
784         {
785                 const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
786                 const char *old_pgoptions = getenv("PGOPTIONS");
787                 char       *new_pgoptions;
788
789                 if (!old_pgoptions)
790                         old_pgoptions = "";
791                 new_pgoptions = psprintf("PGOPTIONS=%s %s",
792                                                                  old_pgoptions, my_pgoptions);
793                 putenv(new_pgoptions);
794         }
795
796         if (temp_instance)
797         {
798                 /*
799                  * Clear out any environment vars that might cause psql to connect to
800                  * the wrong postmaster, or otherwise behave in nondefault ways. (Note
801                  * we also use psql's -X switch consistently, so that ~/.psqlrc files
802                  * won't mess things up.)  Also, set PGPORT to the temp port, and set
803                  * PGHOST depending on whether we are using TCP or Unix sockets.
804                  */
805                 unsetenv("PGDATABASE");
806                 unsetenv("PGUSER");
807                 unsetenv("PGSERVICE");
808                 unsetenv("PGSSLMODE");
809                 unsetenv("PGREQUIRESSL");
810                 unsetenv("PGCONNECT_TIMEOUT");
811                 unsetenv("PGDATA");
812 #ifdef HAVE_UNIX_SOCKETS
813                 if (hostname != NULL)
814                         doputenv("PGHOST", hostname);
815                 else
816                 {
817                         sockdir = getenv("PG_REGRESS_SOCK_DIR");
818                         if (!sockdir)
819                                 sockdir = make_temp_sockdir();
820                         doputenv("PGHOST", sockdir);
821                 }
822 #else
823                 Assert(hostname != NULL);
824                 doputenv("PGHOST", hostname);
825 #endif
826                 unsetenv("PGHOSTADDR");
827                 if (port != -1)
828                 {
829                         char            s[16];
830
831                         sprintf(s, "%d", port);
832                         doputenv("PGPORT", s);
833                 }
834         }
835         else
836         {
837                 const char *pghost;
838                 const char *pgport;
839
840                 /*
841                  * When testing an existing install, we honor existing environment
842                  * variables, except if they're overridden by command line options.
843                  */
844                 if (hostname != NULL)
845                 {
846                         doputenv("PGHOST", hostname);
847                         unsetenv("PGHOSTADDR");
848                 }
849                 if (port != -1)
850                 {
851                         char            s[16];
852
853                         sprintf(s, "%d", port);
854                         doputenv("PGPORT", s);
855                 }
856                 if (user != NULL)
857                         doputenv("PGUSER", user);
858
859                 /*
860                  * Report what we're connecting to
861                  */
862                 pghost = getenv("PGHOST");
863                 pgport = getenv("PGPORT");
864 #ifndef HAVE_UNIX_SOCKETS
865                 if (!pghost)
866                         pghost = "localhost";
867 #endif
868
869                 if (pghost && pgport)
870                         printf(_("(using postmaster on %s, port %s)\n"), pghost, pgport);
871                 if (pghost && !pgport)
872                         printf(_("(using postmaster on %s, default port)\n"), pghost);
873                 if (!pghost && pgport)
874                         printf(_("(using postmaster on Unix socket, port %s)\n"), pgport);
875                 if (!pghost && !pgport)
876                         printf(_("(using postmaster on Unix socket, default port)\n"));
877         }
878
879         convert_sourcefiles();
880         load_resultmap();
881 }
882
883 pg_attribute_unused()
884 static const char *
885 fmtHba(const char *raw)
886 {
887         static char *ret;
888         const char *rp;
889         char       *wp;
890
891         wp = ret = realloc(ret, 3 + strlen(raw) * 2);
892
893         *wp++ = '"';
894         for (rp = raw; *rp; rp++)
895         {
896                 if (*rp == '"')
897                         *wp++ = '"';
898                 *wp++ = *rp;
899         }
900         *wp++ = '"';
901         *wp++ = '\0';
902
903         return ret;
904 }
905
906 #ifdef ENABLE_SSPI
907 /*
908  * Get account and domain/realm names for the current user.  This is based on
909  * pg_SSPI_recvauth().  The returned strings use static storage.
910  */
911 static void
912 current_windows_user(const char **acct, const char **dom)
913 {
914         static char accountname[MAXPGPATH];
915         static char domainname[MAXPGPATH];
916         HANDLE          token;
917         TOKEN_USER *tokenuser;
918         DWORD           retlen;
919         DWORD           accountnamesize = sizeof(accountname);
920         DWORD           domainnamesize = sizeof(domainname);
921         SID_NAME_USE accountnameuse;
922
923         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token))
924         {
925                 fprintf(stderr,
926                                 _("%s: could not open process token: error code %lu\n"),
927                                 progname, GetLastError());
928                 exit(2);
929         }
930
931         if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
932         {
933                 fprintf(stderr,
934                                 _("%s: could not get token information buffer size: error code %lu\n"),
935                                 progname, GetLastError());
936                 exit(2);
937         }
938         tokenuser = pg_malloc(retlen);
939         if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
940         {
941                 fprintf(stderr,
942                                 _("%s: could not get token information: error code %lu\n"),
943                                 progname, GetLastError());
944                 exit(2);
945         }
946
947         if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
948                                                   domainname, &domainnamesize, &accountnameuse))
949         {
950                 fprintf(stderr,
951                                 _("%s: could not look up account SID: error code %lu\n"),
952                                 progname, GetLastError());
953                 exit(2);
954         }
955
956         free(tokenuser);
957
958         *acct = accountname;
959         *dom = domainname;
960 }
961
962 /*
963  * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication.  Permit
964  * the current OS user to authenticate as the bootstrap superuser and as any
965  * user named in a --create-role option.
966  */
967 static void
968 config_sspi_auth(const char *pgdata)
969 {
970         const char *accountname,
971                            *domainname;
972         const char *username;
973         char       *errstr;
974         bool            have_ipv6;
975         char            fname[MAXPGPATH];
976         int                     res;
977         FILE       *hba,
978                            *ident;
979         _stringlist *sl;
980
981         /*
982          * "username", the initdb-chosen bootstrap superuser name, may always
983          * match "accountname", the value SSPI authentication discovers.  The
984          * underlying system functions do not clearly guarantee that.
985          */
986         current_windows_user(&accountname, &domainname);
987         username = get_user_name(&errstr);
988         if (username == NULL)
989         {
990                 fprintf(stderr, "%s: %s\n", progname, errstr);
991                 exit(2);
992         }
993
994         /*
995          * Like initdb.c:setup_config(), determine whether the platform recognizes
996          * ::1 (IPv6 loopback) as a numeric host address string.
997          */
998         {
999                 struct addrinfo *gai_result;
1000                 struct addrinfo hints;
1001                 WSADATA         wsaData;
1002
1003                 hints.ai_flags = AI_NUMERICHOST;
1004                 hints.ai_family = AF_UNSPEC;
1005                 hints.ai_socktype = 0;
1006                 hints.ai_protocol = 0;
1007                 hints.ai_addrlen = 0;
1008                 hints.ai_canonname = NULL;
1009                 hints.ai_addr = NULL;
1010                 hints.ai_next = NULL;
1011
1012                 have_ipv6 = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0 &&
1013                                          getaddrinfo("::1", NULL, &hints, &gai_result) == 0);
1014         }
1015
1016         /* Check a Write outcome and report any error. */
1017 #define CW(cond)        \
1018         do { \
1019                 if (!(cond)) \
1020                 { \
1021                         fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
1022                                         progname, fname, strerror(errno)); \
1023                         exit(2); \
1024                 } \
1025         } while (0)
1026
1027         res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
1028         if (res < 0 || res >= sizeof(fname))
1029         {
1030                 /*
1031                  * Truncating this name is a fatal error, because we must not fail to
1032                  * overwrite an original trust-authentication pg_hba.conf.
1033                  */
1034                 fprintf(stderr, _("%s: directory name too long\n"), progname);
1035                 exit(2);
1036         }
1037         hba = fopen(fname, "w");
1038         if (hba == NULL)
1039         {
1040                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1041                                 progname, fname, strerror(errno));
1042                 exit(2);
1043         }
1044         CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
1045         CW(fputs("host all all 127.0.0.1/32  sspi include_realm=1 map=regress\n",
1046                          hba) >= 0);
1047         if (have_ipv6)
1048                 CW(fputs("host all all ::1/128  sspi include_realm=1 map=regress\n",
1049                                  hba) >= 0);
1050         CW(fclose(hba) == 0);
1051
1052         snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
1053         ident = fopen(fname, "w");
1054         if (ident == NULL)
1055         {
1056                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1057                                 progname, fname, strerror(errno));
1058                 exit(2);
1059         }
1060         CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
1061
1062         /*
1063          * Double-quote for the benefit of account names containing whitespace or
1064          * '#'.  Windows forbids the double-quote character itself, so don't
1065          * bother escaping embedded double-quote characters.
1066          */
1067         CW(fprintf(ident, "regress  \"%s@%s\"  %s\n",
1068                            accountname, domainname, fmtHba(username)) >= 0);
1069         for (sl = extraroles; sl; sl = sl->next)
1070                 CW(fprintf(ident, "regress  \"%s@%s\"  %s\n",
1071                                    accountname, domainname, fmtHba(sl->str)) >= 0);
1072         CW(fclose(ident) == 0);
1073 }
1074 #endif
1075
1076 /*
1077  * Issue a command via psql, connecting to the specified database
1078  *
1079  * Since we use system(), this doesn't return until the operation finishes
1080  */
1081 static void
1082 psql_command(const char *database, const char *query,...)
1083 {
1084         char            query_formatted[1024];
1085         char            query_escaped[2048];
1086         char            psql_cmd[MAXPGPATH + 2048];
1087         va_list         args;
1088         char       *s;
1089         char       *d;
1090
1091         /* Generate the query with insertion of sprintf arguments */
1092         va_start(args, query);
1093         vsnprintf(query_formatted, sizeof(query_formatted), query, args);
1094         va_end(args);
1095
1096         /* Now escape any shell double-quote metacharacters */
1097         d = query_escaped;
1098         for (s = query_formatted; *s; s++)
1099         {
1100                 if (strchr("\\\"$`", *s))
1101                         *d++ = '\\';
1102                 *d++ = *s;
1103         }
1104         *d = '\0';
1105
1106         /* And now we can build and execute the shell command */
1107         snprintf(psql_cmd, sizeof(psql_cmd),
1108                          "\"%s%spsql\" -X -c \"%s\" \"%s\"",
1109                          bindir ? bindir : "",
1110                          bindir ? "/" : "",
1111                          query_escaped,
1112                          database);
1113
1114         if (system(psql_cmd) != 0)
1115         {
1116                 /* psql probably already reported the error */
1117                 fprintf(stderr, _("command failed: %s\n"), psql_cmd);
1118                 exit(2);
1119         }
1120 }
1121
1122 /*
1123  * Spawn a process to execute the given shell command; don't wait for it
1124  *
1125  * Returns the process ID (or HANDLE) so we can wait for it later
1126  */
1127 PID_TYPE
1128 spawn_process(const char *cmdline)
1129 {
1130 #ifndef WIN32
1131         pid_t           pid;
1132
1133         /*
1134          * Must flush I/O buffers before fork.  Ideally we'd use fflush(NULL) here
1135          * ... does anyone still care about systems where that doesn't work?
1136          */
1137         fflush(stdout);
1138         fflush(stderr);
1139         if (logfile)
1140                 fflush(logfile);
1141
1142         pid = fork();
1143         if (pid == -1)
1144         {
1145                 fprintf(stderr, _("%s: could not fork: %s\n"),
1146                                 progname, strerror(errno));
1147                 exit(2);
1148         }
1149         if (pid == 0)
1150         {
1151                 /*
1152                  * In child
1153                  *
1154                  * Instead of using system(), exec the shell directly, and tell it to
1155                  * "exec" the command too.  This saves two useless processes per
1156                  * parallel test case.
1157                  */
1158                 char       *cmdline2;
1159
1160                 cmdline2 = psprintf("exec %s", cmdline);
1161                 execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1162                 fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
1163                                 progname, shellprog, strerror(errno));
1164                 _exit(1);                               /* not exit() here... */
1165         }
1166         /* in parent */
1167         return pid;
1168 #else
1169         PROCESS_INFORMATION pi;
1170         char       *cmdline2;
1171         HANDLE          restrictedToken;
1172
1173         memset(&pi, 0, sizeof(pi));
1174         cmdline2 = psprintf("cmd /c \"%s\"", cmdline);
1175
1176         if ((restrictedToken =
1177                  CreateRestrictedProcess(cmdline2, &pi, progname)) == 0)
1178                 exit(2);
1179
1180         CloseHandle(pi.hThread);
1181         return pi.hProcess;
1182 #endif
1183 }
1184
1185 /*
1186  * Count bytes in file
1187  */
1188 static long
1189 file_size(const char *file)
1190 {
1191         long            r;
1192         FILE       *f = fopen(file, "r");
1193
1194         if (!f)
1195         {
1196                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1197                                 progname, file, strerror(errno));
1198                 return -1;
1199         }
1200         fseek(f, 0, SEEK_END);
1201         r = ftell(f);
1202         fclose(f);
1203         return r;
1204 }
1205
1206 /*
1207  * Count lines in file
1208  */
1209 static int
1210 file_line_count(const char *file)
1211 {
1212         int                     c;
1213         int                     l = 0;
1214         FILE       *f = fopen(file, "r");
1215
1216         if (!f)
1217         {
1218                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1219                                 progname, file, strerror(errno));
1220                 return -1;
1221         }
1222         while ((c = fgetc(f)) != EOF)
1223         {
1224                 if (c == '\n')
1225                         l++;
1226         }
1227         fclose(f);
1228         return l;
1229 }
1230
1231 bool
1232 file_exists(const char *file)
1233 {
1234         FILE       *f = fopen(file, "r");
1235
1236         if (!f)
1237                 return false;
1238         fclose(f);
1239         return true;
1240 }
1241
1242 static bool
1243 directory_exists(const char *dir)
1244 {
1245         struct stat st;
1246
1247         if (stat(dir, &st) != 0)
1248                 return false;
1249         if (S_ISDIR(st.st_mode))
1250                 return true;
1251         return false;
1252 }
1253
1254 /* Create a directory */
1255 static void
1256 make_directory(const char *dir)
1257 {
1258         if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
1259         {
1260                 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
1261                                 progname, dir, strerror(errno));
1262                 exit(2);
1263         }
1264 }
1265
1266 /*
1267  * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9
1268  */
1269 static char *
1270 get_alternative_expectfile(const char *expectfile, int i)
1271 {
1272         char       *last_dot;
1273         int                     ssize = strlen(expectfile) + 2 + 1;
1274         char       *tmp;
1275         char       *s;
1276
1277         if (!(tmp = (char *) malloc(ssize)))
1278                 return NULL;
1279
1280         if (!(s = (char *) malloc(ssize)))
1281         {
1282                 free(tmp);
1283                 return NULL;
1284         }
1285
1286         strcpy(tmp, expectfile);
1287         last_dot = strrchr(tmp, '.');
1288         if (!last_dot)
1289         {
1290                 free(tmp);
1291                 free(s);
1292                 return NULL;
1293         }
1294         *last_dot = '\0';
1295         snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
1296         free(tmp);
1297         return s;
1298 }
1299
1300 /*
1301  * Run a "diff" command and also check that it didn't crash
1302  */
1303 static int
1304 run_diff(const char *cmd, const char *filename)
1305 {
1306         int                     r;
1307
1308         r = system(cmd);
1309         if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
1310         {
1311                 fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
1312                 exit(2);
1313         }
1314 #ifdef WIN32
1315
1316         /*
1317          * On WIN32, if the 'diff' command cannot be found, system() returns 1,
1318          * but produces nothing to stdout, so we check for that here.
1319          */
1320         if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
1321         {
1322                 fprintf(stderr, _("diff command not found: %s\n"), cmd);
1323                 exit(2);
1324         }
1325 #endif
1326
1327         return WEXITSTATUS(r);
1328 }
1329
1330 /*
1331  * Check the actual result file for the given test against expected results
1332  *
1333  * Returns true if different (failure), false if correct match found.
1334  * In the true case, the diff is appended to the diffs file.
1335  */
1336 static bool
1337 results_differ(const char *testname, const char *resultsfile, const char *default_expectfile)
1338 {
1339         char            expectfile[MAXPGPATH];
1340         char            diff[MAXPGPATH];
1341         char            cmd[MAXPGPATH * 3];
1342         char            best_expect_file[MAXPGPATH];
1343         FILE       *difffile;
1344         int                     best_line_count;
1345         int                     i;
1346         int                     l;
1347         const char *platform_expectfile;
1348
1349         /*
1350          * We can pass either the resultsfile or the expectfile, they should have
1351          * the same type (filename.type) anyway.
1352          */
1353         platform_expectfile = get_expectfile(testname, resultsfile);
1354
1355         strlcpy(expectfile, default_expectfile, sizeof(expectfile));
1356         if (platform_expectfile)
1357         {
1358                 /*
1359                  * Replace everything after the last slash in expectfile with what the
1360                  * platform_expectfile contains.
1361                  */
1362                 char       *p = strrchr(expectfile, '/');
1363
1364                 if (p)
1365                         strcpy(++p, platform_expectfile);
1366         }
1367
1368         /* Name to use for temporary diff file */
1369         snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
1370
1371         /* OK, run the diff */
1372         snprintf(cmd, sizeof(cmd),
1373                          "diff %s \"%s\" \"%s\" > \"%s\"",
1374                          basic_diff_opts, expectfile, resultsfile, diff);
1375
1376         /* Is the diff file empty? */
1377         if (run_diff(cmd, diff) == 0)
1378         {
1379                 unlink(diff);
1380                 return false;
1381         }
1382
1383         /* There may be secondary comparison files that match better */
1384         best_line_count = file_line_count(diff);
1385         strcpy(best_expect_file, expectfile);
1386
1387         for (i = 0; i <= 9; i++)
1388         {
1389                 char       *alt_expectfile;
1390
1391                 alt_expectfile = get_alternative_expectfile(expectfile, i);
1392                 if (!alt_expectfile)
1393                 {
1394                         fprintf(stderr, _("Unable to check secondary comparison files: %s\n"),
1395                                         strerror(errno));
1396                         exit(2);
1397                 }
1398
1399                 if (!file_exists(alt_expectfile))
1400                 {
1401                         free(alt_expectfile);
1402                         continue;
1403                 }
1404
1405                 snprintf(cmd, sizeof(cmd),
1406                                  "diff %s \"%s\" \"%s\" > \"%s\"",
1407                                  basic_diff_opts, alt_expectfile, resultsfile, diff);
1408
1409                 if (run_diff(cmd, diff) == 0)
1410                 {
1411                         unlink(diff);
1412                         free(alt_expectfile);
1413                         return false;
1414                 }
1415
1416                 l = file_line_count(diff);
1417                 if (l < best_line_count)
1418                 {
1419                         /* This diff was a better match than the last one */
1420                         best_line_count = l;
1421                         strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
1422                 }
1423                 free(alt_expectfile);
1424         }
1425
1426         /*
1427          * fall back on the canonical results file if we haven't tried it yet and
1428          * haven't found a complete match yet.
1429          */
1430
1431         if (platform_expectfile)
1432         {
1433                 snprintf(cmd, sizeof(cmd),
1434                                  "diff %s \"%s\" \"%s\" > \"%s\"",
1435                                  basic_diff_opts, default_expectfile, resultsfile, diff);
1436
1437                 if (run_diff(cmd, diff) == 0)
1438                 {
1439                         /* No diff = no changes = good */
1440                         unlink(diff);
1441                         return false;
1442                 }
1443
1444                 l = file_line_count(diff);
1445                 if (l < best_line_count)
1446                 {
1447                         /* This diff was a better match than the last one */
1448                         best_line_count = l;
1449                         strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
1450                 }
1451         }
1452
1453         /*
1454          * Use the best comparison file to generate the "pretty" diff, which we
1455          * append to the diffs summary file.
1456          */
1457
1458         /* Write diff header */
1459         difffile = fopen(difffilename, "a");
1460         if (difffile)
1461         {
1462                 fprintf(difffile,
1463                                 "diff %s %s %s\n",
1464                                 pretty_diff_opts, best_expect_file, resultsfile);
1465                 fclose(difffile);
1466         }
1467
1468         /* Run diff */
1469         snprintf(cmd, sizeof(cmd),
1470                          "diff %s \"%s\" \"%s\" >> \"%s\"",
1471                          pretty_diff_opts, best_expect_file, resultsfile, difffilename);
1472         run_diff(cmd, difffilename);
1473
1474         unlink(diff);
1475         return true;
1476 }
1477
1478 /*
1479  * Wait for specified subprocesses to finish, and return their exit
1480  * statuses into statuses[] and stop times into stoptimes[]
1481  *
1482  * If names isn't NULL, print each subprocess's name as it finishes
1483  *
1484  * Note: it's OK to scribble on the pids array, but not on the names array
1485  */
1486 static void
1487 wait_for_tests(PID_TYPE * pids, int *statuses, instr_time *stoptimes,
1488                            char **names, int num_tests)
1489 {
1490         int                     tests_left;
1491         int                     i;
1492
1493 #ifdef WIN32
1494         PID_TYPE   *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
1495
1496         memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
1497 #endif
1498
1499         tests_left = num_tests;
1500         while (tests_left > 0)
1501         {
1502                 PID_TYPE        p;
1503
1504 #ifndef WIN32
1505                 int                     exit_status;
1506
1507                 p = wait(&exit_status);
1508
1509                 if (p == INVALID_PID)
1510                 {
1511                         fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
1512                                         strerror(errno));
1513                         exit(2);
1514                 }
1515 #else
1516                 DWORD           exit_status;
1517                 int                     r;
1518
1519                 r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
1520                 if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
1521                 {
1522                         fprintf(stderr, _("failed to wait for subprocesses: error code %lu\n"),
1523                                         GetLastError());
1524                         exit(2);
1525                 }
1526                 p = active_pids[r - WAIT_OBJECT_0];
1527                 /* compact the active_pids array */
1528                 active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
1529 #endif                                                  /* WIN32 */
1530
1531                 for (i = 0; i < num_tests; i++)
1532                 {
1533                         if (p == pids[i])
1534                         {
1535 #ifdef WIN32
1536                                 GetExitCodeProcess(pids[i], &exit_status);
1537                                 CloseHandle(pids[i]);
1538 #endif
1539                                 pids[i] = INVALID_PID;
1540                                 statuses[i] = (int) exit_status;
1541                                 INSTR_TIME_SET_CURRENT(stoptimes[i]);
1542                                 if (names)
1543                                         status(" %s", names[i]);
1544                                 tests_left--;
1545                                 break;
1546                         }
1547                 }
1548         }
1549
1550 #ifdef WIN32
1551         free(active_pids);
1552 #endif
1553 }
1554
1555 /*
1556  * report nonzero exit code from a test process
1557  */
1558 static void
1559 log_child_failure(int exitstatus)
1560 {
1561         if (WIFEXITED(exitstatus))
1562                 status(_(" (test process exited with exit code %d)"),
1563                            WEXITSTATUS(exitstatus));
1564         else if (WIFSIGNALED(exitstatus))
1565         {
1566 #if defined(WIN32)
1567                 status(_(" (test process was terminated by exception 0x%X)"),
1568                            WTERMSIG(exitstatus));
1569 #else
1570                 status(_(" (test process was terminated by signal %d: %s)"),
1571                            WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
1572 #endif
1573         }
1574         else
1575                 status(_(" (test process exited with unrecognized status %d)"),
1576                            exitstatus);
1577 }
1578
1579 /*
1580  * Run all the tests specified in one schedule file
1581  */
1582 static void
1583 run_schedule(const char *schedule, test_function tfunc)
1584 {
1585 #define MAX_PARALLEL_TESTS 100
1586         char       *tests[MAX_PARALLEL_TESTS];
1587         _stringlist *resultfiles[MAX_PARALLEL_TESTS];
1588         _stringlist *expectfiles[MAX_PARALLEL_TESTS];
1589         _stringlist *tags[MAX_PARALLEL_TESTS];
1590         PID_TYPE        pids[MAX_PARALLEL_TESTS];
1591         instr_time      starttimes[MAX_PARALLEL_TESTS];
1592         instr_time      stoptimes[MAX_PARALLEL_TESTS];
1593         int                     statuses[MAX_PARALLEL_TESTS];
1594         _stringlist *ignorelist = NULL;
1595         char            scbuf[1024];
1596         FILE       *scf;
1597         int                     line_num = 0;
1598
1599         memset(tests, 0, sizeof(tests));
1600         memset(resultfiles, 0, sizeof(resultfiles));
1601         memset(expectfiles, 0, sizeof(expectfiles));
1602         memset(tags, 0, sizeof(tags));
1603
1604         scf = fopen(schedule, "r");
1605         if (!scf)
1606         {
1607                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1608                                 progname, schedule, strerror(errno));
1609                 exit(2);
1610         }
1611
1612         while (fgets(scbuf, sizeof(scbuf), scf))
1613         {
1614                 char       *test = NULL;
1615                 char       *c;
1616                 int                     num_tests;
1617                 bool            inword;
1618                 int                     i;
1619
1620                 line_num++;
1621
1622                 /* strip trailing whitespace, especially the newline */
1623                 i = strlen(scbuf);
1624                 while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
1625                         scbuf[--i] = '\0';
1626
1627                 if (scbuf[0] == '\0' || scbuf[0] == '#')
1628                         continue;
1629                 if (strncmp(scbuf, "test: ", 6) == 0)
1630                         test = scbuf + 6;
1631                 else if (strncmp(scbuf, "ignore: ", 8) == 0)
1632                 {
1633                         c = scbuf + 8;
1634                         while (*c && isspace((unsigned char) *c))
1635                                 c++;
1636                         add_stringlist_item(&ignorelist, c);
1637
1638                         /*
1639                          * Note: ignore: lines do not run the test, they just say that
1640                          * failure of this test when run later on is to be ignored. A bit
1641                          * odd but that's how the shell-script version did it.
1642                          */
1643                         continue;
1644                 }
1645                 else
1646                 {
1647                         fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1648                                         schedule, line_num, scbuf);
1649                         exit(2);
1650                 }
1651
1652                 num_tests = 0;
1653                 inword = false;
1654                 for (c = test;; c++)
1655                 {
1656                         if (*c == '\0' || isspace((unsigned char) *c))
1657                         {
1658                                 if (inword)
1659                                 {
1660                                         /* Reached end of a test name */
1661                                         char            sav;
1662
1663                                         if (num_tests >= MAX_PARALLEL_TESTS)
1664                                         {
1665                                                 fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1666                                                                 MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
1667                                                 exit(2);
1668                                         }
1669                                         sav = *c;
1670                                         *c = '\0';
1671                                         tests[num_tests] = pg_strdup(test);
1672                                         num_tests++;
1673                                         *c = sav;
1674                                         inword = false;
1675                                 }
1676                                 if (*c == '\0')
1677                                         break;          /* loop exit is here */
1678                         }
1679                         else if (!inword)
1680                         {
1681                                 /* Start of a test name */
1682                                 test = c;
1683                                 inword = true;
1684                         }
1685                 }
1686
1687                 if (num_tests == 0)
1688                 {
1689                         fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1690                                         schedule, line_num, scbuf);
1691                         exit(2);
1692                 }
1693
1694                 if (num_tests == 1)
1695                 {
1696                         status(_("test %-28s ... "), tests[0]);
1697                         pids[0] = (tfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
1698                         INSTR_TIME_SET_CURRENT(starttimes[0]);
1699                         wait_for_tests(pids, statuses, stoptimes, NULL, 1);
1700                         /* status line is finished below */
1701                 }
1702                 else if (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
1703                 {
1704                         fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1705                                         max_concurrent_tests, schedule, line_num, scbuf);
1706                         exit(2);
1707                 }
1708                 else if (max_connections > 0 && max_connections < num_tests)
1709                 {
1710                         int                     oldest = 0;
1711
1712                         status(_("parallel group (%d tests, in groups of %d): "),
1713                                    num_tests, max_connections);
1714                         for (i = 0; i < num_tests; i++)
1715                         {
1716                                 if (i - oldest >= max_connections)
1717                                 {
1718                                         wait_for_tests(pids + oldest, statuses + oldest,
1719                                                                    stoptimes + oldest,
1720                                                                    tests + oldest, i - oldest);
1721                                         oldest = i;
1722                                 }
1723                                 pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1724                                 INSTR_TIME_SET_CURRENT(starttimes[i]);
1725                         }
1726                         wait_for_tests(pids + oldest, statuses + oldest,
1727                                                    stoptimes + oldest,
1728                                                    tests + oldest, i - oldest);
1729                         status_end();
1730                 }
1731                 else
1732                 {
1733                         status(_("parallel group (%d tests): "), num_tests);
1734                         for (i = 0; i < num_tests; i++)
1735                         {
1736                                 pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1737                                 INSTR_TIME_SET_CURRENT(starttimes[i]);
1738                         }
1739                         wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
1740                         status_end();
1741                 }
1742
1743                 /* Check results for all tests */
1744                 for (i = 0; i < num_tests; i++)
1745                 {
1746                         _stringlist *rl,
1747                                            *el,
1748                                            *tl;
1749                         bool            differ = false;
1750
1751                         if (num_tests > 1)
1752                                 status(_("     %-28s ... "), tests[i]);
1753
1754                         /*
1755                          * Advance over all three lists simultaneously.
1756                          *
1757                          * Compare resultfiles[j] with expectfiles[j] always. Tags are
1758                          * optional but if there are tags, the tag list has the same
1759                          * length as the other two lists.
1760                          */
1761                         for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
1762                                  rl != NULL;    /* rl and el have the same length */
1763                                  rl = rl->next, el = el->next,
1764                                  tl = tl ? tl->next : NULL)
1765                         {
1766                                 bool            newdiff;
1767
1768                                 newdiff = results_differ(tests[i], rl->str, el->str);
1769                                 if (newdiff && tl)
1770                                 {
1771                                         printf("%s ", tl->str);
1772                                 }
1773                                 differ |= newdiff;
1774                         }
1775
1776                         if (differ)
1777                         {
1778                                 bool            ignore = false;
1779                                 _stringlist *sl;
1780
1781                                 for (sl = ignorelist; sl != NULL; sl = sl->next)
1782                                 {
1783                                         if (strcmp(tests[i], sl->str) == 0)
1784                                         {
1785                                                 ignore = true;
1786                                                 break;
1787                                         }
1788                                 }
1789                                 if (ignore)
1790                                 {
1791                                         status(_("failed (ignored)"));
1792                                         fail_ignore_count++;
1793                                 }
1794                                 else
1795                                 {
1796                                         status(_("FAILED"));
1797                                         fail_count++;
1798                                 }
1799                         }
1800                         else
1801                         {
1802                                 status(_("ok    ")); /* align with FAILED */
1803                                 success_count++;
1804                         }
1805
1806                         if (statuses[i] != 0)
1807                                 log_child_failure(statuses[i]);
1808
1809                         INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
1810                         status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptimes[i]));
1811
1812                         status_end();
1813                 }
1814
1815                 for (i = 0; i < num_tests; i++)
1816                 {
1817                         pg_free(tests[i]);
1818                         tests[i] = NULL;
1819                         free_stringlist(&resultfiles[i]);
1820                         free_stringlist(&expectfiles[i]);
1821                         free_stringlist(&tags[i]);
1822                 }
1823         }
1824
1825         free_stringlist(&ignorelist);
1826
1827         fclose(scf);
1828 }
1829
1830 /*
1831  * Run a single test
1832  */
1833 static void
1834 run_single_test(const char *test, test_function tfunc)
1835 {
1836         PID_TYPE        pid;
1837         instr_time      starttime;
1838         instr_time      stoptime;
1839         int                     exit_status;
1840         _stringlist *resultfiles = NULL;
1841         _stringlist *expectfiles = NULL;
1842         _stringlist *tags = NULL;
1843         _stringlist *rl,
1844                            *el,
1845                            *tl;
1846         bool            differ = false;
1847
1848         status(_("test %-28s ... "), test);
1849         pid = (tfunc) (test, &resultfiles, &expectfiles, &tags);
1850         INSTR_TIME_SET_CURRENT(starttime);
1851         wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
1852
1853         /*
1854          * Advance over all three lists simultaneously.
1855          *
1856          * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
1857          * but if there are tags, the tag list has the same length as the other
1858          * two lists.
1859          */
1860         for (rl = resultfiles, el = expectfiles, tl = tags;
1861                  rl != NULL;                    /* rl and el have the same length */
1862                  rl = rl->next, el = el->next,
1863                  tl = tl ? tl->next : NULL)
1864         {
1865                 bool            newdiff;
1866
1867                 newdiff = results_differ(test, rl->str, el->str);
1868                 if (newdiff && tl)
1869                 {
1870                         printf("%s ", tl->str);
1871                 }
1872                 differ |= newdiff;
1873         }
1874
1875         if (differ)
1876         {
1877                 status(_("FAILED"));
1878                 fail_count++;
1879         }
1880         else
1881         {
1882                 status(_("ok    ")); /* align with FAILED */
1883                 success_count++;
1884         }
1885
1886         if (exit_status != 0)
1887                 log_child_failure(exit_status);
1888
1889         INSTR_TIME_SUBTRACT(stoptime, starttime);
1890         status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptime));
1891
1892         status_end();
1893 }
1894
1895 /*
1896  * Create the summary-output files (making them empty if already existing)
1897  */
1898 static void
1899 open_result_files(void)
1900 {
1901         char            file[MAXPGPATH];
1902         FILE       *difffile;
1903
1904         /* create outputdir directory if not present */
1905         if (!directory_exists(outputdir))
1906                 make_directory(outputdir);
1907
1908         /* create the log file (copy of running status output) */
1909         snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1910         logfilename = pg_strdup(file);
1911         logfile = fopen(logfilename, "w");
1912         if (!logfile)
1913         {
1914                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1915                                 progname, logfilename, strerror(errno));
1916                 exit(2);
1917         }
1918
1919         /* create the diffs file as empty */
1920         snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1921         difffilename = pg_strdup(file);
1922         difffile = fopen(difffilename, "w");
1923         if (!difffile)
1924         {
1925                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1926                                 progname, difffilename, strerror(errno));
1927                 exit(2);
1928         }
1929         /* we don't keep the diffs file open continuously */
1930         fclose(difffile);
1931
1932         /* also create the results directory if not present */
1933         snprintf(file, sizeof(file), "%s/results", outputdir);
1934         if (!directory_exists(file))
1935                 make_directory(file);
1936 }
1937
1938 static void
1939 drop_database_if_exists(const char *dbname)
1940 {
1941         header(_("dropping database \"%s\""), dbname);
1942         psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname);
1943 }
1944
1945 static void
1946 create_database(const char *dbname)
1947 {
1948         _stringlist *sl;
1949
1950         /*
1951          * We use template0 so that any installation-local cruft in template1 will
1952          * not mess up the tests.
1953          */
1954         header(_("creating database \"%s\""), dbname);
1955         if (encoding)
1956                 psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
1957                                          (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1958         else
1959                 psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
1960                                          (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1961         psql_command(dbname,
1962                                  "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
1963                                  "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
1964                                  "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
1965                                  "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
1966                                  "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
1967                                  "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
1968                                  dbname, dbname, dbname, dbname, dbname, dbname);
1969
1970         /*
1971          * Install any requested procedural languages.  We use CREATE OR REPLACE
1972          * so that this will work whether or not the language is preinstalled.
1973          */
1974         for (sl = loadlanguage; sl != NULL; sl = sl->next)
1975         {
1976                 header(_("installing %s"), sl->str);
1977                 psql_command(dbname, "CREATE OR REPLACE LANGUAGE \"%s\"", sl->str);
1978         }
1979
1980         /*
1981          * Install any requested extensions.  We use CREATE IF NOT EXISTS so that
1982          * this will work whether or not the extension is preinstalled.
1983          */
1984         for (sl = loadextension; sl != NULL; sl = sl->next)
1985         {
1986                 header(_("installing %s"), sl->str);
1987                 psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
1988         }
1989 }
1990
1991 static void
1992 drop_role_if_exists(const char *rolename)
1993 {
1994         header(_("dropping role \"%s\""), rolename);
1995         psql_command("postgres", "DROP ROLE IF EXISTS \"%s\"", rolename);
1996 }
1997
1998 static void
1999 create_role(const char *rolename, const _stringlist *granted_dbs)
2000 {
2001         header(_("creating role \"%s\""), rolename);
2002         psql_command("postgres", "CREATE ROLE \"%s\" WITH LOGIN", rolename);
2003         for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
2004         {
2005                 psql_command("postgres", "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
2006                                          granted_dbs->str, rolename);
2007         }
2008 }
2009
2010 static void
2011 help(void)
2012 {
2013         printf(_("PostgreSQL regression test driver\n"));
2014         printf(_("\n"));
2015         printf(_("Usage:\n  %s [OPTION]... [EXTRA-TEST]...\n"), progname);
2016         printf(_("\n"));
2017         printf(_("Options:\n"));
2018         printf(_("      --bindir=BINPATH          use BINPATH for programs that are run;\n"));
2019         printf(_("                                if empty, use PATH from the environment\n"));
2020         printf(_("      --config-auth=DATADIR     update authentication settings for DATADIR\n"));
2021         printf(_("      --create-role=ROLE        create the specified role before testing\n"));
2022         printf(_("      --dbname=DB               use database DB (default \"regression\")\n"));
2023         printf(_("      --debug                   turn on debug mode in programs that are run\n"));
2024         printf(_("      --dlpath=DIR              look for dynamic libraries in DIR\n"));
2025         printf(_("      --encoding=ENCODING       use ENCODING as the encoding\n"));
2026         printf(_("  -h, --help                    show this help, then exit\n"));
2027         printf(_("      --inputdir=DIR            take input files from DIR (default \".\")\n"));
2028         printf(_("      --launcher=CMD            use CMD as launcher of psql\n"));
2029         printf(_("      --load-extension=EXT      load the named extension before running the\n"));
2030         printf(_("                                tests; can appear multiple times\n"));
2031         printf(_("      --load-language=LANG      load the named language before running the\n"));
2032         printf(_("                                tests; can appear multiple times\n"));
2033         printf(_("      --max-connections=N       maximum number of concurrent connections\n"));
2034         printf(_("                                (default is 0, meaning unlimited)\n"));
2035         printf(_("      --max-concurrent-tests=N  maximum number of concurrent tests in schedule\n"));
2036         printf(_("                                (default is 0, meaning unlimited)\n"));
2037         printf(_("      --outputdir=DIR           place output files in DIR (default \".\")\n"));
2038         printf(_("      --schedule=FILE           use test ordering schedule from FILE\n"));
2039         printf(_("                                (can be used multiple times to concatenate)\n"));
2040         printf(_("      --temp-instance=DIR       create a temporary instance in DIR\n"));
2041         printf(_("      --use-existing            use an existing installation\n"));
2042         printf(_("  -V, --version                 output version information, then exit\n"));
2043         printf(_("\n"));
2044         printf(_("Options for \"temp-instance\" mode:\n"));
2045         printf(_("      --no-locale               use C locale\n"));
2046         printf(_("      --port=PORT               start postmaster on PORT\n"));
2047         printf(_("      --temp-config=FILE        append contents of FILE to temporary config\n"));
2048         printf(_("\n"));
2049         printf(_("Options for using an existing installation:\n"));
2050         printf(_("      --host=HOST               use postmaster running on HOST\n"));
2051         printf(_("      --port=PORT               use postmaster running at PORT\n"));
2052         printf(_("      --user=USER               connect as USER\n"));
2053         printf(_("\n"));
2054         printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
2055         printf(_("if the tests could not be run for some reason.\n"));
2056         printf(_("\n"));
2057         printf(_("Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
2058 }
2059
2060 int
2061 regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc)
2062 {
2063         static struct option long_options[] = {
2064                 {"help", no_argument, NULL, 'h'},
2065                 {"version", no_argument, NULL, 'V'},
2066                 {"dbname", required_argument, NULL, 1},
2067                 {"debug", no_argument, NULL, 2},
2068                 {"inputdir", required_argument, NULL, 3},
2069                 {"load-language", required_argument, NULL, 4},
2070                 {"max-connections", required_argument, NULL, 5},
2071                 {"encoding", required_argument, NULL, 6},
2072                 {"outputdir", required_argument, NULL, 7},
2073                 {"schedule", required_argument, NULL, 8},
2074                 {"temp-instance", required_argument, NULL, 9},
2075                 {"no-locale", no_argument, NULL, 10},
2076                 {"host", required_argument, NULL, 13},
2077                 {"port", required_argument, NULL, 14},
2078                 {"user", required_argument, NULL, 15},
2079                 {"bindir", required_argument, NULL, 16},
2080                 {"dlpath", required_argument, NULL, 17},
2081                 {"create-role", required_argument, NULL, 18},
2082                 {"temp-config", required_argument, NULL, 19},
2083                 {"use-existing", no_argument, NULL, 20},
2084                 {"launcher", required_argument, NULL, 21},
2085                 {"load-extension", required_argument, NULL, 22},
2086                 {"config-auth", required_argument, NULL, 24},
2087                 {"max-concurrent-tests", required_argument, NULL, 25},
2088                 {NULL, 0, NULL, 0}
2089         };
2090
2091         _stringlist *sl;
2092         int                     c;
2093         int                     i;
2094         int                     option_index;
2095         char            buf[MAXPGPATH * 4];
2096         char            buf2[MAXPGPATH * 4];
2097
2098         progname = get_progname(argv[0]);
2099         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
2100
2101         get_restricted_token(progname);
2102
2103         atexit(stop_postmaster);
2104
2105 #ifndef HAVE_UNIX_SOCKETS
2106         /* no unix domain sockets available, so change default */
2107         hostname = "localhost";
2108 #endif
2109
2110         /*
2111          * We call the initialization function here because that way we can set
2112          * default parameters and let them be overwritten by the commandline.
2113          */
2114         ifunc(argc, argv);
2115
2116         if (getenv("PG_REGRESS_DIFF_OPTS"))
2117                 pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
2118
2119         while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
2120         {
2121                 switch (c)
2122                 {
2123                         case 'h':
2124                                 help();
2125                                 exit(0);
2126                         case 'V':
2127                                 puts("pg_regress (PostgreSQL) " PG_VERSION);
2128                                 exit(0);
2129                         case 1:
2130
2131                                 /*
2132                                  * If a default database was specified, we need to remove it
2133                                  * before we add the specified one.
2134                                  */
2135                                 free_stringlist(&dblist);
2136                                 split_to_stringlist(optarg, ",", &dblist);
2137                                 break;
2138                         case 2:
2139                                 debug = true;
2140                                 break;
2141                         case 3:
2142                                 inputdir = pg_strdup(optarg);
2143                                 break;
2144                         case 4:
2145                                 add_stringlist_item(&loadlanguage, optarg);
2146                                 break;
2147                         case 5:
2148                                 max_connections = atoi(optarg);
2149                                 break;
2150                         case 6:
2151                                 encoding = pg_strdup(optarg);
2152                                 break;
2153                         case 7:
2154                                 outputdir = pg_strdup(optarg);
2155                                 break;
2156                         case 8:
2157                                 add_stringlist_item(&schedulelist, optarg);
2158                                 break;
2159                         case 9:
2160                                 temp_instance = make_absolute_path(optarg);
2161                                 break;
2162                         case 10:
2163                                 nolocale = true;
2164                                 break;
2165                         case 13:
2166                                 hostname = pg_strdup(optarg);
2167                                 break;
2168                         case 14:
2169                                 port = atoi(optarg);
2170                                 port_specified_by_user = true;
2171                                 break;
2172                         case 15:
2173                                 user = pg_strdup(optarg);
2174                                 break;
2175                         case 16:
2176                                 /* "--bindir=" means to use PATH */
2177                                 if (strlen(optarg))
2178                                         bindir = pg_strdup(optarg);
2179                                 else
2180                                         bindir = NULL;
2181                                 break;
2182                         case 17:
2183                                 dlpath = pg_strdup(optarg);
2184                                 break;
2185                         case 18:
2186                                 split_to_stringlist(optarg, ",", &extraroles);
2187                                 break;
2188                         case 19:
2189                                 add_stringlist_item(&temp_configs, optarg);
2190                                 break;
2191                         case 20:
2192                                 use_existing = true;
2193                                 break;
2194                         case 21:
2195                                 launcher = pg_strdup(optarg);
2196                                 break;
2197                         case 22:
2198                                 add_stringlist_item(&loadextension, optarg);
2199                                 break;
2200                         case 24:
2201                                 config_auth_datadir = pg_strdup(optarg);
2202                                 break;
2203                         case 25:
2204                                 max_concurrent_tests = atoi(optarg);
2205                                 break;
2206                         default:
2207                                 /* getopt_long already emitted a complaint */
2208                                 fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
2209                                                 progname);
2210                                 exit(2);
2211                 }
2212         }
2213
2214         /*
2215          * if we still have arguments, they are extra tests to run
2216          */
2217         while (argc - optind >= 1)
2218         {
2219                 add_stringlist_item(&extra_tests, argv[optind]);
2220                 optind++;
2221         }
2222
2223         if (config_auth_datadir)
2224         {
2225 #ifdef ENABLE_SSPI
2226                 config_sspi_auth(config_auth_datadir);
2227 #endif
2228                 exit(0);
2229         }
2230
2231         if (temp_instance && !port_specified_by_user)
2232
2233                 /*
2234                  * To reduce chances of interference with parallel installations, use
2235                  * a port number starting in the private range (49152-65535)
2236                  * calculated from the version number.  This aids !HAVE_UNIX_SOCKETS
2237                  * systems; elsewhere, the use of a private socket directory already
2238                  * prevents interference.
2239                  */
2240                 port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
2241
2242         inputdir = make_absolute_path(inputdir);
2243         outputdir = make_absolute_path(outputdir);
2244         dlpath = make_absolute_path(dlpath);
2245
2246         /*
2247          * Initialization
2248          */
2249         open_result_files();
2250
2251         initialize_environment();
2252
2253 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
2254         unlimit_core_size();
2255 #endif
2256
2257         if (temp_instance)
2258         {
2259                 FILE       *pg_conf;
2260                 const char *env_wait;
2261                 int                     wait_seconds;
2262
2263                 /*
2264                  * Prepare the temp instance
2265                  */
2266
2267                 if (directory_exists(temp_instance))
2268                 {
2269                         header(_("removing existing temp instance"));
2270                         if (!rmtree(temp_instance, true))
2271                         {
2272                                 fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2273                                                 progname, temp_instance);
2274                                 exit(2);
2275                         }
2276                 }
2277
2278                 header(_("creating temporary instance"));
2279
2280                 /* make the temp instance top directory */
2281                 make_directory(temp_instance);
2282
2283                 /* and a directory for log files */
2284                 snprintf(buf, sizeof(buf), "%s/log", outputdir);
2285                 if (!directory_exists(buf))
2286                         make_directory(buf);
2287
2288                 /* initdb */
2289                 header(_("initializing database system"));
2290                 snprintf(buf, sizeof(buf),
2291                                  "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync%s%s > \"%s/log/initdb.log\" 2>&1",
2292                                  bindir ? bindir : "",
2293                                  bindir ? "/" : "",
2294                                  temp_instance,
2295                                  debug ? " --debug" : "",
2296                                  nolocale ? " --no-locale" : "",
2297                                  outputdir);
2298                 if (system(buf))
2299                 {
2300                         fprintf(stderr, _("\n%s: initdb failed\nExamine %s/log/initdb.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
2301                         exit(2);
2302                 }
2303
2304                 /*
2305                  * Adjust the default postgresql.conf for regression testing. The user
2306                  * can specify a file to be appended; in any case we expand logging
2307                  * and set max_prepared_transactions to enable testing of prepared
2308                  * xacts.  (Note: to reduce the probability of unexpected shmmax
2309                  * failures, don't set max_prepared_transactions any higher than
2310                  * actually needed by the prepared_xacts regression test.)
2311                  */
2312                 snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
2313                 pg_conf = fopen(buf, "a");
2314                 if (pg_conf == NULL)
2315                 {
2316                         fprintf(stderr, _("\n%s: could not open \"%s\" for adding extra config: %s\n"), progname, buf, strerror(errno));
2317                         exit(2);
2318                 }
2319                 fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
2320                 fputs("log_autovacuum_min_duration = 0\n", pg_conf);
2321                 fputs("log_checkpoints = on\n", pg_conf);
2322                 fputs("log_line_prefix = '%m [%p] %q%a '\n", pg_conf);
2323                 fputs("log_lock_waits = on\n", pg_conf);
2324                 fputs("log_temp_files = 128kB\n", pg_conf);
2325                 fputs("max_prepared_transactions = 2\n", pg_conf);
2326
2327                 for (sl = temp_configs; sl != NULL; sl = sl->next)
2328                 {
2329                         char       *temp_config = sl->str;
2330                         FILE       *extra_conf;
2331                         char            line_buf[1024];
2332
2333                         extra_conf = fopen(temp_config, "r");
2334                         if (extra_conf == NULL)
2335                         {
2336                                 fprintf(stderr, _("\n%s: could not open \"%s\" to read extra config: %s\n"), progname, temp_config, strerror(errno));
2337                                 exit(2);
2338                         }
2339                         while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
2340                                 fputs(line_buf, pg_conf);
2341                         fclose(extra_conf);
2342                 }
2343
2344                 fclose(pg_conf);
2345
2346 #ifdef ENABLE_SSPI
2347
2348                 /*
2349                  * Since we successfully used the same buffer for the much-longer
2350                  * "initdb" command, this can't truncate.
2351                  */
2352                 snprintf(buf, sizeof(buf), "%s/data", temp_instance);
2353                 config_sspi_auth(buf);
2354 #elif !defined(HAVE_UNIX_SOCKETS)
2355 #error Platform has no means to secure the test installation.
2356 #endif
2357
2358                 /*
2359                  * Check if there is a postmaster running already.
2360                  */
2361                 snprintf(buf2, sizeof(buf2),
2362                                  "\"%s%spsql\" -X postgres <%s 2>%s",
2363                                  bindir ? bindir : "",
2364                                  bindir ? "/" : "",
2365                                  DEVNULL, DEVNULL);
2366
2367                 for (i = 0; i < 16; i++)
2368                 {
2369                         if (system(buf2) == 0)
2370                         {
2371                                 char            s[16];
2372
2373                                 if (port_specified_by_user || i == 15)
2374                                 {
2375                                         fprintf(stderr, _("port %d apparently in use\n"), port);
2376                                         if (!port_specified_by_user)
2377                                                 fprintf(stderr, _("%s: could not determine an available port\n"), progname);
2378                                         fprintf(stderr, _("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.\n"));
2379                                         exit(2);
2380                                 }
2381
2382                                 fprintf(stderr, _("port %d apparently in use, trying %d\n"), port, port + 1);
2383                                 port++;
2384                                 sprintf(s, "%d", port);
2385                                 doputenv("PGPORT", s);
2386                         }
2387                         else
2388                                 break;
2389                 }
2390
2391                 /*
2392                  * Start the temp postmaster
2393                  */
2394                 header(_("starting postmaster"));
2395                 snprintf(buf, sizeof(buf),
2396                                  "\"%s%spostgres\" -D \"%s/data\" -F%s "
2397                                  "-c \"listen_addresses=%s\" -k \"%s\" "
2398                                  "> \"%s/log/postmaster.log\" 2>&1",
2399                                  bindir ? bindir : "",
2400                                  bindir ? "/" : "",
2401                                  temp_instance, debug ? " -d 5" : "",
2402                                  hostname ? hostname : "", sockdir ? sockdir : "",
2403                                  outputdir);
2404                 postmaster_pid = spawn_process(buf);
2405                 if (postmaster_pid == INVALID_PID)
2406                 {
2407                         fprintf(stderr, _("\n%s: could not spawn postmaster: %s\n"),
2408                                         progname, strerror(errno));
2409                         exit(2);
2410                 }
2411
2412                 /*
2413                  * Wait till postmaster is able to accept connections; normally this
2414                  * is only a second or so, but Cygwin is reportedly *much* slower, and
2415                  * test builds using Valgrind or similar tools might be too.  Hence,
2416                  * allow the default timeout of 60 seconds to be overridden from the
2417                  * PGCTLTIMEOUT environment variable.
2418                  */
2419                 env_wait = getenv("PGCTLTIMEOUT");
2420                 if (env_wait != NULL)
2421                 {
2422                         wait_seconds = atoi(env_wait);
2423                         if (wait_seconds <= 0)
2424                                 wait_seconds = 60;
2425                 }
2426                 else
2427                         wait_seconds = 60;
2428
2429                 for (i = 0; i < wait_seconds; i++)
2430                 {
2431                         /* Done if psql succeeds */
2432                         if (system(buf2) == 0)
2433                                 break;
2434
2435                         /*
2436                          * Fail immediately if postmaster has exited
2437                          */
2438 #ifndef WIN32
2439                         if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
2440 #else
2441                         if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
2442 #endif
2443                         {
2444                                 fprintf(stderr, _("\n%s: postmaster failed\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
2445                                 exit(2);
2446                         }
2447
2448                         pg_usleep(1000000L);
2449                 }
2450                 if (i >= wait_seconds)
2451                 {
2452                         fprintf(stderr, _("\n%s: postmaster did not respond within %d seconds\nExamine %s/log/postmaster.log for the reason\n"),
2453                                         progname, wait_seconds, outputdir);
2454
2455                         /*
2456                          * If we get here, the postmaster is probably wedged somewhere in
2457                          * startup.  Try to kill it ungracefully rather than leaving a
2458                          * stuck postmaster that might interfere with subsequent test
2459                          * attempts.
2460                          */
2461 #ifndef WIN32
2462                         if (kill(postmaster_pid, SIGKILL) != 0 &&
2463                                 errno != ESRCH)
2464                                 fprintf(stderr, _("\n%s: could not kill failed postmaster: %s\n"),
2465                                                 progname, strerror(errno));
2466 #else
2467                         if (TerminateProcess(postmaster_pid, 255) == 0)
2468                                 fprintf(stderr, _("\n%s: could not kill failed postmaster: error code %lu\n"),
2469                                                 progname, GetLastError());
2470 #endif
2471
2472                         exit(2);
2473                 }
2474
2475                 postmaster_running = true;
2476
2477 #ifdef _WIN64
2478 /* need a series of two casts to convert HANDLE without compiler warning */
2479 #define ULONGPID(x) (unsigned long) (unsigned long long) (x)
2480 #else
2481 #define ULONGPID(x) (unsigned long) (x)
2482 #endif
2483                 printf(_("running on port %d with PID %lu\n"),
2484                            port, ULONGPID(postmaster_pid));
2485         }
2486         else
2487         {
2488                 /*
2489                  * Using an existing installation, so may need to get rid of
2490                  * pre-existing database(s) and role(s)
2491                  */
2492                 if (!use_existing)
2493                 {
2494                         for (sl = dblist; sl; sl = sl->next)
2495                                 drop_database_if_exists(sl->str);
2496                         for (sl = extraroles; sl; sl = sl->next)
2497                                 drop_role_if_exists(sl->str);
2498                 }
2499         }
2500
2501         /*
2502          * Create the test database(s) and role(s)
2503          */
2504         if (!use_existing)
2505         {
2506                 for (sl = dblist; sl; sl = sl->next)
2507                         create_database(sl->str);
2508                 for (sl = extraroles; sl; sl = sl->next)
2509                         create_role(sl->str, dblist);
2510         }
2511
2512         /*
2513          * Ready to run the tests
2514          */
2515         header(_("running regression test queries"));
2516
2517         for (sl = schedulelist; sl != NULL; sl = sl->next)
2518         {
2519                 run_schedule(sl->str, tfunc);
2520         }
2521
2522         for (sl = extra_tests; sl != NULL; sl = sl->next)
2523         {
2524                 run_single_test(sl->str, tfunc);
2525         }
2526
2527         /*
2528          * Shut down temp installation's postmaster
2529          */
2530         if (temp_instance)
2531         {
2532                 header(_("shutting down postmaster"));
2533                 stop_postmaster();
2534         }
2535
2536         /*
2537          * If there were no errors, remove the temp instance immediately to
2538          * conserve disk space.  (If there were errors, we leave the instance in
2539          * place for possible manual investigation.)
2540          */
2541         if (temp_instance && fail_count == 0 && fail_ignore_count == 0)
2542         {
2543                 header(_("removing temporary instance"));
2544                 if (!rmtree(temp_instance, true))
2545                         fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2546                                         progname, temp_instance);
2547         }
2548
2549         fclose(logfile);
2550
2551         /*
2552          * Emit nice-looking summary message
2553          */
2554         if (fail_count == 0 && fail_ignore_count == 0)
2555                 snprintf(buf, sizeof(buf),
2556                                  _(" All %d tests passed. "),
2557                                  success_count);
2558         else if (fail_count == 0)       /* fail_count=0, fail_ignore_count>0 */
2559                 snprintf(buf, sizeof(buf),
2560                                  _(" %d of %d tests passed, %d failed test(s) ignored. "),
2561                                  success_count,
2562                                  success_count + fail_ignore_count,
2563                                  fail_ignore_count);
2564         else if (fail_ignore_count == 0)        /* fail_count>0 && fail_ignore_count=0 */
2565                 snprintf(buf, sizeof(buf),
2566                                  _(" %d of %d tests failed. "),
2567                                  fail_count,
2568                                  success_count + fail_count);
2569         else
2570                 /* fail_count>0 && fail_ignore_count>0 */
2571                 snprintf(buf, sizeof(buf),
2572                                  _(" %d of %d tests failed, %d of these failures ignored. "),
2573                                  fail_count + fail_ignore_count,
2574                                  success_count + fail_count + fail_ignore_count,
2575                                  fail_ignore_count);
2576
2577         putchar('\n');
2578         for (i = strlen(buf); i > 0; i--)
2579                 putchar('=');
2580         printf("\n%s\n", buf);
2581         for (i = strlen(buf); i > 0; i--)
2582                 putchar('=');
2583         putchar('\n');
2584         putchar('\n');
2585
2586         if (file_size(difffilename) > 0)
2587         {
2588                 printf(_("The differences that caused some tests to fail can be viewed in the\n"
2589                                  "file \"%s\".  A copy of the test summary that you see\n"
2590                                  "above is saved in the file \"%s\".\n\n"),
2591                            difffilename, logfilename);
2592         }
2593         else
2594         {
2595                 unlink(difffilename);
2596                 unlink(logfilename);
2597         }
2598
2599         if (fail_count != 0)
2600                 exit(1);
2601
2602         return 0;
2603 }