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