PostgreSQL Source Code  git master
pg_regress.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include "common/logging.h"
#include "common/restricted_token.h"
#include "common/string.h"
#include "common/username.h"
#include "getopt_long.h"
#include "lib/stringinfo.h"
#include "libpq/pqcomm.h"
#include "pg_config_paths.h"
#include "pg_regress.h"
#include "portability/instr_time.h"
Include dependency graph for pg_regress.c:

Go to the source code of this file.

Data Structures

struct  _resultmap
 

Macros

#define psql_command(database, ...)
 
#define MAX_PARALLEL_TESTS   100
 
#define ULONGPID(x)   (unsigned long) (x)
 

Typedefs

typedef struct _resultmap _resultmap
 

Functions

static bool directory_exists (const char *dir)
 
static void make_directory (const char *dir)
 
static void header (const char *fmt,...) pg_attribute_printf(1
 
static void static void status (const char *fmt,...) pg_attribute_printf(1
 
static void static void static StringInfo psql_start_command (void)
 
static void psql_add_command (StringInfo buf, const char *query,...) pg_attribute_printf(2
 
static void static void psql_end_command (StringInfo buf, const char *database)
 
void add_stringlist_item (_stringlist **listhead, const char *str)
 
static void free_stringlist (_stringlist **listhead)
 
static void split_to_stringlist (const char *s, const char *delim, _stringlist **listhead)
 
static void status_end (void)
 
static void stop_postmaster (void)
 
static bool string_matches_pattern (const char *str, const char *pattern)
 
static void load_resultmap (void)
 
static const char * get_expectfile (const char *testname, const char *file)
 
static void initialize_environment (void)
 
PID_TYPE spawn_process (const char *cmdline)
 
static long file_size (const char *file)
 
static int file_line_count (const char *file)
 
bool file_exists (const char *file)
 
static char * get_alternative_expectfile (const char *expectfile, int i)
 
static int run_diff (const char *cmd, const char *filename)
 
static bool results_differ (const char *testname, const char *resultsfile, const char *default_expectfile)
 
static void wait_for_tests (PID_TYPE *pids, int *statuses, instr_time *stoptimes, char **names, int num_tests)
 
static void log_child_failure (int exitstatus)
 
static void run_schedule (const char *schedule, test_start_function startfunc, postprocess_result_function postfunc)
 
static void run_single_test (const char *test, test_start_function startfunc, postprocess_result_function postfunc)
 
static void open_result_files (void)
 
static void drop_database_if_exists (const char *dbname)
 
static void create_database (const char *dbname)
 
static void drop_role_if_exists (const char *rolename)
 
static void create_role (const char *rolename, const _stringlist *granted_dbs)
 
static void help (void)
 
int regression_main (int argc, char *argv[], init_function ifunc, test_start_function startfunc, postprocess_result_function postfunc)
 

Variables

char * host_platform = HOST_TUPLE
 
static char * shellprog = SHELLPROG
 
const char * basic_diff_opts = ""
 
const char * pretty_diff_opts = "-U3"
 
_stringlistdblist = NULL
 
bool debug = false
 
char * inputdir = "."
 
char * outputdir = "."
 
char * bindir = PGBINDIR
 
char * launcher = NULL
 
static _stringlistloadextension = NULL
 
static int max_connections = 0
 
static int max_concurrent_tests = 0
 
static char * encoding = NULL
 
static _stringlistschedulelist = NULL
 
static _stringlistextra_tests = NULL
 
static char * temp_instance = NULL
 
static _stringlisttemp_configs = NULL
 
static bool nolocale = false
 
static bool use_existing = false
 
static char * hostname = NULL
 
static int port = -1
 
static bool port_specified_by_user = false
 
static char * dlpath = PKGLIBDIR
 
static char * user = NULL
 
static _stringlistextraroles = NULL
 
static char * config_auth_datadir = NULL
 
static const char * progname
 
static char * logfilename
 
static FILE * logfile
 
static char * difffilename
 
static const char * sockdir
 
static _resultmapresultmap = NULL
 
static PID_TYPE postmaster_pid = INVALID_PID
 
static bool postmaster_running = false
 
static int success_count = 0
 
static int fail_count = 0
 
static int fail_ignore_count = 0
 

Macro Definition Documentation

◆ MAX_PARALLEL_TESTS

#define MAX_PARALLEL_TESTS   100

◆ psql_command

#define psql_command (   database,
  ... 
)
Value:
do { \
StringInfo cmdbuf = psql_start_command(); \
psql_add_command(cmdbuf, __VA_ARGS__); \
psql_end_command(cmdbuf, database); \
} while (0)
static void static void static StringInfo psql_start_command(void)
Definition: pg_regress.c:988

Definition at line 1060 of file pg_regress.c.

◆ ULONGPID

#define ULONGPID (   x)    (unsigned long) (x)

Typedef Documentation

◆ _resultmap

typedef struct _resultmap _resultmap

Function Documentation

◆ add_stringlist_item()

void add_stringlist_item ( _stringlist **  listhead,
const char *  str 
)

Definition at line 159 of file pg_regress.c.

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 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
struct _stringlist * next
Definition: pg_regress.h:27
char * str
Definition: pg_regress.h:26

References _stringlist::next, pg_malloc(), pg_strdup(), generate_unaccent_rules::str, and _stringlist::str.

Referenced by ecpg_start_test(), isolation_init(), isolation_start_test(), psql_init(), psql_start_test(), regression_main(), run_schedule(), and split_to_stringlist().

◆ create_database()

static void create_database ( const char *  dbname)
static

Definition at line 1912 of file pg_regress.c.

1913 {
1915  _stringlist *sl;
1916 
1917  /*
1918  * We use template0 so that any installation-local cruft in template1 will
1919  * not mess up the tests.
1920  */
1921  header(_("creating database \"%s\""), dbname);
1922  if (encoding)
1923  psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
1924  (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1925  else
1926  psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
1927  (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1929  "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
1930  "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
1931  "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
1932  "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
1933  "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
1934  "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
1936  psql_end_command(buf, "postgres");
1937 
1938  /*
1939  * Install any requested extensions. We use CREATE IF NOT EXISTS so that
1940  * this will work whether or not the extension is preinstalled.
1941  */
1942  for (sl = loadextension; sl != NULL; sl = sl->next)
1943  {
1944  header(_("installing %s"), sl->str);
1945  psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
1946  }
1947 }
#define _(x)
Definition: elog.c:89
static bool nolocale
Definition: pg_regress.c:89
static void psql_add_command(StringInfo buf, const char *query,...) pg_attribute_printf(2
Definition: pg_regress.c:1000
static void static void psql_end_command(StringInfo buf, const char *database)
Definition: pg_regress.c:1037
static _stringlist * loadextension
Definition: pg_regress.c:81
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:212
static char * encoding
Definition: pg_regress.c:84
#define psql_command(database,...)
Definition: pg_regress.c:1060
static char * buf
Definition: pg_test_fsync.c:67
char * dbname
Definition: streamutil.c:51

References _, buf, dbname, encoding, header(), loadextension, _stringlist::next, nolocale, psql_add_command(), psql_command, psql_end_command(), psql_start_command(), and _stringlist::str.

Referenced by regression_main().

◆ create_role()

static void create_role ( const char *  rolename,
const _stringlist granted_dbs 
)
static

Definition at line 1962 of file pg_regress.c.

1963 {
1965 
1966  header(_("creating role \"%s\""), rolename);
1967  psql_add_command(buf, "CREATE ROLE \"%s\" WITH LOGIN", rolename);
1968  for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
1969  {
1970  psql_add_command(buf, "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
1971  granted_dbs->str, rolename);
1972  }
1973  psql_end_command(buf, "postgres");
1974 }

References _, buf, header(), _stringlist::next, psql_add_command(), psql_end_command(), psql_start_command(), and _stringlist::str.

Referenced by regression_main().

◆ directory_exists()

static bool directory_exists ( const char *  dir)
static

Definition at line 1198 of file pg_regress.c.

1199 {
1200  struct stat st;
1201 
1202  if (stat(dir, &st) != 0)
1203  return false;
1204  if (S_ISDIR(st.st_mode))
1205  return true;
1206  return false;
1207 }
#define stat
Definition: win32_port.h:283
#define S_ISDIR(m)
Definition: win32_port.h:324

References S_ISDIR, stat::st_mode, and stat.

Referenced by open_result_files(), and regression_main().

◆ drop_database_if_exists()

static void drop_database_if_exists ( const char *  dbname)
static

Definition at line 1900 of file pg_regress.c.

1901 {
1903 
1904  header(_("dropping database \"%s\""), dbname);
1905  /* Set warning level so we don't see chatter about nonexistent DB */
1906  psql_add_command(buf, "SET client_min_messages = warning");
1907  psql_add_command(buf, "DROP DATABASE IF EXISTS \"%s\"", dbname);
1908  psql_end_command(buf, "postgres");
1909 }

References _, buf, dbname, header(), psql_add_command(), psql_end_command(), and psql_start_command().

Referenced by regression_main().

◆ drop_role_if_exists()

static void drop_role_if_exists ( const char *  rolename)
static

Definition at line 1950 of file pg_regress.c.

1951 {
1953 
1954  header(_("dropping role \"%s\""), rolename);
1955  /* Set warning level so we don't see chatter about nonexistent role */
1956  psql_add_command(buf, "SET client_min_messages = warning");
1957  psql_add_command(buf, "DROP ROLE IF EXISTS \"%s\"", rolename);
1958  psql_end_command(buf, "postgres");
1959 }

References _, buf, header(), psql_add_command(), psql_end_command(), and psql_start_command().

Referenced by regression_main().

◆ file_exists()

bool file_exists ( const char *  file)

Definition at line 1187 of file pg_regress.c.

1188 {
1189  FILE *f = fopen(file, "r");
1190 
1191  if (!f)
1192  return false;
1193  fclose(f);
1194  return true;
1195 }

Referenced by results_differ().

◆ file_line_count()

static int file_line_count ( const char *  file)
static

Definition at line 1165 of file pg_regress.c.

1166 {
1167  int c;
1168  int l = 0;
1169  FILE *f = fopen(file, "r");
1170 
1171  if (!f)
1172  {
1173  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1174  progname, file, strerror(errno));
1175  return -1;
1176  }
1177  while ((c = fgetc(f)) != EOF)
1178  {
1179  if (c == '\n')
1180  l++;
1181  }
1182  fclose(f);
1183  return l;
1184 }
static const char * progname
Definition: pg_regress.c:100
#define strerror
Definition: port.h:238
#define fprintf
Definition: port.h:229
char * c

References _, fprintf, progname, and strerror.

Referenced by results_differ().

◆ file_size()

static long file_size ( const char *  file)
static

Definition at line 1144 of file pg_regress.c.

1145 {
1146  long r;
1147  FILE *f = fopen(file, "r");
1148 
1149  if (!f)
1150  {
1151  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1152  progname, file, strerror(errno));
1153  return -1;
1154  }
1155  fseek(f, 0, SEEK_END);
1156  r = ftell(f);
1157  fclose(f);
1158  return r;
1159 }

References _, fprintf, progname, and strerror.

Referenced by regression_main(), and run_diff().

◆ free_stringlist()

static void free_stringlist ( _stringlist **  listhead)
static

Definition at line 180 of file pg_regress.c.

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 }
#define free(a)
Definition: header.h:65
static void free_stringlist(_stringlist **listhead)
Definition: pg_regress.c:180

References free.

Referenced by regression_main(), and run_schedule().

◆ get_alternative_expectfile()

static char* get_alternative_expectfile ( const char *  expectfile,
int  i 
)
static

Definition at line 1225 of file pg_regress.c.

1226 {
1227  char *last_dot;
1228  int ssize = strlen(expectfile) + 2 + 1;
1229  char *tmp;
1230  char *s;
1231 
1232  if (!(tmp = (char *) malloc(ssize)))
1233  return NULL;
1234 
1235  if (!(s = (char *) malloc(ssize)))
1236  {
1237  free(tmp);
1238  return NULL;
1239  }
1240 
1241  strcpy(tmp, expectfile);
1242  last_dot = strrchr(tmp, '.');
1243  if (!last_dot)
1244  {
1245  free(tmp);
1246  free(s);
1247  return NULL;
1248  }
1249  *last_dot = '\0';
1250  snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
1251  free(tmp);
1252  return s;
1253 }
#define malloc(a)
Definition: header.h:50
int i
Definition: isn.c:73
#define snprintf
Definition: port.h:225

References free, i, malloc, and snprintf.

Referenced by results_differ().

◆ get_expectfile()

static const char* get_expectfile ( const char *  testname,
const char *  file 
)
static

Definition at line 537 of file pg_regress.c.

538 {
539  char *file_type;
540  _resultmap *rm;
541 
542  /*
543  * Determine the file type from the file name. This is just what is
544  * following the last dot in the file name.
545  */
546  if (!file || !(file_type = strrchr(file, '.')))
547  return NULL;
548 
549  file_type++;
550 
551  for (rm = resultmap; rm != NULL; rm = rm->next)
552  {
553  if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
554  {
555  return rm->resultfile;
556  }
557  }
558 
559  return NULL;
560 }
static _resultmap * resultmap
Definition: pg_regress.c:111
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

References _resultmap::next, _resultmap::resultfile, resultmap, _resultmap::test, and _resultmap::type.

Referenced by results_differ().

◆ header()

◆ help()

static void help ( void  )
static

Definition at line 1977 of file pg_regress.c.

1978 {
1979  printf(_("PostgreSQL regression test driver\n"));
1980  printf(_("\n"));
1981  printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
1982  printf(_("\n"));
1983  printf(_("Options:\n"));
1984  printf(_(" --bindir=BINPATH use BINPATH for programs that are run;\n"));
1985  printf(_(" if empty, use PATH from the environment\n"));
1986  printf(_(" --config-auth=DATADIR update authentication settings for DATADIR\n"));
1987  printf(_(" --create-role=ROLE create the specified role before testing\n"));
1988  printf(_(" --dbname=DB use database DB (default \"regression\")\n"));
1989  printf(_(" --debug turn on debug mode in programs that are run\n"));
1990  printf(_(" --dlpath=DIR look for dynamic libraries in DIR\n"));
1991  printf(_(" --encoding=ENCODING use ENCODING as the encoding\n"));
1992  printf(_(" -h, --help show this help, then exit\n"));
1993  printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n"));
1994  printf(_(" --launcher=CMD use CMD as launcher of psql\n"));
1995  printf(_(" --load-extension=EXT load the named extension before running the\n"));
1996  printf(_(" tests; can appear multiple times\n"));
1997  printf(_(" --max-connections=N maximum number of concurrent connections\n"));
1998  printf(_(" (default is 0, meaning unlimited)\n"));
1999  printf(_(" --max-concurrent-tests=N maximum number of concurrent tests in schedule\n"));
2000  printf(_(" (default is 0, meaning unlimited)\n"));
2001  printf(_(" --outputdir=DIR place output files in DIR (default \".\")\n"));
2002  printf(_(" --schedule=FILE use test ordering schedule from FILE\n"));
2003  printf(_(" (can be used multiple times to concatenate)\n"));
2004  printf(_(" --temp-instance=DIR create a temporary instance in DIR\n"));
2005  printf(_(" --use-existing use an existing installation\n"));
2006  printf(_(" -V, --version output version information, then exit\n"));
2007  printf(_("\n"));
2008  printf(_("Options for \"temp-instance\" mode:\n"));
2009  printf(_(" --no-locale use C locale\n"));
2010  printf(_(" --port=PORT start postmaster on PORT\n"));
2011  printf(_(" --temp-config=FILE append contents of FILE to temporary config\n"));
2012  printf(_("\n"));
2013  printf(_("Options for using an existing installation:\n"));
2014  printf(_(" --host=HOST use postmaster running on HOST\n"));
2015  printf(_(" --port=PORT use postmaster running at PORT\n"));
2016  printf(_(" --user=USER connect as USER\n"));
2017  printf(_("\n"));
2018  printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
2019  printf(_("if the tests could not be run for some reason.\n"));
2020  printf(_("\n"));
2021  printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2022  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
2023 }
#define printf(...)
Definition: port.h:231

References _, printf, and progname.

Referenced by regression_main().

◆ initialize_environment()

static void initialize_environment ( void  )
static

Definition at line 566 of file pg_regress.c.

567 {
568  /*
569  * Set default application_name. (The test_start_function may choose to
570  * override this, but if it doesn't, we have something useful in place.)
571  */
572  setenv("PGAPPNAME", "pg_regress", 1);
573 
574  /*
575  * Set variables that the test scripts may need to refer to.
576  */
577  setenv("PG_ABS_SRCDIR", inputdir, 1);
578  setenv("PG_ABS_BUILDDIR", outputdir, 1);
579  setenv("PG_LIBDIR", dlpath, 1);
580  setenv("PG_DLSUFFIX", DLSUFFIX, 1);
581 
582  if (nolocale)
583  {
584  /*
585  * Clear out any non-C locale settings
586  */
587  unsetenv("LC_COLLATE");
588  unsetenv("LC_CTYPE");
589  unsetenv("LC_MONETARY");
590  unsetenv("LC_NUMERIC");
591  unsetenv("LC_TIME");
592  unsetenv("LANG");
593 
594  /*
595  * Most platforms have adopted the POSIX locale as their
596  * implementation-defined default locale. Exceptions include native
597  * Windows, macOS with --enable-nls, and Cygwin with --enable-nls.
598  * (Use of --enable-nls matters because libintl replaces setlocale().)
599  * Also, PostgreSQL does not support macOS with locale environment
600  * variables unset; see PostmasterMain().
601  */
602 #if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
603  setenv("LANG", "C", 1);
604 #endif
605  }
606 
607  /*
608  * Set translation-related settings to English; otherwise psql will
609  * produce translated messages and produce diffs. (XXX If we ever support
610  * translation of pg_regress, this needs to be moved elsewhere, where psql
611  * is actually called.)
612  */
613  unsetenv("LANGUAGE");
614  unsetenv("LC_ALL");
615  setenv("LC_MESSAGES", "C", 1);
616 
617  /*
618  * Set encoding as requested
619  */
620  if (encoding)
621  setenv("PGCLIENTENCODING", encoding, 1);
622  else
623  unsetenv("PGCLIENTENCODING");
624 
625  /*
626  * Set timezone and datestyle for datetime-related tests
627  */
628  setenv("PGTZ", "PST8PDT", 1);
629  setenv("PGDATESTYLE", "Postgres, MDY", 1);
630 
631  /*
632  * Likewise set intervalstyle to ensure consistent results. This is a bit
633  * more painful because we must use PGOPTIONS, and we want to preserve the
634  * user's ability to set other variables through that.
635  */
636  {
637  const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
638  const char *old_pgoptions = getenv("PGOPTIONS");
639  char *new_pgoptions;
640 
641  if (!old_pgoptions)
642  old_pgoptions = "";
643  new_pgoptions = psprintf("%s %s",
644  old_pgoptions, my_pgoptions);
645  setenv("PGOPTIONS", new_pgoptions, 1);
646  free(new_pgoptions);
647  }
648 
649  if (temp_instance)
650  {
651  /*
652  * Clear out any environment vars that might cause psql to connect to
653  * the wrong postmaster, or otherwise behave in nondefault ways. (Note
654  * we also use psql's -X switch consistently, so that ~/.psqlrc files
655  * won't mess things up.) Also, set PGPORT to the temp port, and set
656  * PGHOST depending on whether we are using TCP or Unix sockets.
657  *
658  * This list should be kept in sync with PostgreSQL/Test/Utils.pm.
659  */
660  unsetenv("PGCHANNELBINDING");
661  /* PGCLIENTENCODING, see above */
662  unsetenv("PGCONNECT_TIMEOUT");
663  unsetenv("PGDATA");
664  unsetenv("PGDATABASE");
665  unsetenv("PGGSSENCMODE");
666  unsetenv("PGGSSLIB");
667  /* PGHOSTADDR, see below */
668  unsetenv("PGKRBSRVNAME");
669  unsetenv("PGPASSFILE");
670  unsetenv("PGPASSWORD");
671  unsetenv("PGREQUIREPEER");
672  unsetenv("PGREQUIRESSL");
673  unsetenv("PGSERVICE");
674  unsetenv("PGSERVICEFILE");
675  unsetenv("PGSSLCERT");
676  unsetenv("PGSSLCRL");
677  unsetenv("PGSSLCRLDIR");
678  unsetenv("PGSSLKEY");
679  unsetenv("PGSSLMAXPROTOCOLVERSION");
680  unsetenv("PGSSLMINPROTOCOLVERSION");
681  unsetenv("PGSSLMODE");
682  unsetenv("PGSSLROOTCERT");
683  unsetenv("PGSSLSNI");
684  unsetenv("PGTARGETSESSIONATTRS");
685  unsetenv("PGUSER");
686  /* PGPORT, see below */
687  /* PGHOST, see below */
688 
689 #ifdef HAVE_UNIX_SOCKETS
690  if (hostname != NULL)
691  setenv("PGHOST", hostname, 1);
692  else
693  {
694  sockdir = getenv("PG_REGRESS_SOCK_DIR");
695  if (!sockdir)
696  sockdir = make_temp_sockdir();
697  setenv("PGHOST", sockdir, 1);
698  }
699 #else
700  Assert(hostname != NULL);
701  setenv("PGHOST", hostname, 1);
702 #endif
703  unsetenv("PGHOSTADDR");
704  if (port != -1)
705  {
706  char s[16];
707 
708  sprintf(s, "%d", port);
709  setenv("PGPORT", s, 1);
710  }
711  }
712  else
713  {
714  const char *pghost;
715  const char *pgport;
716 
717  /*
718  * When testing an existing install, we honor existing environment
719  * variables, except if they're overridden by command line options.
720  */
721  if (hostname != NULL)
722  {
723  setenv("PGHOST", hostname, 1);
724  unsetenv("PGHOSTADDR");
725  }
726  if (port != -1)
727  {
728  char s[16];
729 
730  sprintf(s, "%d", port);
731  setenv("PGPORT", s, 1);
732  }
733  if (user != NULL)
734  setenv("PGUSER", user, 1);
735 
736  /*
737  * However, we *don't* honor PGDATABASE, since we certainly don't wish
738  * to connect to whatever database the user might like as default.
739  * (Most tests override PGDATABASE anyway, but there are some ECPG
740  * test cases that don't.)
741  */
742  unsetenv("PGDATABASE");
743 
744  /*
745  * Report what we're connecting to
746  */
747  pghost = getenv("PGHOST");
748  pgport = getenv("PGPORT");
749  if (!pghost)
750  {
751  /* Keep this bit in sync with libpq's default host location: */
752 #ifdef HAVE_UNIX_SOCKETS
753  if (DEFAULT_PGSOCKET_DIR[0])
754  /* do nothing, we'll print "Unix socket" below */ ;
755  else
756 #endif
757  pghost = "localhost"; /* DefaultHost in fe-connect.c */
758  }
759 
760  if (pghost && pgport)
761  printf(_("(using postmaster on %s, port %s)\n"), pghost, pgport);
762  if (pghost && !pgport)
763  printf(_("(using postmaster on %s, default port)\n"), pghost);
764  if (!pghost && pgport)
765  printf(_("(using postmaster on Unix socket, port %s)\n"), pgport);
766  if (!pghost && !pgport)
767  printf(_("(using postmaster on Unix socket, default port)\n"));
768  }
769 
770  load_resultmap();
771 }
Assert(fmt[strlen(fmt) - 1] !='\n')
#define DEFAULT_PGSOCKET_DIR
static char * user
Definition: pg_regress.c:95
static void load_resultmap(void)
Definition: pg_regress.c:455
static int port
Definition: pg_regress.c:92
char * outputdir
Definition: pg_regress.c:78
char * inputdir
Definition: pg_regress.c:77
static char * temp_instance
Definition: pg_regress.c:87
static const char * sockdir
Definition: pg_regress.c:104
static char * dlpath
Definition: pg_regress.c:94
static char * hostname
Definition: pg_regress.c:91
const char * pghost
Definition: pgbench.c:307
const char * pgport
Definition: pgbench.c:308
#define sprintf
Definition: port.h:227
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define unsetenv(x)
Definition: win32_port.h:508
#define setenv(x, y, z)
Definition: win32_port.h:507

References _, Assert(), DEFAULT_PGSOCKET_DIR, dlpath, encoding, free, hostname, inputdir, load_resultmap(), nolocale, outputdir, pghost, pgport, port, printf, psprintf(), setenv, sockdir, sprintf, temp_instance, unsetenv, and user.

Referenced by regression_main().

◆ load_resultmap()

static void load_resultmap ( void  )
static

Definition at line 455 of file pg_regress.c.

456 {
457  char buf[MAXPGPATH];
458  FILE *f;
459 
460  /* scan the file ... */
461  snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
462  f = fopen(buf, "r");
463  if (!f)
464  {
465  /* OK if it doesn't exist, else complain */
466  if (errno == ENOENT)
467  return;
468  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
469  progname, buf, strerror(errno));
470  exit(2);
471  }
472 
473  while (fgets(buf, sizeof(buf), f))
474  {
475  char *platform;
476  char *file_type;
477  char *expected;
478  int i;
479 
480  /* strip trailing whitespace, especially the newline */
481  i = strlen(buf);
482  while (i > 0 && isspace((unsigned char) buf[i - 1]))
483  buf[--i] = '\0';
484 
485  /* parse out the line fields */
486  file_type = strchr(buf, ':');
487  if (!file_type)
488  {
489  fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
490  buf);
491  exit(2);
492  }
493  *file_type++ = '\0';
494 
495  platform = strchr(file_type, ':');
496  if (!platform)
497  {
498  fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
499  buf);
500  exit(2);
501  }
502  *platform++ = '\0';
503  expected = strchr(platform, '=');
504  if (!expected)
505  {
506  fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
507  buf);
508  exit(2);
509  }
510  *expected++ = '\0';
511 
512  /*
513  * if it's for current platform, save it in resultmap list. Note: by
514  * adding at the front of the list, we ensure that in ambiguous cases,
515  * the last match in the resultmap file is used. This mimics the
516  * behavior of the old shell script.
517  */
518  if (string_matches_pattern(host_platform, platform))
519  {
520  _resultmap *entry = pg_malloc(sizeof(_resultmap));
521 
522  entry->test = pg_strdup(buf);
523  entry->type = pg_strdup(file_type);
524  entry->resultfile = pg_strdup(expected);
525  entry->next = resultmap;
526  resultmap = entry;
527  }
528  }
529  fclose(f);
530 }
exit(1)
#define MAXPGPATH
char * host_platform
Definition: pg_regress.c:55
static bool string_matches_pattern(const char *str, const char *pattern)
Definition: pg_regress.c:381

