PostgreSQL Source Code  git master
pg_regress.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.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)
 
static void unlimit_core_size (void)
 
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 void remove_temp (void)
 
static void signal_remove_temp (SIGNAL_ARGS)
 
static const char * make_temp_sockdir (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 * expecteddir = "."
 
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 const char * temp_sockdir
 
static char sockself [MAXPGPATH]
 
static char socklock [MAXPGPATH]
 
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:972

Definition at line 1045 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 155 of file pg_regress.c.

156 {
157  _stringlist *newentry = pg_malloc(sizeof(_stringlist));
158  _stringlist *oldentry;
159 
160  newentry->str = pg_strdup(str);
161  newentry->next = NULL;
162  if (*listhead == NULL)
163  *listhead = newentry;
164  else
165  {
166  for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
167  /* skip */ ;
168  oldentry->next = newentry;
169  }
170 }
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 1894 of file pg_regress.c.

1895 {
1897  _stringlist *sl;
1898 
1899  /*
1900  * We use template0 so that any installation-local cruft in template1 will
1901  * not mess up the tests.
1902  */
1903  header(_("creating database \"%s\""), dbname);
1904  if (encoding)
1905  psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
1906  (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1907  else
1908  psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
1909  (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
1911  "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
1912  "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
1913  "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
1914  "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
1915  "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
1916  "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
1918  psql_end_command(buf, "postgres");
1919 
1920  /*
1921  * Install any requested extensions. We use CREATE IF NOT EXISTS so that
1922  * this will work whether or not the extension is preinstalled.
1923  */
1924  for (sl = loadextension; sl != NULL; sl = sl->next)
1925  {
1926  header(_("installing %s"), sl->str);
1927  psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
1928  }
1929 }
#define _(x)
Definition: elog.c:90
static bool nolocale
Definition: pg_regress.c:87
static void psql_add_command(StringInfo buf, const char *query,...) pg_attribute_printf(2
Definition: pg_regress.c:984
static void static void psql_end_command(StringInfo buf, const char *database)
Definition: pg_regress.c:1021
static _stringlist * loadextension
Definition: pg_regress.c:79
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:208
static char * encoding
Definition: pg_regress.c:82
#define psql_command(database,...)
Definition: pg_regress.c:1045
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 1944 of file pg_regress.c.

1945 {
1947 
1948  header(_("creating role \"%s\""), rolename);
1949  psql_add_command(buf, "CREATE ROLE \"%s\" WITH LOGIN", rolename);
1950  for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
1951  {
1952  psql_add_command(buf, "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
1953  granted_dbs->str, rolename);
1954  }
1955  psql_end_command(buf, "postgres");
1956 }

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 1179 of file pg_regress.c.

1180 {
1181  struct stat st;
1182 
1183  if (stat(dir, &st) != 0)
1184  return false;
1185  if (S_ISDIR(st.st_mode))
1186  return true;
1187  return false;
1188 }
#define stat
Definition: win32_port.h:286
#define S_ISDIR(m)
Definition: win32_port.h:327

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 1882 of file pg_regress.c.

1883 {
1885 
1886  header(_("dropping database \"%s\""), dbname);
1887  /* Set warning level so we don't see chatter about nonexistent DB */
1888  psql_add_command(buf, "SET client_min_messages = warning");
1889  psql_add_command(buf, "DROP DATABASE IF EXISTS \"%s\"", dbname);
1890  psql_end_command(buf, "postgres");
1891 }

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 1932 of file pg_regress.c.

1933 {
1935 
1936  header(_("dropping role \"%s\""), rolename);
1937  /* Set warning level so we don't see chatter about nonexistent role */
1938  psql_add_command(buf, "SET client_min_messages = warning");
1939  psql_add_command(buf, "DROP ROLE IF EXISTS \"%s\"", rolename);
1940  psql_end_command(buf, "postgres");
1941 }

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 1168 of file pg_regress.c.

1169 {
1170  FILE *f = fopen(file, "r");
1171 
1172  if (!f)
1173  return false;
1174  fclose(f);
1175  return true;
1176 }

Referenced by results_differ().

◆ file_line_count()

static int file_line_count ( const char *  file)
static

Definition at line 1146 of file pg_regress.c.

1147 {
1148  int c;
1149  int l = 0;
1150  FILE *f = fopen(file, "r");
1151 
1152  if (!f)
1153  {
1154  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1155  progname, file, strerror(errno));
1156  return -1;
1157  }
1158  while ((c = fgetc(f)) != EOF)
1159  {
1160  if (c == '\n')
1161  l++;
1162  }
1163  fclose(f);
1164  return l;
1165 }
static const char * progname
Definition: pg_regress.c:98
#define strerror
Definition: port.h:247
#define fprintf
Definition: port.h:238
char * c

References _, fprintf, progname, and strerror.

Referenced by results_differ().

◆ file_size()

static long file_size ( const char *  file)
static

Definition at line 1125 of file pg_regress.c.

1126 {
1127  long r;
1128  FILE *f = fopen(file, "r");
1129 
1130  if (!f)
1131  {
1132  fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1133  progname, file, strerror(errno));
1134  return -1;
1135  }
1136  fseek(f, 0, SEEK_END);
1137  r = ftell(f);
1138  fclose(f);
1139  return r;
1140 }

References _, fprintf, progname, and strerror.

Referenced by regression_main(), and run_diff().

◆ free_stringlist()

static void free_stringlist ( _stringlist **  listhead)
static

Definition at line 176 of file pg_regress.c.

177 {
178  if (listhead == NULL || *listhead == NULL)
179  return;
180  if ((*listhead)->next != NULL)
181  free_stringlist(&((*listhead)->next));
182  free((*listhead)->str);
183  free(*listhead);
184  *listhead = NULL;
185 }
#define free(a)
Definition: header.h:65
static void free_stringlist(_stringlist **listhead)
Definition: pg_regress.c:176

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 1206 of file pg_regress.c.

1207 {
1208  char *last_dot;
1209  int ssize = strlen(expectfile) + 2 + 1;
1210  char *tmp;
1211  char *s;
1212 
1213  if (!(tmp = (char *) malloc(ssize)))
1214  return NULL;
1215 
1216  if (!(s = (char *) malloc(ssize)))
1217  {
1218  free(tmp);
1219  return NULL;
1220  }
1221 
1222  strcpy(tmp, expectfile);
1223  last_dot = strrchr(tmp, '.');
1224  if (!last_dot)
1225  {
1226  free(tmp);
1227  free(s);
1228  return NULL;
1229  }
1230  *last_dot = '\0';
1231  snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
1232  free(tmp);
1233  return s;
1234 }
#define malloc(a)
Definition: header.h:50
int i
Definition: isn.c:73
#define snprintf
Definition: port.h:234

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 528 of file pg_regress.c.

529 {
530  char *file_type;
531  _resultmap *rm;
532 
533  /*
534  * Determine the file type from the file name. This is just what is
535  * following the last dot in the file name.
536  */
537  if (!file || !(file_type = strrchr(file, '.')))
538  return NULL;
539 
540  file_type++;
541 
542  for (rm = resultmap; rm != NULL; rm = rm->next)
543  {
544  if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
545  {
546  return rm->resultfile;
547  }
548  }
549 
550  return NULL;
551 }
static _resultmap * resultmap
Definition: pg_regress.c:107
char * resultfile
Definition: pg_regress.c:45
struct _resultmap * next
Definition: pg_regress.c:46
char * test
Definition: pg_regress.c:43
char * type
Definition: pg_regress.c:44

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

Referenced by results_differ().

◆ header()

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

◆ help()

static void help ( void  )
static

Definition at line 1959 of file pg_regress.c.

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

References _, printf, and progname.

Referenced by regression_main().

◆ initialize_environment()

static void initialize_environment ( void  )
static

Definition at line 557 of file pg_regress.c.

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

References _, DEFAULT_PGSOCKET_DIR, dlpath, encoding, free, hostname, inputdir, load_resultmap(), make_temp_sockdir(), 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 446 of file pg_regress.c.

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

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 1496 of file pg_regress.c.

1497 {
1498  if (WIFEXITED(exitstatus))
1499  status(_(" (test process exited with exit code %d)"),
1500  WEXITSTATUS(exitstatus));
1501  else if (WIFSIGNALED(exitstatus))
1502  {
1503 #if defined(WIN32)
1504  status(_(" (test process was terminated by exception 0x%X)"),
1505  WTERMSIG(exitstatus));
1506 #else
1507  status(_(" (test process was terminated by signal %d: %s)"),
1508  WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
1509 #endif
1510  }
1511  else
1512  status(_(" (test process exited with unrecognized status %d)"),
1513  exitstatus);
1514 }
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
const char * pg_strsignal(int signum)
Definition: pgstrsignal.c:42
#define WIFEXITED(w)
Definition: win32_port.h:160
#define WIFSIGNALED(w)
Definition: win32_port.h:161
#define WTERMSIG(w)
Definition: win32_port.h:163
#define WEXITSTATUS(w)
Definition: win32_port.h:162

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 1192 of file pg_regress.c.

1193 {
1194  if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
1195  {
1196  fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
1197  progname, dir, strerror(errno));
1198  exit(2);
1199  }
1200 }
#define S_IRWXG
Definition: win32_port.h:312
#define S_IRWXO
Definition: win32_port.h:324
#define mkdir(a, b)
Definition: win32_port.h:80
#define S_IRWXU
Definition: win32_port.h:300

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

Referenced by open_result_files(), and regression_main().

◆ make_temp_sockdir()

static const char* make_temp_sockdir ( void  )
static

Definition at line 327 of file pg_regress.c.

328 {
329  char *template = psprintf("%s/pg_regress-XXXXXX",
330  getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
331 
332  temp_sockdir = mkdtemp(template);
333  if (temp_sockdir == NULL)
334  {
335  fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
336  progname, template, strerror(errno));
337  exit(2);
338  }
339 
340  /* Stage file names for remove_temp(). Unsafe in a signal handler. */
342  snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
343 
344  /* Remove the directory during clean exit. */
345  atexit(remove_temp);
346 
347  /*
348  * Remove the directory before dying to the usual signals. Omit SIGQUIT,
349  * preserving it as a quick, untidy exit.
350  */
352  pqsignal(SIGINT, signal_remove_temp);
354  pqsignal(SIGTERM, signal_remove_temp);
355 
356  return temp_sockdir;
357 }
static void signal_remove_temp(SIGNAL_ARGS)
Definition: pg_regress.c:306
static void remove_temp(void)
Definition: pg_regress.c:294
static const char * temp_sockdir
Definition: pg_regress.c:103
static char sockself[MAXPGPATH]
Definition: pg_regress.c:104
static char socklock[MAXPGPATH]
Definition: pg_regress.c:105
char * mkdtemp(char *path)
Definition: mkdtemp.c:286
#define UNIXSOCK_PATH(path, port, sockdir)
Definition: pqcomm.h:32
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:197
#define SIGHUP
Definition: win32_port.h:176
#define SIGPIPE
Definition: win32_port.h:181

References _, exit(), fprintf, mkdtemp(), port, pqsignal(), progname, psprintf(), remove_temp(), SIGHUP, signal_remove_temp(), SIGPIPE, snprintf, socklock, sockself, strerror, temp_sockdir, and UNIXSOCK_PATH.

Referenced by initialize_environment().

◆ open_result_files()

static void open_result_files ( void  )
static

Definition at line 1842 of file pg_regress.c.

1843 {
1844  char file[MAXPGPATH];
1845  FILE *difffile;
1846 
1847  /* create outputdir directory if not present */
1850 
1851  /* create the log file (copy of running status output) */
1852  snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1853  logfilename = pg_strdup(file);
1854  logfile = fopen(logfilename, "w");
1855  if (!logfile)
1856  {
1857  fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1858  progname, logfilename, strerror(errno));
1859  exit(2);
1860  }
1861 
1862  /* create the diffs file as empty */
1863  snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1864  difffilename = pg_strdup(file);
1865  difffile = fopen(difffilename, "w");
1866  if (!difffile)
1867  {
1868  fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1869  progname, difffilename, strerror(errno));
1870  exit(2);
1871  }
1872  /* we don't keep the diffs file open continuously */
1873  fclose(difffile);
1874 
1875  /* also create the results directory if not present */
1876  snprintf(file, sizeof(file), "%s/results", outputdir);
1877  if (!directory_exists(file))
1878  make_directory(file);
1879 }
static bool directory_exists(const char *dir)
Definition: pg_regress.c:1179
static char * logfilename
Definition: pg_regress.c:99
static void make_directory(const char *dir)
Definition: pg_regress.c:1192
static char * difffilename
Definition: pg_regress.c:101
static FILE * logfile
Definition: pg_regress.c:100

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 984 of file pg_regress.c.

