PostgreSQL Source Code git master
pg_regress.h File Reference
#include <unistd.h>
Include dependency graph for pg_regress.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  _stringlist
 

Macros

#define PID_TYPE   pid_t
 
#define INVALID_PID   (-1)
 

Typedefs

typedef struct _stringlist _stringlist
 
typedef void(* init_function) (int argc, char **argv)
 
typedef PID_TYPE(* test_start_function) (const char *testname, _stringlist **resultfiles, _stringlist **expectfiles, _stringlist **tags)
 
typedef void(* postprocess_result_function) (const char *filename)
 

Functions

int regression_main (int argc, char *argv[], init_function ifunc, test_start_function startfunc, postprocess_result_function postfunc)
 
void add_stringlist_item (_stringlist **listhead, const char *str)
 
PID_TYPE spawn_process (const char *cmdline)
 
bool file_exists (const char *file)
 

Variables

char * bindir
 
char * libdir
 
char * datadir
 
char * host_platform
 
_stringlistdblist
 
bool debug
 
char * inputdir
 
char * outputdir
 
char * expecteddir
 
char * launcher
 
const char * basic_diff_opts
 
const char * pretty_diff_opts
 

Macro Definition Documentation

◆ INVALID_PID

#define INVALID_PID   (-1)

Definition at line 15 of file pg_regress.h.

◆ PID_TYPE

#define PID_TYPE   pid_t

Definition at line 14 of file pg_regress.h.

Typedef Documentation

◆ _stringlist

typedef struct _stringlist _stringlist

◆ init_function

typedef void(* init_function) (int argc, char **argv)

Definition at line 33 of file pg_regress.h.

◆ postprocess_result_function

typedef void(* postprocess_result_function) (const char *filename)

Definition at line 42 of file pg_regress.h.

◆ test_start_function

typedef PID_TYPE(* test_start_function) (const char *testname, _stringlist **resultfiles, _stringlist **expectfiles, _stringlist **tags)

Definition at line 36 of file pg_regress.h.

Function Documentation

◆ add_stringlist_item()

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

Definition at line 197 of file pg_regress.c.

198{
199 _stringlist *newentry = pg_malloc(sizeof(_stringlist));
200 _stringlist *oldentry;
201
202 newentry->str = pg_strdup(str);
203 newentry->next = NULL;
204 if (*listhead == NULL)
205 *listhead = newentry;
206 else
207 {
208 for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
209 /* skip */ ;
210 oldentry->next = newentry;
211 }
212}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
const char * str
char * str
Definition: initdb.c:92
struct _stringlist * next
Definition: initdb.c:93

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

Referenced by regression_main(), and split_to_stringlist().

◆ file_exists()

bool file_exists ( const char *  file)

Definition at line 1307 of file pg_regress.c.

1308{
1309 FILE *f = fopen(file, "r");
1310
1311 if (!f)
1312 return false;
1313 fclose(f);
1314 return true;
1315}

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

◆ regression_main()

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

Definition at line 2069 of file pg_regress.c.