References _, buf, exit(), fprintf, host_platform, i, inputdir, MAXPGPATH, _resultmap::next, pg_malloc(), pg_strdup(), progname, _resultmap::resultfile, resultmap, snprintf, strerror, string_matches_pattern(), _resultmap::test, and _resultmap::type.

Referenced by initialize_environment().

◆ log_child_failure()

static void log_child_failure ( int  exitstatus)
static

Definition at line 1514 of file pg_regress.c.

1515 {
1516  if (WIFEXITED(exitstatus))
1517  status(_(" (test process exited with exit code %d)"),
1518  WEXITSTATUS(exitstatus));
1519  else if (WIFSIGNALED(exitstatus))
1520  {
1521 #if defined(WIN32)
1522  status(_(" (test process was terminated by exception 0x%X)"),
1523  WTERMSIG(exitstatus));
1524 #else
1525  status(_(" (test process was terminated by signal %d: %s)"),
1526  WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
1527 #endif
1528  }
1529  else
1530  status(_(" (test process exited with unrecognized status %d)"),
1531  exitstatus);
1532 }
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
const char * pg_strsignal(int signum)
Definition: pgstrsignal.c:42
#define WIFEXITED(w)
Definition: win32_port.h:151
#define WIFSIGNALED(w)
Definition: win32_port.h:152
#define WTERMSIG(w)
Definition: win32_port.h:154
#define WEXITSTATUS(w)
Definition: win32_port.h:153

References _, pg_strsignal(), status(), WEXITSTATUS, WIFEXITED, WIFSIGNALED, and WTERMSIG.

Referenced by run_schedule(), and run_single_test().

◆ make_directory()

static void make_directory ( const char *  dir)
static

Definition at line 1211 of file pg_regress.c.

1212 {
1213  if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
1214  {
1215  fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
1216  progname, dir, strerror(errno));
1217  exit(2);
1218  }
1219 }
#define S_IRWXG
Definition: win32_port.h:309
#define S_IRWXO
Definition: win32_port.h:321
#define mkdir(a, b)
Definition: win32_port.h:71
#define S_IRWXU
Definition: win32_port.h:297