985 {
986  StringInfoData cmdbuf;
987  const char *cmdptr;
988 
989  /* Add each command as a -c argument in the psql call */
990  appendStringInfoString(buf, " -c \"");
991 
992  /* Generate the query with insertion of sprintf arguments */
993  initStringInfo(&cmdbuf);
994  for (;;)
995  {
996  va_list args;
997  int needed;
998 
999  va_start(args, query);
1000  needed = appendStringInfoVA(&cmdbuf, query, args);
1001  va_end(args);
1002  if (needed == 0)
1003  break; /* success */
1004  enlargeStringInfo(&cmdbuf, needed);
1005  }
1006 
1007  /* Now escape any shell double-quote metacharacters */
1008  for (cmdptr = cmdbuf.data; *cmdptr; cmdptr++)
1009  {
1010  if (strchr("\\\"$`", *cmdptr))
1011  appendStringInfoChar(buf, '\\');
1012  appendStringInfoChar(buf, *cmdptr);
1013  }
1014 
1015  appendStringInfoChar(buf, '"');
1016 
1017  pfree(cmdbuf.data);
1018 }
void pfree(void *pointer)
Definition: mcxt.c:1252
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 1021 of file pg_regress.c.

1022 {
1023  /* Add the database name --- assume it needs no extra escaping */
1025  " \"%s\"",
1026  database);
1027 
1028  /* And now we can execute the shell command */
1029  fflush(NULL);
1030  if (system(buf->data) != 0)
1031  {
1032  /* psql probably already reported the error */
1033  fprintf(stderr, _("command failed: %s\n"), buf->data);
1034  exit(2);
1035  }
1036 
1037  /* Clean up */
1038  pfree(buf->data);
1039  pfree(buf);
1040 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91

