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