References _, exit(), fprintf, mkdir, progname, S_IRWXG, S_IRWXO, S_IRWXU, and strerror.

Referenced by open_result_files(), and regression_main().

◆ open_result_files()

static void open_result_files ( void  )
static

Definition at line 1860 of file pg_regress.c.

1861 {
1862  char file[MAXPGPATH];
1863  FILE *difffile;
1864 
1865  /* create outputdir directory if not present */
1868 
1869  /* create the log file (copy of running status output) */
1870  snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1871  logfilename = pg_strdup(file);
1872  logfile = fopen(logfilename, "w");
1873  if (!logfile)
1874  {
1875  fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1876  progname, logfilename, strerror(errno));
1877  exit(2);
1878  }
1879 
1880  /* create the diffs file as empty */
1881  snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1882  difffilename = pg_strdup(file);
1883  difffile = fopen(difffilename, "w");
1884  if (!difffile)
1885  {
1886  fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1887  progname, difffilename, strerror(errno));
1888  exit(2);
1889  }
1890  /* we don't keep the diffs file open continuously */
1891  fclose(difffile);
1892 
1893  /* also create the results directory if not present */
1894  snprintf(file, sizeof(file), "%s/results", outputdir);
1895  if (!directory_exists(file))
1896  make_directory(file);
1897 }
static bool directory_exists(const char *dir)
Definition: pg_regress.c:1198
static char * logfilename
Definition: pg_regress.c:101
static void make_directory(const char *dir)
Definition: pg_regress.c:1211
static char * difffilename
Definition: pg_regress.c:103
static FILE * logfile
Definition: pg_regress.c:102

References _, difffilename, directory_exists(), exit(), fprintf, logfile, logfilename, make_directory(), MAXPGPATH, outputdir, pg_strdup(), progname, snprintf, and strerror.

Referenced by regression_main().

◆ psql_add_command()

static void psql_add_command ( StringInfo  buf,
const char *  query,
  ... 
)
static

Definition at line 1000 of file pg_regress.c.

1001 {
1002  StringInfoData cmdbuf;
1003  const char *cmdptr;
1004 
1005  /* Add each command as a -c argument in the psql call */
1006  appendStringInfoString(buf, " -c \"");
1007 
1008  /* Generate the query with insertion of sprintf arguments */
1009  initStringInfo(&cmdbuf);
1010  for (;;)
1011  {
1012  va_list args;
1013  int needed;
1014 
1015  va_start(args, query);
1016  needed = appendStringInfoVA(&cmdbuf, query, args);
1017  va_end(args);
1018  if (needed == 0)
1019  break; /* success */
1020  enlargeStringInfo(&cmdbuf, needed);
1021  }
1022 
1023  /* Now escape any shell double-quote metacharacters */
1024  for (cmdptr = cmdbuf.data; *cmdptr; cmdptr++)
1025  {
1026  if (strchr("\\\"$`", *cmdptr))
1027  appendStringInfoChar(buf, '\\');
1028  appendStringInfoChar(buf, *cmdptr);
1029  }
1030 
1031  appendStringInfoChar(buf, '"');
1032 
1033  pfree(cmdbuf.data);
1034 }
void pfree(void *pointer)
Definition: mcxt.c:1175
int appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
Definition: stringinfo.c:133
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

References appendStringInfoChar(), appendStringInfoString(), appendStringInfoVA(), generate_unaccent_rules::args, buf, StringInfoData::data, enlargeStringInfo(), initStringInfo(), pfree(), va_end(), and va_start().

Referenced by create_database(), create_role(), drop_database_if_exists(), and drop_role_if_exists().

◆ psql_end_command()

static void psql_end_command ( StringInfo  buf,
const char *  database 
)
static

Definition at line 1037 of file pg_regress.c.

1038 {
1039  /* Add the database name --- assume it needs no extra escaping */
1041  " \"%s\"",
1042  database);
1043 
1044  /* And now we can execute the shell command */
1045  if (system(buf->data) != 0)
1046  {
1047  /* psql probably already reported the error */
1048  fprintf(stderr, _("command failed: %s\n"), buf->data);
1049  exit(2);
1050  }
1051 
1052  /* Clean up */
1053  pfree(buf->data);
1054  pfree(buf);
1055 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91

References _, appendStringInfo(), buf, exit(), fprintf, and pfree().