References _, appendStringInfo(), buf, exit(), fflush(), 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 972 of file pg_regress.c.

973 {
975 
977  "\"%s%spsql\" -X",
978  bindir ? bindir : "",
979  bindir ? "/" : "");
980  return buf;
981 }
char * bindir
Definition: pg_regress.c:77
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 2009 of file pg_regress.c.

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

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(), expecteddir, extra_tests, extraroles, fail_count, fail_ignore_count, fflush(), 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, unlimit_core_size(), use_existing, user, and wait_seconds.

Referenced by main().

◆ remove_temp()

static void remove_temp ( void  )
static

Definition at line 294 of file pg_regress.c.

295 {
297  unlink(sockself);
298  unlink(socklock);
299  rmdir(temp_sockdir);
300 }
Assert(fmt[strlen(fmt) - 1] !='\n')

References Assert(), socklock, sockself, and temp_sockdir.

Referenced by make_temp_sockdir(), and signal_remove_temp().

◆ results_differ()

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

Definition at line 1274 of file pg_regress.c.

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

1241 {
1242  int r;
1243 
1244  fflush(NULL);
1245  r = system(cmd);
1246  if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
1247  {
1248  fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
1249  exit(2);
1250  }
1251 #ifdef WIN32
1252 
1253  /*
1254  * On WIN32, if the 'diff' command cannot be found, system() returns 1,
1255  * but produces nothing to stdout, so we check for that here.
1256  */
1257  if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
1258  {
1259  fprintf(stderr, _("diff command not found: %s\n"), cmd);
1260  exit(2);
1261  }
1262 #endif
1263 
1264  return WEXITSTATUS(r);
1265 }
static char * filename
Definition: pg_dumpall.c:119