2073{
2074 static struct option long_options[] = {
2075 {"help", no_argument, NULL, 'h'},
2076 {"version", no_argument, NULL, 'V'},
2077 {"dbname", required_argument, NULL, 1},
2078 {"debug", no_argument, NULL, 2},
2079 {"inputdir", required_argument, NULL, 3},
2080 {"max-connections", required_argument, NULL, 5},
2081 {"encoding", required_argument, NULL, 6},
2082 {"outputdir", required_argument, NULL, 7},
2083 {"schedule", required_argument, NULL, 8},
2084 {"temp-instance", required_argument, NULL, 9},
2085 {"no-locale", no_argument, NULL, 10},
2086 {"host", required_argument, NULL, 13},
2087 {"port", required_argument, NULL, 14},
2088 {"user", required_argument, NULL, 15},
2089 {"bindir", required_argument, NULL, 16},
2090 {"dlpath", required_argument, NULL, 17},
2091 {"create-role", required_argument, NULL, 18},
2092 {"temp-config", required_argument, NULL, 19},
2093 {"use-existing", no_argument, NULL, 20},
2094 {"launcher", required_argument, NULL, 21},
2095 {"load-extension", required_argument, NULL, 22},
2096 {"config-auth", required_argument, NULL, 24},
2097 {"max-concurrent-tests", required_argument, NULL, 25},
2098 {"expecteddir", required_argument, NULL, 26},
2099 {NULL, 0, NULL, 0}
2100 };
2101
2102 bool use_unix_sockets;
2103 _stringlist *sl;
2104 int c;
2105 int i;
2106 int option_index;
2107 char buf[MAXPGPATH * 4];
2108
2109 pg_logging_init(argv[0]);
2110 progname = get_progname(argv[0]);
2111 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
2112
2114
2115 atexit(stop_postmaster);
2116
2117#if defined(WIN32)
2118
2119 /*
2120 * We don't use Unix-domain sockets on Windows by default (see comment at
2121 * remove_temp() for a reason). Override at your own risk.
2122 */
2123 use_unix_sockets = getenv("PG_TEST_USE_UNIX_SOCKETS") ? true : false;
2124#else
2125 use_unix_sockets = true;
2126#endif
2127
2128 if (!use_unix_sockets)
2129 hostname = "localhost";
2130
2131 /*
2132 * We call the initialization function here because that way we can set
2133 * default parameters and let them be overwritten by the commandline.
2134 */
2135 ifunc(argc, argv);
2136
2137 if (getenv("PG_REGRESS_DIFF_OPTS"))
2138 pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
2139
2140 while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
2141 {
2142 switch (c)
2143 {
2144 case 'h':
2145 help();
2146 exit(0);
2147 case 'V':
2148 puts("pg_regress (PostgreSQL) " PG_VERSION);
2149 exit(0);
2150 case 1:
2151
2152 /*
2153 * If a default database was specified, we need to remove it
2154 * before we add the specified one.
2155 */
2158 break;
2159 case 2:
2160 debug = true;
2161 break;
2162 case 3:
2164 break;
2165 case 5:
2166 max_connections = atoi(optarg);
2167 break;
2168 case 6:
2170 break;
2171 case 7:
2173 break;
2174 case 8:
2176 break;
2177 case 9:
2179 break;
2180 case 10:
2181 nolocale = true;
2182 break;
2183 case 13:
2185 break;
2186 case 14:
2187 port = atoi(optarg);
2189 break;
2190 case 15:
2192 break;
2193 case 16:
2194 /* "--bindir=" means to use PATH */
2195 if (strlen(optarg))
2197 else
2198 bindir = NULL;
2199 break;
2200 case 17:
2202 break;
2203 case 18:
2205 break;
2206 case 19:
2208 break;
2209 case 20:
2210 use_existing = true;
2211 break;
2212 case 21:
2214 break;
2215 case 22:
2217 break;
2218 case 24:
2220 break;
2221 case 25:
2223 break;
2224 case 26:
2226 break;
2227 default:
2228 /* getopt_long already emitted a complaint */
2229 pg_log_error_hint("Try \"%s --help\" for more information.",
2230 progname);
2231 exit(2);
2232 }
2233 }
2234
2235 /*
2236 * if we still have arguments, they are extra tests to run
2237 */
2238 while (argc - optind >= 1)
2239 {
2241 optind++;
2242 }
2243
2244 /*
2245 * We must have a database to run the tests in; either a default name, or
2246 * one supplied by the --dbname switch.
2247 */
2248 if (!(dblist && dblist->str && dblist->str[0]))
2249 {
2250 bail("no database name was specified");
2251 }
2252
2254 {
2255#ifdef ENABLE_SSPI
2256 if (!use_unix_sockets)
2257 config_sspi_auth(config_auth_datadir, user);
2258#endif
2259 exit(0);
2260 }
2261
2263
2264 /*
2265 * To reduce chances of interference with parallel installations, use
2266 * a port number starting in the private range (49152-65535)
2267 * calculated from the version number. This aids non-Unix socket mode
2268 * systems; elsewhere, the use of a private socket directory already
2269 * prevents interference.
2270 */
2271 port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
2272
2277
2278 /*
2279 * Initialization
2280 */
2282
2284
2285#if defined(HAVE_GETRLIMIT)
2287#endif
2288
2289 if (temp_instance)
2290 {
2291 StringInfoData cmd;
2292 FILE *pg_conf;
2293 const char *env_wait;
2294 int wait_seconds;
2295 const char *initdb_template_dir;
2296 const char *keywords[4];
2297 const char *values[4];
2298 PGPing rv;
2299 const char *initdb_extra_opts_env;
2300
2301 /*
2302 * Prepare the temp instance
2303 */
2304
2306 {
2307 if (!rmtree(temp_instance, true))
2308 {
2309 bail("could not remove temp instance \"%s\"", temp_instance);
2310 }
2311 }
2312
2313 /* make the temp instance top directory */
2315
2316 /* and a directory for log files */
2317 snprintf(buf, sizeof(buf), "%s/log", outputdir);
2318 if (!directory_exists(buf))
2320
2321 initdb_extra_opts_env = getenv("PG_TEST_INITDB_EXTRA_OPTS");
2322
2323 initStringInfo(&cmd);
2324
2325 /*
2326 * Create data directory.
2327 *
2328 * If available, use a previously initdb'd cluster as a template by
2329 * copying it. For a lot of tests, that's substantially cheaper.
2330 *
2331 * There's very similar code in Cluster.pm, but we can't easily de
2332 * duplicate it until we require perl at build time.
2333 */
2334 initdb_template_dir = getenv("INITDB_TEMPLATE");
2335 if (initdb_template_dir == NULL || nolocale || debug || initdb_extra_opts_env)
2336 {
2337 note("initializing database system by running initdb");
2338
2339 appendStringInfo(&cmd,
2340 "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync",
2341 bindir ? bindir : "",
2342 bindir ? "/" : "",
2344 if (debug)
2345 appendStringInfoString(&cmd, " --debug");
2346 if (nolocale)
2347 appendStringInfoString(&cmd, " --no-locale");
2348 if (initdb_extra_opts_env)
2349 appendStringInfo(&cmd, " %s", initdb_extra_opts_env);
2350 appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
2351 fflush(NULL);
2352 if (system(cmd.data))
2353 {
2354 bail("initdb failed\n"
2355 "# Examine \"%s/log/initdb.log\" for the reason.\n"
2356 "# Command was: %s",
2357 outputdir, cmd.data);
2358 }
2359 }
2360 else
2361 {
2362#ifndef WIN32
2363 const char *copycmd = "cp -RPp \"%s\" \"%s/data\"";
2364 int expected_exitcode = 0;
2365#else
2366 const char *copycmd = "robocopy /E /NJS /NJH /NFL /NDL /NP \"%s\" \"%s/data\"";
2367 int expected_exitcode = 1; /* 1 denotes files were copied */
2368#endif
2369
2370 note("initializing database system by copying initdb template");
2371
2372 appendStringInfo(&cmd,
2373 copycmd,
2374 initdb_template_dir,
2376 appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir);
2377 fflush(NULL);
2378 if (system(cmd.data) != expected_exitcode)
2379 {
2380 bail("copying of initdb template failed\n"
2381 "# Examine \"%s/log/initdb.log\" for the reason.\n"
2382 "# Command was: %s",
2383 outputdir, cmd.data);
2384 }
2385 }
2386
2387 pfree(cmd.data);
2388
2389 /*
2390 * Adjust the default postgresql.conf for regression testing. The user
2391 * can specify a file to be appended; in any case we expand logging
2392 * and set max_prepared_transactions to enable testing of prepared
2393 * xacts. (Note: to reduce the probability of unexpected shmmax
2394 * failures, don't set max_prepared_transactions any higher than
2395 * actually needed by the prepared_xacts regression test.)
2396 */
2397 snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
2398 pg_conf = fopen(buf, "a");
2399 if (pg_conf == NULL)
2400 bail("could not open \"%s\" for adding extra config: %m", buf);
2401
2402 fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
2403 fputs("log_autovacuum_min_duration = 0\n", pg_conf);
2404 fputs("log_checkpoints = on\n", pg_conf);
2405 fputs("log_line_prefix = '%m %b[%p] %q%a '\n", pg_conf);
2406 fputs("log_lock_waits = on\n", pg_conf);
2407 fputs("log_temp_files = 128kB\n", pg_conf);
2408 fputs("max_prepared_transactions = 2\n", pg_conf);
2409
2410 for (sl = temp_configs; sl != NULL; sl = sl->next)
2411 {
2412 char *temp_config = sl->str;
2413 FILE *extra_conf;
2414 char line_buf[1024];
2415
2416 extra_conf = fopen(temp_config, "r");
2417 if (extra_conf == NULL)
2418 {
2419 bail("could not open \"%s\" to read extra config: %m",
2420 temp_config);
2421 }
2422 while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
2423 fputs(line_buf, pg_conf);
2424 fclose(extra_conf);
2425 }
2426
2427 fclose(pg_conf);
2428
2429#ifdef ENABLE_SSPI
2430 if (!use_unix_sockets)
2431 {
2432 /*
2433 * Since we successfully used the same buffer for the much-longer
2434 * "initdb" command, this can't truncate.
2435 */
2436 snprintf(buf, sizeof(buf), "%s/data", temp_instance);
2437 config_sspi_auth(buf, NULL);
2438 }
2439#endif
2440
2441 /*
2442 * Prepare the connection params for checking the state of the server
2443 * before starting the tests.
2444 */
2445 sprintf(portstr, "%d", port);
2446 keywords[0] = "dbname";
2447 values[0] = "postgres";
2448 keywords[1] = "port";
2449 values[1] = portstr;
2450 keywords[2] = "host";
2452 keywords[3] = NULL;
2453 values[3] = NULL;
2454
2455 /*
2456 * Check if there is a postmaster running already.
2457 */
2458 for (i = 0; i < 16; i++)
2459 {
2460 rv = PQpingParams(keywords, values, 1);
2461
2462 if (rv == PQPING_OK)
2463 {
2464 if (port_specified_by_user || i == 15)
2465 {
2466 note("port %d apparently in use", port);
2468 note("could not determine an available port");
2469 bail("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.");
2470 }
2471
2472 note("port %d apparently in use, trying %d", port, port + 1);
2473 port++;
2474 sprintf(portstr, "%d", port);
2475 setenv("PGPORT", portstr, 1);
2476 }
2477 else
2478 break;
2479 }
2480
2481 /*
2482 * Start the temp postmaster
2483 */
2484 snprintf(buf, sizeof(buf),
2485 "\"%s%spostgres\" -D \"%s/data\" -F%s "
2486 "-c \"listen_addresses=%s\" -k \"%s\" "
2487 "> \"%s/log/postmaster.log\" 2>&1",
2488 bindir ? bindir : "",
2489 bindir ? "/" : "",
2490 temp_instance, debug ? " -d 5" : "",
2491 hostname ? hostname : "", sockdir ? sockdir : "",
2492 outputdir);
2495 bail("could not spawn postmaster: %m");
2496
2497 /*
2498 * Wait till postmaster is able to accept connections; normally takes
2499 * only a fraction of a second or so, but Cygwin is reportedly *much*
2500 * slower, and test builds using Valgrind or similar tools might be
2501 * too. Hence, allow the default timeout of 60 seconds to be
2502 * overridden from the PGCTLTIMEOUT environment variable.
2503 */
2504 env_wait = getenv("PGCTLTIMEOUT");
2505 if (env_wait != NULL)
2506 {
2507 wait_seconds = atoi(env_wait);
2508 if (wait_seconds <= 0)
2509 wait_seconds = 60;
2510 }
2511 else
2512 wait_seconds = 60;
2513
2514 for (i = 0; i < wait_seconds * WAIT_TICKS_PER_SECOND; i++)
2515 {
2516 /*
2517 * It's fairly unlikely that the server is responding immediately
2518 * so we start with sleeping before checking instead of the other
2519 * way around.
2520 */
2521 pg_usleep(1000000L / WAIT_TICKS_PER_SECOND);
2522
2523 rv = PQpingParams(keywords, values, 1);
2524
2525 /* Done if the server is running and accepts connections */
2526 if (rv == PQPING_OK)
2527 break;
2528
2529 if (rv == PQPING_NO_ATTEMPT)
2530 bail("attempting to connect to postmaster failed");
2531
2532 /*
2533 * Fail immediately if postmaster has exited
2534 */
2535#ifndef WIN32
2536 if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
2537#else
2538 if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
2539#endif
2540 {
2541 bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason",
2542 outputdir);
2543 }
2544 }
2546 {
2547 diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason",
2549
2550 /*
2551 * If we get here, the postmaster is probably wedged somewhere in
2552 * startup. Try to kill it ungracefully rather than leaving a
2553 * stuck postmaster that might interfere with subsequent test
2554 * attempts.
2555 */
2556#ifndef WIN32
2557 if (kill(postmaster_pid, SIGKILL) != 0 && errno != ESRCH)
2558 bail("could not kill failed postmaster: %m");
2559#else
2560 if (TerminateProcess(postmaster_pid, 255) == 0)
2561 bail("could not kill failed postmaster: error code %lu",
2562 GetLastError());
2563#endif
2564 bail("postmaster failed");
2565 }
2566
2567 postmaster_running = true;
2568
2569#ifdef _WIN64
2570/* need a series of two casts to convert HANDLE without compiler warning */
2571#define ULONGPID(x) (unsigned long) (unsigned long long) (x)
2572#else
2573#define ULONGPID(x) (unsigned long) (x)
2574#endif
2575 note("using temp instance on port %d with PID %lu",
2577 }
2578 else
2579 {
2580 /*
2581 * Using an existing installation, so may need to get rid of
2582 * pre-existing database(s) and role(s)
2583 */
2584 if (!use_existing)
2585 {
2586 for (sl = dblist; sl; sl = sl->next)
2588 for (sl = extraroles; sl; sl = sl->next)
2590 }
2591 }
2592
2593 /*
2594 * Create the test database(s) and role(s)
2595 */
2596 if (!use_existing)
2597 {
2598 for (sl = dblist; sl; sl = sl->next)
2599 create_database(sl->str);
2600 for (sl = extraroles; sl; sl = sl->next)
2601 create_role(sl->str, dblist);
2602 }
2603
2604 /*
2605 * Ready to run the tests
2606 */
2607 for (sl = schedulelist; sl != NULL; sl = sl->next)
2608 {
2609 run_schedule(sl->str, startfunc, postfunc);
2610 }
2611
2612 for (sl = extra_tests; sl != NULL; sl = sl->next)
2613 {
2614 run_single_test(sl->str, startfunc, postfunc);
2615 }
2616
2617 /*
2618 * Shut down temp installation's postmaster
2619 */
2620 if (temp_instance)
2621 {
2623 }
2624
2625 /*
2626 * If there were no errors, remove the temp instance immediately to
2627 * conserve disk space. (If there were errors, we leave the instance in
2628 * place for possible manual investigation.)
2629 */
2630 if (temp_instance && fail_count == 0)
2631 {
2632 if (!rmtree(temp_instance, true))
2633 diag("could not remove temp instance \"%s\"",
2635 }
2636
2637 /*
2638 * Emit a TAP compliant Plan
2639 */
2641
2642 /*
2643 * Emit nice-looking summary message
2644 */
2645 if (fail_count == 0)
2646 note("All %d tests passed.", success_count);
2647 else
2648 diag("%d of %d tests failed.", fail_count, success_count + fail_count);
2649
2650 if (file_size(difffilename) > 0)
2651 {
2652 diag("The differences that caused some tests to fail can be viewed in the file \"%s\".",
2653 difffilename);
2654 diag("A copy of the test summary that you see above is saved in the file \"%s\".",
2655 logfilename);
2656 }
2657 else
2658 {
2659 unlink(difffilename);
2660 unlink(logfilename);
2661 }
2662
2663 fclose(logfile);
2664 logfile = NULL;
2665
2666 if (fail_count != 0)
2667 exit(1);
2668
2669 return 0;
2670}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1171
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:429
PGPing PQpingParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:722
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:25
#define required_argument
Definition: getopt_long.h:26
return true
Definition: isn.c:125
int i
Definition: isn.c:72
static const JsonPathKeyword keywords[]
PGPing
Definition: libpq-fe.h:170
@ PQPING_OK
Definition: libpq-fe.h:171
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:174
static void const char fflush(stdout)
exit(1)
void pg_logging_init(const char *argv0)
Definition: logging.c:83
#define pg_log_error_hint(...)
Definition: logging.h:112
void pfree(void *pointer)
Definition: mcxt.c:1521
#define MAXPGPATH
static int wait_seconds
Definition: pg_ctl.c:76
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
#define plan(x)
Definition: pg_regress.c:161
static bool use_existing
Definition: pg_regress.c:113
static void open_result_files(void)
Definition: pg_regress.c:1916
static int max_connections
Definition: pg_regress.c:105
static char * user
Definition: pg_regress.c:119
static bool port_specified_by_user
Definition: pg_regress.c:117
static bool nolocale
Definition: pg_regress.c:112
#define diag(...)
Definition: pg_regress.c:164
static void stop_postmaster(void)
Definition: pg_regress.c:433
static int max_concurrent_tests
Definition: pg_regress.c:106
static void create_database(const char *dbname)
Definition: pg_regress.c:1960
static void free_stringlist(_stringlist **listhead)
Definition: pg_regress.c:218
static void drop_role_if_exists(const char *rolename)
Definition: pg_regress.c:1994
bool debug
Definition: pg_regress.c:98
static void unlimit_core_size(void)
Definition: pg_regress.c:174
static bool directory_exists(const char *dir)
Definition: pg_regress.c:1318
static _stringlist * schedulelist
Definition: pg_regress.c:108
#define WAIT_TICKS_PER_SECOND
Definition: pg_regress.c:82
static _stringlist * loadextension
Definition: pg_regress.c:104
static char * logfilename
Definition: pg_regress.c:125
static _stringlist * temp_configs
Definition: pg_regress.c:111
static _stringlist * extra_tests
Definition: pg_regress.c:109
static int port
Definition: pg_regress.c:115
char * outputdir
Definition: pg_regress.c:100
static void make_directory(const char *dir)
Definition: pg_regress.c:1331
static void split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
Definition: pg_regress.c:233
#define note(...)
Definition: pg_regress.c:162
static void run_single_test(const char *test, test_start_function startfunc, postprocess_result_function postfunc)
Definition: pg_regress.c:1849
char * launcher
Definition: pg_regress.c:103
const char * pretty_diff_opts
Definition: pg_regress.c:65
char * inputdir
Definition: pg_regress.c:99
static char * difffilename
Definition: pg_regress.c:127
char * expecteddir
Definition: pg_regress.c:101
static char * config_auth_datadir
Definition: pg_regress.c:121
static void drop_database_if_exists(const char *dbname)
Definition: pg_regress.c:1949
static FILE * logfile
Definition: pg_regress.c:126
static char portstr[16]
Definition: pg_regress.c:116
static void initialize_environment(void)
Definition: pg_regress.c:723
static char * temp_instance
Definition: pg_regress.c:110
static char * encoding
Definition: pg_regress.c:107
static void help(void)
Definition: pg_regress.c:2019
static const char * sockdir
Definition: pg_regress.c:128
static long file_size(const char *file)
Definition: pg_regress.c:1266
static bool postmaster_running
Definition: pg_regress.c:138
_stringlist * dblist
Definition: pg_regress.c:97
static const char * progname
Definition: pg_regress.c:124
static char * dlpath
Definition: pg_regress.c:118
static _stringlist * extraroles
Definition: pg_regress.c:120
PID_TYPE spawn_process(const char *cmdline)
Definition: pg_regress.c:1204
char * bindir
Definition: pg_regress.c:102
#define bail(...)
Definition: pg_regress.c:167
static void create_role(const char *rolename, const _stringlist *granted_dbs)
Definition: pg_regress.c:2005
static void run_schedule(const char *schedule, test_start_function startfunc, postprocess_result_function postfunc)
Definition: pg_regress.c:1643
void add_stringlist_item(_stringlist **listhead, const char *str)
Definition: pg_regress.c:197
static int success_count
Definition: pg_regress.c:140
#define ULONGPID(x)
static char * hostname
Definition: pg_regress.c:114
static int fail_count
Definition: pg_regress.c:141
static PID_TYPE postmaster_pid
Definition: pg_regress.c:137
#define INVALID_PID
Definition: pg_regress.h:15
static char * buf
Definition: pg_test_fsync.c:72
#define sprintf
Definition: port.h:241
#define snprintf
Definition: port.h:239
char * make_absolute_path(const char *path)
Definition: path.c:807
const char * get_progname(const char *argv0)
Definition: path.c:652
char * c
void get_restricted_token(void)
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:50
void pg_usleep(long microsec)
Definition: signal.c:53
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
#define kill(pid, sig)
Definition: win32_port.h:493
#define setenv(x, y, z)
Definition: win32_port.h:545
#define SIGKILL
Definition: win32_port.h:162

References add_stringlist_item(), appendStringInfo(), appendStringInfoString(), bail, bindir, buf, config_auth_datadir, create_database(), create_role(), StringInfoData::data, dblist, debug, diag, difffilename, directory_exists(), dlpath, drop_database_if_exists(), drop_role_if_exists(), encoding, exit(), expecteddir, extra_tests, extraroles, fail_count, fflush(), file_size(), free_stringlist(), get_progname(), get_restricted_token(), getopt_long(), help(), hostname, i, initialize_environment(), initStringInfo(), inputdir, INVALID_PID, keywords, kill, launcher, loadextension, logfile, logfilename, make_absolute_path(), make_directory(), max_concurrent_tests, max_connections, MAXPGPATH, _stringlist::next, no_argument, nolocale, note, open_result_files(), optarg, optind, outputdir, pfree(), pg_log_error_hint, pg_logging_init(), pg_strdup(), PG_TEXTDOMAIN, pg_usleep(), plan, port, port_specified_by_user, portstr, postmaster_pid, postmaster_running, PQPING_NO_ATTEMPT, PQPING_OK, PQpingParams(), pretty_diff_opts, 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, success_count, temp_configs, temp_instance, true, ULONGPID, unlimit_core_size(), use_existing, user, values, wait_seconds, and WAIT_TICKS_PER_SECOND.

Referenced by main().

◆ spawn_process()

PID_TYPE spawn_process ( const char *  cmdline)

Definition at line 1204 of file pg_regress.c.

1205{
1206#ifndef WIN32
1207 pid_t pid;
1208
1209 /*
1210 * Must flush I/O buffers before fork.
1211 */
1212 fflush(NULL);
1213
1214#ifdef EXEC_BACKEND
1215 pg_disable_aslr();
1216#endif
1217
1218 pid = fork();
1219 if (pid == -1)
1220 {
1221 bail("could not fork: %m");
1222 }
1223 if (pid == 0)
1224 {
1225 /*
1226 * In child
1227 *
1228 * Instead of using system(), exec the shell directly, and tell it to
1229 * "exec" the command too. This saves two useless processes per
1230 * parallel test case.
1231 */
1232 char *cmdline2;
1233
1234 cmdline2 = psprintf("exec %s", cmdline);
1235 execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
1236 /* Not using the normal bail() here as we want _exit */
1237 bail_noatexit("could not exec \"%s\": %m", shellprog);
1238 }
1239 /* in parent */
1240 return pid;
1241#else
1242 PROCESS_INFORMATION pi;
1243 char *cmdline2;
1244 const char *comspec;
1245
1246 /* Find CMD.EXE location using COMSPEC, if it's set */
1247 comspec = getenv("COMSPEC");
1248 if (comspec == NULL)
1249 comspec = "CMD";
1250
1251 memset(&pi, 0, sizeof(pi));
1252 cmdline2 = psprintf("\"%s\" /c \"%s\"", comspec, cmdline);
1253
1254 if (!CreateRestrictedProcess(cmdline2, &pi))
1255 exit(2);
1256
1257 CloseHandle(pi.hThread);
1258 return pi.hProcess;
1259#endif
1260}
static char * shellprog
Definition: pg_regress.c:55
#define bail_noatexit(...)
Definition: pg_regress.c:166
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43

References bail, bail_noatexit, exit(), fflush(), psprintf(), and shellprog.

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

Variable Documentation

◆ basic_diff_opts

const char* basic_diff_opts
extern

Definition at line 64 of file pg_regress.c.

Referenced by results_differ().

◆ bindir

char* bindir
extern

◆ datadir

◆ dblist

◆ debug

bool debug
extern

Definition at line 98 of file pg_regress.c.

Referenced by regression_main().

◆ expecteddir

char* expecteddir
extern

Definition at line 101 of file pg_regress.c.

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

◆ host_platform

char* host_platform
extern

Definition at line 52 of file pg_regress.c.

Referenced by load_resultmap().

◆ inputdir

◆ launcher

char* launcher
extern

Definition at line 103 of file pg_regress.c.

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

◆ libdir

char* libdir
extern

◆ outputdir

◆ pretty_diff_opts

const char* pretty_diff_opts
extern

Definition at line 65 of file pg_regress.c.

Referenced by regression_main(), and results_differ().