Referenced by create_database(), create_role(), drop_database_if_exists(), and drop_role_if_exists().

◆ psql_start_command()

static StringInfo psql_start_command ( void  )
static

Definition at line 988 of file pg_regress.c.

989 {
991 
993  "\"%s%spsql\" -X",
994  bindir ? bindir : "",
995  bindir ? "/" : "");
996  return buf;
997 }
char * bindir
Definition: pg_regress.c:79
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References appendStringInfo(), bindir, buf, and makeStringInfo().

Referenced by create_database(), create_role(), drop_database_if_exists(), and drop_role_if_exists().

◆ regression_main()

int regression_main ( int  argc,
char *  argv[],
init_function  ifunc,
test_start_function  startfunc,
postprocess_result_function  postfunc 
)

Definition at line 2026 of file pg_regress.c.

2030 {
2031  static struct option long_options[] = {
2032  {"help", no_argument, NULL, 'h'},
2033  {"version", no_argument, NULL, 'V'},
2034  {"dbname", required_argument, NULL, 1},
2035  {"debug", no_argument, NULL, 2},
2036  {"inputdir", required_argument, NULL, 3},
2037  {"max-connections", required_argument, NULL, 5},
2038  {"encoding", required_argument, NULL, 6},
2039  {"outputdir", required_argument, NULL, 7},
2040  {"schedule", required_argument, NULL, 8},
2041  {"temp-instance", required_argument, NULL, 9},
2042  {"no-locale", no_argument, NULL, 10},
2043  {"host", required_argument, NULL, 13},
2044  {"port", required_argument, NULL, 14},
2045  {"user", required_argument, NULL, 15},
2046  {"bindir", required_argument, NULL, 16},
2047  {"dlpath", required_argument, NULL, 17},
2048  {"create-role", required_argument, NULL, 18},
2049  {"temp-config", required_argument, NULL, 19},
2050  {"use-existing", no_argument, NULL, 20},
2051  {"launcher", required_argument, NULL, 21},
2052  {"load-extension", required_argument, NULL, 22},
2053  {"config-auth", required_argument, NULL, 24},
2054  {"max-concurrent-tests", required_argument, NULL, 25},
2055  {NULL, 0, NULL, 0}
2056  };
2057 
2058  bool use_unix_sockets;
2059  _stringlist *sl;
2060  int c;
2061  int i;
2062  int option_index;
2063  char buf[MAXPGPATH * 4];
2064  char buf2[MAXPGPATH * 4];
2065 
2066  pg_logging_init(argv[0]);
2067  progname = get_progname(argv[0]);
2068  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
2069 
2071 
2072  atexit(stop_postmaster);
2073 
2074 #if !defined(HAVE_UNIX_SOCKETS)
2075  use_unix_sockets = false;
2076 #elif defined(WIN32)
2077 
2078  /*
2079  * We don't use Unix-domain sockets on Windows by default, even if the
2080  * build supports them. (See comment at remove_temp() for a reason.)
2081  * Override at your own risk.
2082  */
2083  use_unix_sockets = getenv("PG_TEST_USE_UNIX_SOCKETS") ? true : false;
2084 #else
2085  use_unix_sockets = true;
2086 #endif
2087 
2088  if (!use_unix_sockets)
2089  hostname = "localhost";
2090 
2091  /*
2092  * We call the initialization function here because that way we can set
2093  * default parameters and let them be overwritten by the commandline.
2094  */
2095  ifunc(argc, argv);
2096 
2097  if (getenv("PG_REGRESS_DIFF_OPTS"))
2098  pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
2099 
2100  while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
2101  {
2102  switch (c)
2103  {
2104  case 'h':
2105  help();
2106  exit(0);
2107  case 'V':
2108  puts("pg_regress (PostgreSQL) " PG_VERSION);
2109  exit(0);
2110  case 1:
2111 
2112  /*
2113  * If a default database was specified, we need to remove it
2114  * before we add the specified one.
2115  */
2118  break;
2119  case 2:
2120  debug = true;
2121  break;
2122  case 3:
2124  break;
2125  case 5:
2126  max_connections = atoi(optarg);
2127  break;
2128  case 6:
2130  break;
2131  case 7:
2133  break;
2134  case 8:
2136  break;
2137  case 9:
2139  break;
2140  case 10:
2141  nolocale = true;
2142  break;
2143  case 13:
2145  break;
2146  case 14:
2147  port = atoi(optarg);
2148  port_specified_by_user = true;
2149  break;
2150  case 15:
2151  user = pg_strdup(optarg);
2152  break;
2153  case 16:
2154  /* "--bindir=" means to use PATH */
2155  if (strlen(optarg))
2156  bindir = pg_strdup(optarg);
2157  else
2158  bindir = NULL;
2159  break;
2160  case 17:
2161  dlpath = pg_strdup(optarg);
2162  break;
2163  case 18:
2165  break;
2166  case 19:
2168  break;
2169  case 20:
2170  use_existing = true;
2171  break;
2172  case 21:
2174  break;
2175  case 22:
2177  break;
2178  case 24:
2180  break;
2181  case 25:
2182  max_concurrent_tests = atoi(optarg);
2183  break;
2184  default:
2185  /* getopt_long already emitted a complaint */
2186  fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
2187  progname);
2188  exit(2);
2189  }
2190  }
2191 
2192  /*
2193  * if we still have arguments, they are extra tests to run
2194  */
2195  while (argc - optind >= 1)
2196  {
2198  optind++;
2199  }
2200 
2201  if (config_auth_datadir)
2202  {
2203 #ifdef ENABLE_SSPI
2204  if (!use_unix_sockets)
2205  config_sspi_auth(config_auth_datadir, user);
2206 #endif
2207  exit(0);
2208  }
2209 
2211 
2212  /*
2213  * To reduce chances of interference with parallel installations, use
2214  * a port number starting in the private range (49152-65535)
2215  * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
2216  * systems; elsewhere, the use of a private socket directory already
2217  * prevents interference.
2218  */
2219  port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
2220 
2224 
2225  /*
2226  * Initialization
2227  */
2229 
2231 
2232 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
2233  unlimit_core_size();
2234 #endif
2235 
2236  if (temp_instance)
2237  {
2238  FILE *pg_conf;
2239  const char *env_wait;
2240  int wait_seconds;
2241 
2242  /*
2243  * Prepare the temp instance
2244  */
2245 
2247  {
2248  header(_("removing existing temp instance"));
2249  if (!rmtree(temp_instance, true))
2250  {
2251  fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2253  exit(2);
2254  }
2255  }
2256 
2257  header(_("creating temporary instance"));
2258 
2259  /* make the temp instance top directory */
2261 
2262  /* and a directory for log files */
2263  snprintf(buf, sizeof(buf), "%s/log", outputdir);
2264  if (!directory_exists(buf))
2266 
2267  /* initdb */
2268  header(_("initializing database system"));
2269  snprintf(buf, sizeof(buf),
2270  "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync%s%s > \"%s/log/initdb.log\" 2>&1",
2271  bindir ? bindir : "",
2272  bindir ? "/" : "",
2273  temp_instance,
2274  debug ? " --debug" : "",
2275  nolocale ? " --no-locale" : "",
2276  outputdir);
2277  if (system(buf))
2278  {
2279  fprintf(stderr, _("\n%s: initdb failed\nExamine %s/log/initdb.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
2280  exit(2);
2281  }
2282 
2283  /*
2284  * Adjust the default postgresql.conf for regression testing. The user
2285  * can specify a file to be appended; in any case we expand logging
2286  * and set max_prepared_transactions to enable testing of prepared
2287  * xacts. (Note: to reduce the probability of unexpected shmmax
2288  * failures, don't set max_prepared_transactions any higher than
2289  * actually needed by the prepared_xacts regression test.)
2290  */
2291  snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
2292  pg_conf = fopen(buf, "a");
2293  if (pg_conf == NULL)
2294  {
2295  fprintf(stderr, _("\n%s: could not open \"%s\" for adding extra config: %s\n"), progname, buf, strerror(errno));
2296  exit(2);
2297  }
2298  fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
2299  fputs("log_autovacuum_min_duration = 0\n", pg_conf);
2300  fputs("log_checkpoints = on\n", pg_conf);
2301  fputs("log_line_prefix = '%m %b[%p] %q%a '\n", pg_conf);
2302  fputs("log_lock_waits = on\n", pg_conf);
2303  fputs("log_temp_files = 128kB\n", pg_conf);
2304  fputs("max_prepared_transactions = 2\n", pg_conf);
2305 
2306  for (sl = temp_configs; sl != NULL; sl = sl->next)
2307  {
2308  char *temp_config = sl->str;
2309  FILE *extra_conf;
2310  char line_buf[1024];
2311 
2312  extra_conf = fopen(temp_config, "r");
2313  if (extra_conf == NULL)
2314  {
2315  fprintf(stderr, _("\n%s: could not open \"%s\" to read extra config: %s\n"), progname, temp_config, strerror(errno));
2316  exit(2);
2317  }
2318  while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
2319  fputs(line_buf, pg_conf);
2320  fclose(extra_conf);
2321  }
2322 
2323  fclose(pg_conf);
2324 
2325 #ifdef ENABLE_SSPI
2326  if (!use_unix_sockets)
2327  {
2328  /*
2329  * Since we successfully used the same buffer for the much-longer
2330  * "initdb" command, this can't truncate.
2331  */
2332  snprintf(buf, sizeof(buf), "%s/data", temp_instance);
2333  config_sspi_auth(buf, NULL);
2334  }
2335 #elif !defined(HAVE_UNIX_SOCKETS)
2336 #error Platform has no means to secure the test installation.
2337 #endif
2338 
2339  /*
2340  * Check if there is a postmaster running already.
2341  */
2342  snprintf(buf2, sizeof(buf2),
2343  "\"%s%spsql\" -X postgres <%s 2>%s",
2344  bindir ? bindir : "",
2345  bindir ? "/" : "",
2346  DEVNULL, DEVNULL);
2347 
2348  for (i = 0; i < 16; i++)
2349  {
2350  if (system(buf2) == 0)
2351  {
2352  char s[16];
2353 
2354  if (port_specified_by_user || i == 15)
2355  {
2356  fprintf(stderr, _("port %d apparently in use\n"), port);
2358  fprintf(stderr, _("%s: could not determine an available port\n"), progname);
2359  fprintf(stderr, _("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.\n"));
2360  exit(2);
2361  }
2362 
2363  fprintf(stderr, _("port %d apparently in use, trying %d\n"), port, port + 1);
2364  port++;
2365  sprintf(s, "%d", port);
2366  setenv("PGPORT", s, 1);
2367  }
2368  else
2369  break;
2370  }
2371 
2372  /*
2373  * Start the temp postmaster
2374  */
2375  header(_("starting postmaster"));
2376  snprintf(buf, sizeof(buf),
2377  "\"%s%spostgres\" -D \"%s/data\" -F%s "
2378  "-c \"listen_addresses=%s\" -k \"%s\" "
2379  "> \"%s/log/postmaster.log\" 2>&1",
2380  bindir ? bindir : "",
2381  bindir ? "/" : "",
2382  temp_instance, debug ? " -d 5" : "",
2383  hostname ? hostname : "", sockdir ? sockdir : "",
2384  outputdir);
2386  if (postmaster_pid == INVALID_PID)
2387  {
2388  fprintf(stderr, _("\n%s: could not spawn postmaster: %s\n"),
2389  progname, strerror(errno));
2390  exit(2);
2391  }
2392 
2393  /*
2394  * Wait till postmaster is able to accept connections; normally this
2395  * is only a second or so, but Cygwin is reportedly *much* slower, and
2396  * test builds using Valgrind or similar tools might be too. Hence,
2397  * allow the default timeout of 60 seconds to be overridden from the
2398  * PGCTLTIMEOUT environment variable.
2399  */
2400  env_wait = getenv("PGCTLTIMEOUT");
2401  if (env_wait != NULL)
2402  {
2403  wait_seconds = atoi(env_wait);
2404  if (wait_seconds <= 0)
2405  wait_seconds = 60;
2406  }
2407  else
2408  wait_seconds = 60;
2409 
2410  for (i = 0; i < wait_seconds; i++)
2411  {
2412  /* Done if psql succeeds */
2413  if (system(buf2) == 0)
2414  break;
2415 
2416  /*
2417  * Fail immediately if postmaster has exited
2418  */
2419 #ifndef WIN32
2420  if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
2421 #else
2422  if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
2423 #endif
2424  {
2425  fprintf(stderr, _("\n%s: postmaster failed\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
2426  exit(2);
2427  }
2428 
2429  pg_usleep(1000000L);
2430  }
2431  if (i >= wait_seconds)
2432  {
2433  fprintf(stderr, _("\n%s: postmaster did not respond within %d seconds\nExamine %s/log/postmaster.log for the reason\n"),
2435 
2436  /*
2437  * If we get here, the postmaster is probably wedged somewhere in
2438  * startup. Try to kill it ungracefully rather than leaving a
2439  * stuck postmaster that might interfere with subsequent test
2440  * attempts.
2441  */
2442 #ifndef WIN32
2443  if (kill(postmaster_pid, SIGKILL) != 0 &&
2444  errno != ESRCH)
2445  fprintf(stderr, _("\n%s: could not kill failed postmaster: %s\n"),
2446  progname, strerror(errno));
2447 #else
2448  if (TerminateProcess(postmaster_pid, 255) == 0)
2449  fprintf(stderr, _("\n%s: could not kill failed postmaster: error code %lu\n"),
2450  progname, GetLastError());
2451 #endif
2452 
2453  exit(2);
2454  }
2455 
2456  postmaster_running = true;
2457 
2458 #ifdef _WIN64
2459 /* need a series of two casts to convert HANDLE without compiler warning */
2460 #define ULONGPID(x) (unsigned long) (unsigned long long) (x)
2461 #else
2462 #define ULONGPID(x) (unsigned long) (x)
2463 #endif
2464  printf(_("running on port %d with PID %lu\n"),
2466  }
2467  else
2468  {
2469  /*
2470  * Using an existing installation, so may need to get rid of
2471  * pre-existing database(s) and role(s)
2472  */
2473  if (!use_existing)
2474  {
2475  for (sl = dblist; sl; sl = sl->next)
2477  for (sl = extraroles; sl; sl = sl->next)
2478  drop_role_if_exists(sl->str);
2479  }
2480  }
2481 
2482  /*
2483  * Create the test database(s) and role(s)
2484  */
2485  if (!use_existing)
2486  {
2487  for (sl = dblist; sl; sl = sl->next)
2488  create_database(sl->str);
2489  for (sl = extraroles; sl; sl = sl->next)
2490  create_role(sl->str, dblist);
2491  }
2492 
2493  /*
2494  * Ready to run the tests
2495  */
2496  header(_("running regression test queries"));
2497 
2498  for (sl = schedulelist; sl != NULL; sl = sl->next)
2499  {
2500  run_schedule(sl->str, startfunc, postfunc);
2501  }
2502 
2503  for (sl = extra_tests; sl != NULL; sl = sl->next)
2504  {
2505  run_single_test(sl->str, startfunc, postfunc);
2506  }
2507 
2508  /*
2509  * Shut down temp installation's postmaster
2510  */
2511  if (temp_instance)
2512  {
2513  header(_("shutting down postmaster"));
2514  stop_postmaster();
2515  }
2516 
2517  /*
2518  * If there were no errors, remove the temp instance immediately to
2519  * conserve disk space. (If there were errors, we leave the instance in
2520  * place for possible manual investigation.)
2521  */
2522  if (temp_instance && fail_count == 0 && fail_ignore_count == 0)
2523  {
2524  header(_("removing temporary instance"));
2525  if (!rmtree(temp_instance, true))
2526  fprintf(stderr, _("\n%s: could not remove temp instance \"%s\"\n"),
2528  }
2529 
2530  fclose(logfile);
2531 
2532  /*
2533  * Emit nice-looking summary message
2534  */
2535  if (fail_count == 0 && fail_ignore_count == 0)
2536  snprintf(buf, sizeof(buf),
2537  _(" All %d tests passed. "),
2538  success_count);
2539  else if (fail_count == 0) /* fail_count=0, fail_ignore_count>0 */
2540  snprintf(buf, sizeof(buf),
2541  _(" %d of %d tests passed, %d failed test(s) ignored. "),
2542  success_count,
2545  else if (fail_ignore_count == 0) /* fail_count>0 && fail_ignore_count=0 */
2546  snprintf(buf, sizeof(buf),
2547  _(" %d of %d tests failed. "),
2548  fail_count,
2550  else
2551  /* fail_count>0 && fail_ignore_count>0 */
2552  snprintf(buf, sizeof(buf),
2553  _(" %d of %d tests failed, %d of these failures ignored. "),
2557 
2558  putchar('\n');
2559  for (i = strlen(buf); i > 0; i--)
2560  putchar('=');
2561  printf("\n%s\n", buf);
2562  for (i = strlen(buf); i > 0; i--)
2563  putchar('=');
2564  putchar('\n');
2565  putchar('\n');
2566 
2567  if (file_size(difffilename) > 0)
2568  {
2569  printf(_("The differences that caused some tests to fail can be viewed in the\n"
2570  "file \"%s\". A copy of the test summary that you see\n"
2571  "above is saved in the file \"%s\".\n\n"),
2573  }
2574  else
2575  {
2576  unlink(difffilename);
2577  unlink(logfilename);
2578  }
2579 
2580  if (fail_count != 0)
2581  exit(1);
2582 
2583  return 0;
2584 }
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1212
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:446
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
return true
Definition: isn.c:126
void pg_logging_init(const char *argv0)
Definition: logging.c:83
static int wait_seconds
Definition: pg_ctl.c:80
PGDLLIMPORT int optind
Definition: getopt.c:50
PGDLLIMPORT char * optarg
Definition: getopt.c:52
static bool use_existing
Definition: pg_regress.c:90
static void open_result_files(void)
Definition: pg_regress.c:1860
static int max_connections
Definition: pg_regress.c:82
static bool port_specified_by_user
Definition: pg_regress.c:93
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:1912
static void drop_role_if_exists(const char *rolename)
Definition: pg_regress.c:1950
bool debug
Definition: pg_regress.c:76
static _stringlist * schedulelist
Definition: pg_regress.c:85
static _stringlist * temp_configs
Definition: pg_regress.c:88
static _stringlist * extra_tests
Definition: pg_regress.c:86
static void split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
Definition: pg_regress.c:195
static void run_single_test(const char *test, test_start_function startfunc, postprocess_result_function postfunc)
Definition: pg_regress.c:1792
char * launcher
Definition: pg_regress.c:80
const char * pretty_diff_opts
Definition: pg_regress.c:68
static char * config_auth_datadir
Definition: pg_regress.c:97
static void drop_database_if_exists(const char *dbname)
Definition: pg_regress.c:1900
static void initialize_environment(void)
Definition: pg_regress.c:566
static int fail_ignore_count
Definition: pg_regress.c:118
static void help(void)
Definition: pg_regress.c:1977
static long file_size(const char *file)
Definition: pg_regress.c:1144
static bool postmaster_running
Definition: pg_regress.c:114
_stringlist * dblist
Definition: pg_regress.c:75
static _stringlist * extraroles
Definition: pg_regress.c:96
PID_TYPE spawn_process(const char *cmdline)
Definition: pg_regress.c:1073
static void create_role(const char *rolename, const _stringlist *granted_dbs)
Definition: pg_regress.c:1962
static void run_schedule(const char *schedule, test_start_function startfunc, postprocess_result_function postfunc)
Definition: pg_regress.c:1538
void add_stringlist_item(_stringlist **listhead, const char *str)
Definition: pg_regress.c:159
static int success_count
Definition: pg_regress.c:116
#define ULONGPID(x)
static int fail_count
Definition: pg_regress.c:117
static PID_TYPE postmaster_pid
Definition: pg_regress.c:113
#define INVALID_PID
Definition: pg_regress.h:15
char * make_absolute_path(const char *path)
Definition: path.c:729
const char * get_progname(const char *argv0)
Definition: path.c:574
#define DEVNULL
Definition: port.h:156
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
#define kill(pid, sig)
Definition: win32_port.h:464
#define SIGKILL
Definition: win32_port.h:171

References _, add_stringlist_item(), bindir, buf, config_auth_datadir, create_database(), create_role(), dblist, debug, DEVNULL, difffilename, directory_exists(), dlpath, drop_database_if_exists(), drop_role_if_exists(), encoding, exit(), extra_tests, extraroles, fail_count, fail_ignore_count, file_size(), fprintf, free_stringlist(), get_progname(), get_restricted_token(), getopt_long(), header(), help(), hostname, i, initialize_environment(), inputdir, INVALID_PID, kill, launcher, loadextension, logfile, logfilename, make_absolute_path(), make_directory(), max_concurrent_tests, max_connections, MAXPGPATH, _stringlist::next, no_argument, nolocale, open_result_files(), optarg, optind, outputdir, pg_logging_init(), pg_strdup(), PG_TEXTDOMAIN, pg_usleep(), port, port_specified_by_user, postmaster_pid, postmaster_running, pretty_diff_opts, printf, progname, required_argument, rmtree(), run_schedule(), run_single_test(), schedulelist, set_pglocale_pgservice(), setenv, SIGKILL, snprintf, sockdir, spawn_process(), split_to_stringlist(), sprintf, stop_postmaster(), _stringlist::str, strerror, success_count, temp_configs, temp_instance, true, ULONGPID, use_existing, user, and wait_seconds.

Referenced by main().

◆ results_differ()

static bool results_differ ( const char *  testname,
const char *  resultsfile,
const char *  default_expectfile 
)
static

Definition at line 1292 of file pg_regress.c.

1293 {
1294  char expectfile[MAXPGPATH];
1295  char diff[MAXPGPATH];
1296  char cmd[MAXPGPATH * 3];
1297  char best_expect_file[MAXPGPATH];
1298  FILE *difffile;
1299  int best_line_count;
1300  int i;
1301  int l;
1302  const char *platform_expectfile;
1303 
1304  /*
1305  * We can pass either the resultsfile or the expectfile, they should have
1306  * the same type (filename.type) anyway.
1307  */
1308  platform_expectfile = get_expectfile(testname, resultsfile);
1309 
1310  strlcpy(expectfile, default_expectfile, sizeof(expectfile));
1311  if (platform_expectfile)
1312  {
1313  /*
1314  * Replace everything after the last slash in expectfile with what the
1315  * platform_expectfile contains.
1316  */
1317  char *p = strrchr(expectfile, '/');
1318 
1319  if (p)
1320  strcpy(++p, platform_expectfile);
1321  }
1322 
1323  /* Name to use for temporary diff file */
1324  snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
1325 
1326  /* OK, run the diff */
1327  snprintf(cmd, sizeof(cmd),
1328  "diff %s \"%s\" \"%s\" > \"%s\"",
1329  basic_diff_opts, expectfile, resultsfile, diff);
1330 
1331  /* Is the diff file empty? */
1332  if (run_diff(cmd, diff) == 0)
1333  {
1334  unlink(diff);
1335  return false;
1336  }
1337 
1338  /* There may be secondary comparison files that match better */
1339  best_line_count = file_line_count(diff);
1340  strcpy(best_expect_file, expectfile);
1341 
1342  for (i = 0; i <= 9; i++)
1343  {
1344  char *alt_expectfile;
1345 
1346  alt_expectfile = get_alternative_expectfile(expectfile, i);
1347  if (!alt_expectfile)
1348  {
1349  fprintf(stderr, _("Unable to check secondary comparison files: %s\n"),
1350  strerror(errno));
1351  exit(2);
1352  }
1353 
1354  if (!file_exists(alt_expectfile))
1355  {
1356  free(alt_expectfile);
1357  continue;
1358  }
1359 
1360  snprintf(cmd, sizeof(cmd),
1361  "diff %s \"%s\" \"%s\" > \"%s\"",
1362  basic_diff_opts, alt_expectfile, resultsfile, diff);
1363 
1364  if (run_diff(cmd, diff) == 0)
1365  {
1366  unlink(diff);
1367  free(alt_expectfile);
1368  return false;
1369  }
1370 
1371  l = file_line_count(diff);
1372  if (l < best_line_count)
1373  {
1374  /* This diff was a better match than the last one */
1375  best_line_count = l;
1376  strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
1377  }
1378  free(alt_expectfile);
1379  }
1380 
1381  /*
1382  * fall back on the canonical results file if we haven't tried it yet and
1383  * haven't found a complete match yet.
1384  */
1385 
1386  if (platform_expectfile)
1387  {
1388  snprintf(cmd, sizeof(cmd),
1389  "diff %s \"%s\" \"%s\" > \"%s\"",
1390  basic_diff_opts, default_expectfile, resultsfile, diff);
1391 
1392  if (run_diff(cmd, diff) == 0)
1393  {
1394  /* No diff = no changes = good */
1395  unlink(diff);
1396  return false;
1397  }
1398 
1399  l = file_line_count(diff);
1400  if (l < best_line_count)
1401  {
1402  /* This diff was a better match than the last one */
1403  best_line_count = l;
1404  strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
1405  }
1406  }
1407 
1408  /*
1409  * Use the best comparison file to generate the "pretty" diff, which we
1410  * append to the diffs summary file.
1411  */
1412 
1413  /* Write diff header */
1414  difffile = fopen(difffilename, "a");
1415  if (difffile)
1416  {
1417  fprintf(difffile,
1418  "diff %s %s %s\n",
1419  pretty_diff_opts, best_expect_file, resultsfile);
1420  fclose(difffile);
1421  }
1422 
1423  /* Run diff */
1424  snprintf(cmd, sizeof(cmd),
1425  "diff %s \"%s\" \"%s\" >> \"%s\"",
1426  pretty_diff_opts, best_expect_file, resultsfile, difffilename);
1427  run_diff(cmd, difffilename);
1428 
1429  unlink(diff);
1430  return true;
1431 }
static int file_line_count(const char *file)
Definition: pg_regress.c:1165
bool file_exists(const char *file)
Definition: pg_regress.c:1187
static int run_diff(const char *cmd, const char *filename)
Definition: pg_regress.c:1259
static const char * get_expectfile(const char *testname, const char *file)
Definition: pg_regress.c:537
const char * basic_diff_opts
Definition: pg_regress.c:67
static char * get_alternative_expectfile(const char *expectfile, int i)
Definition: pg_regress.c:1225
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

References _, basic_diff_opts, difffilename, exit(), file_exists(), file_line_count(), fprintf, free, get_alternative_expectfile(), get_expectfile(), i, MAXPGPATH, pretty_diff_opts, run_diff(), snprintf, strerror, and strlcpy().

Referenced by run_schedule(), and run_single_test().

◆ run_diff()

static int run_diff ( const char *  cmd,
const char *  filename 
)
static

Definition at line 1259 of file pg_regress.c.

1260 {
1261  int r;
1262 
1263  r = system(cmd);
1264  if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
1265  {
1266  fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
1267  exit(2);
1268  }
1269 #ifdef WIN32
1270 
1271  /*
1272  * On WIN32, if the 'diff' command cannot be found, system() returns 1,
1273  * but produces nothing to stdout, so we check for that here.
1274  */
1275  if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
1276  {
1277  fprintf(stderr, _("diff command not found: %s\n"), cmd);
1278  exit(2);
1279  }
1280 #endif
1281 
1282  return WEXITSTATUS(r);
1283 }
static char * filename
Definition: pg_dumpall.c:94

References _, exit(), file_size(), filename, fprintf, WEXITSTATUS, and WIFEXITED.

Referenced by results_differ().

◆ run_schedule()

static void run_schedule ( const char *  schedule,
test_start_function  startfunc,
postprocess_result_function  postfunc 
)
static

Definition at line 1538 of file pg_regress.c.

1540 {
1541 #define MAX_PARALLEL_TESTS 100
1542  char *tests[MAX_PARALLEL_TESTS];
1543  _stringlist *resultfiles[MAX_PARALLEL_TESTS];
1544  _stringlist *expectfiles[MAX_PARALLEL_TESTS];
1547  instr_time starttimes[MAX_PARALLEL_TESTS];
1548  instr_time stoptimes[MAX_PARALLEL_TESTS];
1549  int statuses[MAX_PARALLEL_TESTS];
1550  _stringlist *ignorelist = NULL;
1551  char scbuf[1024];
1552  FILE *scf;
1553  int line_num = 0;
1554 
1555  memset(tests, 0, sizeof(tests));
1556  memset(resultfiles, 0, sizeof(resultfiles));
1557  memset(expectfiles, 0, sizeof(expectfiles));
1558  memset(tags, 0, sizeof(tags));
1559 
1560  scf = fopen(schedule, "r");
1561  if (!scf)
1562  {
1563  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1564  progname, schedule, strerror(errno));
1565  exit(2);
1566  }
1567 
1568  while (fgets(scbuf, sizeof(scbuf), scf))
1569  {
1570  char *test = NULL;
1571  char *c;
1572  int num_tests;
1573  bool inword;
1574  int i;
1575 
1576  line_num++;
1577 
1578  /* strip trailing whitespace, especially the newline */
1579  i = strlen(scbuf);
1580  while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
1581  scbuf[--i] = '\0';
1582 
1583  if (scbuf[0] == '\0' || scbuf[0] == '#')
1584  continue;
1585  if (strncmp(scbuf, "test: ", 6) == 0)
1586  test = scbuf + 6;
1587  else if (strncmp(scbuf, "ignore: ", 8) == 0)
1588  {
1589  c = scbuf + 8;
1590  while (*c && isspace((unsigned char) *c))
1591  c++;
1592  add_stringlist_item(&ignorelist, c);
1593 
1594  /*
1595  * Note: ignore: lines do not run the test, they just say that
1596  * failure of this test when run later on is to be ignored. A bit
1597  * odd but that's how the shell-script version did it.
1598  */
1599  continue;
1600  }
1601  else
1602  {
1603  fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1604  schedule, line_num, scbuf);
1605  exit(2);
1606  }
1607 
1608  num_tests = 0;
1609  inword = false;
1610  for (c = test;; c++)
1611  {
1612  if (*c == '\0' || isspace((unsigned char) *c))
1613  {
1614  if (inword)
1615  {
1616  /* Reached end of a test name */
1617  char sav;
1618 
1619  if (num_tests >= MAX_PARALLEL_TESTS)
1620  {
1621  fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1622  MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
1623  exit(2);
1624  }
1625  sav = *c;
1626  *c = '\0';
1627  tests[num_tests] = pg_strdup(test);
1628  num_tests++;
1629  *c = sav;
1630  inword = false;
1631  }
1632  if (*c == '\0')
1633  break; /* loop exit is here */
1634  }
1635  else if (!inword)
1636  {
1637  /* Start of a test name */
1638  test = c;
1639  inword = true;
1640  }
1641  }
1642 
1643  if (num_tests == 0)
1644  {
1645  fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1646  schedule, line_num, scbuf);
1647  exit(2);
1648  }
1649 
1650  if (num_tests == 1)
1651  {
1652  status(_("test %-28s ... "), tests[0]);
1653  pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
1654  INSTR_TIME_SET_CURRENT(starttimes[0]);
1655  wait_for_tests(pids, statuses, stoptimes, NULL, 1);
1656  /* status line is finished below */
1657  }
1658  else if (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
1659  {
1660  fprintf(stderr, _("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s\n"),
1661  max_concurrent_tests, schedule, line_num, scbuf);
1662  exit(2);
1663  }
1664  else if (max_connections > 0 && max_connections < num_tests)
1665  {
1666  int oldest = 0;
1667 
1668  status(_("parallel group (%d tests, in groups of %d): "),
1669  num_tests, max_connections);
1670  for (i = 0; i < num_tests; i++)
1671  {
1672  if (i - oldest >= max_connections)
1673  {
1674  wait_for_tests(pids + oldest, statuses + oldest,
1675  stoptimes + oldest,
1676  tests + oldest, i - oldest);
1677  oldest = i;
1678  }
1679  pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1680  INSTR_TIME_SET_CURRENT(starttimes[i]);
1681  }
1682  wait_for_tests(pids + oldest, statuses + oldest,
1683  stoptimes + oldest,
1684  tests + oldest, i - oldest);
1685  status_end();
1686  }
1687  else
1688  {
1689  status(_("parallel group (%d tests): "), num_tests);
1690  for (i = 0; i < num_tests; i++)
1691  {
1692  pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1693  INSTR_TIME_SET_CURRENT(starttimes[i]);
1694  }
1695  wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
1696  status_end();
1697  }
1698 
1699  /* Check results for all tests */
1700  for (i = 0; i < num_tests; i++)
1701  {
1702  _stringlist *rl,
1703  *el,
1704  *tl;
1705  bool differ = false;
1706 
1707  if (num_tests > 1)
1708  status(_(" %-28s ... "), tests[i]);
1709 
1710  /*
1711  * Advance over all three lists simultaneously.
1712  *
1713  * Compare resultfiles[j] with expectfiles[j] always. Tags are
1714  * optional but if there are tags, the tag list has the same
1715  * length as the other two lists.
1716  */
1717  for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
1718  rl != NULL; /* rl and el have the same length */
1719  rl = rl->next, el = el->next,
1720  tl = tl ? tl->next : NULL)
1721  {
1722  bool newdiff;
1723 
1724  if (postfunc)
1725  (*postfunc) (rl->str);
1726  newdiff = results_differ(tests[i], rl->str, el->str);
1727  if (newdiff && tl)
1728  {
1729  printf("%s ", tl->str);
1730  }
1731  differ |= newdiff;
1732  }
1733 
1734  if (differ)
1735  {
1736  bool ignore = false;
1737  _stringlist *sl;
1738 
1739  for (sl = ignorelist; sl != NULL; sl = sl->next)
1740  {
1741  if (strcmp(tests[i], sl->str) == 0)
1742  {
1743  ignore = true;
1744  break;
1745  }
1746  }
1747  if (ignore)
1748  {
1749  status(_("failed (ignored)"));
1751  }
1752  else
1753  {
1754  status(_("FAILED"));
1755  fail_count++;
1756  }
1757  }
1758  else
1759  {
1760  status(_("ok ")); /* align with FAILED */
1761  success_count++;
1762  }
1763 
1764  if (statuses[i] != 0)
1765  log_child_failure(statuses[i]);
1766 
1767  INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
1768  status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptimes[i]));
1769 
1770  status_end();
1771  }
1772 
1773  for (i = 0; i < num_tests; i++)
1774  {
1775  pg_free(tests[i]);
1776  tests[i] = NULL;
1777  free_stringlist(&resultfiles[i]);
1778  free_stringlist(&expectfiles[i]);
1779  free_stringlist(&tags[i]);
1780  }
1781  }
1782 
1783  free_stringlist(&ignorelist);
1784 
1785  fclose(scf);
1786 }
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#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
static void status_end(void)
Definition: pg_regress.c:250
#define MAX_PARALLEL_TESTS
static void log_child_failure(int exitstatus)
Definition: pg_regress.c:1514
static void wait_for_tests(PID_TYPE *pids, int *statuses, instr_time *stoptimes, char **names, int num_tests)
Definition: pg_regress.c:1442
static bool results_differ(const char *testname, const char *resultsfile, const char *default_expectfile)
Definition: pg_regress.c:1292
#define PID_TYPE
Definition: pg_regress.h:14
static void test(void)

References _, add_stringlist_item(), exit(), fail_count, fail_ignore_count, fprintf, free_stringlist(), i, INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, log_child_failure(), max_concurrent_tests, max_connections, MAX_PARALLEL_TESTS, _stringlist::next, pg_free(), pg_strdup(), PID_TYPE, printf, progname, results_differ(), status(), status_end(), _stringlist::str, strerror, success_count, test(), and wait_for_tests().

Referenced by regression_main().

◆ run_single_test()

static void run_single_test ( const char *  test,
test_start_function  startfunc,
postprocess_result_function  postfunc 
)
static

Definition at line 1792 of file pg_regress.c.

1794 {
1795  PID_TYPE pid;
1796  instr_time starttime;
1797  instr_time stoptime;
1798  int exit_status;
1799  _stringlist *resultfiles = NULL;
1800  _stringlist *expectfiles = NULL;
1801  _stringlist *tags = NULL;
1802  _stringlist *rl,
1803  *el,
1804  *tl;
1805  bool differ = false;
1806 
1807  status(_("test %-28s ... "), test);
1808  pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
1809  INSTR_TIME_SET_CURRENT(starttime);
1810  wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
1811 
1812  /*
1813  * Advance over all three lists simultaneously.
1814  *
1815  * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
1816  * but if there are tags, the tag list has the same length as the other
1817  * two lists.
1818  */
1819  for (rl = resultfiles, el = expectfiles, tl = tags;
1820  rl != NULL; /* rl and el have the same length */
1821  rl = rl->next, el = el->next,
1822  tl = tl ? tl->next : NULL)
1823  {
1824  bool newdiff;
1825 
1826  if (postfunc)
1827  (*postfunc) (rl->str);
1828  newdiff = results_differ(test, rl->str, el->str);
1829  if (newdiff && tl)
1830  {
1831  printf("%s ", tl->str);
1832  }
1833  differ |= newdiff;
1834  }
1835 
1836  if (differ)
1837  {
1838  status(_("FAILED"));
1839  fail_count++;
1840  }
1841  else
1842  {
1843  status(_("ok ")); /* align with FAILED */
1844  success_count++;
1845  }
1846 
1847  if (exit_status != 0)
1848  log_child_failure(exit_status);
1849 
1850  INSTR_TIME_SUBTRACT(stoptime, starttime);
1851  status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptime));
1852 
1853  status_end();
1854 }

References _, fail_count, INSTR_TIME_GET_MILLISEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, log_child_failure(), _stringlist::next, PID_TYPE, printf, results_differ(), status(), status_end(), _stringlist::str, success_count, test(), and wait_for_tests().

Referenced by regression_main().

◆ spawn_process()

PID_TYPE spawn_process ( const char *  cmdline)

Definition at line 1073 of file pg_regress.c.

1074 {
1075 #ifndef WIN32
1076  pid_t pid;
1077 
1078  /*
1079  * Must flush I/O buffers before fork. Ideally we'd use fflush(NULL) here
1080  * ... does anyone still care about systems where that doesn't work?
1081  */
1082  fflush(stdout);
1083  fflush(stderr);
1084  if (logfile)
1085  fflush(logfile);
1086 
1087 #ifdef EXEC_BACKEND
1088  pg_disable_aslr();
1089 #endif
1090 
1091  pid = fork();
1092  if (pid == -1)
1093  {
1094  fprintf(stderr, _("%s: could not fork: %s\n"),
1095  progname, strerror(errno));
1096  exit(2);
1097  }
1098  if (pid == 0)
1099  {
1100  /*
1101  * In child
1102  *
1103  * Instead of using system(), exec the shell directly, and tell it to
1104  * "exec" the command too. This saves two useless processes per
1105  * parallel test case.
1106  */
1107  char *cmdline2;
1108 
1109  cmdline2 = psprintf("exec %s", cmdline);
1110  execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1111  fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
1112  progname, shellprog, strerror(errno));
1113  _exit(1); /* not exit() here... */
1114  }
1115  /* in parent */
1116  return pid;
1117 #else
1118  PROCESS_INFORMATION pi;
1119  char *cmdline2;
1120  HANDLE restrictedToken;
1121  const char *comspec;
1122 
1123  /* Find CMD.EXE location using COMSPEC, if it's set */
1124  comspec = getenv("COMSPEC");
1125  if (comspec == NULL)
1126  comspec = "CMD";
1127 
1128  memset(&pi, 0, sizeof(pi));
1129  cmdline2 = psprintf("\"%s\" /c \"%s\"", comspec, cmdline);
1130 
1131  if ((restrictedToken =
1132  CreateRestrictedProcess(cmdline2, &pi)) == 0)
1133  exit(2);
1134 
1135  CloseHandle(pi.hThread);
1136  return pi.hProcess;
1137 #endif
1138 }
static char * shellprog
Definition: pg_regress.c:58

References _, exit(), fflush(), fprintf, logfile, progname, psprintf(), shellprog, generate_unaccent_rules::stdout, and strerror.

Referenced by ecpg_start_test(), isolation_start_test(), psql_start_test(), and regression_main().

◆ split_to_stringlist()

static void split_to_stringlist ( const char *  s,
const char *  delim,
_stringlist **  listhead 
)
static

Definition at line 195 of file pg_regress.c.

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 }

References add_stringlist_item(), free, and pg_strdup().

Referenced by regression_main().

◆ status()

static void status ( const char *  fmt,
  ... 
)
static

Definition at line 229 of file pg_regress.c.

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 }
vfprintf(stderr, fmt, args)