References _, exit(), fflush(), 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 1520 of file pg_regress.c.

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

1776 {
1777  PID_TYPE pid;
1778  instr_time starttime;
1779  instr_time stoptime;
1780  int exit_status;
1781  _stringlist *resultfiles = NULL;
1782  _stringlist *expectfiles = NULL;
1783  _stringlist *tags = NULL;
1784  _stringlist *rl,
1785  *el,
1786  *tl;
1787  bool differ = false;
1788 
1789  status(_("test %-28s ... "), test);
1790  pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
1791  INSTR_TIME_SET_CURRENT(starttime);
1792  wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
1793 
1794  /*
1795  * Advance over all three lists simultaneously.
1796  *
1797  * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
1798  * but if there are tags, the tag list has the same length as the other
1799  * two lists.
1800  */
1801  for (rl = resultfiles, el = expectfiles, tl = tags;
1802  rl != NULL; /* rl and el have the same length */
1803  rl = rl->next, el = el->next,
1804  tl = tl ? tl->next : NULL)
1805  {
1806  bool newdiff;
1807 
1808  if (postfunc)
1809  (*postfunc) (rl->str);
1810  newdiff = results_differ(test, rl->str, el->str);
1811  if (newdiff && tl)
1812  {
1813  printf("%s ", tl->str);
1814  }
1815  differ |= newdiff;
1816  }
1817 
1818  if (differ)
1819  {
1820  status(_("FAILED"));
1821  fail_count++;
1822  }
1823  else
1824  {
1825  status(_("ok ")); /* align with FAILED */
1826  success_count++;
1827  }
1828 
1829  if (exit_status != 0)
1830  log_child_failure(exit_status);
1831 
1832  INSTR_TIME_SUBTRACT(stoptime, starttime);
1833  status(_(" %8.0f ms"), INSTR_TIME_GET_MILLISEC(stoptime));
1834 
1835  status_end();
1836 }

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().

