#include "pg_regress.h"#include <ctype.h>#include <sys/stat.h>#include <sys/wait.h>#include <signal.h>#include <unistd.h>#include "getopt_long.h"#include "pg_config_paths.h"
Go to the source code of this file.
Data Structures | |
| struct | _resultmap |
Defines | |
| #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,...) __attribute__((format(PG_PRINTF_ATTRIBUTE |
| static void static void | status (const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE |
| static void static void static void | psql_command (const char *database, const char *query,...) __attribute__((format(PG_PRINTF_ATTRIBUTE |
| static void static void static 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 bool | string_matches_pattern (const char *str, const char *pattern) |
| void | replace_string (char *string, char *replace, char *replacement) |
| static void | convert_sourcefiles_in (char *source_subdir, char *dest_dir, char *dest_subdir, char *suffix) |
| static void | convert_sourcefiles (void) |
| static void | load_resultmap (void) |
| static const char * | get_expectfile (const char *testname, const char *file) |
| static void | doputenv (const char *var, const char *val) |
| static void | add_to_path (const char *pathname, char separator, const char *addval) |
| 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, char **names, int num_tests) |
| static void | log_child_failure (int exitstatus) |
| static void | run_schedule (const char *schedule, test_function tfunc) |
| static void | run_single_test (const char *test, test_function tfunc) |
| 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 char * | make_absolute_path (const char *in) |
| static void | help (void) |
| int | regression_main (int argc, char *argv[], init_function ifunc, test_function tfunc) |
Variables | |
| char * | bindir = PGBINDIR |
| char * | libdir = LIBDIR |
| char * | datadir = PGSHAREDIR |
| char * | host_platform = HOST_TUPLE |
| static char * | makeprog = MAKEPROG |
| static char * | shellprog = SHELLPROG |
| const char * | basic_diff_opts = "" |
| const char * | pretty_diff_opts = "-C3" |
| _stringlist * | dblist = NULL |
| bool | debug = false |
| char * | inputdir = "." |
| char * | outputdir = "." |
| char * | psqldir = PGBINDIR |
| char * | launcher = NULL |
| static _stringlist * | loadlanguage = NULL |
| static _stringlist * | loadextension = NULL |
| static int | max_connections = 0 |
| static char * | encoding = NULL |
| static _stringlist * | schedulelist = NULL |
| static _stringlist * | extra_tests = NULL |
| static char * | temp_install = NULL |
| static char * | temp_config = NULL |
| static char * | top_builddir = 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 _stringlist * | extraroles = NULL |
| static _stringlist * | extra_install = NULL |
| static const char * | progname |
| static char * | logfilename |
| static FILE * | logfile |
| static char * | difffilename |
| static _resultmap * | resultmap = 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 |
| #define MAX_PARALLEL_TESTS 100 |
Referenced by run_schedule().
| #define ULONGPID | ( | x | ) | (unsigned long) (x) |
Referenced by regression_main().
| typedef struct _resultmap _resultmap |
| static void static void static void void add_stringlist_item | ( | _stringlist ** | listhead, | |
| const char * | str | |||
| ) |
Definition at line 180 of file pg_regress.c.
References malloc, _stringlist::next, NULL, 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().
{
_stringlist *newentry = malloc(sizeof(_stringlist));
_stringlist *oldentry;
newentry->str = strdup(str);
newentry->next = NULL;
if (*listhead == NULL)
*listhead = newentry;
else
{
for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
/* skip */ ;
oldentry->next = newentry;
}
}
| static void add_to_path | ( | const char * | pathname, | |
| char | separator, | |||
| const char * | addval | |||
| ) | [static] |
Definition at line 668 of file pg_regress.c.
References malloc, and putenv.
Referenced by initialize_environment().
{
char *oldval = getenv(pathname);
char *newval;
if (!oldval || !oldval[0])
{
/* no previous value */
newval = malloc(strlen(pathname) + strlen(addval) + 2);
sprintf(newval, "%s=%s", pathname, addval);
}
else
{
newval = malloc(strlen(pathname) + strlen(addval) + strlen(oldval) + 3);
sprintf(newval, "%s=%s%c%s", pathname, addval, separator, oldval);
}
putenv(newval);
}
| static void convert_sourcefiles | ( | void | ) | [static] |
Definition at line 524 of file pg_regress.c.
References convert_sourcefiles_in(), inputdir, and outputdir.
Referenced by initialize_environment().
{
convert_sourcefiles_in("input", inputdir, "sql", "sql");
convert_sourcefiles_in("output", outputdir, "expected", "out");
}
| static void convert_sourcefiles_in | ( | char * | source_subdir, | |
| char * | dest_dir, | |||
| char * | dest_subdir, | |||
| char * | suffix | |||
| ) | [static] |
Definition at line 410 of file pg_regress.c.
References _, directory_exists(), dlpath, inputdir, make_directory(), MAXPGPATH, name, outputdir, pgfnames(), pgfnames_cleanup(), progname, replace_string(), rmtree(), snprintf(), and strerror().
Referenced by convert_sourcefiles().
{
char testtablespace[MAXPGPATH];
char indir[MAXPGPATH];
struct stat st;
int ret;
char **name;
char **names;
int count = 0;
snprintf(indir, MAXPGPATH, "%s/%s", inputdir, source_subdir);
/* Check that indir actually exists and is a directory */
ret = stat(indir, &st);
if (ret != 0 || !S_ISDIR(st.st_mode))
{
/*
* No warning, to avoid noise in tests that do not have these
* directories; for example, ecpg, contrib and src/pl.
*/
return;
}
names = pgfnames(indir);
if (!names)
/* Error logged in pgfnames */
exit(2);
snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir);
#ifdef WIN32
/*
* On Windows only, clean out the test tablespace dir, or create it if it
* doesn't exist. On other platforms we expect the Makefile to take care
* of that. (We don't migrate that functionality in here because it'd be
* harder to cope with platform-specific issues such as SELinux.)
*
* XXX it would be better if pg_regress.c had nothing at all to do with
* testtablespace, and this were handled by a .BAT file or similar on
* Windows. See pgsql-hackers discussion of 2008-01-18.
*/
if (directory_exists(testtablespace))
rmtree(testtablespace, true);
make_directory(testtablespace);
#endif
/* finally loop on each file and do the replacement */
for (name = names; *name; name++)
{
char srcfile[MAXPGPATH];
char destfile[MAXPGPATH];
char prefix[MAXPGPATH];
FILE *infile,
*outfile;
char line[1024];
/* reject filenames not finishing in ".source" */
if (strlen(*name) < 8)
continue;
if (strcmp(*name + strlen(*name) - 7, ".source") != 0)
continue;
count++;
/* build the full actual paths to open */
snprintf(prefix, strlen(*name) - 6, "%s", *name);
snprintf(srcfile, MAXPGPATH, "%s/%s", indir, *name);
snprintf(destfile, MAXPGPATH, "%s/%s/%s.%s", dest_dir, dest_subdir,
prefix, suffix);
infile = fopen(srcfile, "r");
if (!infile)
{
fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
progname, srcfile, strerror(errno));
exit(2);
}
outfile = fopen(destfile, "w");
if (!outfile)
{
fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
progname, destfile, strerror(errno));
exit(2);
}
while (fgets(line, sizeof(line), infile))
{
replace_string(line, "@abs_srcdir@", inputdir);
replace_string(line, "@abs_builddir@", outputdir);
replace_string(line, "@testtablespace@", testtablespace);
replace_string(line, "@libdir@", dlpath);
replace_string(line, "@DLSUFFIX@", DLSUFFIX);
fputs(line, outfile);
}
fclose(infile);
fclose(outfile);
}
/*
* If we didn't process any files, complain because it probably means
* somebody neglected to pass the needed --inputdir argument.
*/
if (count <= 0)
{
fprintf(stderr, _("%s: no *.source files found in \"%s\"\n"),
progname, indir);
exit(2);
}
pgfnames_cleanup(names);
}
| static void create_database | ( | const char * | dbname | ) | [static] |
Definition at line 1782 of file pg_regress.c.
References _, encoding, header(), _stringlist::next, nolocale, psql_command(), and _stringlist::str.
Referenced by regression_main().
{
_stringlist *sl;
/*
* We use template0 so that any installation-local cruft in template1 will
* not mess up the tests.
*/
header(_("creating database \"%s\""), dbname);
if (encoding)
psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
(nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
else
psql_command("postgres", "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
(nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
psql_command(dbname,
"ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
"ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
"ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
"ALTER DATABASE \"%s\" SET lc_time TO 'C';"
"ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
dbname, dbname, dbname, dbname, dbname);
/*
* Install any requested procedural languages. We use CREATE OR REPLACE
* so that this will work whether or not the language is preinstalled.
*/
for (sl = loadlanguage; sl != NULL; sl = sl->next)
{
header(_("installing %s"), sl->str);
psql_command(dbname, "CREATE OR REPLACE LANGUAGE \"%s\"", sl->str);
}
/*
* Install any requested extensions. We use CREATE IF NOT EXISTS so that
* this will work whether or not the extension is preinstalled.
*/
for (sl = loadextension; sl != NULL; sl = sl->next)
{
header(_("installing %s"), sl->str);
psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
}
}
| static void create_role | ( | const char * | rolename, | |
| const _stringlist * | granted_dbs | |||
| ) | [static] |
Definition at line 1834 of file pg_regress.c.
References _, header(), _stringlist::next, psql_command(), and _stringlist::str.
Referenced by regression_main().
{
header(_("creating role \"%s\""), rolename);
psql_command("postgres", "CREATE ROLE \"%s\" WITH LOGIN", rolename);
for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
{
psql_command("postgres", "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
granted_dbs->str, rolename);
}
}
| static bool directory_exists | ( | const char * | dir | ) | [static] |
Definition at line 1133 of file pg_regress.c.
Referenced by convert_sourcefiles_in(), open_result_files(), and regression_main().
{
struct stat st;
if (stat(dir, &st) != 0)
return false;
if (S_ISDIR(st.st_mode))
return true;
return false;
}
| static void doputenv | ( | const char * | var, | |
| const char * | val | |||
| ) | [static] |
Definition at line 655 of file pg_regress.c.
References malloc, and putenv.
Referenced by initialize_environment(), and regression_main().
| static void drop_database_if_exists | ( | const char * | dbname | ) | [static] |
Definition at line 1775 of file pg_regress.c.
References _, header(), and psql_command().
Referenced by regression_main().
{
header(_("dropping database \"%s\""), dbname);
psql_command("postgres", "DROP DATABASE IF EXISTS \"%s\"", dbname);
}
| static void drop_role_if_exists | ( | const char * | rolename | ) | [static] |
Definition at line 1827 of file pg_regress.c.
References _, header(), and psql_command().
Referenced by regression_main().
{
header(_("dropping role \"%s\""), rolename);
psql_command("postgres", "DROP ROLE IF EXISTS \"%s\"", rolename);
}
| bool file_exists | ( | const char * | file | ) |
Definition at line 1122 of file pg_regress.c.
{
FILE *f = fopen(file, "r");
if (!f)
return false;
fclose(f);
return true;
}
| static int file_line_count | ( | const char * | file | ) | [static] |
Definition at line 1100 of file pg_regress.c.
References _, progname, and strerror().
Referenced by results_differ().
| static long file_size | ( | const char * | file | ) | [static] |
Definition at line 1079 of file pg_regress.c.
References _, progname, and strerror().
Referenced by regression_main(), and run_diff().
| static void free_stringlist | ( | _stringlist ** | listhead | ) | [static] |
Definition at line 201 of file pg_regress.c.
Referenced by regression_main(), and run_schedule().
| static char* get_alternative_expectfile | ( | const char * | expectfile, | |
| int | i | |||
| ) | [static] |
Definition at line 1160 of file pg_regress.c.
References free, malloc, and snprintf().
Referenced by results_differ().
{
char *last_dot;
int ssize = strlen(expectfile) + 2 + 1;
char *tmp = (char *) malloc(ssize);
char *s = (char *) malloc(ssize);
strcpy(tmp, expectfile);
last_dot = strrchr(tmp, '.');
if (!last_dot)
{
free(tmp);
free(s);
return NULL;
}
*last_dot = '\0';
snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
free(tmp);
return s;
}
| static const char* get_expectfile | ( | const char * | testname, | |
| const char * | file | |||
| ) | [static] |
Definition at line 626 of file pg_regress.c.
References _resultmap::next, _resultmap::resultfile, _resultmap::test, and _resultmap::type.
Referenced by results_differ().
{
char *file_type;
_resultmap *rm;
/*
* Determine the file type from the file name. This is just what is
* following the last dot in the file name.
*/
if (!file || !(file_type = strrchr(file, '.')))
return NULL;
file_type++;
for (rm = resultmap; rm != NULL; rm = rm->next)
{
if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
{
return rm->resultfile;
}
}
return NULL;
}
| static void header | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 233 of file pg_regress.c.
References vsnprintf().
Referenced by _tarPositionTo(), create_database(), create_role(), decodePageSplitRecord(), drop_database_if_exists(), drop_role_if_exists(), ExecHashJoinGetSavedTuple(), ReceiveTarFile(), and regression_main().
{
char tmp[64];
va_list ap;
va_start(ap, fmt);
vsnprintf(tmp, sizeof(tmp), fmt, ap);
va_end(ap);
fprintf(stdout, "============== %-38s ==============\n", tmp);
fflush(stdout);
}
| static void help | ( | void | ) | [static] |
Definition at line 1874 of file pg_regress.c.
Referenced by regression_main().
{
printf(_("PostgreSQL regression test driver\n"));
printf(_("\n"));
printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
printf(_("\n"));
printf(_("Options:\n"));
printf(_(" --create-role=ROLE create the specified role before testing\n"));
printf(_(" --dbname=DB use database DB (default \"regression\")\n"));
printf(_(" --debug turn on debug mode in programs that are run\n"));
printf(_(" --dlpath=DIR look for dynamic libraries in DIR\n"));
printf(_(" --encoding=ENCODING use ENCODING as the encoding\n"));
printf(_(" --inputdir=DIR take input files from DIR (default \".\")\n"));
printf(_(" --launcher=CMD use CMD as launcher of psql\n"));
printf(_(" --load-extension=EXT load the named extension before running the\n"));
printf(_(" tests; can appear multiple times\n"));
printf(_(" --load-language=LANG load the named language before running the\n"));
printf(_(" tests; can appear multiple times\n"));
printf(_(" --max-connections=N maximum number of concurrent connections\n"));
printf(_(" (default is 0, meaning unlimited)\n"));
printf(_(" --outputdir=DIR place output files in DIR (default \".\")\n"));
printf(_(" --schedule=FILE use test ordering schedule from FILE\n"));
printf(_(" (can be used multiple times to concatenate)\n"));
printf(_(" --temp-install=DIR create a temporary installation in DIR\n"));
printf(_(" --use-existing use an existing installation\n"));
printf(_("\n"));
printf(_("Options for \"temp-install\" mode:\n"));
printf(_(" --extra-install=DIR additional directory to install (e.g., contrib)\n"));
printf(_(" --no-locale use C locale\n"));
printf(_(" --port=PORT start postmaster on PORT\n"));
printf(_(" --temp-config=FILE append contents of FILE to temporary config\n"));
printf(_(" --top-builddir=DIR (relative) path to top level build directory\n"));
printf(_("\n"));
printf(_("Options for using an existing installation:\n"));
printf(_(" --host=HOST use postmaster running on HOST\n"));
printf(_(" --port=PORT use postmaster running at PORT\n"));
printf(_(" --user=USER connect as USER\n"));
printf(_(" --psqldir=DIR use psql in DIR (default: configured bindir)\n"));
printf(_("\n"));
printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
printf(_("if the tests could not be run for some reason.\n"));
printf(_("\n"));
printf(_("Report bugs to <[email protected]>.\n"));
}
| static void initialize_environment | ( | void | ) | [static] |
Definition at line 691 of file pg_regress.c.
References _, add_to_path(), bindir, convert_sourcefiles(), datadir, doputenv(), encoding, hostname, libdir, load_resultmap(), malloc, nolocale, NULL, pghost, pgport, port, psqldir, putenv, temp_install, unsetenv, and user.
Referenced by regression_main().
{
char *tmp;
putenv("PGAPPNAME=pg_regress");
if (nolocale)
{
/*
* Clear out any non-C locale settings
*/
unsetenv("LC_COLLATE");
unsetenv("LC_CTYPE");
unsetenv("LC_MONETARY");
unsetenv("LC_NUMERIC");
unsetenv("LC_TIME");
unsetenv("LANG");
/* On Windows the default locale cannot be English, so force it */
#if defined(WIN32) || defined(__CYGWIN__)
putenv("LANG=en");
#endif
}
/*
* Set translation-related settings to English; otherwise psql will
* produce translated messages and produce diffs. (XXX If we ever support
* translation of pg_regress, this needs to be moved elsewhere, where psql
* is actually called.)
*/
unsetenv("LANGUAGE");
unsetenv("LC_ALL");
putenv("LC_MESSAGES=C");
/*
* Set encoding as requested
*/
if (encoding)
doputenv("PGCLIENTENCODING", encoding);
else
unsetenv("PGCLIENTENCODING");
/*
* Set timezone and datestyle for datetime-related tests
*/
putenv("PGTZ=PST8PDT");
putenv("PGDATESTYLE=Postgres, MDY");
/*
* Likewise set intervalstyle to ensure consistent results. This is a bit
* more painful because we must use PGOPTIONS, and we want to preserve the
* user's ability to set other variables through that.
*/
{
const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
const char *old_pgoptions = getenv("PGOPTIONS");
char *new_pgoptions;
if (!old_pgoptions)
old_pgoptions = "";
new_pgoptions = malloc(strlen(old_pgoptions) + strlen(my_pgoptions) + 12);
sprintf(new_pgoptions, "PGOPTIONS=%s %s", old_pgoptions, my_pgoptions);
putenv(new_pgoptions);
}
if (temp_install)
{
/*
* Clear out any environment vars that might cause psql to connect to
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
* we also use psql's -X switch consistently, so that ~/.psqlrc files
* won't mess things up.) Also, set PGPORT to the temp port, and set
* or unset PGHOST depending on whether we are using TCP or Unix
* sockets.
*/
unsetenv("PGDATABASE");
unsetenv("PGUSER");
unsetenv("PGSERVICE");
unsetenv("PGSSLMODE");
unsetenv("PGREQUIRESSL");
unsetenv("PGCONNECT_TIMEOUT");
unsetenv("PGDATA");
if (hostname != NULL)
doputenv("PGHOST", hostname);
else
unsetenv("PGHOST");
unsetenv("PGHOSTADDR");
if (port != -1)
{
char s[16];
sprintf(s, "%d", port);
doputenv("PGPORT", s);
}
/*
* GNU make stores some flags in the MAKEFLAGS environment variable to
* pass arguments to its own children. If we are invoked by make,
* that causes the make invoked by us to think its part of the make
* task invoking us, and so it tries to communicate with the toplevel
* make. Which fails.
*
* Unset the variable to protect against such problems. We also reset
* MAKELEVEL to be certain the child doesn't notice the make above us.
*/
unsetenv("MAKEFLAGS");
unsetenv("MAKELEVEL");
/*
* Adjust path variables to point into the temp-install tree
*/
tmp = malloc(strlen(temp_install) + 32 + strlen(bindir));
sprintf(tmp, "%s/install/%s", temp_install, bindir);
bindir = tmp;
tmp = malloc(strlen(temp_install) + 32 + strlen(libdir));
sprintf(tmp, "%s/install/%s", temp_install, libdir);
libdir = tmp;
tmp = malloc(strlen(temp_install) + 32 + strlen(datadir));
sprintf(tmp, "%s/install/%s", temp_install, datadir);
datadir = tmp;
/* psql will be installed into temp-install bindir */
psqldir = bindir;
/*
* Set up shared library paths to include the temp install.
*
* LD_LIBRARY_PATH covers many platforms. DYLD_LIBRARY_PATH works on
* Darwin, and maybe other Mach-based systems. LIBPATH is for AIX.
* Windows needs shared libraries in PATH (only those linked into
* executables, not dlopen'ed ones). Feel free to account for others
* as well.
*/
add_to_path("LD_LIBRARY_PATH", ':', libdir);
add_to_path("DYLD_LIBRARY_PATH", ':', libdir);
add_to_path("LIBPATH", ':', libdir);
#if defined(WIN32)
add_to_path("PATH", ';', libdir);
#elif defined(__CYGWIN__)
add_to_path("PATH", ':', libdir);
#endif
}
else
{
const char *pghost;
const char *pgport;
/*
* When testing an existing install, we honor existing environment
* variables, except if they're overridden by command line options.
*/
if (hostname != NULL)
{
doputenv("PGHOST", hostname);
unsetenv("PGHOSTADDR");
}
if (port != -1)
{
char s[16];
sprintf(s, "%d", port);
doputenv("PGPORT", s);
}
if (user != NULL)
doputenv("PGUSER", user);
/*
* Report what we're connecting to
*/
pghost = getenv("PGHOST");
pgport = getenv("PGPORT");
#ifndef HAVE_UNIX_SOCKETS
if (!pghost)
pghost = "localhost";
#endif
if (pghost && pgport)
printf(_("(using postmaster on %s, port %s)\n"), pghost, pgport);
if (pghost && !pgport)
printf(_("(using postmaster on %s, default port)\n"), pghost);
if (!pghost && pgport)
printf(_("(using postmaster on Unix socket, port %s)\n"), pgport);
if (!pghost && !pgport)
printf(_("(using postmaster on Unix socket, default port)\n"));
}
convert_sourcefiles();
load_resultmap();
}
| static void load_resultmap | ( | void | ) | [static] |
Definition at line 544 of file pg_regress.c.
References _, buf, host_platform, i, inputdir, malloc, _resultmap::next, progname, _resultmap::resultfile, snprintf(), strerror(), string_matches_pattern(), _resultmap::test, and _resultmap::type.
Referenced by initialize_environment().
{
char buf[MAXPGPATH];
FILE *f;
/* scan the file ... */
snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
f = fopen(buf, "r");
if (!f)
{
/* OK if it doesn't exist, else complain */
if (errno == ENOENT)
return;
fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
progname, buf, strerror(errno));
exit(2);
}
while (fgets(buf, sizeof(buf), f))
{
char *platform;
char *file_type;
char *expected;
int i;
/* strip trailing whitespace, especially the newline */
i = strlen(buf);
while (i > 0 && isspace((unsigned char) buf[i - 1]))
buf[--i] = '\0';
/* parse out the line fields */
file_type = strchr(buf, ':');
if (!file_type)
{
fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
buf);
exit(2);
}
*file_type++ = '\0';
platform = strchr(file_type, ':');
if (!platform)
{
fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
buf);
exit(2);
}
*platform++ = '\0';
expected = strchr(platform, '=');
if (!expected)
{
fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
buf);
exit(2);
}
*expected++ = '\0';
/*
* if it's for current platform, save it in resultmap list. Note: by
* adding at the front of the list, we ensure that in ambiguous cases,
* the last match in the resultmap file is used. This mimics the
* behavior of the old shell script.
*/
if (string_matches_pattern(host_platform, platform))
{
_resultmap *entry = malloc(sizeof(_resultmap));
entry->test = strdup(buf);
entry->type = strdup(file_type);
entry->resultfile = strdup(expected);
entry->next = resultmap;
resultmap = entry;
}
}
fclose(f);
}
| static void log_child_failure | ( | int | exitstatus | ) | [static] |
Definition at line 1424 of file pg_regress.c.
References _, status(), WEXITSTATUS, WIFEXITED, WIFSIGNALED, and WTERMSIG.
Referenced by run_schedule(), and run_single_test().
{
if (WIFEXITED(exitstatus))
status(_(" (test process exited with exit code %d)"),
WEXITSTATUS(exitstatus));
else if (WIFSIGNALED(exitstatus))
{
#if defined(WIN32)
status(_(" (test process was terminated by exception 0x%X)"),
WTERMSIG(exitstatus));
#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
status(_(" (test process was terminated by signal %d: %s)"),
WTERMSIG(exitstatus),
WTERMSIG(exitstatus) < NSIG ?
sys_siglist[WTERMSIG(exitstatus)] : "(unknown))");
#else
status(_(" (test process was terminated by signal %d)"),
WTERMSIG(exitstatus));
#endif
}
else
status(_(" (test process exited with unrecognized status %d)"),
exitstatus);
}
| static char* make_absolute_path | ( | const char * | in | ) | [static] |
Definition at line 1846 of file pg_regress.c.
References _, canonicalize_path(), is_absolute_path, malloc, and strerror().
{
char *result;
if (is_absolute_path(in))
result = strdup(in);
else
{
static char cwdbuf[MAXPGPATH];
if (!cwdbuf[0])
{
if (!getcwd(cwdbuf, sizeof(cwdbuf)))
{
fprintf(stderr, _("could not get current working directory: %s\n"), strerror(errno));
exit(2);
}
}
result = malloc(strlen(cwdbuf) + strlen(in) + 2);
sprintf(result, "%s/%s", cwdbuf, in);
}
canonicalize_path(result);
return result;
}
| static void make_directory | ( | const char * | dir | ) | [static] |
Definition at line 1146 of file pg_regress.c.
References _, mkdir, progname, S_IRWXG, S_IRWXO, and strerror().
Referenced by convert_sourcefiles_in(), open_result_files(), and regression_main().
| static void open_result_files | ( | void | ) | [static] |
Definition at line 1739 of file pg_regress.c.
References _, difffilename, directory_exists(), logfile, logfilename, make_directory(), outputdir, progname, snprintf(), and strerror().
Referenced by regression_main().
{
char file[MAXPGPATH];
FILE *difffile;
/* create the log file (copy of running status output) */
snprintf(file, sizeof(file), "%s/regression.out", outputdir);
logfilename = strdup(file);
logfile = fopen(logfilename, "w");
if (!logfile)
{
fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
progname, logfilename, strerror(errno));
exit(2);
}
/* create the diffs file as empty */
snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
difffilename = strdup(file);
difffile = fopen(difffilename, "w");
if (!difffile)
{
fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
progname, difffilename, strerror(errno));
exit(2);
}
/* we don't keep the diffs file open continuously */
fclose(difffile);
/* also create the output directory if not present */
snprintf(file, sizeof(file), "%s/results", outputdir);
if (!directory_exists(file))
make_directory(file);
}
| static void psql_command | ( | const char * | database, | |
| const char * | query, | |||
| ... | ||||
| ) | [static] |
Definition at line 888 of file pg_regress.c.
References _, MAXPGPATH, psqldir, snprintf(), system(), SYSTEMQUOTE, and vsnprintf().
Referenced by create_database(), create_role(), drop_database_if_exists(), and drop_role_if_exists().
{
char query_formatted[1024];
char query_escaped[2048];
char psql_cmd[MAXPGPATH + 2048];
va_list args;
char *s;
char *d;
/* Generate the query with insertion of sprintf arguments */
va_start(args, query);
vsnprintf(query_formatted, sizeof(query_formatted), query, args);
va_end(args);
/* Now escape any shell double-quote metacharacters */
d = query_escaped;
for (s = query_formatted; *s; s++)
{
if (strchr("\\\"$`", *s))
*d++ = '\\';
*d++ = *s;
}
*d = '\0';
/* And now we can build and execute the shell command */
snprintf(psql_cmd, sizeof(psql_cmd),
SYSTEMQUOTE "\"%s%spsql\" -X -c \"%s\" \"%s\"" SYSTEMQUOTE,
psqldir ? psqldir : "",
psqldir ? "/" : "",
query_escaped,
database);
if (system(psql_cmd) != 0)
{
/* psql probably already reported the error */
fprintf(stderr, _("command failed: %s\n"), psql_cmd);
exit(2);
}
}
| int regression_main | ( | int | argc, | |
| char * | argv[], | |||
| init_function | ifunc, | |||
| test_function | tfunc | |||
| ) |
Definition at line 1920 of file pg_regress.c.
References _, add_stringlist_item(), bindir, buf, create_database(), create_role(), datadir, debug, DEVNULL, difffilename, directory_exists(), dlpath, doputenv(), drop_database_if_exists(), drop_role_if_exists(), encoding, fail_count, fail_ignore_count, file_size(), free_stringlist(), get_progname(), getopt_long(), header(), help(), hostname, i, initialize_environment(), inputdir, INVALID_PID, launcher, logfile, logfilename, make_absolute_path(), make_directory(), makeprog, max_connections, MAXPGPATH, _stringlist::next, nolocale, NULL, open_result_files(), optarg, optind, outputdir, PG_TEXTDOMAIN, pg_usleep(), port, port_specified_by_user, postmaster_pid, postmaster_running, pretty_diff_opts, progname, psqldir, rmtree(), run_schedule(), run_single_test(), set_pglocale_pgservice(), SIGKILL, snprintf(), spawn_process(), split_to_stringlist(), stop_postmaster(), _stringlist::str, strerror(), success_count, system(), SYSTEMQUOTE, temp_config, temp_install, top_builddir, ULONGPID, unlink(), use_existing, and user.
Referenced by main().
{
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"dbname", required_argument, NULL, 1},
{"debug", no_argument, NULL, 2},
{"inputdir", required_argument, NULL, 3},
{"load-language", required_argument, NULL, 4},
{"max-connections", required_argument, NULL, 5},
{"encoding", required_argument, NULL, 6},
{"outputdir", required_argument, NULL, 7},
{"schedule", required_argument, NULL, 8},
{"temp-install", required_argument, NULL, 9},
{"no-locale", no_argument, NULL, 10},
{"top-builddir", required_argument, NULL, 11},
{"host", required_argument, NULL, 13},
{"port", required_argument, NULL, 14},
{"user", required_argument, NULL, 15},
{"psqldir", required_argument, NULL, 16},
{"dlpath", required_argument, NULL, 17},
{"create-role", required_argument, NULL, 18},
{"temp-config", required_argument, NULL, 19},
{"use-existing", no_argument, NULL, 20},
{"launcher", required_argument, NULL, 21},
{"load-extension", required_argument, NULL, 22},
{"extra-install", required_argument, NULL, 23},
{NULL, 0, NULL, 0}
};
_stringlist *sl;
int c;
int i;
int option_index;
char buf[MAXPGPATH * 4];
char buf2[MAXPGPATH * 4];
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
atexit(stop_postmaster);
#ifndef HAVE_UNIX_SOCKETS
/* no unix domain sockets available, so change default */
hostname = "localhost";
#endif
/*
* We call the initialization function here because that way we can set
* default parameters and let them be overwritten by the commandline.
*/
ifunc();
if (getenv("PG_REGRESS_DIFF_OPTS"))
pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
{
switch (c)
{
case 'h':
help();
exit(0);
case 'V':
puts("pg_regress (PostgreSQL) " PG_VERSION);
exit(0);
case 1:
/*
* If a default database was specified, we need to remove it
* before we add the specified one.
*/
free_stringlist(&dblist);
split_to_stringlist(strdup(optarg), ", ", &dblist);
break;
case 2:
debug = true;
break;
case 3:
inputdir = strdup(optarg);
break;
case 4:
add_stringlist_item(&loadlanguage, optarg);
break;
case 5:
max_connections = atoi(optarg);
break;
case 6:
encoding = strdup(optarg);
break;
case 7:
outputdir = strdup(optarg);
break;
case 8:
add_stringlist_item(&schedulelist, optarg);
break;
case 9:
temp_install = make_absolute_path(optarg);
break;
case 10:
nolocale = true;
break;
case 11:
top_builddir = strdup(optarg);
break;
case 13:
hostname = strdup(optarg);
break;
case 14:
port = atoi(optarg);
port_specified_by_user = true;
break;
case 15:
user = strdup(optarg);
break;
case 16:
/* "--psqldir=" should mean to use PATH */
if (strlen(optarg))
psqldir = strdup(optarg);
break;
case 17:
dlpath = strdup(optarg);
break;
case 18:
split_to_stringlist(strdup(optarg), ", ", &extraroles);
break;
case 19:
temp_config = strdup(optarg);
break;
case 20:
use_existing = true;
break;
case 21:
launcher = strdup(optarg);
break;
case 22:
add_stringlist_item(&loadextension, optarg);
break;
case 23:
add_stringlist_item(&extra_install, optarg);
break;
default:
/* getopt_long already emitted a complaint */
fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
progname);
exit(2);
}
}
/*
* if we still have arguments, they are extra tests to run
*/
while (argc - optind >= 1)
{
add_stringlist_item(&extra_tests, argv[optind]);
optind++;
}
if (temp_install && !port_specified_by_user)
/*
* To reduce chances of interference with parallel installations, use
* a port number starting in the private range (49152-65535)
* calculated from the version number.
*/
port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
inputdir = make_absolute_path(inputdir);
outputdir = make_absolute_path(outputdir);
dlpath = make_absolute_path(dlpath);
/*
* Initialization
*/
open_result_files();
initialize_environment();
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
unlimit_core_size();
#endif
if (temp_install)
{
FILE *pg_conf;
_stringlist *sl;
/*
* Prepare the temp installation
*/
if (!top_builddir)
{
fprintf(stderr, _("--top-builddir must be specified when using --temp-install\n"));
exit(2);
}
if (directory_exists(temp_install))
{
header(_("removing existing temp installation"));
rmtree(temp_install, true);
}
header(_("creating temporary installation"));
/* make the temp install top directory */
make_directory(temp_install);
/* and a directory for log files */
snprintf(buf, sizeof(buf), "%s/log", outputdir);
if (!directory_exists(buf))
make_directory(buf);
/* "make install" */
#ifndef WIN32_ONLY_COMPILER
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install > \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
makeprog, top_builddir, temp_install, outputdir);
#else
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "perl \"%s/src/tools/msvc/install.pl\" \"%s/install\" >\"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
top_builddir, temp_install, outputdir);
#endif
if (system(buf))
{
fprintf(stderr, _("\n%s: installation failed\nExamine %s/log/install.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
exit(2);
}
for (sl = extra_install; sl != NULL; sl = sl->next)
{
#ifndef WIN32_ONLY_COMPILER
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "\"%s\" -C \"%s/%s\" DESTDIR=\"%s/install\" install >> \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
makeprog, top_builddir, sl->str, temp_install, outputdir);
#else
fprintf(stderr, _("\n%s: --extra-install option not supported on this platform\n"), progname);
exit(2);
#endif
if (system(buf))
{
fprintf(stderr, _("\n%s: installation failed\nExamine %s/log/install.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
exit(2);
}
}
/* initdb */
header(_("initializing database system"));
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean --nosync%s%s > \"%s/log/initdb.log\" 2>&1" SYSTEMQUOTE,
bindir, temp_install, datadir,
debug ? " --debug" : "",
nolocale ? " --no-locale" : "",
outputdir);
if (system(buf))
{
fprintf(stderr, _("\n%s: initdb failed\nExamine %s/log/initdb.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
exit(2);
}
/*
* Adjust the default postgresql.conf as needed for regression
* testing. The user can specify a file to be appended; in any case we
* set max_prepared_transactions to enable testing of prepared xacts.
* (Note: to reduce the probability of unexpected shmmax failures,
* don't set max_prepared_transactions any higher than actually needed
* by the prepared_xacts regression test.)
*/
snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_install);
pg_conf = fopen(buf, "a");
if (pg_conf == NULL)
{
fprintf(stderr, _("\n%s: could not open \"%s\" for adding extra config: %s\n"), progname, buf, strerror(errno));
exit(2);
}
fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
fputs("max_prepared_transactions = 2\n", pg_conf);
if (temp_config != NULL)
{
FILE *extra_conf;
char line_buf[1024];
extra_conf = fopen(temp_config, "r");
if (extra_conf == NULL)
{
fprintf(stderr, _("\n%s: could not open \"%s\" to read extra config: %s\n"), progname, temp_config, strerror(errno));
exit(2);
}
while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
fputs(line_buf, pg_conf);
fclose(extra_conf);
}
fclose(pg_conf);
/*
* Check if there is a postmaster running already.
*/
snprintf(buf2, sizeof(buf2),
SYSTEMQUOTE "\"%s/psql\" -X postgres <%s 2>%s" SYSTEMQUOTE,
bindir, DEVNULL, DEVNULL);
for (i = 0; i < 16; i++)
{
if (system(buf2) == 0)
{
char s[16];
if (port_specified_by_user || i == 15)
{
fprintf(stderr, _("port %d apparently in use\n"), port);
if (!port_specified_by_user)
fprintf(stderr, _("%s: could not determine an available port\n"), progname);
fprintf(stderr, _("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.\n"));
exit(2);
}
fprintf(stderr, _("port %d apparently in use, trying %d\n"), port, port + 1);
port++;
sprintf(s, "%d", port);
doputenv("PGPORT", s);
}
else
break;
}
/*
* Start the temp postmaster
*/
header(_("starting postmaster"));
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
bindir, temp_install,
debug ? " -d 5" : "",
hostname ? hostname : "",
outputdir);
postmaster_pid = spawn_process(buf);
if (postmaster_pid == INVALID_PID)
{
fprintf(stderr, _("\n%s: could not spawn postmaster: %s\n"),
progname, strerror(errno));
exit(2);
}
/*
* Wait till postmaster is able to accept connections (normally only a
* second or so, but Cygwin is reportedly *much* slower). Don't wait
* forever, however.
*/
for (i = 0; i < 60; i++)
{
/* Done if psql succeeds */
if (system(buf2) == 0)
break;
/*
* Fail immediately if postmaster has exited
*/
#ifndef WIN32
if (kill(postmaster_pid, 0) != 0)
#else
if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
#endif
{
fprintf(stderr, _("\n%s: postmaster failed\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
exit(2);
}
pg_usleep(1000000L);
}
if (i >= 60)
{
fprintf(stderr, _("\n%s: postmaster did not respond within 60 seconds\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
/*
* If we get here, the postmaster is probably wedged somewhere in
* startup. Try to kill it ungracefully rather than leaving a
* stuck postmaster that might interfere with subsequent test
* attempts.
*/
#ifndef WIN32
if (kill(postmaster_pid, SIGKILL) != 0 &&
errno != ESRCH)
fprintf(stderr, _("\n%s: could not kill failed postmaster: %s\n"),
progname, strerror(errno));
#else
if (TerminateProcess(postmaster_pid, 255) == 0)
fprintf(stderr, _("\n%s: could not kill failed postmaster: error code %lu\n"),
progname, GetLastError());
#endif
exit(2);
}
postmaster_running = true;
#ifdef WIN64
/* need a series of two casts to convert HANDLE without compiler warning */
#define ULONGPID(x) (unsigned long) (unsigned long long) (x)
#else
#define ULONGPID(x) (unsigned long) (x)
#endif
printf(_("running on port %d with PID %lu\n"),
port, ULONGPID(postmaster_pid));
}
else
{
/*
* Using an existing installation, so may need to get rid of
* pre-existing database(s) and role(s)
*/
if (!use_existing)
{
for (sl = dblist; sl; sl = sl->next)
drop_database_if_exists(sl->str);
for (sl = extraroles; sl; sl = sl->next)
drop_role_if_exists(sl->str);
}
}
/*
* Create the test database(s) and role(s)
*/
if (!use_existing)
{
for (sl = dblist; sl; sl = sl->next)
create_database(sl->str);
for (sl = extraroles; sl; sl = sl->next)
create_role(sl->str, dblist);
}
/*
* Ready to run the tests
*/
header(_("running regression test queries"));
for (sl = schedulelist; sl != NULL; sl = sl->next)
{
run_schedule(sl->str, tfunc);
}
for (sl = extra_tests; sl != NULL; sl = sl->next)
{
run_single_test(sl->str, tfunc);
}
/*
* Shut down temp installation's postmaster
*/
if (temp_install)
{
header(_("shutting down postmaster"));
stop_postmaster();
}
fclose(logfile);
/*
* Emit nice-looking summary message
*/
if (fail_count == 0 && fail_ignore_count == 0)
snprintf(buf, sizeof(buf),
_(" All %d tests passed. "),
success_count);
else if (fail_count == 0) /* fail_count=0, fail_ignore_count>0 */
snprintf(buf, sizeof(buf),
_(" %d of %d tests passed, %d failed test(s) ignored. "),
success_count,
success_count + fail_ignore_count,
fail_ignore_count);
else if (fail_ignore_count == 0) /* fail_count>0 && fail_ignore_count=0 */
snprintf(buf, sizeof(buf),
_(" %d of %d tests failed. "),
fail_count,
success_count + fail_count);
else
/* fail_count>0 && fail_ignore_count>0 */
snprintf(buf, sizeof(buf),
_(" %d of %d tests failed, %d of these failures ignored. "),
fail_count + fail_ignore_count,
success_count + fail_count + fail_ignore_count,
fail_ignore_count);
putchar('\n');
for (i = strlen(buf); i > 0; i--)
putchar('=');
printf("\n%s\n", buf);
for (i = strlen(buf); i > 0; i--)
putchar('=');
putchar('\n');
putchar('\n');
if (file_size(difffilename) > 0)
{
printf(_("The differences that caused some tests to fail can be viewed in the\n"
"file \"%s\". A copy of the test summary that you see\n"
"above is saved in the file \"%s\".\n\n"),
difffilename, logfilename);
}
else
{
unlink(difffilename);
unlink(logfilename);
}
if (fail_count != 0)
exit(1);
return 0;
}
| void replace_string | ( | char * | string, | |
| char * | replace, | |||
| char * | replacement | |||
| ) |
Definition at line 388 of file pg_regress.c.
References free, NULL, and strlcpy().
Referenced by convert_sourcefiles_in(), ecpg_filter(), and ecpg_start_test().
| static bool results_differ | ( | const char * | testname, | |
| const char * | resultsfile, | |||
| const char * | default_expectfile | |||
| ) | [static] |
Definition at line 1218 of file pg_regress.c.
References basic_diff_opts, difffilename, file_exists(), file_line_count(), free, get_alternative_expectfile(), get_expectfile(), i, MAXPGPATH, pretty_diff_opts, run_diff(), snprintf(), SYSTEMQUOTE, and unlink().
Referenced by run_schedule(), and run_single_test().
{
char expectfile[MAXPGPATH];
char diff[MAXPGPATH];
char cmd[MAXPGPATH * 3];
char best_expect_file[MAXPGPATH];
FILE *difffile;
int best_line_count;
int i;
int l;
const char *platform_expectfile;
/*
* We can pass either the resultsfile or the expectfile, they should have
* the same type (filename.type) anyway.
*/
platform_expectfile = get_expectfile(testname, resultsfile);
strcpy(expectfile, default_expectfile);
if (platform_expectfile)
{
/*
* Replace everything afer the last slash in expectfile with what the
* platform_expectfile contains.
*/
char *p = strrchr(expectfile, '/');
if (p)
strcpy(++p, platform_expectfile);
}
/* Name to use for temporary diff file */
snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
/* OK, run the diff */
snprintf(cmd, sizeof(cmd),
SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
basic_diff_opts, expectfile, resultsfile, diff);
/* Is the diff file empty? */
if (run_diff(cmd, diff) == 0)
{
unlink(diff);
return false;
}
/* There may be secondary comparison files that match better */
best_line_count = file_line_count(diff);
strcpy(best_expect_file, expectfile);
for (i = 0; i <= 9; i++)
{
char *alt_expectfile;
alt_expectfile = get_alternative_expectfile(expectfile, i);
if (!file_exists(alt_expectfile))
continue;
snprintf(cmd, sizeof(cmd),
SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
basic_diff_opts, alt_expectfile, resultsfile, diff);
if (run_diff(cmd, diff) == 0)
{
unlink(diff);
return false;
}
l = file_line_count(diff);
if (l < best_line_count)
{
/* This diff was a better match than the last one */
best_line_count = l;
strcpy(best_expect_file, alt_expectfile);
}
free(alt_expectfile);
}
/*
* fall back on the canonical results file if we haven't tried it yet and
* haven't found a complete match yet.
*/
if (platform_expectfile)
{
snprintf(cmd, sizeof(cmd),
SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
basic_diff_opts, default_expectfile, resultsfile, diff);
if (run_diff(cmd, diff) == 0)
{
/* No diff = no changes = good */
unlink(diff);
return false;
}
l = file_line_count(diff);
if (l < best_line_count)
{
/* This diff was a better match than the last one */
best_line_count = l;
strcpy(best_expect_file, default_expectfile);
}
}
/*
* Use the best comparison file to generate the "pretty" diff, which we
* append to the diffs summary file.
*/
snprintf(cmd, sizeof(cmd),
SYSTEMQUOTE "diff %s \"%s\" \"%s\" >> \"%s\"" SYSTEMQUOTE,
pretty_diff_opts, best_expect_file, resultsfile, difffilename);
run_diff(cmd, difffilename);
/* And append a separator */
difffile = fopen(difffilename, "a");
if (difffile)
{
fprintf(difffile,
"\n======================================================================\n\n");
fclose(difffile);
}
unlink(diff);
return true;
}
| static int run_diff | ( | const char * | cmd, | |
| const char * | filename | |||
| ) | [static] |
Definition at line 1185 of file pg_regress.c.
References _, file_size(), system(), WEXITSTATUS, and WIFEXITED.
Referenced by results_differ().
{
int r;
r = system(cmd);
if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
{
fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
exit(2);
}
#ifdef WIN32
/*
* On WIN32, if the 'diff' command cannot be found, system() returns 1,
* but produces nothing to stdout, so we check for that here.
*/
if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
{
fprintf(stderr, _("diff command not found: %s\n"), cmd);
exit(2);
}
#endif
return WEXITSTATUS(r);
}
| static void run_schedule | ( | const char * | schedule, | |
| test_function | tfunc | |||
| ) | [static] |
Definition at line 1453 of file pg_regress.c.
References _, add_stringlist_item(), fail_count, fail_ignore_count, free_stringlist(), i, log_child_failure(), max_connections, MAX_PARALLEL_TESTS, _stringlist::next, NULL, PID_TYPE, progname, results_differ(), status(), status_end(), _stringlist::str, strerror(), success_count, test(), and wait_for_tests().
Referenced by regression_main().
{
#define MAX_PARALLEL_TESTS 100
char *tests[MAX_PARALLEL_TESTS];
_stringlist *resultfiles[MAX_PARALLEL_TESTS];
_stringlist *expectfiles[MAX_PARALLEL_TESTS];
_stringlist *tags[MAX_PARALLEL_TESTS];
PID_TYPE pids[MAX_PARALLEL_TESTS];
int statuses[MAX_PARALLEL_TESTS];
_stringlist *ignorelist = NULL;
char scbuf[1024];
FILE *scf;
int line_num = 0;
memset(resultfiles, 0, sizeof(_stringlist *) * MAX_PARALLEL_TESTS);
memset(expectfiles, 0, sizeof(_stringlist *) * MAX_PARALLEL_TESTS);
memset(tags, 0, sizeof(_stringlist *) * MAX_PARALLEL_TESTS);
scf = fopen(schedule, "r");
if (!scf)
{
fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
progname, schedule, strerror(errno));
exit(2);
}
while (fgets(scbuf, sizeof(scbuf), scf))
{
char *test = NULL;
char *c;
int num_tests;
bool inword;
int i;
line_num++;
for (i = 0; i < MAX_PARALLEL_TESTS; i++)
{
if (resultfiles[i] == NULL)
break;
free_stringlist(&resultfiles[i]);
free_stringlist(&expectfiles[i]);
free_stringlist(&tags[i]);
}
/* strip trailing whitespace, especially the newline */
i = strlen(scbuf);
while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
scbuf[--i] = '\0';
if (scbuf[0] == '\0' || scbuf[0] == '#')
continue;
if (strncmp(scbuf, "test: ", 6) == 0)
test = scbuf + 6;
else if (strncmp(scbuf, "ignore: ", 8) == 0)
{
c = scbuf + 8;
while (*c && isspace((unsigned char) *c))
c++;
add_stringlist_item(&ignorelist, c);
/*
* Note: ignore: lines do not run the test, they just say that
* failure of this test when run later on is to be ignored. A bit
* odd but that's how the shell-script version did it.
*/
continue;
}
else
{
fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
schedule, line_num, scbuf);
exit(2);
}
num_tests = 0;
inword = false;
for (c = test; *c; c++)
{
if (isspace((unsigned char) *c))
{
*c = '\0';
inword = false;
}
else if (!inword)
{
if (num_tests >= MAX_PARALLEL_TESTS)
{
/* can't print scbuf here, it's already been trashed */
fprintf(stderr, _("too many parallel tests in schedule file \"%s\", line %d\n"),
schedule, line_num);
exit(2);
}
tests[num_tests] = c;
num_tests++;
inword = true;
}
}
if (num_tests == 0)
{
fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
schedule, line_num, scbuf);
exit(2);
}
if (num_tests == 1)
{
status(_("test %-24s ... "), tests[0]);
pids[0] = (tfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
wait_for_tests(pids, statuses, NULL, 1);
/* status line is finished below */
}
else if (max_connections > 0 && max_connections < num_tests)
{
int oldest = 0;
status(_("parallel group (%d tests, in groups of %d): "),
num_tests, max_connections);
for (i = 0; i < num_tests; i++)
{
if (i - oldest >= max_connections)
{
wait_for_tests(pids + oldest, statuses + oldest,
tests + oldest, i - oldest);
oldest = i;
}
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
}
wait_for_tests(pids + oldest, statuses + oldest,
tests + oldest, i - oldest);
status_end();
}
else
{
status(_("parallel group (%d tests): "), num_tests);
for (i = 0; i < num_tests; i++)
{
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
}
wait_for_tests(pids, statuses, tests, num_tests);
status_end();
}
/* Check results for all tests */
for (i = 0; i < num_tests; i++)
{
_stringlist *rl,
*el,
*tl;
bool differ = false;
if (num_tests > 1)
status(_(" %-24s ... "), tests[i]);
/*
* Advance over all three lists simultaneously.
*
* Compare resultfiles[j] with expectfiles[j] always. Tags are
* optional but if there are tags, the tag list has the same
* length as the other two lists.
*/
for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
rl != NULL; /* rl and el have the same length */
rl = rl->next, el = el->next)
{
bool newdiff;
if (tl)
tl = tl->next; /* tl has the same length as rl and el
* if it exists */
newdiff = results_differ(tests[i], rl->str, el->str);
if (newdiff && tl)
{
printf("%s ", tl->str);
}
differ |= newdiff;
}
if (differ)
{
bool ignore = false;
_stringlist *sl;
for (sl = ignorelist; sl != NULL; sl = sl->next)
{
if (strcmp(tests[i], sl->str) == 0)
{
ignore = true;
break;
}
}
if (ignore)
{
status(_("failed (ignored)"));
fail_ignore_count++;
}
else
{
status(_("FAILED"));
fail_count++;
}
}
else
{
status(_("ok"));
success_count++;
}
if (statuses[i] != 0)
log_child_failure(statuses[i]);
status_end();
}
}
fclose(scf);
}
| static void run_single_test | ( | const char * | test, | |
| test_function | tfunc | |||
| ) | [static] |
Definition at line 1677 of file pg_regress.c.
References _, fail_count, log_child_failure(), _stringlist::next, NULL, PID_TYPE, results_differ(), status(), status_end(), _stringlist::str, success_count, and wait_for_tests().
Referenced by regression_main().
{
PID_TYPE pid;
int exit_status;
_stringlist *resultfiles = NULL;
_stringlist *expectfiles = NULL;
_stringlist *tags = NULL;
_stringlist *rl,
*el,
*tl;
bool differ = false;
status(_("test %-24s ... "), test);
pid = (tfunc) (test, &resultfiles, &expectfiles, &tags);
wait_for_tests(&pid, &exit_status, NULL, 1);
/*
* Advance over all three lists simultaneously.
*
* Compare resultfiles[j] with expectfiles[j] always. Tags are optional
* but if there are tags, the tag list has the same length as the other
* two lists.
*/
for (rl = resultfiles, el = expectfiles, tl = tags;
rl != NULL; /* rl and el have the same length */
rl = rl->next, el = el->next)
{
bool newdiff;
if (tl)
tl = tl->next; /* tl has the same length as rl and el if it
* exists */
newdiff = results_differ(test, rl->str, el->str);
if (newdiff && tl)
{
printf("%s ", tl->str);
}
differ |= newdiff;
}
if (differ)
{
status(_("FAILED"));
fail_count++;
}
else
{
status(_("ok"));
success_count++;
}
if (exit_status != 0)
log_child_failure(exit_status);
status_end();
}
| PID_TYPE spawn_process | ( | const char * | cmdline | ) |
Definition at line 934 of file pg_regress.c.
References _, BOOL(), free, logfile, malloc, NULL, progname, shellprog, strerror(), and TRUE.
Referenced by ecpg_start_test(), isolation_start_test(), psql_start_test(), and regression_main().
{
#ifndef WIN32
pid_t pid;
/*
* Must flush I/O buffers before fork. Ideally we'd use fflush(NULL) here
* ... does anyone still care about systems where that doesn't work?
*/
fflush(stdout);
fflush(stderr);
if (logfile)
fflush(logfile);
pid = fork();
if (pid == -1)
{
fprintf(stderr, _("%s: could not fork: %s\n"),
progname, strerror(errno));
exit(2);
}
if (pid == 0)
{
/*
* In child
*
* Instead of using system(), exec the shell directly, and tell it to
* "exec" the command too. This saves two useless processes per
* parallel test case.
*/
char *cmdline2 = malloc(strlen(cmdline) + 6);
sprintf(cmdline2, "exec %s", cmdline);
execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
progname, shellprog, strerror(errno));
_exit(1); /* not exit() here... */
}
/* in parent */
return pid;
#else
char *cmdline2;
BOOL b;
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE origToken;
HANDLE restrictedToken;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
SID_AND_ATTRIBUTES dropSids[2];
__CreateRestrictedToken _CreateRestrictedToken = NULL;
HANDLE Advapi32Handle;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
if (Advapi32Handle != NULL)
{
_CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
}
if (_CreateRestrictedToken == NULL)
{
if (Advapi32Handle != NULL)
FreeLibrary(Advapi32Handle);
fprintf(stderr, _("%s: cannot create restricted tokens on this platform\n"),
progname);
exit(2);
}
/* Open the current token to use as base for the restricted one */
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
{
fprintf(stderr, _("could not open process token: error code %lu\n"),
GetLastError());
exit(2);
}
/* Allocate list of SIDs to remove */
ZeroMemory(&dropSids, sizeof(dropSids));
if (!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &dropSids[0].Sid) ||
!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &dropSids[1].Sid))
{
fprintf(stderr, _("could not allocate SIDs: error code %lu\n"), GetLastError());
exit(2);
}
b = _CreateRestrictedToken(origToken,
DISABLE_MAX_PRIVILEGE,
sizeof(dropSids) / sizeof(dropSids[0]),
dropSids,
0, NULL,
0, NULL,
&restrictedToken);
FreeSid(dropSids[1].Sid);
FreeSid(dropSids[0].Sid);
CloseHandle(origToken);
FreeLibrary(Advapi32Handle);
if (!b)
{
fprintf(stderr, _("could not create restricted token: error code %lu\n"),
GetLastError());
exit(2);
}
cmdline2 = malloc(strlen(cmdline) + 8);
sprintf(cmdline2, "cmd /c %s", cmdline);
#ifndef __CYGWIN__
AddUserToTokenDacl(restrictedToken);
#endif
if (!CreateProcessAsUser(restrictedToken,
NULL,
cmdline2,
NULL,
NULL,
TRUE,
CREATE_SUSPENDED,
NULL,
NULL,
&si,
&pi))
{
fprintf(stderr, _("could not start process for \"%s\": error code %lu\n"),
cmdline2, GetLastError());
exit(2);
}
free(cmdline2);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
return pi.hProcess;
#endif
}
| static void split_to_stringlist | ( | const char * | s, | |
| const char * | delim, | |||
| _stringlist ** | listhead | |||
| ) | [static] |
Definition at line 216 of file pg_regress.c.
References add_stringlist_item(), free, and NULL.
Referenced by regression_main().
{
char *sc = strdup(s);
char *token = strtok(sc, delim);
while (token)
{
add_stringlist_item(listhead, token);
token = strtok(NULL, delim);
}
free(sc);
}
| static void status | ( | const char * | fmt, | |
| ... | ||||
| ) | [static] |
Definition at line 250 of file pg_regress.c.
References logfile.
Referenced by _MasterEndParallelItem(), ClientAuthentication(), ecpg_execute(), ecpg_store_result(), exec_command(), GetMultiXactIdHintBits(), HandleSlashCmds(), heap_lock_tuple(), log_child_failure(), MultiXactIdGetUpdateXid(), mxid_to_string(), pgrowlocks(), pqFunctionCall2(), pqFunctionCall3(), PQresetPoll(), RecordNewMultiXact(), restore_toc_entry(), run_schedule(), run_single_test(), setQFout(), test_postmaster_connection(), and wait_for_tests().
| static void status_end | ( | void | ) | [static] |
Definition at line 271 of file pg_regress.c.
References logfile.
Referenced by run_schedule(), and run_single_test().
| static void stop_postmaster | ( | void | ) | [static] |
Definition at line 283 of file pg_regress.c.
References _, bindir, buf, MAXPGPATH, postmaster_running, progname, snprintf(), system(), SYSTEMQUOTE, and temp_install.
{
if (postmaster_running)
{
/* We use pg_ctl to issue the kill and wait for stop */
char buf[MAXPGPATH * 2];
int r;
/* On Windows, system() seems not to force fflush, so... */
fflush(stdout);
fflush(stderr);
snprintf(buf, sizeof(buf),
SYSTEMQUOTE "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast" SYSTEMQUOTE,
bindir, temp_install);
r = system(buf);
if (r != 0)
{
fprintf(stderr, _("\n%s: could not stop postmaster: exit code was %d\n"),
progname, r);
_exit(2); /* not exit(), that could be recursive */
}
postmaster_running = false;
}
}
| static bool string_matches_pattern | ( | const char * | str, | |
| const char * | pattern | |||
| ) | [static] |
Definition at line 323 of file pg_regress.c.
Referenced by load_resultmap().
{
while (*str && *pattern)
{
if (*pattern == '.' && pattern[1] == '*')
{
pattern += 2;
/* Trailing .* matches everything. */
if (*pattern == '\0')
return true;
/*
* Otherwise, scan for a text position at which we can match the
* rest of the pattern.
*/
while (*str)
{
/*
* Optimization to prevent most recursion: don't recurse
* unless first pattern char might match this text char.
*/
if (*str == *pattern || *pattern == '.')
{
if (string_matches_pattern(str, pattern))
return true;
}
str++;
}
/*
* End of text with no match.
*/
return false;
}
else if (*pattern != '.' && *str != *pattern)
{
/*
* Not the single-character wildcard and no explicit match? Then
* time to quit...
*/
return false;
}
str++;
pattern++;
}
if (*pattern == '\0')
return true; /* end of pattern, so declare match */
/* End of input string. Do we have matching pattern remaining? */
while (*pattern == '.' && pattern[1] == '*')
pattern += 2;
if (*pattern == '\0')
return true; /* end of pattern, so declare match */
return false;
}
| static void wait_for_tests | ( | PID_TYPE * | pids, | |
| int * | statuses, | |||
| char ** | names, | |||
| int | num_tests | |||
| ) | [static] |
Definition at line 1354 of file pg_regress.c.
References _, FALSE, free, i, INVALID_PID, malloc, PID_TYPE, status(), and strerror().
Referenced by run_schedule(), and run_single_test().
{
int tests_left;
int i;
#ifdef WIN32
PID_TYPE *active_pids = malloc(num_tests * sizeof(PID_TYPE));
memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
#endif
tests_left = num_tests;
while (tests_left > 0)
{
PID_TYPE p;
#ifndef WIN32
int exit_status;
p = wait(&exit_status);
if (p == INVALID_PID)
{
fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
strerror(errno));
exit(2);
}
#else
DWORD exit_status;
int r;
r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
{
fprintf(stderr, _("failed to wait for subprocesses: error code %lu\n"),
GetLastError());
exit(2);
}
p = active_pids[r - WAIT_OBJECT_0];
/* compact the active_pids array */
active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
#endif /* WIN32 */
for (i = 0; i < num_tests; i++)
{
if (p == pids[i])
{
#ifdef WIN32
GetExitCodeProcess(pids[i], &exit_status);
CloseHandle(pids[i]);
#endif
pids[i] = INVALID_PID;
statuses[i] = (int) exit_status;
if (names)
status(" %s", names[i]);
tests_left--;
break;
}
}
}
#ifdef WIN32
free(active_pids);
#endif
}
| const char* basic_diff_opts = "" |
Definition at line 74 of file pg_regress.c.
Referenced by results_differ().
| char* bindir = PGBINDIR |
Definition at line 55 of file pg_regress.c.
Referenced by initialize_environment(), regression_main(), and stop_postmaster().
| char* datadir = PGSHAREDIR |
Definition at line 57 of file pg_regress.c.
Referenced by fuzzy_open_file(), initialize_environment(), and regression_main().
| _stringlist* dblist = NULL |
Definition at line 82 of file pg_regress.c.
Referenced by do_start_worker(), get_database_list(), isolation_init(), isolation_start_test(), psql_init(), psql_start_test(), and rebuild_database_list().
| bool debug = false |
Definition at line 83 of file pg_regress.c.
char* difffilename [static] |
Definition at line 111 of file pg_regress.c.
Referenced by open_result_files(), regression_main(), and results_differ().
char* dlpath = PKGLIBDIR [static] |
Definition at line 102 of file pg_regress.c.
Referenced by convert_sourcefiles_in(), and regression_main().
char* encoding = NULL [static] |
Definition at line 91 of file pg_regress.c.
Referenced by create_database(), initialize_environment(), and regression_main().
_stringlist* extra_install = NULL [static] |
Definition at line 105 of file pg_regress.c.
_stringlist* extra_tests = NULL [static] |
Definition at line 93 of file pg_regress.c.
_stringlist* extraroles = NULL [static] |
Definition at line 104 of file pg_regress.c.
int fail_count = 0 [static] |
Definition at line 119 of file pg_regress.c.
Referenced by regression_main(), run_schedule(), and run_single_test().
int fail_ignore_count = 0 [static] |
Definition at line 120 of file pg_regress.c.
Referenced by regression_main(), and run_schedule().
| char* host_platform = HOST_TUPLE |
Definition at line 58 of file pg_regress.c.
Referenced by load_resultmap().
char* hostname = NULL [static] |
Definition at line 99 of file pg_regress.c.
Referenced by initialize_environment(), and regression_main().
| char* inputdir = "." |
Definition at line 84 of file pg_regress.c.
Referenced by convert_sourcefiles(), convert_sourcefiles_in(), ecpg_start_test(), isolation_start_test(), load_resultmap(), psql_start_test(), and regression_main().
| char* launcher = NULL |
Definition at line 87 of file pg_regress.c.
Referenced by isolation_start_test(), psql_start_test(), and regression_main().
| char* libdir = LIBDIR |
Definition at line 56 of file pg_regress.c.
Referenced by initialize_environment().
_stringlist* loadextension = NULL [static] |
Definition at line 89 of file pg_regress.c.
_stringlist* loadlanguage = NULL [static] |
Definition at line 88 of file pg_regress.c.
FILE* logfile [static] |
Definition at line 110 of file pg_regress.c.
Referenced by open_result_files(), regression_main(), spawn_process(), status(), status_end(), threadRun(), and write_syslogger_file().
char* logfilename [static] |
Definition at line 109 of file pg_regress.c.
Referenced by open_result_files(), and regression_main().
char* makeprog = MAKEPROG [static] |
Definition at line 61 of file pg_regress.c.
Referenced by regression_main().
int max_connections = 0 [static] |
Definition at line 90 of file pg_regress.c.
Referenced by regression_main(), and run_schedule().
Definition at line 97 of file pg_regress.c.
Referenced by create_database(), initialize_environment(), and regression_main().
| char* outputdir = "." |
Definition at line 85 of file pg_regress.c.
Referenced by convert_sourcefiles(), convert_sourcefiles_in(), ecpg_start_test(), isolation_start_test(), open_result_files(), psql_start_test(), and regression_main().
int port = -1 [static] |
Definition at line 100 of file pg_regress.c.
Referenced by ECPGconnect(), inet_client_addr(), inet_client_port(), inet_server_addr(), inet_server_port(), initialize_environment(), log_disconnections(), main(), regression_main(), ServerLoop(), and ssl_client_serial().
bool port_specified_by_user = false [static] |
Definition at line 101 of file pg_regress.c.
Referenced by regression_main().
PID_TYPE postmaster_pid = INVALID_PID [static] |
Definition at line 115 of file pg_regress.c.
Referenced by regression_main().
bool postmaster_running = false [static] |
Definition at line 116 of file pg_regress.c.
Referenced by regression_main(), and stop_postmaster().
| const char* pretty_diff_opts = "-C3" |
Definition at line 75 of file pg_regress.c.
Referenced by regression_main(), and results_differ().
const char* progname [static] |
Definition at line 108 of file pg_regress.c.
| char* psqldir = PGBINDIR |
Definition at line 86 of file pg_regress.c.
Referenced by initialize_environment(), psql_command(), psql_start_test(), and regression_main().
_resultmap* resultmap = NULL [static] |
Definition at line 113 of file pg_regress.c.
_stringlist* schedulelist = NULL [static] |
Definition at line 92 of file pg_regress.c.
char* shellprog = SHELLPROG [static] |
Definition at line 65 of file pg_regress.c.
Referenced by spawn_process().
int success_count = 0 [static] |
Definition at line 118 of file pg_regress.c.
Referenced by regression_main(), run_schedule(), and run_single_test().
char* temp_config = NULL [static] |
Definition at line 95 of file pg_regress.c.
Referenced by regression_main().
char* temp_install = NULL [static] |
Definition at line 94 of file pg_regress.c.
Referenced by initialize_environment(), regression_main(), and stop_postmaster().
char* top_builddir = NULL [static] |
Definition at line 96 of file pg_regress.c.
Referenced by regression_main().
bool use_existing = false [static] |
Definition at line 98 of file pg_regress.c.
Referenced by regression_main().
char* user = NULL [static] |
Definition at line 103 of file pg_regress.c.
Referenced by conninfo_uri_parse_options(), exec_command(), initialize_environment(), main(), postgresAcquireSampleRowsFunc(), postgresAnalyzeForeignTable(), postgresBeginForeignModify(), postgresBeginForeignScan(), regression_main(), and usage().
1.7.1