References fflush(), fmt, logfile, generate_unaccent_rules::stdout, va_end(), va_start(), and vfprintf().

Referenced by _bt_first(), _bt_parallel_seize(), _bt_readnextpage(), _bt_steppage(), apw_start_leader_worker(), AtAbort_Portals(), AtCleanup_Portals(), AtEOSubXact_RelationCache(), AtEOXact_RelationCache(), AtPrepare_Locks(), AtSubAbort_Portals(), AtSubCleanup_Portals(), AtSubCommit_Portals(), auth_delay_checks(), auth_failed(), BackendInitialize(), BaseBackup(), be_lo_lseek(), be_lo_lseek64(), bf_check_supported_key_len(), buildWorkerResponse(), check_icu_locale(), check_worker_status(), CheckForSessionAndXactLocks(), ClientAuthentication(), compute_new_xmax_infomask(), ConditionalMultiXactIdWait(), dblink_get_connections(), DestroyPartitionDirectory(), do_lo_export(), do_lo_unlink(), Do_MultiXactIdWait(), DoesMultiXactIdConflict(), dshash_delete_current(), dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), ecpg_process_output(), ecpg_store_result(), exec_command(), exec_command_crosstabview(), exec_command_d(), exec_command_edit(), exec_command_ef_ev(), exec_command_g(), exec_command_gdesc(), exec_command_gexec(), exec_command_gset(), exec_command_lo(), exec_command_quit(), exec_command_sf_sv(), exec_command_write(), executeQueryOrDie(), ExecuteSqlQuery(), ExitPostmaster(), FindStreamingStart(), finish_spin_delay(), forget_invalid_pages(), forget_invalid_pages_db(), ForgetPortalSnapshots(), FreezeMultiXactId(), get_collation_actual_version(), get_prompt(), GetMultiXactIdHintBits(), HandleSlashCmds(), hash_seq_init(), hash_seq_search(), hash_seq_term(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), HoldPinnedPortals(), init_spin_delay(), InvalidateAttoptCacheCallback(), InvalidateOprCacheCallBack(), InvalidateOprProofCacheCallBack(), InvalidateShippableCacheCallback(), InvalidateTableSpaceCacheCallback(), InvalidateTSCacheCallBack(), jspIsMutableWalker(), libpqrcv_connect(), ListenToWorkers(), lo_read(), lo_write(), LockReassignCurrentOwner(), LockReleaseAll(), LockReleaseCurrentOwner(), LockReleaseSession(), log_child_failure(), logicalrep_partmap_invalidate_cb(), logicalrep_relmap_invalidate_cb(), make_icu_collator(), mark_dump_job_done(), mark_restore_job_done(), MultiXactIdCreateFromMembers(), MultiXactIdExpand(), MultiXactIdGetUpdateXid(), MultiXactIdWait(), mxid_to_string(), mxstatus_to_string(), parallel_restore(), parseServiceInfo(), parseWorkerResponse(), perform_spin_delay(), pg_backup_start(), pg_backup_stop(), pg_cryptohash_final(), pg_cryptohash_init(), pg_cryptohash_update(), pg_hmac_final(), pg_hmac_init(), pg_hmac_update(), pg_prepared_xact(), pg_xact_status(), pgrowlocks(), plperl_spi_execute_fetch_result(), PLy_spi_execute_fetch_result(), PortalErrorCleanup(), PortalHashTableDeleteAll(), PostmasterMain(), PostPrepare_Locks(), pqFunctionCall3(), pqGetline3(), PQmakeEmptyPGresult(), PQresetPoll(), PQresStatus(), PQsetClientEncoding(), PreCommit_Portals(), RecordNewMultiXact(), rel_sync_cache_publication_cb(), rel_sync_cache_relation_cb(), RelationCacheInitializePhase3(), RelationCacheInvalidate(), RelfilenodeMapInvalidateCallback(), restore_toc_entry(), run_reindex_command(), run_schedule(), run_single_test(), run_vacuum_command(), sepgsql_client_auth(), SerializeUncommittedEnums(), set_status_by_pages(), shm_mq_counterparty_gone(), shm_mq_wait_internal(), smgrcloseall(), smgrreleaseall(), StandbyReleaseAllLocks(), StandbyReleaseOldLocks(), test_config_settings(), test_lockmode_for_conflict(), test_pipelined_insert(), ThereAreNoReadyPortals(), TransactionGroupUpdateXidStatus(), TransactionIdGetStatus(), TransactionIdSetPageStatus(), TransactionIdSetPageStatusInternal(), TransactionIdSetStatusBit(), TransactionIdSetTreeStatus(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TypeCacheTypCallback(), usage(), uuid_generate_internal(), varstr_abbrev_convert(), varstr_cmp(), varstrfastcmp_locale(), wait_for_postmaster_start(), wait_for_tests(), WaitForBackgroundWorkerShutdown(), WaitForBackgroundWorkerStartup(), WaitForCommands(), WaitForParallelWorkersToAttach(), WaitForParallelWorkersToExit(), WaitForReplicationWorkerAttach(), WaitForTerminatingWorkers(), worker_spi_launch(), write_relcache_init_file(), and XLogCheckInvalidPages().

◆ status_end()

static void status_end ( void  )
static

Definition at line 250 of file pg_regress.c.

251 {
252  fprintf(stdout, "\n");
253  fflush(stdout);
254  if (logfile)
255  fprintf(logfile, "\n");
256 }

References fflush(), fprintf, logfile, and generate_unaccent_rules::stdout.

Referenced by run_schedule(), and run_single_test().

◆ stop_postmaster()

static void stop_postmaster ( void  )
static

Definition at line 262 of file pg_regress.c.

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 }