◆ signal_remove_temp()

static void signal_remove_temp ( SIGNAL_ARGS  )
static

Definition at line 306 of file pg_regress.c.

307 {
308  remove_temp();
309 
310  pqsignal(postgres_signal_arg, SIG_DFL);
311  raise(postgres_signal_arg);
312 }
#define SIG_DFL
Definition: win32_port.h:171

References pqsignal(), remove_temp(), and SIG_DFL.

Referenced by make_temp_sockdir().

◆ spawn_process()

PID_TYPE spawn_process ( const char *  cmdline)

Definition at line 1058 of file pg_regress.c.

1059 {
1060 #ifndef WIN32
1061  pid_t pid;
1062 
1063  /*
1064  * Must flush I/O buffers before fork.
1065  */
1066  fflush(NULL);
1067 
1068 #ifdef EXEC_BACKEND
1069  pg_disable_aslr();
1070 #endif
1071 
1072  pid = fork();
1073  if (pid == -1)
1074  {
1075  fprintf(stderr, _("%s: could not fork: %s\n"),
1076  progname, strerror(errno));
1077  exit(2);
1078  }
1079  if (pid == 0)
1080  {
1081  /*
1082  * In child
1083  *
1084  * Instead of using system(), exec the shell directly, and tell it to
1085  * "exec" the command too. This saves two useless processes per
1086  * parallel test case.
1087  */
1088  char *cmdline2;
1089 
1090  cmdline2 = psprintf("exec %s", cmdline);
1091  execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1092  fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
1093  progname, shellprog, strerror(errno));
1094  _exit(1); /* not exit() here... */
1095  }
1096  /* in parent */
1097  return pid;
1098 #else
1099  PROCESS_INFORMATION pi;
1100  char *cmdline2;
1101  HANDLE restrictedToken;
1102  const char *comspec;
1103 
1104  /* Find CMD.EXE location using COMSPEC, if it's set */
1105  comspec = getenv("COMSPEC");
1106  if (comspec == NULL)
1107  comspec = "CMD";
1108 
1109  memset(&pi, 0, sizeof(pi));
1110  cmdline2 = psprintf("\"%s\" /c \"%s\"", comspec, cmdline);
1111 
1112  if ((restrictedToken =
1113  CreateRestrictedProcess(cmdline2, &pi)) == 0)
1114  exit(2);
1115 
1116  CloseHandle(pi.hThread);
1117  return pi.hProcess;
1118 #endif
1119 }
static char * shellprog
Definition: pg_regress.c:55

