/* for resultmap we need a list of pairs of strings */ typedefstruct _resultmap
{ char *test; char *type; char *resultfile; struct _resultmap *next;
} _resultmap;
/* *IfthiswasaBailmessage,thebailprotocolmessagemustgotostdout *separately.
*/ if (type == BAIL)
{
fprintf(stdout, "Bail out!"); if (logfile)
fprintf(logfile, "Bail out!");
}
va_end(argp_logfile);
if (type != NOTE_DETAIL)
{
fprintf(fp, "\n"); if (logfile)
fprintf(logfile, "\n");
}
fflush(NULL);
}
/* *shutdowntemppostmaster
*/ staticvoid
stop_postmaster(void)
{ if (postmaster_running)
{ /* We use pg_ctl to issue the kill and wait for stop */ char buf[MAXPGPATH * 2]; int r;
snprintf(buf, sizeof(buf), "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
bindir ? bindir : "",
bindir ? "/" : "",
temp_instance);
fflush(NULL);
r = system(buf); if (r != 0)
{ /* Not using the normal bail() as we want _exit */
bail_noatexit(_("could not stop postmaster: exit code was %d"), r);
}
temp_sockdir = mkdtemp(template); if (temp_sockdir == NULL)
bail("could not create directory \"%s\": %m", template);
/* Stage file names for remove_temp(). Unsafe in a signal handler. */
UNIXSOCK_PATH(sockself, port, temp_sockdir);
snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
/* Remove the directory during clean exit. */
atexit(remove_temp);
if (*pattern == '\0') returntrue; /* 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') returntrue; /* end of pattern, so declare match */
/* 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;
bail("could not open file \"%s\" for reading: %m", buf);
}
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((unsignedchar) buf[i - 1]))
buf[--i] = '\0';
/* parse out the line fields */
file_type = strchr(buf, ':'); if (!file_type)
{
bail("incorrectly formatted resultmap entry: %s", buf);
}
*file_type++ = '\0';
/* *Reportwhatwe'reconnectingto
*/
pghost = getenv("PGHOST");
pgport = getenv("PGPORT"); if (!pghost)
{ /* Keep this bit in sync with libpq's default host location: */ if (DEFAULT_PGSOCKET_DIR[0]) /* do nothing, we'll print "Unix socket" below */ ; else
pghost = "localhost"; /* DefaultHost in fe-connect.c */
}
if (pghost && pgport)
note("using postmaster on %s, port %s", pghost, pgport); if (pghost && !pgport)
note("using postmaster on %s, default port", pghost); if (!pghost && pgport)
note("using postmaster on Unix socket, port %s", pgport); if (!pghost && !pgport)
note("using postmaster on Unix socket, default port");
}
load_resultmap();
}
#ifdef ENABLE_SSPI
/* support for config_sspi_auth() */ staticconstchar *
fmtHba(constchar *raw)
{ staticchar *ret; constchar *rp; char *wp;
/* Check a Write outcome and report any error. */ #define CW(cond) \ do { \ if (!(cond)) \
bail("could not write to file \"%s\": %m", fname); \
} while (0)
res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata); if (res < 0 || res >= sizeof(fname))
{ /* *Truncatingthisnameisafatalerror,becausewemustnotfailto *overwriteanoriginaltrust-authenticationpg_hba.conf.
*/
bail("directory name too long");
}
hba = fopen(fname, "w"); if (hba == NULL)
{
bail("could not open file \"%s\" for writing: %m", fname);
}
CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
CW(fputs("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n",
hba) >= 0); if (have_ipv6)
CW(fputs("host all all ::1/128 sspi include_realm=1 map=regress\n",
hba) >= 0);
CW(fclose(hba) == 0);
snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
ident = fopen(fname, "w"); if (ident == NULL)
{
bail("could not open file \"%s\" for writing: %m", fname);
}
CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
/* Now escape any shell double-quote metacharacters */ for (cmdptr = cmdbuf.data; *cmdptr; cmdptr++)
{ if (strchr("\\\"$`", *cmdptr))
appendStringInfoChar(buf, '\\');
appendStringInfoChar(buf, *cmdptr);
}
appendStringInfoChar(buf, '"');
pfree(cmdbuf.data);
}
staticvoid
psql_end_command(StringInfo buf, constchar *database)
{ /* Add the database name --- assume it needs no extra escaping */
appendStringInfo(buf, " \"%s\"",
database);
/* And now we can execute the shell command */
fflush(NULL); if (system(buf->data) != 0)
{ /* psql probably already reported the error */
bail("command failed: %s", buf->data);
}
pid = fork(); if (pid == -1)
{
bail("could not fork: %m");
} if (pid == 0)
{ /* *Inchild * *Insteadofusingsystem(),exectheshelldirectly,andtellitto *"exec"thecommandtoo.Thissavestwouselessprocessesper *paralleltestcase.
*/ char *cmdline2;
cmdline2 = psprintf("exec %s", cmdline);
execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL); /* Not using the normal bail() here as we want _exit */
bail_noatexit("could not exec \"%s\": %m", shellprog);
} /* in parent */ return pid; #else
PROCESS_INFORMATION pi; char *cmdline2; constchar *comspec;
/* Find CMD.EXE location using COMSPEC, if it's set */
comspec = getenv("COMSPEC"); if (comspec == NULL)
comspec = "CMD";
if (run_diff(cmd, diff) == 0)
{
unlink(diff);
free(alt_expectfile); returnfalse;
}
l = file_line_count(diff); if (l < best_line_count)
{ /* This diff was a better match than the last one */
best_line_count = l;
strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
}
free(alt_expectfile);
}
if (run_diff(cmd, diff) == 0)
{ /* No diff = no changes = good */
unlink(diff); returnfalse;
}
l = file_line_count(diff); if (l < best_line_count)
{ /* This diff was a better match than the last one */
best_line_count = l;
strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
}
}
tests_left = num_tests; while (tests_left > 0)
{
PID_TYPE p;
#ifndef WIN32 int exit_status;
p = wait(&exit_status);
if (p == INVALID_PID)
bail("failed to wait for subprocesses: %m"); #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)
{
bail("failed to wait for subprocesses: error code %lu",
GetLastError());
}
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;
INSTR_TIME_SET_CURRENT(stoptimes[i]); if (names)
note_detail(" %s", names[i]);
tests_left--; break;
}
}
}
#ifdef WIN32
free(active_pids); #endif
}
/* *reportnonzeroexitcodefromatestprocess
*/ staticvoid
log_child_failure(int exitstatus)
{ if (WIFEXITED(exitstatus))
diag("(test process exited with exit code %d)",
WEXITSTATUS(exitstatus)); elseif (WIFSIGNALED(exitstatus))
{ #ifdefined(WIN32)
diag("(test process was terminated by exception 0x%X)",
WTERMSIG(exitstatus)); #else
diag("(test process was terminated by signal %d: %s)",
WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus))); #endif
} else
diag("(test process exited with unrecognized status %d)", exitstatus);
}
scf = fopen(schedule, "r"); if (!scf)
bail("could not open file \"%s\" for reading: %m", schedule);
while (fgets(scbuf, sizeof(scbuf), scf))
{ char *test = NULL; char *c; int num_tests; bool inword; int i;
line_num++;
/* strip trailing whitespace, especially the newline */
i = strlen(scbuf); while (i > 0 && isspace((unsignedchar) scbuf[i - 1]))
scbuf[--i] = '\0';
if (scbuf[0] == '\0' || scbuf[0] == '#') continue; if (strncmp(scbuf, "test: ", 6) == 0)
test = scbuf + 6; else
{
bail("syntax error in schedule file \"%s\" line %d: %s",
schedule, line_num, scbuf);
}
num_tests = 0;
inword = false; for (c = test;; c++)
{ if (*c == '\0' || isspace((unsignedchar) *c))
{ if (inword)
{ /* Reached end of a test name */ char sav;
if (num_tests >= MAX_PARALLEL_TESTS)
{
bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
}
sav = *c;
*c = '\0';
tests[num_tests] = pg_strdup(test);
num_tests++;
*c = sav;
inword = false;
} if (*c == '\0') break; /* loop exit is here */
} elseif (!inword)
{ /* Start of a test name */
test = c;
inword = true;
}
}
if (num_tests == 0)
{
bail("syntax error in schedule file \"%s\" line %d: %s",
schedule, line_num, scbuf);
}
if (num_tests == 1)
{
pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
INSTR_TIME_SET_CURRENT(starttimes[0]);
wait_for_tests(pids, statuses, stoptimes, NULL, 1); /* status line is finished below */
} elseif (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
{
bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
max_concurrent_tests, schedule, line_num, scbuf);
} elseif (max_connections > 0 && max_connections < num_tests)
{ int oldest = 0;
note_detail("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,
stoptimes + oldest,
tests + oldest, i - oldest);
oldest = i;
}
pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
INSTR_TIME_SET_CURRENT(starttimes[i]);
}
wait_for_tests(pids + oldest, statuses + oldest,
stoptimes + oldest,
tests + oldest, i - oldest);
note_end();
} else
{
note_detail("parallel group (%d tests): ", num_tests); for (i = 0; i < num_tests; i++)
{
pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
INSTR_TIME_SET_CURRENT(starttimes[i]);
}
wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
note_end();
}
/* Check results for all tests */ for (i = 0; i < num_tests; i++)
{
_stringlist *rl,
*el,
*tl; bool differ = false;
INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
/* *Advanceoverallthreelistssimultaneously. * *Compareresultfiles[j]withexpectfiles[j]always.Tagsare *optionalbutiftherearetags,thetaglisthasthesame *lengthastheothertwolists.
*/ 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,
tl = tl ? tl->next : NULL)
{ bool newdiff;
/* create outputdir directory if not present */ if (!directory_exists(outputdir))
make_directory(outputdir);
/* create the log file (copy of running status output) */
snprintf(file, sizeof(file), "%s/regression.out", outputdir);
logfilename = pg_strdup(file);
logfile = fopen(logfilename, "w"); if (!logfile)
bail("could not open file \"%s\" for writing: %m", logfilename);
/* create the diffs file as empty */
snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
difffilename = pg_strdup(file);
difffile = fopen(difffilename, "w"); if (!difffile)
bail("could not open file \"%s\" for writing: %m", difffilename);
/* we don't keep the diffs file open continuously */
fclose(difffile);
/* also create the results directory if not present */
snprintf(file, sizeof(file), "%s/results", outputdir); if (!directory_exists(file))
make_directory(file);
}
/* Set warning level so we don't see chatter about nonexistent DB */
psql_add_command(buf, "SET client_min_messages = warning");
psql_add_command(buf, "DROP DATABASE IF EXISTS \"%s\"", dbname);
psql_end_command(buf, "postgres");
}
/* Set warning level so we don't see chatter about nonexistent role */
psql_add_command(buf, "SET client_min_messages = warning");
psql_add_command(buf, "DROP ROLE IF EXISTS \"%s\"", rolename);
psql_end_command(buf, "postgres");
}
psql_add_command(buf, "CREATE ROLE \"%s\" WITH LOGIN", rolename); for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
{
psql_add_command(buf, "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
granted_dbs->str, rolename);
}
psql_end_command(buf, "postgres");
}
staticvoid
help(void)
{
printf(_("PostgreSQL regression test driver\n"));
printf(_("\n"));
printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
printf(_("\n"));
printf(_("Options:\n"));
printf(_(" --bindir=BINPATH use BINPATH for programs that are run;\n"));
printf(_(" if empty, use PATH from the environment\n"));
printf(_(" --config-auth=DATADIR update authentication settings for DATADIR\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(_(" --expecteddir=DIR take expected files from DIR (default \".\")\n"));
printf(_(" -h, --help show this help, then exit\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(_(" --max-connections=N maximum number of concurrent connections\n"));
printf(_(" (default is 0, meaning unlimited)\n"));
printf(_(" --max-concurrent-tests=N maximum number of concurrent tests in schedule\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-instance=DIR create a temporary instance in DIR\n"));
printf(_(" --use-existing use an existing installation\n"));
printf(_(" -V, --version output version information, then exit\n"));
printf(_("\n"));
printf(_("Options for \"temp-instance\" mode:\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(_("\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(_("\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 <%s>.\n"), PACKAGE_BUGREPORT);
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
}
extra_conf = fopen(temp_config, "r"); if (extra_conf == NULL)
{
bail("could not open \"%s\" to read extra config: %m",
temp_config);
} while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
fputs(line_buf, pg_conf);
fclose(extra_conf);
}
/* *Checkifthereisapostmasterrunningalready.
*/ for (i = 0; i < 16; i++)
{
rv = PQpingParams(keywords, values, 1);
if (rv == PQPING_OK)
{ if (port_specified_by_user || i == 15)
{
note("port %d apparently in use", port); if (!port_specified_by_user)
note("could not determine an available port");
bail("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.");
}
for (i = 0; i < wait_seconds * WAIT_TICKS_PER_SECOND; i++)
{ /* *It'sfairlyunlikelythattheserverisrespondingimmediately *sowestartwithsleepingbeforecheckinginsteadoftheother *wayaround.
*/
pg_usleep(1000000L / WAIT_TICKS_PER_SECOND);
rv = PQpingParams(keywords, values, 1);
/* Done if the server is running and accepts connections */ if (rv == PQPING_OK) break;
if (rv == PQPING_NO_ATTEMPT)
bail("attempting to connect to postmaster failed");
/* *Failimmediatelyifpostmasterhasexited
*/ #ifndef WIN32 if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid) #else if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0) #endif
{
bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason",
outputdir);
}
} if (i >= wait_seconds * WAIT_TICKS_PER_SECOND)
{
diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason",
wait_seconds, outputdir);
if (file_size(difffilename) > 0)
{
diag("The differences that caused some tests to fail can be viewed in the file \"%s\".",
difffilename);
diag("A copy of the test summary that you see above is saved in the file \"%s\".",
logfilename);
} else
{
unlink(difffilename);
unlink(logfilename);
}
fclose(logfile);
logfile = NULL;
if (fail_count != 0) exit(1);
return0;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.49Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.