References _, bindir, buf, fflush(), fprintf, MAXPGPATH, postmaster_running, progname, snprintf, generate_unaccent_rules::stdout, and temp_instance.

Referenced by regression_main().

◆ string_matches_pattern()

static bool string_matches_pattern ( const char *  str,
const char *  pattern 
)
static

Definition at line 381 of file pg_regress.c.

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 }

References generate_unaccent_rules::str.

Referenced by load_resultmap().

◆ wait_for_tests()

static void wait_for_tests ( PID_TYPE pids,
int *  statuses,
instr_time stoptimes,
char **  names,
int  num_tests 
)
static

Definition at line 1442 of file pg_regress.c.

1444 {
1445  int tests_left;
1446  int i;
1447 
1448 #ifdef WIN32
1449  PID_TYPE *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
1450 
1451  memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
1452 #endif
1453 
1454  tests_left = num_tests;
1455  while (tests_left > 0)
1456  {
1457  PID_TYPE p;
1458 
1459 #ifndef WIN32
1460  int exit_status;
1461 
1462  p = wait(&exit_status);
1463 
1464  if (p == INVALID_PID)
1465  {
1466  fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
1467  strerror(errno));
1468  exit(2);
1469  }
1470 #else
1471  DWORD exit_status;
1472  int r;
1473 
1474  r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
1475  if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
1476  {
1477  fprintf(stderr, _("failed to wait for subprocesses: error code %lu\n"),
1478  GetLastError());
1479  exit(2);
1480  }
1481  p = active_pids[r - WAIT_OBJECT_0];
1482  /* compact the active_pids array */
1483  active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
1484 #endif /* WIN32 */
1485 
1486  for (i = 0; i < num_tests; i++)
1487  {
1488  if (p == pids[i])
1489  {
1490 #ifdef WIN32
1491  GetExitCodeProcess(pids[i], &exit_status);
1492  CloseHandle(pids[i]);
1493 #endif
1494  pids[i] = INVALID_PID;
1495  statuses[i] = (int) exit_status;
1496  INSTR_TIME_SET_CURRENT(stoptimes[i]);
1497  if (names)
1498  status(" %s", names[i]);
1499  tests_left--;
1500  break;
1501  }
1502  }
1503  }
1504 
1505 #ifdef WIN32
1506  free(active_pids);
1507 #endif
1508 }