References _, exit(), fflush(), fprintf, progname, psprintf(), shellprog, 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 191 of file pg_regress.c.

192 {
193  char *sc = pg_strdup(s);
194  char *token = strtok(sc, delim);
195 
196  while (token)
197  {
198  add_stringlist_item(listhead, token);
199  token = strtok(NULL, delim);
200  }
201  free(sc);
202 }

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

Referenced by regression_main().

◆ status()

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

Definition at line 225 of file pg_regress.c.

226 {
227  va_list ap;
228 
229  va_start(ap, fmt);
230  vfprintf(stdout, fmt, ap);
231  fflush(stdout);
232  va_end(ap);
233 
234  if (logfile)
235  {
236  va_start(ap, fmt);
237  vfprintf(logfile, fmt, ap);
238  va_end(ap);
239  }
240 }
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(), fdatasync(), 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(), libpqrcv_connect(), ListenToWorkers(), lo_read(), lo_write(), LockReassignCurrentOwner(), LockReleaseAll(), LockReleaseCurrentOwner(), LockReleaseSession(), log_child_failure(), logicalrep_partmap_invalidate_cb(), logicalrep_partmap_reset_relmap(), 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(), RelfilenumberMapInvalidateCallback(), restore_toc_entry(), run_reindex_command(), run_schedule(), run_single_test(), run_vacuum_command(), SendBaseBackup(), 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 246 of file pg_regress.c.

247 {
248  fprintf(stdout, "\n");
249  fflush(stdout);
250  if (logfile)
251  fprintf(logfile, "\n");
252 }

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 258 of file pg_regress.c.

259 {
260  if (postmaster_running)
261  {
262  /* We use pg_ctl to issue the kill and wait for stop */
263  char buf[MAXPGPATH * 2];
264  int r;
265 
266  snprintf(buf, sizeof(buf),
267  "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
268  bindir ? bindir : "",
269  bindir ? "/" : "",
270  temp_instance);
271  fflush(NULL);
272  r = system(buf);
273  if (r != 0)
274  {
275  fprintf(stderr, _("\n%s: could not stop postmaster: exit code was %d\n"),
276  progname, r);
277  _exit(2); /* not exit(), that could be recursive */
278  }
279 
280  postmaster_running = false;
281  }
282 }

References _, bindir, buf, fflush(), fprintf, MAXPGPATH, postmaster_running, progname, snprintf, 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 372 of file pg_regress.c.