References _, exit(), fprintf, free, i, INSTR_TIME_SET_CURRENT, INVALID_PID, pg_malloc(), PID_TYPE, status(), and strerror.

Referenced by run_schedule(), and run_single_test().

Variable Documentation

◆ basic_diff_opts

const char* basic_diff_opts = ""

Definition at line 67 of file pg_regress.c.

Referenced by results_differ().

◆ bindir

char* bindir = PGBINDIR

Definition at line 79 of file pg_regress.c.

Referenced by psql_start_command(), psql_start_test(), regression_main(), and stop_postmaster().

◆ config_auth_datadir

char* config_auth_datadir = NULL
static

Definition at line 97 of file pg_regress.c.

Referenced by regression_main().

◆ dblist

◆ debug

bool debug = false

Definition at line 76 of file pg_regress.c.

Referenced by regression_main().

◆ difffilename

char* difffilename
static

Definition at line 103 of file pg_regress.c.

Referenced by open_result_files(), regression_main(), and results_differ().

◆ dlpath

char* dlpath = PKGLIBDIR
static

Definition at line 94 of file pg_regress.c.

Referenced by initialize_environment(), and regression_main().

◆ encoding

char* encoding = NULL
static

Definition at line 84 of file pg_regress.c.

Referenced by create_database(), initialize_environment(), and regression_main().