373 {
374  while (*str && *pattern)
375  {
376  if (*pattern == '.' && pattern[1] == '*')
377  {
378  pattern += 2;
379  /* Trailing .* matches everything. */
380  if (*pattern == '\0')
381  return true;
382 
383  /*
384  * Otherwise, scan for a text position at which we can match the
385  * rest of the pattern.
386  */
387  while (*str)
388  {
389  /*
390  * Optimization to prevent most recursion: don't recurse
391  * unless first pattern char might match this text char.
392  */
393  if (*str == *pattern || *pattern == '.')
394  {
395  if (string_matches_pattern(str, pattern))
396  return true;
397  }
398 
399  str++;
400  }
401 
402  /*
403  * End of text with no match.
404  */
405  return false;
406  }
407  else if (*pattern != '.' && *str != *pattern)
408  {
409  /*
410  * Not the single-character wildcard and no explicit match? Then
411  * time to quit...
412  */
413  return false;
414  }
415 
416  str++;
417  pattern++;
418  }
419 
420  if (*pattern == '\0')
421  return true; /* end of pattern, so declare match */
422 
423  /* End of input string. Do we have matching pattern remaining? */
424  while (*pattern == '.' && pattern[1] == '*')
425  pattern += 2;
426  if (*pattern == '\0')
427  return true; /* end of pattern, so declare match */
428 
429  return false;
430 }

References generate_unaccent_rules::str.

Referenced by load_resultmap().

◆ unlimit_core_size()

static void unlimit_core_size ( void  )
static

Definition at line 130 of file pg_regress.c.

131 {
132  struct rlimit lim;
133 
134  getrlimit(RLIMIT_CORE, &lim);
135  if (lim.rlim_max == 0)
136  {
137  fprintf(stderr,
138  _("%s: could not set core size: disallowed by hard limit\n"),
139  progname);
140  return;
141  }
142  else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
143  {
144  lim.rlim_cur = lim.rlim_max;
145  setrlimit(RLIMIT_CORE, &lim);
146  }
147 }

References _, fprintf, and progname.

Referenced by regression_main().

◆ 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 1424 of file pg_regress.c.

1426 {
1427  int tests_left;
1428  int i;
1429 
1430 #ifdef WIN32
1431  PID_TYPE *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
1432 
1433  memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
1434 #endif
1435 
1436  tests_left = num_tests;
1437  while (tests_left > 0)
1438  {
1439  PID_TYPE p;
1440 
1441 #ifndef WIN32
1442  int exit_status;
1443 
1444  p = wait(&exit_status);
1445 
1446  if (p == INVALID_PID)
1447  {
1448  fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
1449  strerror(errno));
1450  exit(2);
1451  }
1452 #else
1453  DWORD exit_status;
1454  int r;
1455 
1456  r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
1457  if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
1458  {
1459  fprintf(stderr, _("failed to wait for subprocesses: error code %lu\n"),
1460  GetLastError());
1461  exit(2);
1462  }
1463  p = active_pids[r - WAIT_OBJECT_0];
1464  /* compact the active_pids array */
1465  active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
1466 #endif /* WIN32 */
1467 
1468  for (i = 0; i < num_tests; i++)
1469  {
1470  if (p == pids[i])
1471  {
1472 #ifdef WIN32
1473  GetExitCodeProcess(pids[i], &exit_status);
1474  CloseHandle(pids[i]);
1475 #endif
1476  pids[i] = INVALID_PID;
1477  statuses[i] = (int) exit_status;
1478  INSTR_TIME_SET_CURRENT(stoptimes[i]);
1479  if (names)
1480  status(" %s", names[i]);
1481  tests_left--;
1482  break;
1483  }
1484  }
1485  }
1486 
1487 #ifdef WIN32
1488  free(active_pids);
1489 #endif
1490 }

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 64 of file pg_regress.c.

Referenced by results_differ().

◆ bindir

char* bindir = PGBINDIR

Definition at line 77 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 95 of file pg_regress.c.

Referenced by regression_main().

◆ dblist

◆ debug

bool debug = false

Definition at line 73 of file pg_regress.c.