◆ extra_tests

_stringlist* extra_tests = NULL
static

Definition at line 86 of file pg_regress.c.

Referenced by regression_main().

◆ extraroles

_stringlist* extraroles = NULL
static

Definition at line 96 of file pg_regress.c.

Referenced by regression_main().

◆ fail_count

int fail_count = 0
static

Definition at line 117 of file pg_regress.c.

Referenced by regression_main(), run_schedule(), and run_single_test().

◆ fail_ignore_count

int fail_ignore_count = 0
static

Definition at line 118 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ host_platform

char* host_platform = HOST_TUPLE

Definition at line 55 of file pg_regress.c.

Referenced by load_resultmap().

◆ hostname

char* hostname = NULL
static

◆ inputdir

◆ launcher

char* launcher = NULL

Definition at line 80 of file pg_regress.c.

Referenced by isolation_start_test(), psql_start_test(), and regression_main().

◆ loadextension

_stringlist* loadextension = NULL
static

Definition at line 81 of file pg_regress.c.

Referenced by create_database(), and regression_main().

◆ logfile

FILE* logfile
static

◆ logfilename

char* logfilename
static

Definition at line 101 of file pg_regress.c.

Referenced by open_result_files(), and regression_main().

◆ max_concurrent_tests

int max_concurrent_tests = 0
static

Definition at line 83 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ max_connections

int max_connections = 0
static

Definition at line 82 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ nolocale

bool nolocale = false
static

Definition at line 89 of file pg_regress.c.

Referenced by create_database(), initialize_environment(), and regression_main().

◆ outputdir

◆ port

int port = -1
static

Definition at line 92 of file pg_regress.c.

Referenced by auth_delay_checks(), auth_failed(), auth_peer(), BackendInitialize(), BackendRun(), BackendStartup(), be_gssapi_get_auth(), be_gssapi_get_enc(), be_gssapi_get_princ(), be_gssapi_read(), be_gssapi_write(), be_tls_close(), be_tls_get_cipher(), be_tls_get_cipher_bits(), be_tls_get_peer_issuer_name(), be_tls_get_peer_serial(), be_tls_get_peer_subject_name(), be_tls_get_version(), be_tls_open_server(), be_tls_read(), be_tls_write(), check_hba(), check_hostname(), CheckMD5Auth(), CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), CheckSASLAuth(), ClientAuthentication(), ConnCreate(), conninfo_uri_parse_options(), do_connect(), ECPGconnect(), hba_getauthmethod(), ident_inet(), inet_client_addr(), inet_client_port(), inet_server_addr(), inet_server_port(), initialize_environment(), log_disconnections(), main(), my_SSL_set_fd(), passwordFromFile(), PerformAuthentication(), PerformRadiusTransaction(), pq_getkeepalivescount(), pq_getkeepalivesidle(), pq_getkeepalivesinterval(), pq_gettcpusertimeout(), pq_setkeepalivescount(), pq_setkeepalivesidle(), pq_setkeepalivesinterval(), pq_settcpusertimeout(), process_startup_options(), ProcessStartupPacket(), read_or_wait(), regression_main(), report_fork_failure_to_client(), scram_get_mechanisms(), scram_init(), secure_close(), secure_open_gssapi(), secure_open_server(), secure_raw_read(), secure_raw_write(), secure_read(), secure_write(), sepgsql_client_auth(), ServerLoop(), set_authn_id(), and StreamConnection().

◆ port_specified_by_user

bool port_specified_by_user = false
static

Definition at line 93 of file pg_regress.c.

Referenced by regression_main().

◆ postmaster_pid

PID_TYPE postmaster_pid = INVALID_PID
static

Definition at line 113 of file pg_regress.c.

Referenced by regression_main().

◆ postmaster_running

bool postmaster_running = false
static

Definition at line 114 of file pg_regress.c.

Referenced by regression_main(), and stop_postmaster().

◆ pretty_diff_opts

const char* pretty_diff_opts = "-U3"

Definition at line 68 of file pg_regress.c.

Referenced by regression_main(), and results_differ().

◆ progname

◆ resultmap

_resultmap* resultmap = NULL
static

Definition at line 111 of file pg_regress.c.

Referenced by get_expectfile(), and load_resultmap().

◆ schedulelist

_stringlist* schedulelist = NULL
static

Definition at line 85 of file pg_regress.c.

Referenced by regression_main().

◆ shellprog

char* shellprog = SHELLPROG
static

Definition at line 58 of file pg_regress.c.

Referenced by spawn_process().

◆ sockdir

const char* sockdir
static

Definition at line 104 of file pg_regress.c.

Referenced by initialize_environment(), and regression_main().

◆ success_count

int success_count = 0
static

Definition at line 116 of file pg_regress.c.

Referenced by regression_main(), run_schedule(), and run_single_test().

◆ temp_configs

_stringlist* temp_configs = NULL
static

Definition at line 88 of file pg_regress.c.

Referenced by regression_main().

◆ temp_instance

char* temp_instance = NULL
static

Definition at line 87 of file pg_regress.c.

Referenced by initialize_environment(), regression_main(), and stop_postmaster().

◆ use_existing

bool use_existing = false
static

Definition at line 90 of file pg_regress.c.

Referenced by regression_main().

◆ user