Referenced by regression_main().

◆ difffilename

char* difffilename
static

Definition at line 101 of file pg_regress.c.

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

◆ dlpath

char* dlpath = PKGLIBDIR
static

Definition at line 92 of file pg_regress.c.

Referenced by initialize_environment(), and regression_main().

◆ encoding

char* encoding = NULL
static

Definition at line 82 of file pg_regress.c.

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

◆ expecteddir

char* expecteddir = "."

Definition at line 76 of file pg_regress.c.

Referenced by ecpg_start_test(), and regression_main().

◆ extra_tests

_stringlist* extra_tests = NULL
static

Definition at line 84 of file pg_regress.c.

Referenced by regression_main().

◆ extraroles

_stringlist* extraroles = NULL
static

Definition at line 94 of file pg_regress.c.

Referenced by regression_main().

◆ fail_count

int fail_count = 0
static

Definition at line 113 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 114 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ host_platform

char* host_platform = HOST_TUPLE

Definition at line 52 of file pg_regress.c.

Referenced by load_resultmap().

◆ hostname

char* hostname = NULL
static

◆ inputdir

◆ launcher

char* launcher = NULL

Definition at line 78 of file pg_regress.c.

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

◆ loadextension

_stringlist* loadextension = NULL
static

Definition at line 79 of file pg_regress.c.

Referenced by create_database(), and regression_main().

◆ logfile

FILE* logfile
static

◆ logfilename

char* logfilename
static

Definition at line 99 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 81 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ max_connections

int max_connections = 0
static

Definition at line 80 of file pg_regress.c.

Referenced by regression_main(), and run_schedule().

◆ nolocale

bool nolocale = false
static

Definition at line 87 of file pg_regress.c.

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

◆ outputdir

◆ port

int port = -1
static

Definition at line 90 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(), ConnFree(), 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(), make_temp_sockdir(), 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 91 of file pg_regress.c.

Referenced by regression_main().

◆ postmaster_pid

PID_TYPE postmaster_pid = INVALID_PID
static

Definition at line 109 of file pg_regress.c.

Referenced by regression_main().

◆ postmaster_running

bool postmaster_running = false
static

Definition at line 110 of file pg_regress.c.

Referenced by regression_main(), and stop_postmaster().

◆ pretty_diff_opts

const char* pretty_diff_opts = "-U3"

Definition at line 65 of file pg_regress.c.

Referenced by regression_main(), and results_differ().

◆ progname

◆ resultmap

_resultmap* resultmap = NULL
static

Definition at line 107 of file pg_regress.c.

Referenced by get_expectfile(), and load_resultmap().

◆ schedulelist

_stringlist* schedulelist = NULL
static

Definition at line 83 of file pg_regress.c.

Referenced by regression_main().

◆ shellprog

char* shellprog = SHELLPROG
static

Definition at line 55 of file pg_regress.c.

Referenced by spawn_process().

◆ sockdir

const char* sockdir
static

Definition at line 102 of file pg_regress.c.

Referenced by initialize_environment(), and regression_main().

◆ socklock

char socklock[MAXPGPATH]
static

Definition at line 105 of file pg_regress.c.

Referenced by make_temp_sockdir(), and remove_temp().

◆ sockself

char sockself[MAXPGPATH]
static

Definition at line 104 of file pg_regress.c.

Referenced by make_temp_sockdir(), and remove_temp().

◆ success_count

int success_count = 0
static

Definition at line 112 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 86 of file pg_regress.c.

Referenced by regression_main().

◆ temp_instance

char* temp_instance = NULL
static

Definition at line 85 of file pg_regress.c.

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

◆ temp_sockdir

const char* temp_sockdir
static

Definition at line 103 of file pg_regress.c.

Referenced by make_temp_sockdir(), and remove_temp().

◆ use_existing

bool use_existing = false
static

Definition at line 88 of file pg_regress.c.

Referenced by regression_main().

◆ user