LCOV - differential code coverage report
Current view: top level - src/test/regress - pg_regress.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 73.1 % 888 649 79 44 100 16 50 379 70 150 142 360 31 95
Current Date: 2023-04-08 15:15:32 Functions: 85.4 % 41 35 3 3 31 4 5 30 1 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * pg_regress --- regression test driver
       4                 :  *
       5                 :  * This is a C implementation of the previous shell script for running
       6                 :  * the regression tests, and should be mostly compatible with it.
       7                 :  * Initial author of C translation: Magnus Hagander
       8                 :  *
       9                 :  * This code is released under the terms of the PostgreSQL License.
      10                 :  *
      11                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      12                 :  * Portions Copyright (c) 1994, Regents of the University of California
      13                 :  *
      14                 :  * src/test/regress/pg_regress.c
      15                 :  *
      16                 :  *-------------------------------------------------------------------------
      17                 :  */
      18                 : 
      19                 : #include "postgres_fe.h"
      20                 : 
      21                 : #include <ctype.h>
      22                 : #include <sys/resource.h>
      23                 : #include <sys/stat.h>
      24                 : #include <sys/time.h>
      25                 : #include <sys/wait.h>
      26                 : #include <signal.h>
      27                 : #include <unistd.h>
      28                 : 
      29                 : #include "common/logging.h"
      30                 : #include "common/restricted_token.h"
      31                 : #include "common/string.h"
      32                 : #include "common/username.h"
      33                 : #include "getopt_long.h"
      34                 : #include "lib/stringinfo.h"
      35                 : #include "libpq/pqcomm.h"     /* needed for UNIXSOCK_PATH() */
      36                 : #include "pg_config_paths.h"
      37                 : #include "pg_regress.h"
      38                 : #include "portability/instr_time.h"
      39                 : 
      40                 : /* for resultmap we need a list of pairs of strings */
      41                 : typedef struct _resultmap
      42                 : {
      43                 :     char       *test;
      44                 :     char       *type;
      45                 :     char       *resultfile;
      46                 :     struct _resultmap *next;
      47                 : } _resultmap;
      48                 : 
      49                 : /*
      50                 :  * Values obtained from Makefile.
      51                 :  */
      52                 : char       *host_platform = HOST_TUPLE;
      53                 : 
      54                 : #ifndef WIN32                   /* not used in WIN32 case */
      55                 : static char *shellprog = SHELLPROG;
      56                 : #endif
      57                 : 
      58                 : /*
      59                 :  * On Windows we use -w in diff switches to avoid problems with inconsistent
      60                 :  * newline representation.  The actual result files will generally have
      61                 :  * Windows-style newlines, but the comparison files might or might not.
      62                 :  */
      63                 : #ifndef WIN32
      64                 : const char *basic_diff_opts = "";
      65                 : const char *pretty_diff_opts = "-U3";
      66                 : #else
      67                 : const char *basic_diff_opts = "-w";
      68                 : const char *pretty_diff_opts = "-w -U3";
      69                 : #endif
      70                 : 
      71                 : /*
      72                 :  * The width of the testname field when printing to ensure vertical alignment
      73                 :  * of test runtimes. This number is somewhat arbitrarily chosen to match the
      74                 :  * older pre-TAP output format.
      75                 :  */
      76                 : #define TESTNAME_WIDTH 36
      77                 : 
      78                 : typedef enum TAPtype
      79                 : {
      80                 :     DIAG = 0,
      81                 :     BAIL,
      82                 :     NOTE,
      83                 :     NOTE_DETAIL,
      84                 :     NOTE_END,
      85                 :     TEST_STATUS,
      86                 :     PLAN,
      87                 :     NONE
      88                 : }           TAPtype;
      89                 : 
      90                 : /* options settable from command line */
      91                 : _stringlist *dblist = NULL;
      92                 : bool        debug = false;
      93                 : char       *inputdir = ".";
      94                 : char       *outputdir = ".";
      95                 : char       *expecteddir = ".";
      96                 : char       *bindir = PGBINDIR;
      97                 : char       *launcher = NULL;
      98                 : static _stringlist *loadextension = NULL;
      99                 : static int  max_connections = 0;
     100                 : static int  max_concurrent_tests = 0;
     101                 : static char *encoding = NULL;
     102                 : static _stringlist *schedulelist = NULL;
     103                 : static _stringlist *extra_tests = NULL;
     104                 : static char *temp_instance = NULL;
     105                 : static _stringlist *temp_configs = NULL;
     106                 : static bool nolocale = false;
     107                 : static bool use_existing = false;
     108                 : static char *hostname = NULL;
     109                 : static int  port = -1;
     110                 : static bool port_specified_by_user = false;
     111                 : static char *dlpath = PKGLIBDIR;
     112                 : static char *user = NULL;
     113                 : static _stringlist *extraroles = NULL;
     114                 : static char *config_auth_datadir = NULL;
     115                 : 
     116                 : /* internal variables */
     117                 : static const char *progname;
     118                 : static char *logfilename;
     119                 : static FILE *logfile;
     120                 : static char *difffilename;
     121                 : static const char *sockdir;
     122                 : static const char *temp_sockdir;
     123                 : static char sockself[MAXPGPATH];
     124                 : static char socklock[MAXPGPATH];
     125                 : static StringInfo failed_tests = NULL;
     126                 : static bool in_note = false;
     127                 : 
     128                 : static _resultmap *resultmap = NULL;
     129                 : 
     130                 : static PID_TYPE postmaster_pid = INVALID_PID;
     131                 : static bool postmaster_running = false;
     132                 : 
     133                 : static int  success_count = 0;
     134                 : static int  fail_count = 0;
     135                 : 
     136                 : static bool directory_exists(const char *dir);
     137                 : static void make_directory(const char *dir);
     138                 : 
     139                 : static void test_status_print(bool ok, const char *testname, double runtime, bool parallel);
     140                 : static void test_status_ok(const char *testname, double runtime, bool parallel);
     141                 : static void test_status_failed(const char *testname, double runtime, bool parallel);
     142                 : static void bail_out(bool noatexit, const char *fmt,...) pg_attribute_printf(2, 3);
     143                 : static void emit_tap_output(TAPtype type, const char *fmt,...) pg_attribute_printf(2, 3);
     144                 : static void emit_tap_output_v(TAPtype type, const char *fmt, va_list argp) pg_attribute_printf(2, 0);
     145                 : 
     146                 : static StringInfo psql_start_command(void);
     147                 : static void psql_add_command(StringInfo buf, const char *query,...) pg_attribute_printf(2, 3);
     148                 : static void psql_end_command(StringInfo buf, const char *database);
     149                 : 
     150                 : /*
     151                 :  * Convenience macros for printing TAP output with a more shorthand syntax
     152                 :  * aimed at making the code more readable.
     153                 :  */
     154                 : #define plan(x)             emit_tap_output(PLAN, "1..%i", (x))
     155                 : #define note(...)           emit_tap_output(NOTE, __VA_ARGS__)
     156                 : #define note_detail(...)    emit_tap_output(NOTE_DETAIL, __VA_ARGS__)
     157                 : #define diag(...)           emit_tap_output(DIAG, __VA_ARGS__)
     158                 : #define note_end()          emit_tap_output(NOTE_END, "\n");
     159                 : #define bail_noatexit(...)  bail_out(true, __VA_ARGS__)
     160                 : #define bail(...)           bail_out(false, __VA_ARGS__)
     161                 : 
     162                 : /*
     163                 :  * allow core files if possible.
     164                 :  */
     165                 : #if defined(HAVE_GETRLIMIT)
     166                 : static void
     167 GIC          84 : unlimit_core_size(void)
     168                 : {
     169                 :     struct rlimit lim;
     170                 : 
     171              84 :     getrlimit(RLIMIT_CORE, &lim);
     172              84 :     if (lim.rlim_max == 0)
     173                 :     {
     174 UNC           0 :         diag("could not set core size: disallowed by hard limit");
     175 UIC           0 :         return;
     176                 :     }
     177 GIC          84 :     else if (lim.rlim_max == RLIM_INFINITY || lim.rlim_cur < lim.rlim_max)
     178                 :     {
     179              84 :         lim.rlim_cur = lim.rlim_max;
     180              84 :         setrlimit(RLIMIT_CORE, &lim);
     181                 :     }
     182                 : }
     183                 : #endif
     184                 : 
     185                 : 
     186                 : /*
     187                 :  * Add an item at the end of a stringlist.
     188                 :  */
     189                 : void
     190            3382 : add_stringlist_item(_stringlist **listhead, const char *str)
     191                 : {
     192            3382 :     _stringlist *newentry = pg_malloc(sizeof(_stringlist));
     193                 :     _stringlist *oldentry;
     194                 : 
     195            3382 :     newentry->str = pg_strdup(str);
     196            3382 :     newentry->next = NULL;
     197            3382 :     if (*listhead == NULL)
     198 CBC        2785 :         *listhead = newentry;
     199                 :     else
     200                 :     {
     201 GIC        2607 :         for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
     202 ECB             :              /* skip */ ;
     203 CBC         597 :         oldentry->next = newentry;
     204                 :     }
     205 GBC        3382 : }
     206 EUB             : 
     207                 : /*
     208 ECB             :  * Free a stringlist.
     209                 :  */
     210                 : static void
     211 CBC        2900 : free_stringlist(_stringlist **listhead)
     212                 : {
     213 GIC        2900 :     if (listhead == NULL || *listhead == NULL)
     214             755 :         return;
     215            2145 :     if ((*listhead)->next != NULL)
     216             372 :         free_stringlist(&((*listhead)->next));
     217            2145 :     free((*listhead)->str);
     218            2145 :     free(*listhead);
     219            2145 :     *listhead = NULL;
     220                 : }
     221 ECB             : 
     222                 : /*
     223                 :  * Split a delimited string into a stringlist
     224                 :  */
     225                 : static void
     226 CBC         100 : split_to_stringlist(const char *s, const char *delim, _stringlist **listhead)
     227 ECB             : {
     228 CBC         100 :     char       *sc = pg_strdup(s);
     229             100 :     char       *token = strtok(sc, delim);
     230                 : 
     231 GIC         205 :     while (token)
     232 ECB             :     {
     233 GIC         105 :         add_stringlist_item(listhead, token);
     234 CBC         105 :         token = strtok(NULL, delim);
     235                 :     }
     236             100 :     free(sc);
     237 GIC         100 : }
     238                 : 
     239                 : /*
     240                 :  * Bailing out is for unrecoverable errors which prevents further testing to
     241                 :  * occur and after which the test run should be aborted. By passing noatexit
     242                 :  * as true the process will terminate with _exit(2) and skipping registered
     243                 :  * exit handlers, thus avoid any risk of bottomless recursion calls to exit.
     244                 :  */
     245 ECB             : static void
     246 UNC           0 : bail_out(bool noatexit, const char *fmt,...)
     247 ECB             : {
     248                 :     va_list     ap;
     249                 : 
     250 LBC           0 :     va_start(ap, fmt);
     251 UNC           0 :     emit_tap_output_v(BAIL, fmt, ap);
     252 LBC           0 :     va_end(ap);
     253                 : 
     254 UNC           0 :     if (noatexit)
     255               0 :         _exit(2);
     256                 : 
     257               0 :     exit(2);
     258                 : }
     259                 : 
     260                 : /*
     261                 :  * Print the result of a test run and associated metadata like runtime. Care
     262                 :  * is taken to align testnames and runtimes vertically to ensure the output
     263                 :  * is human readable while still TAP compliant. Tests run in parallel are
     264                 :  * prefixed with a '+' and sequential tests with a '-'. This distinction was
     265                 :  * previously indicated by 'test' prefixing sequential tests while parallel
     266                 :  * tests were indented by four leading spaces. The meson TAP parser consumes
     267                 :  * leading space however, so a non-whitespace prefix of the same length is
     268                 :  * required for both.
     269                 :  */
     270 ECB             : static void
     271 GNC        1110 : test_status_print(bool ok, const char *testname, double runtime, bool parallel)
     272                 : {
     273            1110 :     int         testnumber = fail_count + success_count;
     274                 : 
     275                 :     /*
     276                 :      * Testnumbers are padded to 5 characters to ensure that testnames align
     277                 :      * vertically (assuming at most 9999 tests).  Testnames are prefixed with
     278                 :      * a leading character to indicate being run in parallel or not. A leading
     279                 :      * '+' indicates a parellel test, '-' indicates a single test.
     280                 :      */
     281            1110 :     emit_tap_output(TEST_STATUS, "%sok %-5i%*s %c %-*s %8.0f ms",
     282                 :                     (ok ? "" : "not "),
     283                 :                     testnumber,
     284                 :     /* If ok, indent with four spaces matching "not " */
     285                 :                     (ok ? (int) strlen("not ") : 0), "",
     286                 :     /* Prefix a parallel test '+' and a single test with '-' */
     287                 :                     (parallel ? '+' : '-'),
     288                 :     /* Testnames are padded to align runtimes */
     289                 :                     TESTNAME_WIDTH, testname,
     290                 :                     runtime);
     291            1110 : }
     292 ECB             : 
     293                 : static void
     294 GNC        1110 : test_status_ok(const char *testname, double runtime, bool parallel)
     295                 : {
     296            1110 :     success_count++;
     297                 : 
     298            1110 :     test_status_print(true, testname, runtime, parallel);
     299            1110 : }
     300                 : 
     301                 : static void
     302 UNC           0 : test_status_failed(const char *testname, double runtime, bool parallel)
     303                 : {
     304                 :     /*
     305                 :      * Save failed tests in a buffer such that we can print a summary at the
     306                 :      * end with diag() to ensure it's shown even under test harnesses.
     307                 :      */
     308               0 :     if (!failed_tests)
     309               0 :         failed_tests = makeStringInfo();
     310                 :     else
     311               0 :         appendStringInfoChar(failed_tests, ',');
     312                 : 
     313               0 :     appendStringInfo(failed_tests, " %s", testname);
     314                 : 
     315               0 :     fail_count++;
     316                 : 
     317               0 :     test_status_print(false, testname, runtime, parallel);
     318               0 : }
     319                 : 
     320                 : 
     321                 : static void
     322 GNC        2091 : emit_tap_output(TAPtype type, const char *fmt,...)
     323                 : {
     324                 :     va_list     argp;
     325                 : 
     326            2091 :     va_start(argp, fmt);
     327            2091 :     emit_tap_output_v(type, fmt, argp);
     328            2091 :     va_end(argp);
     329            2091 : }
     330                 : 
     331                 : static void
     332            2091 : emit_tap_output_v(TAPtype type, const char *fmt, va_list argp)
     333                 : {
     334                 :     va_list     argp_logfile;
     335                 :     FILE       *fp;
     336                 : 
     337                 :     /*
     338                 :      * Diagnostic output will be hidden by prove unless printed to stderr. The
     339                 :      * Bail message is also printed to stderr to aid debugging under a harness
     340                 :      * which might otherwise not emit such an important message.
     341                 :      */
     342            2091 :     if (type == DIAG || type == BAIL)
     343 UNC           0 :         fp = stderr;
     344                 :     else
     345 GNC        2091 :         fp = stdout;
     346                 : 
     347                 :     /*
     348                 :      * If we are ending a note_detail line we can avoid further processing and
     349                 :      * immediately return following a newline.
     350                 :      */
     351            2091 :     if (type == NOTE_END)
     352                 :     {
     353              54 :         in_note = false;
     354              54 :         fprintf(fp, "\n");
     355              54 :         if (logfile)
     356              54 :             fprintf(logfile, "\n");
     357              54 :         return;
     358                 :     }
     359                 : 
     360                 :     /* Make a copy of the va args for printing to the logfile */
     361            2037 :     va_copy(argp_logfile, argp);
     362                 : 
     363                 :     /*
     364                 :      * Non-protocol output such as diagnostics or notes must be prefixed by a
     365                 :      * '#' character. We print the Bail message like this too.
     366                 :      */
     367            2037 :     if ((type == NOTE || type == DIAG || type == BAIL)
     368            1869 :         || (type == NOTE_DETAIL && !in_note))
     369                 :     {
     370             222 :         fprintf(fp, "# ");
     371             222 :         if (logfile)
     372             222 :             fprintf(logfile, "# ");
     373                 :     }
     374            2037 :     vfprintf(fp, fmt, argp);
     375 GBC        2037 :     if (logfile)
     376 GNC        2037 :         vfprintf(logfile, fmt, argp_logfile);
     377                 : 
     378                 :     /*
     379                 :      * If we are entering into a note with more details to follow, register
     380                 :      * that the leading '#' has been printed such that subsequent details
     381                 :      * aren't prefixed as well.
     382                 :      */
     383            2037 :     if (type == NOTE_DETAIL)
     384             675 :         in_note = true;
     385                 : 
     386                 :     /*
     387                 :      * If this was a Bail message, the bail protocol message must go to stdout
     388                 :      * separately.
     389                 :      */
     390            2037 :     if (type == BAIL)
     391                 :     {
     392 UNC           0 :         fprintf(stdout, "Bail out!");
     393               0 :         if (logfile)
     394               0 :             fprintf(logfile, "Bail out!");
     395                 :     }
     396                 : 
     397 GNC        2037 :     va_end(argp_logfile);
     398                 : 
     399            2037 :     if (type != NOTE_DETAIL)
     400                 :     {
     401            1362 :         fprintf(fp, "\n");
     402            1362 :         if (logfile)
     403            1362 :             fprintf(logfile, "\n");
     404                 :     }
     405            2037 :     fflush(NULL);
     406                 : }
     407 EUB             : 
     408                 : /*
     409                 :  * shut down temp postmaster
     410                 :  */
     411                 : static void
     412 GIC         385 : stop_postmaster(void)
     413                 : {
     414             385 :     if (postmaster_running)
     415                 :     {
     416                 :         /* We use pg_ctl to issue the kill and wait for stop */
     417                 :         char        buf[MAXPGPATH * 2];
     418                 :         int         r;
     419                 : 
     420             164 :         snprintf(buf, sizeof(buf),
     421                 :                  "\"%s%spg_ctl\" stop -D \"%s/data\" -s",
     422              82 :                  bindir ? bindir : "",
     423              82 :                  bindir ? "/" : "",
     424                 :                  temp_instance);
     425 GNC          82 :         fflush(NULL);
     426 GIC          82 :         r = system(buf);
     427              82 :         if (r != 0)
     428 ECB             :         {
     429                 :             /* Not using the normal bail() as we want _exit */
     430 UNC           0 :             bail_noatexit(_("could not stop postmaster: exit code was %d"), r);
     431                 :         }
     432                 : 
     433 GIC          82 :         postmaster_running = false;
     434                 :     }
     435             385 : }
     436                 : 
     437                 : /*
     438                 :  * Remove the socket temporary directory.  pg_regress never waits for a
     439 ECB             :  * postmaster exit, so it is indeterminate whether the postmaster has yet to
     440                 :  * unlink the socket and lock file.  Unlink them here so we can proceed to
     441                 :  * remove the directory.  Ignore errors; leaking a temporary directory is
     442                 :  * unimportant.  This can run from a signal handler.  The code is not
     443                 :  * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
     444                 :  * on Windows, pg_regress does not use Unix sockets by default.
     445                 :  */
     446                 : static void
     447 GBC          82 : remove_temp(void)
     448                 : {
     449 GIC          82 :     Assert(temp_sockdir);
     450              82 :     unlink(sockself);
     451              82 :     unlink(socklock);
     452              82 :     rmdir(temp_sockdir);
     453 GBC          82 : }
     454 EUB             : 
     455                 : /*
     456                 :  * Signal handler that calls remove_temp() and reraises the signal.
     457                 :  */
     458                 : static void
     459 UNC           0 : signal_remove_temp(SIGNAL_ARGS)
     460 EUB             : {
     461 UIC           0 :     remove_temp();
     462 EUB             : 
     463 UNC           0 :     pqsignal(postgres_signal_arg, SIG_DFL);
     464               0 :     raise(postgres_signal_arg);
     465 UIC           0 : }
     466                 : 
     467 ECB             : /*
     468                 :  * Create a temporary directory suitable for the server's Unix-domain socket.
     469                 :  * The directory will have mode 0700 or stricter, so no other OS user can open
     470                 :  * our socket to exploit our use of trust authentication.  Most systems
     471                 :  * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
     472                 :  * place the directory under /tmp rather than relative to the possibly-deep
     473                 :  * current working directory.
     474                 :  *
     475                 :  * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
     476                 :  * testing to work in builds that relocate it to a directory not writable to
     477                 :  * the build/test user.
     478                 :  */
     479                 : static const char *
     480 GIC          82 : make_temp_sockdir(void)
     481                 : {
     482              82 :     char       *template = psprintf("%s/pg_regress-XXXXXX",
     483              82 :                                     getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
     484                 : 
     485              82 :     temp_sockdir = mkdtemp(template);
     486              82 :     if (temp_sockdir == NULL)
     487 ECB             :     {
     488 UNC           0 :         bail("could not create directory \"%s\": %s",
     489                 :              template, strerror(errno));
     490                 :     }
     491                 : 
     492                 :     /* Stage file names for remove_temp().  Unsafe in a signal handler. */
     493 GIC          82 :     UNIXSOCK_PATH(sockself, port, temp_sockdir);
     494              82 :     snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
     495 ECB             : 
     496                 :     /* Remove the directory during clean exit. */
     497 CBC          82 :     atexit(remove_temp);
     498 ECB             : 
     499                 :     /*
     500                 :      * Remove the directory before dying to the usual signals.  Omit SIGQUIT,
     501                 :      * preserving it as a quick, untidy exit.
     502                 :      */
     503 GIC          82 :     pqsignal(SIGHUP, signal_remove_temp);
     504              82 :     pqsignal(SIGINT, signal_remove_temp);
     505 CBC          82 :     pqsignal(SIGPIPE, signal_remove_temp);
     506 GIC          82 :     pqsignal(SIGTERM, signal_remove_temp);
     507                 : 
     508              82 :     return temp_sockdir;
     509                 : }
     510 ECB             : 
     511                 : /*
     512                 :  * Check whether string matches pattern
     513                 :  *
     514                 :  * In the original shell script, this function was implemented using expr(1),
     515                 :  * which provides basic regular expressions restricted to match starting at
     516                 :  * the string start (in conventional regex terms, there's an implicit "^"
     517                 :  * at the start of the pattern --- but no implicit "$" at the end).
     518                 :  *
     519                 :  * For now, we only support "." and ".*" as non-literal metacharacters,
     520                 :  * because that's all that anyone has found use for in resultmap.  This
     521                 :  * code could be extended if more functionality is needed.
     522                 :  */
     523                 : static bool
     524 GIC          42 : string_matches_pattern(const char *str, const char *pattern)
     525                 : {
     526 CBC          78 :     while (*str && *pattern)
     527 ECB             :     {
     528 GIC          78 :         if (*pattern == '.' && pattern[1] == '*')
     529                 :         {
     530              24 :             pattern += 2;
     531                 :             /* Trailing .* matches everything. */
     532              24 :             if (*pattern == '\0')
     533 LBC           0 :                 return true;
     534                 : 
     535 EUB             :             /*
     536                 :              * Otherwise, scan for a text position at which we can match the
     537                 :              * rest of the pattern.
     538                 :              */
     539 GIC         282 :             while (*str)
     540 ECB             :             {
     541                 :                 /*
     542                 :                  * Optimization to prevent most recursion: don't recurse
     543                 :                  * unless first pattern char might match this text char.
     544                 :                  */
     545 CBC         258 :                 if (*str == *pattern || *pattern == '.')
     546 ECB             :                 {
     547 GIC          36 :                     if (string_matches_pattern(str, pattern))
     548 LBC           0 :                         return true;
     549                 :                 }
     550                 : 
     551 GIC         258 :                 str++;
     552                 :             }
     553                 : 
     554                 :             /*
     555 ECB             :              * End of text with no match.
     556                 :              */
     557 CBC          24 :             return false;
     558                 :         }
     559 GIC          54 :         else if (*pattern != '.' && *str != *pattern)
     560                 :         {
     561                 :             /*
     562                 :              * Not the single-character wildcard and no explicit match? Then
     563 ECB             :              * time to quit...
     564                 :              */
     565 CBC          18 :             return false;
     566 ECB             :         }
     567                 : 
     568 CBC          36 :         str++;
     569              36 :         pattern++;
     570 ECB             :     }
     571                 : 
     572 UIC           0 :     if (*pattern == '\0')
     573 UBC           0 :         return true;            /* end of pattern, so declare match */
     574                 : 
     575                 :     /* End of input string.  Do we have matching pattern remaining? */
     576 LBC           0 :     while (*pattern == '.' && pattern[1] == '*')
     577 UIC           0 :         pattern += 2;
     578 LBC           0 :     if (*pattern == '\0')
     579 UIC           0 :         return true;            /* end of pattern, so declare match */
     580                 : 
     581               0 :     return false;
     582                 : }
     583                 : 
     584                 : /*
     585                 :  * Scan resultmap file to find which platform-specific expected files to use.
     586                 :  *
     587                 :  * The format of each line of the file is
     588                 :  *         testname/hostplatformpattern=substitutefile
     589                 :  * where the hostplatformpattern is evaluated per the rules of expr(1),
     590 ECB             :  * namely, it is a standard regular expression with an implicit ^ at the start.
     591                 :  * (We currently support only a very limited subset of regular expressions,
     592                 :  * see string_matches_pattern() above.)  What hostplatformpattern will be
     593                 :  * matched against is the config.guess output.  (In the shell-script version,
     594                 :  * we also provided an indication of whether gcc or another compiler was in
     595                 :  * use, but that facility isn't used anymore.)
     596                 :  */
     597                 : static void
     598 GIC          84 : load_resultmap(void)
     599                 : {
     600                 :     char        buf[MAXPGPATH];
     601                 :     FILE       *f;
     602 EUB             : 
     603                 :     /* scan the file ... */
     604 GBC          84 :     snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
     605 GIC          84 :     f = fopen(buf, "r");
     606 GBC          84 :     if (!f)
     607 EUB             :     {
     608                 :         /* OK if it doesn't exist, else complain */
     609 GIC          81 :         if (errno == ENOENT)
     610              81 :             return;
     611 UNC           0 :         bail("could not open file \"%s\" for reading: %s",
     612                 :              buf, strerror(errno));
     613                 :     }
     614                 : 
     615 GIC          12 :     while (fgets(buf, sizeof(buf), f))
     616                 :     {
     617                 :         char       *platform;
     618                 :         char       *file_type;
     619                 :         char       *expected;
     620                 :         int         i;
     621                 : 
     622 ECB             :         /* strip trailing whitespace, especially the newline */
     623 GIC           6 :         i = strlen(buf);
     624 CBC          12 :         while (i > 0 && isspace((unsigned char) buf[i - 1]))
     625               6 :             buf[--i] = '\0';
     626                 : 
     627 ECB             :         /* parse out the line fields */
     628 CBC           6 :         file_type = strchr(buf, ':');
     629 GIC           6 :         if (!file_type)
     630 EUB             :         {
     631 UNC           0 :             bail("incorrectly formatted resultmap entry: %s", buf);
     632                 :         }
     633 CBC           6 :         *file_type++ = '\0';
     634 ECB             : 
     635 GIC           6 :         platform = strchr(file_type, ':');
     636               6 :         if (!platform)
     637 ECB             :         {
     638 UNC           0 :             bail("incorrectly formatted resultmap entry: %s", buf);
     639                 :         }
     640 GIC           6 :         *platform++ = '\0';
     641 CBC           6 :         expected = strchr(platform, '=');
     642               6 :         if (!expected)
     643 ECB             :         {
     644 UNC           0 :             bail("incorrectly formatted resultmap entry: %s", buf);
     645                 :         }
     646 GIC           6 :         *expected++ = '\0';
     647                 : 
     648                 :         /*
     649                 :          * if it's for current platform, save it in resultmap list. Note: by
     650                 :          * adding at the front of the list, we ensure that in ambiguous cases,
     651                 :          * the last match in the resultmap file is used. This mimics the
     652                 :          * behavior of the old shell script.
     653                 :          */
     654               6 :         if (string_matches_pattern(host_platform, platform))
     655                 :         {
     656 UIC           0 :             _resultmap *entry = pg_malloc(sizeof(_resultmap));
     657                 : 
     658               0 :             entry->test = pg_strdup(buf);
     659               0 :             entry->type = pg_strdup(file_type);
     660 LBC           0 :             entry->resultfile = pg_strdup(expected);
     661 UIC           0 :             entry->next = resultmap;
     662 LBC           0 :             resultmap = entry;
     663                 :         }
     664 ECB             :     }
     665 GIC           3 :     fclose(f);
     666 ECB             : }
     667                 : 
     668                 : /*
     669 EUB             :  * Check in resultmap if we should be looking at a different file
     670                 :  */
     671                 : static
     672                 : const char *
     673 GIC        1236 : get_expectfile(const char *testname, const char *file)
     674                 : {
     675 ECB             :     char       *file_type;
     676                 :     _resultmap *rm;
     677                 : 
     678                 :     /*
     679                 :      * Determine the file type from the file name. This is just what is
     680                 :      * following the last dot in the file name.
     681                 :      */
     682 GIC        1236 :     if (!file || !(file_type = strrchr(file, '.')))
     683 LBC           0 :         return NULL;
     684 EUB             : 
     685 GIC        1236 :     file_type++;
     686                 : 
     687 CBC        1236 :     for (rm = resultmap; rm != NULL; rm = rm->next)
     688                 :     {
     689 UIC           0 :         if (strcmp(testname, rm->test) == 0 && strcmp(file_type, rm->type) == 0)
     690                 :         {
     691               0 :             return rm->resultfile;
     692                 :         }
     693 ECB             :     }
     694                 : 
     695 CBC        1236 :     return NULL;
     696                 : }
     697                 : 
     698                 : /*
     699                 :  * Prepare environment variables for running regression tests
     700                 :  */
     701 ECB             : static void
     702 GIC          84 : initialize_environment(void)
     703                 : {
     704 ECB             :     /*
     705                 :      * Set default application_name.  (The test_start_function may choose to
     706                 :      * override this, but if it doesn't, we have something useful in place.)
     707                 :      */
     708 GBC          84 :     setenv("PGAPPNAME", "pg_regress", 1);
     709 EUB             : 
     710                 :     /*
     711                 :      * Set variables that the test scripts may need to refer to.
     712                 :      */
     713 GBC          84 :     setenv("PG_ABS_SRCDIR", inputdir, 1);
     714              84 :     setenv("PG_ABS_BUILDDIR", outputdir, 1);
     715              84 :     setenv("PG_LIBDIR", dlpath, 1);
     716 GIC          84 :     setenv("PG_DLSUFFIX", DLSUFFIX, 1);
     717 EUB             : 
     718 GIC          84 :     if (nolocale)
     719                 :     {
     720                 :         /*
     721                 :          * Clear out any non-C locale settings
     722                 :          */
     723               3 :         unsetenv("LC_COLLATE");
     724               3 :         unsetenv("LC_CTYPE");
     725               3 :         unsetenv("LC_MONETARY");
     726               3 :         unsetenv("LC_NUMERIC");
     727               3 :         unsetenv("LC_TIME");
     728               3 :         unsetenv("LANG");
     729                 : 
     730                 :         /*
     731                 :          * Most platforms have adopted the POSIX locale as their
     732                 :          * implementation-defined default locale.  Exceptions include native
     733                 :          * Windows, macOS with --enable-nls, and Cygwin with --enable-nls.
     734 ECB             :          * (Use of --enable-nls matters because libintl replaces setlocale().)
     735                 :          * Also, PostgreSQL does not support macOS with locale environment
     736                 :          * variables unset; see PostmasterMain().
     737                 :          */
     738                 : #if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
     739                 :         setenv("LANG", "C", 1);
     740                 : #endif
     741                 :     }
     742                 : 
     743                 :     /*
     744                 :      * Set translation-related settings to English; otherwise psql will
     745                 :      * produce translated messages and produce diffs.  (XXX If we ever support
     746                 :      * translation of pg_regress, this needs to be moved elsewhere, where psql
     747 EUB             :      * is actually called.)
     748                 :      */
     749 GIC          84 :     unsetenv("LANGUAGE");
     750              84 :     unsetenv("LC_ALL");
     751 CBC          84 :     setenv("LC_MESSAGES", "C", 1);
     752                 : 
     753                 :     /*
     754                 :      * Set encoding as requested
     755                 :      */
     756 GIC          84 :     if (encoding)
     757               2 :         setenv("PGCLIENTENCODING", encoding, 1);
     758                 :     else
     759 CBC          82 :         unsetenv("PGCLIENTENCODING");
     760 ECB             : 
     761                 :     /*
     762                 :      * Set timezone and datestyle for datetime-related tests
     763                 :      */
     764 CBC          84 :     setenv("PGTZ", "PST8PDT", 1);
     765              84 :     setenv("PGDATESTYLE", "Postgres, MDY", 1);
     766                 : 
     767 EUB             :     /*
     768                 :      * Likewise set intervalstyle to ensure consistent results.  This is a bit
     769 ECB             :      * more painful because we must use PGOPTIONS, and we want to preserve the
     770                 :      * user's ability to set other variables through that.
     771                 :      */
     772                 :     {
     773 GIC          84 :         const char *my_pgoptions = "-c intervalstyle=postgres_verbose";
     774 GBC          84 :         const char *old_pgoptions = getenv("PGOPTIONS");
     775                 :         char       *new_pgoptions;
     776 ECB             : 
     777 CBC          84 :         if (!old_pgoptions)
     778              84 :             old_pgoptions = "";
     779 GIC          84 :         new_pgoptions = psprintf("%s %s",
     780 EUB             :                                  old_pgoptions, my_pgoptions);
     781 GIC          84 :         setenv("PGOPTIONS", new_pgoptions, 1);
     782 CBC          84 :         free(new_pgoptions);
     783                 :     }
     784                 : 
     785 GIC          84 :     if (temp_instance)
     786                 :     {
     787                 :         /*
     788                 :          * Clear out any environment vars that might cause psql to connect to
     789                 :          * the wrong postmaster, or otherwise behave in nondefault ways. (Note
     790 ECB             :          * we also use psql's -X switch consistently, so that ~/.psqlrc files
     791                 :          * won't mess things up.)  Also, set PGPORT to the temp port, and set
     792 EUB             :          * PGHOST depending on whether we are using TCP or Unix sockets.
     793                 :          *
     794                 :          * This list should be kept in sync with PostgreSQL/Test/Utils.pm.
     795                 :          */
     796 GBC          82 :         unsetenv("PGCHANNELBINDING");
     797 EUB             :         /* PGCLIENTENCODING, see above */
     798 GBC          82 :         unsetenv("PGCONNECT_TIMEOUT");
     799 GIC          82 :         unsetenv("PGDATA");
     800              82 :         unsetenv("PGDATABASE");
     801 CBC          82 :         unsetenv("PGGSSENCMODE");
     802 GIC          82 :         unsetenv("PGGSSLIB");
     803                 :         /* PGHOSTADDR, see below */
     804              82 :         unsetenv("PGKRBSRVNAME");
     805              82 :         unsetenv("PGPASSFILE");
     806              82 :         unsetenv("PGPASSWORD");
     807              82 :         unsetenv("PGREQUIREPEER");
     808              82 :         unsetenv("PGREQUIRESSL");
     809 CBC          82 :         unsetenv("PGSERVICE");
     810 GIC          82 :         unsetenv("PGSERVICEFILE");
     811              82 :         unsetenv("PGSSLCERT");
     812              82 :         unsetenv("PGSSLCRL");
     813              82 :         unsetenv("PGSSLCRLDIR");
     814              82 :         unsetenv("PGSSLKEY");
     815              82 :         unsetenv("PGSSLMAXPROTOCOLVERSION");
     816              82 :         unsetenv("PGSSLMINPROTOCOLVERSION");
     817              82 :         unsetenv("PGSSLMODE");
     818 CBC          82 :         unsetenv("PGSSLROOTCERT");
     819 GBC          82 :         unsetenv("PGSSLSNI");
     820 GIC          82 :         unsetenv("PGTARGETSESSIONATTRS");
     821 CBC          82 :         unsetenv("PGUSER");
     822                 :         /* PGPORT, see below */
     823 ECB             :         /* PGHOST, see below */
     824                 : 
     825 GIC          82 :         if (hostname != NULL)
     826 UBC           0 :             setenv("PGHOST", hostname, 1);
     827                 :         else
     828                 :         {
     829 GIC          82 :             sockdir = getenv("PG_REGRESS_SOCK_DIR");
     830 CBC          82 :             if (!sockdir)
     831 GIC          82 :                 sockdir = make_temp_sockdir();
     832              82 :             setenv("PGHOST", sockdir, 1);
     833                 :         }
     834              82 :         unsetenv("PGHOSTADDR");
     835              82 :         if (port != -1)
     836                 :         {
     837                 :             char        s[16];
     838                 : 
     839 CBC          82 :             sprintf(s, "%d", port);
     840 GIC          82 :             setenv("PGPORT", s, 1);
     841                 :         }
     842                 :     }
     843                 :     else
     844 ECB             :     {
     845                 :         const char *pghost;
     846                 :         const char *pgport;
     847                 : 
     848                 :         /*
     849                 :          * When testing an existing install, we honor existing environment
     850                 :          * variables, except if they're overridden by command line options.
     851                 :          */
     852 GIC           2 :         if (hostname != NULL)
     853                 :         {
     854 CBC           2 :             setenv("PGHOST", hostname, 1);
     855               2 :             unsetenv("PGHOSTADDR");
     856 ECB             :         }
     857 CBC           2 :         if (port != -1)
     858 ECB             :         {
     859                 :             char        s[16];
     860                 : 
     861 GIC           2 :             sprintf(s, "%d", port);
     862               2 :             setenv("PGPORT", s, 1);
     863                 :         }
     864               2 :         if (user != NULL)
     865 UIC           0 :             setenv("PGUSER", user, 1);
     866                 : 
     867                 :         /*
     868                 :          * However, we *don't* honor PGDATABASE, since we certainly don't wish
     869                 :          * to connect to whatever database the user might like as default.
     870                 :          * (Most tests override PGDATABASE anyway, but there are some ECPG
     871                 :          * test cases that don't.)
     872                 :          */
     873 GIC           2 :         unsetenv("PGDATABASE");
     874                 : 
     875                 :         /*
     876                 :          * Report what we're connecting to
     877                 :          */
     878               2 :         pghost = getenv("PGHOST");
     879               2 :         pgport = getenv("PGPORT");
     880 CBC           2 :         if (!pghost)
     881 ECB             :         {
     882                 :             /* Keep this bit in sync with libpq's default host location: */
     883 UIC           0 :             if (DEFAULT_PGSOCKET_DIR[0])
     884                 :                  /* do nothing, we'll print "Unix socket" below */ ;
     885                 :             else
     886 LBC           0 :                 pghost = "localhost"; /* DefaultHost in fe-connect.c */
     887                 :         }
     888 ECB             : 
     889 GIC           2 :         if (pghost && pgport)
     890 GNC           2 :             note("using postmaster on %s, port %s", pghost, pgport);
     891 GIC           2 :         if (pghost && !pgport)
     892 UNC           0 :             note("using postmaster on %s, default port", pghost);
     893 CBC           2 :         if (!pghost && pgport)
     894 UNC           0 :             note("using postmaster on Unix socket, port %s", pgport);
     895 GIC           2 :         if (!pghost && !pgport)
     896 UNC           0 :             note("using postmaster on Unix socket, default port");
     897                 :     }
     898                 : 
     899 GIC          84 :     load_resultmap();
     900              84 : }
     901                 : 
     902 ECB             : #ifdef ENABLE_SSPI
     903                 : 
     904                 : /* support for config_sspi_auth() */
     905                 : static const char *
     906                 : fmtHba(const char *raw)
     907                 : {
     908                 :     static char *ret;
     909                 :     const char *rp;
     910                 :     char       *wp;
     911                 : 
     912                 :     wp = ret = pg_realloc(ret, 3 + strlen(raw) * 2);
     913                 : 
     914                 :     *wp++ = '"';
     915                 :     for (rp = raw; *rp; rp++)
     916                 :     {
     917                 :         if (*rp == '"')
     918                 :             *wp++ = '"';
     919                 :         *wp++ = *rp;
     920                 :     }
     921                 :     *wp++ = '"';
     922                 :     *wp++ = '\0';
     923                 : 
     924                 :     return ret;
     925                 : }
     926                 : 
     927                 : /*
     928                 :  * Get account and domain/realm names for the current user.  This is based on
     929                 :  * pg_SSPI_recvauth().  The returned strings use static storage.
     930                 :  */
     931                 : static void
     932                 : current_windows_user(const char **acct, const char **dom)
     933                 : {
     934                 :     static char accountname[MAXPGPATH];
     935                 :     static char domainname[MAXPGPATH];
     936                 :     HANDLE      token;
     937                 :     TOKEN_USER *tokenuser;
     938                 :     DWORD       retlen;
     939                 :     DWORD       accountnamesize = sizeof(accountname);
     940                 :     DWORD       domainnamesize = sizeof(domainname);
     941                 :     SID_NAME_USE accountnameuse;
     942                 : 
     943                 :     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token))
     944                 :     {
     945                 :         bail("could not open process token: error code %lu", GetLastError());
     946                 :     }
     947                 : 
     948                 :     if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
     949                 :     {
     950                 :         bail("could not get token information buffer size: error code %lu",
     951                 :              GetLastError());
     952                 :     }
     953                 :     tokenuser = pg_malloc(retlen);
     954                 :     if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
     955                 :     {
     956                 :         bail("could not get token information: error code %lu",
     957                 :              GetLastError());
     958                 :     }
     959                 : 
     960                 :     if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
     961                 :                           domainname, &domainnamesize, &accountnameuse))
     962                 :     {
     963                 :         bail("could not look up account SID: error code %lu",
     964                 :              GetLastError());
     965                 :     }
     966                 : 
     967                 :     free(tokenuser);
     968                 : 
     969                 :     *acct = accountname;
     970                 :     *dom = domainname;
     971                 : }
     972                 : 
     973                 : /*
     974                 :  * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication.  Permit
     975                 :  * the current OS user to authenticate as the bootstrap superuser and as any
     976                 :  * user named in a --create-role option.
     977                 :  *
     978                 :  * In --config-auth mode, the --user switch can be used to specify the
     979                 :  * bootstrap superuser's name, otherwise we assume it is the default.
     980                 :  */
     981                 : static void
     982                 : config_sspi_auth(const char *pgdata, const char *superuser_name)
     983                 : {
     984                 :     const char *accountname,
     985 EUB             :                *domainname;
     986                 :     char       *errstr;
     987                 :     bool        have_ipv6;
     988                 :     char        fname[MAXPGPATH];
     989                 :     int         res;
     990                 :     FILE       *hba,
     991                 :                *ident;
     992                 :     _stringlist *sl;
     993 ECB             : 
     994                 :     /* Find out the name of the current OS user */
     995                 :     current_windows_user(&accountname, &domainname);
     996                 : 
     997                 :     /* Determine the bootstrap superuser's name */
     998                 :     if (superuser_name == NULL)
     999                 :     {
    1000                 :         /*
    1001                 :          * Compute the default superuser name the same way initdb does.
    1002                 :          *
    1003 EUB             :          * It's possible that this result always matches "accountname", the
    1004                 :          * value SSPI authentication discovers.  But the underlying system
    1005                 :          * functions do not clearly guarantee that.
    1006                 :          */
    1007                 :         superuser_name = get_user_name(&errstr);
    1008                 :         if (superuser_name == NULL)
    1009 ECB             :         {
    1010                 :             bail("%s", errstr);
    1011 EUB             :         }
    1012 ECB             :     }
    1013 EUB             : 
    1014 ECB             :     /*
    1015 EUB             :      * Like initdb.c:setup_config(), determine whether the platform recognizes
    1016                 :      * ::1 (IPv6 loopback) as a numeric host address string.
    1017                 :      */
    1018 ECB             :     {
    1019                 :         struct addrinfo *gai_result;
    1020                 :         struct addrinfo hints;
    1021                 :         WSADATA     wsaData;
    1022                 : 
    1023                 :         hints.ai_flags = AI_NUMERICHOST;
    1024                 :         hints.ai_family = AF_UNSPEC;
    1025                 :         hints.ai_socktype = 0;
    1026                 :         hints.ai_protocol = 0;
    1027                 :         hints.ai_addrlen = 0;
    1028                 :         hints.ai_canonname = NULL;
    1029                 :         hints.ai_addr = NULL;
    1030                 :         hints.ai_next = NULL;
    1031                 : 
    1032                 :         have_ipv6 = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0 &&
    1033                 :                      getaddrinfo("::1", NULL, &hints, &gai_result) == 0);
    1034                 :     }
    1035                 : 
    1036                 :     /* Check a Write outcome and report any error. */
    1037                 : #define CW(cond)    \
    1038                 :     do { \
    1039                 :         if (!(cond)) \
    1040                 :         { \
    1041                 :             bail("could not write to file \"%s\": %s", \
    1042                 :                  fname, strerror(errno)); \
    1043                 :         } \
    1044                 :     } while (0)
    1045                 : 
    1046                 :     res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
    1047                 :     if (res < 0 || res >= sizeof(fname))
    1048                 :     {
    1049                 :         /*
    1050                 :          * Truncating this name is a fatal error, because we must not fail to
    1051                 :          * overwrite an original trust-authentication pg_hba.conf.
    1052                 :          */
    1053                 :         bail("directory name too long");
    1054                 :     }
    1055                 :     hba = fopen(fname, "w");
    1056                 :     if (hba == NULL)
    1057                 :     {
    1058                 :         bail("could not open file \"%s\" for writing: %s",
    1059                 :              fname, strerror(errno));
    1060                 :     }
    1061                 :     CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
    1062                 :     CW(fputs("host all all 127.0.0.1/32  sspi include_realm=1 map=regress\n",
    1063                 :              hba) >= 0);
    1064                 :     if (have_ipv6)
    1065                 :         CW(fputs("host all all ::1/128  sspi include_realm=1 map=regress\n",
    1066                 :                  hba) >= 0);
    1067                 :     CW(fclose(hba) == 0);
    1068                 : 
    1069                 :     snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
    1070                 :     ident = fopen(fname, "w");
    1071                 :     if (ident == NULL)
    1072                 :     {
    1073                 :         bail("could not open file \"%s\" for writing: %s",
    1074                 :              fname, strerror(errno));
    1075                 :     }
    1076                 :     CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
    1077                 : 
    1078                 :     /*
    1079                 :      * Double-quote for the benefit of account names containing whitespace or
    1080                 :      * '#'.  Windows forbids the double-quote character itself, so don't
    1081                 :      * bother escaping embedded double-quote characters.
    1082                 :      */
    1083                 :     CW(fprintf(ident, "regress  \"%s@%s\"  %s\n",
    1084                 :                accountname, domainname, fmtHba(superuser_name)) >= 0);
    1085                 :     for (sl = extraroles; sl; sl = sl->next)
    1086                 :         CW(fprintf(ident, "regress  \"%s@%s\"  %s\n",
    1087                 :                    accountname, domainname, fmtHba(sl->str)) >= 0);
    1088                 :     CW(fclose(ident) == 0);
    1089                 : }
    1090                 : 
    1091                 : #endif                          /* ENABLE_SSPI */
    1092                 : 
    1093                 : /*
    1094                 :  * psql_start_command, psql_add_command, psql_end_command
    1095                 :  *
    1096                 :  * Issue one or more commands within one psql call.
    1097                 :  * Set up with psql_start_command, then add commands one at a time
    1098                 :  * with psql_add_command, and finally execute with psql_end_command.
    1099                 :  *
    1100                 :  * Since we use system(), this doesn't return until the operation finishes
    1101                 :  */
    1102                 : static StringInfo
    1103 GIC          94 : psql_start_command(void)
    1104                 : {
    1105              94 :     StringInfo  buf = makeStringInfo();
    1106                 : 
    1107             188 :     appendStringInfo(buf,
    1108                 :                      "\"%s%spsql\" -X -q",
    1109              94 :                      bindir ? bindir : "",
    1110              94 :                      bindir ? "/" : "");
    1111              94 :     return buf;
    1112                 : }
    1113                 : 
    1114                 : static void
    1115             185 : psql_add_command(StringInfo buf, const char *query,...)
    1116                 : {
    1117                 :     StringInfoData cmdbuf;
    1118                 :     const char *cmdptr;
    1119                 : 
    1120                 :     /* Add each command as a -c argument in the psql call */
    1121             185 :     appendStringInfoString(buf, " -c \"");
    1122                 : 
    1123                 :     /* Generate the query with insertion of sprintf arguments */
    1124             185 :     initStringInfo(&cmdbuf);
    1125                 :     for (;;)
    1126 UIC           0 :     {
    1127                 :         va_list     args;
    1128                 :         int         needed;
    1129                 : 
    1130 GIC         185 :         va_start(args, query);
    1131             185 :         needed = appendStringInfoVA(&cmdbuf, query, args);
    1132             185 :         va_end(args);
    1133             185 :         if (needed == 0)
    1134             185 :             break;              /* success */
    1135 UIC           0 :         enlargeStringInfo(&cmdbuf, needed);
    1136                 :     }
    1137                 : 
    1138                 :     /* Now escape any shell double-quote metacharacters */
    1139 GIC       36777 :     for (cmdptr = cmdbuf.data; *cmdptr; cmdptr++)
    1140                 :     {
    1141           36592 :         if (strchr("\\\"$`", *cmdptr))
    1142            1224 :             appendStringInfoChar(buf, '\\');
    1143           36592 :         appendStringInfoChar(buf, *cmdptr);
    1144                 :     }
    1145                 : 
    1146             185 :     appendStringInfoChar(buf, '"');
    1147                 : 
    1148             185 :     pfree(cmdbuf.data);
    1149             185 : }
    1150                 : 
    1151                 : static void
    1152              94 : psql_end_command(StringInfo buf, const char *database)
    1153                 : {
    1154                 :     /* Add the database name --- assume it needs no extra escaping */
    1155              94 :     appendStringInfo(buf,
    1156                 :                      " \"%s\"",
    1157                 :                      database);
    1158                 : 
    1159                 :     /* And now we can execute the shell command */
    1160 GNC          94 :     fflush(NULL);
    1161 GIC          94 :     if (system(buf->data) != 0)
    1162                 :     {
    1163                 :         /* psql probably already reported the error */
    1164 UNC           0 :         bail("command failed: %s", buf->data);
    1165                 :     }
    1166                 : 
    1167                 :     /* Clean up */
    1168 GIC          94 :     pfree(buf->data);
    1169              94 :     pfree(buf);
    1170              94 : }
    1171                 : 
    1172                 : /*
    1173                 :  * Shorthand macro for the common case of a single command
    1174                 :  */
    1175                 : #define psql_command(database, ...) \
    1176                 :     do { \
    1177                 :         StringInfo cmdbuf = psql_start_command(); \
    1178                 :         psql_add_command(cmdbuf, __VA_ARGS__); \
    1179                 :         psql_end_command(cmdbuf, database); \
    1180                 :     } while (0)
    1181                 : 
    1182                 : /*
    1183                 :  * Spawn a process to execute the given shell command; don't wait for it
    1184                 :  *
    1185                 :  * Returns the process ID (or HANDLE) so we can wait for it later
    1186                 :  */
    1187                 : PID_TYPE
    1188            1192 : spawn_process(const char *cmdline)
    1189                 : {
    1190                 : #ifndef WIN32
    1191                 :     pid_t       pid;
    1192                 : 
    1193                 :     /*
    1194                 :      * Must flush I/O buffers before fork.
    1195                 :      */
    1196 GNC        1192 :     fflush(NULL);
    1197                 : 
    1198                 : #ifdef EXEC_BACKEND
    1199                 :     pg_disable_aslr();
    1200                 : #endif
    1201                 : 
    1202 GIC        1192 :     pid = fork();
    1203            2384 :     if (pid == -1)
    1204                 :     {
    1205 UNC           0 :         bail("could not fork: %s", strerror(errno));
    1206                 :     }
    1207 GIC        2384 :     if (pid == 0)
    1208                 :     {
    1209                 :         /*
    1210                 :          * In child
    1211                 :          *
    1212 ECB             :          * Instead of using system(), exec the shell directly, and tell it to
    1213                 :          * "exec" the command too.  This saves two useless processes per
    1214                 :          * parallel test case.
    1215                 :          */
    1216                 :         char       *cmdline2;
    1217                 : 
    1218 CBC        1192 :         cmdline2 = psprintf("exec %s", cmdline);
    1219            1192 :         execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL);
    1220                 :         /* Not using the normal bail() here as we want _exit */
    1221 GNC        1192 :         bail_noatexit("could not exec \"%s\": %s", shellprog, strerror(errno));
    1222                 :     }
    1223 ECB             :     /* in parent */
    1224 GIC        1192 :     return pid;
    1225                 : #else
    1226                 :     PROCESS_INFORMATION pi;
    1227                 :     char       *cmdline2;
    1228                 :     HANDLE      restrictedToken;
    1229 ECB             :     const char *comspec;
    1230                 : 
    1231                 :     /* Find CMD.EXE location using COMSPEC, if it's set */
    1232                 :     comspec = getenv("COMSPEC");
    1233                 :     if (comspec == NULL)
    1234 EUB             :         comspec = "CMD";
    1235                 : 
    1236                 :     memset(&pi, 0, sizeof(pi));
    1237                 :     cmdline2 = psprintf("\"%s\" /c \"%s\"", comspec, cmdline);
    1238 ECB             : 
    1239                 :     if ((restrictedToken =
    1240                 :          CreateRestrictedProcess(cmdline2, &pi)) == 0)
    1241                 :         exit(2);
    1242                 : 
    1243 EUB             :     CloseHandle(pi.hThread);
    1244                 :     return pi.hProcess;
    1245                 : #endif
    1246                 : }
    1247 ECB             : 
    1248                 : /*
    1249                 :  * Count bytes in file
    1250                 :  */
    1251                 : static long
    1252 GIC          84 : file_size(const char *file)
    1253                 : {
    1254 ECB             :     long        r;
    1255 GIC          84 :     FILE       *f = fopen(file, "r");
    1256 ECB             : 
    1257 CBC          84 :     if (!f)
    1258                 :     {
    1259 UNC           0 :         diag("could not open file \"%s\" for reading: %s",
    1260                 :              file, strerror(errno));
    1261 UIC           0 :         return -1;
    1262                 :     }
    1263 CBC          84 :     fseek(f, 0, SEEK_END);
    1264 GIC          84 :     r = ftell(f);
    1265              84 :     fclose(f);
    1266              84 :     return r;
    1267                 : }
    1268 ECB             : 
    1269                 : /*
    1270                 :  * Count lines in file
    1271                 :  */
    1272 EUB             : static int
    1273 GIC          21 : file_line_count(const char *file)
    1274                 : {
    1275                 :     int         c;
    1276 CBC          21 :     int         l = 0;
    1277              21 :     FILE       *f = fopen(file, "r");
    1278 ECB             : 
    1279 GIC          21 :     if (!f)
    1280                 :     {
    1281 UNC           0 :         diag("could not open file \"%s\" for reading: %s",
    1282                 :              file, strerror(errno));
    1283 UIC           0 :         return -1;
    1284                 :     }
    1285 GIC       98692 :     while ((c = fgetc(f)) != EOF)
    1286                 :     {
    1287           98671 :         if (c == '\n')
    1288            3721 :             l++;
    1289                 :     }
    1290              21 :     fclose(f);
    1291              21 :     return l;
    1292                 : }
    1293                 : 
    1294                 : bool
    1295            2141 : file_exists(const char *file)
    1296 ECB             : {
    1297 GIC        2141 :     FILE       *f = fopen(file, "r");
    1298                 : 
    1299            2141 :     if (!f)
    1300            2120 :         return false;
    1301              21 :     fclose(f);
    1302              21 :     return true;
    1303                 : }
    1304 ECB             : 
    1305                 : static bool
    1306 GIC         332 : directory_exists(const char *dir)
    1307                 : {
    1308                 :     struct stat st;
    1309                 : 
    1310 CBC         332 :     if (stat(dir, &st) != 0)
    1311             255 :         return false;
    1312 GIC          77 :     if (S_ISDIR(st.st_mode))
    1313 GBC          77 :         return true;
    1314 UIC           0 :     return false;
    1315 ECB             : }
    1316                 : 
    1317                 : /* Create a directory */
    1318                 : static void
    1319 GIC         255 : make_directory(const char *dir)
    1320                 : {
    1321             255 :     if (mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
    1322                 :     {
    1323 UNC           0 :         bail("could not create directory \"%s\": %s", dir, strerror(errno));
    1324 ECB             :     }
    1325 CBC         255 : }
    1326                 : 
    1327 ECB             : /*
    1328                 :  * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9
    1329                 :  */
    1330                 : static char *
    1331 GIC          47 : get_alternative_expectfile(const char *expectfile, int i)
    1332                 : {
    1333                 :     char       *last_dot;
    1334              47 :     int         ssize = strlen(expectfile) + 2 + 1;
    1335                 :     char       *tmp;
    1336                 :     char       *s;
    1337                 : 
    1338              47 :     if (!(tmp = (char *) malloc(ssize)))
    1339 UIC           0 :         return NULL;
    1340                 : 
    1341 GIC          47 :     if (!(s = (char *) malloc(ssize)))
    1342                 :     {
    1343 UIC           0 :         free(tmp);
    1344               0 :         return NULL;
    1345                 :     }
    1346                 : 
    1347 GIC          47 :     strcpy(tmp, expectfile);
    1348              47 :     last_dot = strrchr(tmp, '.');
    1349              47 :     if (!last_dot)
    1350                 :     {
    1351 UIC           0 :         free(tmp);
    1352               0 :         free(s);
    1353               0 :         return NULL;
    1354                 :     }
    1355 GIC          47 :     *last_dot = '\0';
    1356              47 :     snprintf(s, ssize, "%s_%d.%s", tmp, i, last_dot + 1);
    1357              47 :     free(tmp);
    1358 CBC          47 :     return s;
    1359                 : }
    1360                 : 
    1361 ECB             : /*
    1362                 :  * Run a "diff" command and also check that it didn't crash
    1363                 :  */
    1364                 : static int
    1365 GBC        1257 : run_diff(const char *cmd, const char *filename)
    1366                 : {
    1367 EUB             :     int         r;
    1368                 : 
    1369 GNC        1257 :     fflush(NULL);
    1370 CBC        1257 :     r = system(cmd);
    1371            1257 :     if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
    1372 ECB             :     {
    1373 UNC           0 :         bail("diff command failed with status %d: %s", r, cmd);
    1374                 :     }
    1375                 : #ifdef WIN32
    1376                 : 
    1377                 :     /*
    1378                 :      * On WIN32, if the 'diff' command cannot be found, system() returns 1,
    1379 ECB             :      * but produces nothing to stdout, so we check for that here.
    1380                 :      */
    1381                 :     if (WEXITSTATUS(r) == 1 && file_size(filename) <= 0)
    1382                 :     {
    1383                 :         bail("diff command not found: %s", cmd);
    1384                 :     }
    1385                 : #endif
    1386 EUB             : 
    1387 GIC        1257 :     return WEXITSTATUS(r);
    1388 EUB             : }
    1389                 : 
    1390 ECB             : /*
    1391                 :  * Check the actual result file for the given test against expected results
    1392                 :  *
    1393                 :  * Returns true if different (failure), false if correct match found.
    1394                 :  * In the true case, the diff is appended to the diffs file.
    1395                 :  */
    1396                 : static bool
    1397 GIC        1236 : results_differ(const char *testname, const char *resultsfile, const char *default_expectfile)
    1398                 : {
    1399                 :     char        expectfile[MAXPGPATH];
    1400 ECB             :     char        diff[MAXPGPATH];
    1401                 :     char        cmd[MAXPGPATH * 3];
    1402                 :     char        best_expect_file[MAXPGPATH];
    1403                 :     FILE       *difffile;
    1404                 :     int         best_line_count;
    1405                 :     int         i;
    1406                 :     int         l;
    1407                 :     const char *platform_expectfile;
    1408                 : 
    1409                 :     /*
    1410                 :      * We can pass either the resultsfile or the expectfile, they should have
    1411                 :      * the same type (filename.type) anyway.
    1412                 :      */
    1413 GIC        1236 :     platform_expectfile = get_expectfile(testname, resultsfile);
    1414                 : 
    1415 CBC        1236 :     strlcpy(expectfile, default_expectfile, sizeof(expectfile));
    1416            1236 :     if (platform_expectfile)
    1417 ECB             :     {
    1418                 :         /*
    1419 EUB             :          * Replace everything after the last slash in expectfile with what the
    1420                 :          * platform_expectfile contains.
    1421                 :          */
    1422 UIC           0 :         char       *p = strrchr(expectfile, '/');
    1423                 : 
    1424 LBC           0 :         if (p)
    1425 UIC           0 :             strcpy(++p, platform_expectfile);
    1426 ECB             :     }
    1427                 : 
    1428 EUB             :     /* Name to use for temporary diff file */
    1429 GIC        1236 :     snprintf(diff, sizeof(diff), "%s.diff", resultsfile);
    1430 ECB             : 
    1431                 :     /* OK, run the diff */
    1432 GIC        1236 :     snprintf(cmd, sizeof(cmd),
    1433                 :              "diff %s \"%s\" \"%s\" > \"%s\"",
    1434                 :              basic_diff_opts, expectfile, resultsfile, diff);
    1435                 : 
    1436 ECB             :     /* Is the diff file empty? */
    1437 GIC        1236 :     if (run_diff(cmd, diff) == 0)
    1438                 :     {
    1439 CBC        1217 :         unlink(diff);
    1440 GIC        1217 :         return false;
    1441                 :     }
    1442                 : 
    1443 ECB             :     /* There may be secondary comparison files that match better */
    1444 GBC          19 :     best_line_count = file_line_count(diff);
    1445 GIC          19 :     strcpy(best_expect_file, expectfile);
    1446 ECB             : 
    1447 GIC          47 :     for (i = 0; i <= 9; i++)
    1448 EUB             :     {
    1449                 :         char       *alt_expectfile;
    1450                 : 
    1451 GIC          47 :         alt_expectfile = get_alternative_expectfile(expectfile, i);
    1452 CBC          47 :         if (!alt_expectfile)
    1453 ECB             :         {
    1454 UNC           0 :             bail("Unable to check secondary comparison files: %s",
    1455                 :                  strerror(errno));
    1456 EUB             :         }
    1457                 : 
    1458 GIC          47 :         if (!file_exists(alt_expectfile))
    1459 ECB             :         {
    1460 CBC          26 :             free(alt_expectfile);
    1461              26 :             continue;
    1462 ECB             :         }
    1463                 : 
    1464 GIC          21 :         snprintf(cmd, sizeof(cmd),
    1465                 :                  "diff %s \"%s\" \"%s\" > \"%s\"",
    1466                 :                  basic_diff_opts, alt_expectfile, resultsfile, diff);
    1467                 : 
    1468              21 :         if (run_diff(cmd, diff) == 0)
    1469 ECB             :         {
    1470 GIC          19 :             unlink(diff);
    1471              19 :             free(alt_expectfile);
    1472              19 :             return false;
    1473 ECB             :         }
    1474                 : 
    1475 CBC           2 :         l = file_line_count(diff);
    1476 GIC           2 :         if (l < best_line_count)
    1477 EUB             :         {
    1478                 :             /* This diff was a better match than the last one */
    1479 GIC           2 :             best_line_count = l;
    1480               2 :             strlcpy(best_expect_file, alt_expectfile, sizeof(best_expect_file));
    1481                 :         }
    1482               2 :         free(alt_expectfile);
    1483                 :     }
    1484                 : 
    1485                 :     /*
    1486                 :      * fall back on the canonical results file if we haven't tried it yet and
    1487                 :      * haven't found a complete match yet.
    1488                 :      */
    1489                 : 
    1490 UIC           0 :     if (platform_expectfile)
    1491 ECB             :     {
    1492 UIC           0 :         snprintf(cmd, sizeof(cmd),
    1493                 :                  "diff %s \"%s\" \"%s\" > \"%s\"",
    1494                 :                  basic_diff_opts, default_expectfile, resultsfile, diff);
    1495                 : 
    1496               0 :         if (run_diff(cmd, diff) == 0)
    1497                 :         {
    1498                 :             /* No diff = no changes = good */
    1499               0 :             unlink(diff);
    1500               0 :             return false;
    1501 ECB             :         }
    1502                 : 
    1503 UIC           0 :         l = file_line_count(diff);
    1504               0 :         if (l < best_line_count)
    1505                 :         {
    1506                 :             /* This diff was a better match than the last one */
    1507               0 :             best_line_count = l;
    1508               0 :             strlcpy(best_expect_file, default_expectfile, sizeof(best_expect_file));
    1509                 :         }
    1510                 :     }
    1511                 : 
    1512                 :     /*
    1513                 :      * Use the best comparison file to generate the "pretty" diff, which we
    1514                 :      * append to the diffs summary file.
    1515                 :      */
    1516                 : 
    1517 ECB             :     /* Write diff header */
    1518 UIC           0 :     difffile = fopen(difffilename, "a");
    1519 LBC           0 :     if (difffile)
    1520 ECB             :     {
    1521 UIC           0 :         fprintf(difffile,
    1522                 :                 "diff %s %s %s\n",
    1523                 :                 pretty_diff_opts, best_expect_file, resultsfile);
    1524               0 :         fclose(difffile);
    1525                 :     }
    1526 EUB             : 
    1527                 :     /* Run diff */
    1528 UBC           0 :     snprintf(cmd, sizeof(cmd),
    1529 EUB             :              "diff %s \"%s\" \"%s\" >> \"%s\"",
    1530                 :              pretty_diff_opts, best_expect_file, resultsfile, difffilename);
    1531 UIC           0 :     run_diff(cmd, difffilename);
    1532                 : 
    1533 LBC           0 :     unlink(diff);
    1534 UIC           0 :     return true;
    1535                 : }
    1536 ECB             : 
    1537                 : /*
    1538                 :  * Wait for specified subprocesses to finish, and return their exit
    1539                 :  * statuses into statuses[] and stop times into stoptimes[]
    1540                 :  *
    1541                 :  * If names isn't NULL, print each subprocess's name as it finishes
    1542                 :  *
    1543                 :  * Note: it's OK to scribble on the pids array, but not on the names array
    1544                 :  */
    1545                 : static void
    1546 GIC         543 : wait_for_tests(PID_TYPE * pids, int *statuses, instr_time *stoptimes,
    1547                 :                char **names, int num_tests)
    1548 ECB             : {
    1549                 :     int         tests_left;
    1550                 :     int         i;
    1551                 : 
    1552                 : #ifdef WIN32
    1553                 :     PID_TYPE   *active_pids = pg_malloc(num_tests * sizeof(PID_TYPE));
    1554                 : 
    1555                 :     memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
    1556                 : #endif
    1557                 : 
    1558 GBC         543 :     tests_left = num_tests;
    1559 GIC        1653 :     while (tests_left > 0)
    1560                 :     {
    1561                 :         PID_TYPE    p;
    1562 ECB             : 
    1563                 : #ifndef WIN32
    1564                 :         int         exit_status;
    1565                 : 
    1566 GIC        1110 :         p = wait(&exit_status);
    1567                 : 
    1568 CBC        1110 :         if (p == INVALID_PID)
    1569                 :         {
    1570 UNC           0 :             bail("failed to wait for subprocesses: %s", strerror(errno));
    1571                 :         }
    1572 ECB             : #else
    1573                 :         DWORD       exit_status;
    1574                 :         int         r;
    1575                 : 
    1576                 :         r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
    1577                 :         if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
    1578                 :         {
    1579                 :             bail("failed to wait for subprocesses: error code %lu",
    1580                 :                  GetLastError());
    1581                 :         }
    1582                 :         p = active_pids[r - WAIT_OBJECT_0];
    1583                 :         /* compact the active_pids array */
    1584                 :         active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
    1585                 : #endif                          /* WIN32 */
    1586                 : 
    1587 GIC        5613 :         for (i = 0; i < num_tests; i++)
    1588                 :         {
    1589            5613 :             if (p == pids[i])
    1590                 :             {
    1591 EUB             : #ifdef WIN32
    1592                 :                 GetExitCodeProcess(pids[i], &exit_status);
    1593                 :                 CloseHandle(pids[i]);
    1594                 : #endif
    1595 GIC        1110 :                 pids[i] = INVALID_PID;
    1596            1110 :                 statuses[i] = (int) exit_status;
    1597 GBC        1110 :                 INSTR_TIME_SET_CURRENT(stoptimes[i]);
    1598 GIC        1110 :                 if (names)
    1599 GNC         621 :                     note_detail(" %s", names[i]);
    1600 GBC        1110 :                 tests_left--;
    1601            1110 :                 break;
    1602                 :             }
    1603                 :         }
    1604 EUB             :     }
    1605                 : 
    1606                 : #ifdef WIN32
    1607                 :     free(active_pids);
    1608                 : #endif
    1609 GBC         543 : }
    1610                 : 
    1611                 : /*
    1612                 :  * report nonzero exit code from a test process
    1613                 :  */
    1614                 : static void
    1615 UIC           0 : log_child_failure(int exitstatus)
    1616                 : {
    1617               0 :     if (WIFEXITED(exitstatus))
    1618 UNC           0 :         diag("(test process exited with exit code %d)",
    1619                 :              WEXITSTATUS(exitstatus));
    1620 UBC           0 :     else if (WIFSIGNALED(exitstatus))
    1621                 :     {
    1622 EUB             : #if defined(WIN32)
    1623                 :         diag("(test process was terminated by exception 0x%X)",
    1624                 :              WTERMSIG(exitstatus));
    1625                 : #else
    1626 UNC           0 :         diag("(test process was terminated by signal %d: %s)",
    1627                 :              WTERMSIG(exitstatus), pg_strsignal(WTERMSIG(exitstatus)));
    1628                 : #endif
    1629 EUB             :     }
    1630                 :     else
    1631 UNC           0 :         diag("(test process exited with unrecognized status %d)", exitstatus);
    1632 UIC           0 : }
    1633 EUB             : 
    1634                 : /*
    1635                 :  * Run all the tests specified in one schedule file
    1636                 :  */
    1637                 : static void
    1638 GIC           5 : run_schedule(const char *schedule, test_start_function startfunc,
    1639                 :              postprocess_result_function postfunc)
    1640                 : {
    1641                 : #define MAX_PARALLEL_TESTS 100
    1642                 :     char       *tests[MAX_PARALLEL_TESTS];
    1643                 :     _stringlist *resultfiles[MAX_PARALLEL_TESTS];
    1644                 :     _stringlist *expectfiles[MAX_PARALLEL_TESTS];
    1645                 :     _stringlist *tags[MAX_PARALLEL_TESTS];
    1646 ECB             :     PID_TYPE    pids[MAX_PARALLEL_TESTS];
    1647                 :     instr_time  starttimes[MAX_PARALLEL_TESTS];
    1648                 :     instr_time  stoptimes[MAX_PARALLEL_TESTS];
    1649                 :     int         statuses[MAX_PARALLEL_TESTS];
    1650                 :     char        scbuf[1024];
    1651                 :     FILE       *scf;
    1652 GIC           5 :     int         line_num = 0;
    1653                 : 
    1654               5 :     memset(tests, 0, sizeof(tests));
    1655               5 :     memset(resultfiles, 0, sizeof(resultfiles));
    1656               5 :     memset(expectfiles, 0, sizeof(expectfiles));
    1657 CBC           5 :     memset(tags, 0, sizeof(tags));
    1658 ECB             : 
    1659 GIC           5 :     scf = fopen(schedule, "r");
    1660               5 :     if (!scf)
    1661                 :     {
    1662 UNC           0 :         bail("could not open file \"%s\" for reading: %s",
    1663                 :              schedule, strerror(errno));
    1664 ECB             :     }
    1665                 : 
    1666 CBC         581 :     while (fgets(scbuf, sizeof(scbuf), scf))
    1667                 :     {
    1668 GBC         576 :         char       *test = NULL;
    1669                 :         char       *c;
    1670                 :         int         num_tests;
    1671                 :         bool        inword;
    1672                 :         int         i;
    1673                 : 
    1674 GIC         576 :         line_num++;
    1675                 : 
    1676                 :         /* strip trailing whitespace, especially the newline */
    1677             576 :         i = strlen(scbuf);
    1678            1152 :         while (i > 0 && isspace((unsigned char) scbuf[i - 1]))
    1679             576 :             scbuf[--i] = '\0';
    1680                 : 
    1681             576 :         if (scbuf[0] == '\0' || scbuf[0] == '#')
    1682             327 :             continue;
    1683             249 :         if (strncmp(scbuf, "test: ", 6) == 0)
    1684             249 :             test = scbuf + 6;
    1685 ECB             :         else
    1686                 :         {
    1687 UNC           0 :             bail("syntax error in schedule file \"%s\" line %d: %s",
    1688                 :                  schedule, line_num, scbuf);
    1689                 :         }
    1690                 : 
    1691 GIC         249 :         num_tests = 0;
    1692 CBC         249 :         inword = false;
    1693 GIC        9612 :         for (c = test;; c++)
    1694                 :         {
    1695            9612 :             if (*c == '\0' || isspace((unsigned char) *c))
    1696                 :             {
    1697             816 :                 if (inword)
    1698 EUB             :                 {
    1699                 :                     /* Reached end of a test name */
    1700                 :                     char        sav;
    1701                 : 
    1702 GIC         816 :                     if (num_tests >= MAX_PARALLEL_TESTS)
    1703 EUB             :                     {
    1704 UNC           0 :                         bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
    1705                 :                              MAX_PARALLEL_TESTS, schedule, line_num, scbuf);
    1706                 :                     }
    1707 GIC         816 :                     sav = *c;
    1708 GBC         816 :                     *c = '\0';
    1709 GIC         816 :                     tests[num_tests] = pg_strdup(test);
    1710             816 :                     num_tests++;
    1711             816 :                     *c = sav;
    1712             816 :                     inword = false;
    1713 EUB             :                 }
    1714 GBC         816 :                 if (*c == '\0')
    1715 GIC         249 :                     break;      /* loop exit is here */
    1716                 :             }
    1717            8796 :             else if (!inword)
    1718                 :             {
    1719                 :                 /* Start of a test name */
    1720 CBC         816 :                 test = c;
    1721 GIC         816 :                 inword = true;
    1722                 :             }
    1723                 :         }
    1724                 : 
    1725             249 :         if (num_tests == 0)
    1726                 :         {
    1727 UNC           0 :             bail("syntax error in schedule file \"%s\" line %d: %s",
    1728                 :                  schedule, line_num, scbuf);
    1729                 :         }
    1730                 : 
    1731 GIC         249 :         if (num_tests == 1)
    1732                 :         {
    1733             195 :             pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
    1734 CBC         195 :             INSTR_TIME_SET_CURRENT(starttimes[0]);
    1735             195 :             wait_for_tests(pids, statuses, stoptimes, NULL, 1);
    1736 ECB             :             /* status line is finished below */
    1737                 :         }
    1738 GIC          54 :         else if (max_concurrent_tests > 0 && max_concurrent_tests < num_tests)
    1739 ECB             :         {
    1740 UNC           0 :             bail("too many parallel tests (more than %d) in schedule file \"%s\" line %d: %s",
    1741                 :                  max_concurrent_tests, schedule, line_num, scbuf);
    1742                 :         }
    1743 GIC          54 :         else if (max_connections > 0 && max_connections < num_tests)
    1744 UIC           0 :         {
    1745 LBC           0 :             int         oldest = 0;
    1746                 : 
    1747 UNC           0 :             note_detail("parallel group (%d tests, in groups of %d): ",
    1748                 :                         num_tests, max_connections);
    1749 UIC           0 :             for (i = 0; i < num_tests; i++)
    1750                 :             {
    1751               0 :                 if (i - oldest >= max_connections)
    1752                 :                 {
    1753 LBC           0 :                     wait_for_tests(pids + oldest, statuses + oldest,
    1754 UIC           0 :                                    stoptimes + oldest,
    1755               0 :                                    tests + oldest, i - oldest);
    1756 LBC           0 :                     oldest = i;
    1757 ECB             :                 }
    1758 LBC           0 :                 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
    1759 UIC           0 :                 INSTR_TIME_SET_CURRENT(starttimes[i]);
    1760 ECB             :             }
    1761 LBC           0 :             wait_for_tests(pids + oldest, statuses + oldest,
    1762               0 :                            stoptimes + oldest,
    1763               0 :                            tests + oldest, i - oldest);
    1764 UNC           0 :             note_end();
    1765                 :         }
    1766 EUB             :         else
    1767                 :         {
    1768 GNC          54 :             note_detail("parallel group (%d tests): ", num_tests);
    1769 GIC         675 :             for (i = 0; i < num_tests; i++)
    1770 ECB             :             {
    1771 CBC         621 :                 pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
    1772             621 :                 INSTR_TIME_SET_CURRENT(starttimes[i]);
    1773                 :             }
    1774              54 :             wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
    1775 GNC          54 :             note_end();
    1776 ECB             :         }
    1777                 : 
    1778                 :         /* Check results for all tests */
    1779 GIC        1065 :         for (i = 0; i < num_tests; i++)
    1780                 :         {
    1781 ECB             :             _stringlist *rl,
    1782                 :                        *el,
    1783 EUB             :                        *tl;
    1784 GIC         816 :             bool        differ = false;
    1785                 : 
    1786 GNC         816 :             INSTR_TIME_SUBTRACT(stoptimes[i], starttimes[i]);
    1787 ECB             : 
    1788                 :             /*
    1789                 :              * Advance over all three lists simultaneously.
    1790                 :              *
    1791                 :              * Compare resultfiles[j] with expectfiles[j] always. Tags are
    1792                 :              * optional but if there are tags, the tag list has the same
    1793                 :              * length as the other two lists.
    1794                 :              */
    1795 CBC         816 :             for (rl = resultfiles[i], el = expectfiles[i], tl = tags[i];
    1796 GIC        1756 :                  rl != NULL;    /* rl and el have the same length */
    1797             940 :                  rl = rl->next, el = el->next,
    1798 CBC         940 :                  tl = tl ? tl->next : NULL)
    1799 ECB             :             {
    1800                 :                 bool        newdiff;
    1801                 : 
    1802 GIC         940 :                 if (postfunc)
    1803 CBC         186 :                     (*postfunc) (rl->str);
    1804 GIC         940 :                 newdiff = results_differ(tests[i], rl->str, el->str);
    1805 GBC         940 :                 if (newdiff && tl)
    1806                 :                 {
    1807 UNC           0 :                     diag("tag: %s", tl->str);
    1808                 :                 }
    1809 CBC         940 :                 differ |= newdiff;
    1810                 :             }
    1811 ECB             : 
    1812 GNC         816 :             if (statuses[i] != 0)
    1813 ECB             :             {
    1814 UNC           0 :                 test_status_failed(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
    1815               0 :                 log_child_failure(statuses[i]);
    1816                 :             }
    1817 EUB             :             else
    1818                 :             {
    1819 GNC         816 :                 if (differ)
    1820                 :                 {
    1821 UNC           0 :                     test_status_failed(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
    1822                 :                 }
    1823                 :                 else
    1824                 :                 {
    1825 GNC         816 :                     test_status_ok(tests[i], INSTR_TIME_GET_MILLISEC(stoptimes[i]), (num_tests > 1));
    1826                 :                 }
    1827 EUB             :             }
    1828 ECB             :         }
    1829                 : 
    1830 GIC        1065 :         for (i = 0; i < num_tests; i++)
    1831 ECB             :         {
    1832 CBC         816 :             pg_free(tests[i]);
    1833 GIC         816 :             tests[i] = NULL;
    1834             816 :             free_stringlist(&resultfiles[i]);
    1835             816 :             free_stringlist(&expectfiles[i]);
    1836 CBC         816 :             free_stringlist(&tags[i]);
    1837                 :         }
    1838                 :     }
    1839                 : 
    1840 GIC           5 :     fclose(scf);
    1841 CBC           5 : }
    1842                 : 
    1843                 : /*
    1844                 :  * Run a single test
    1845                 :  */
    1846                 : static void
    1847 GIC         294 : run_single_test(const char *test, test_start_function startfunc,
    1848                 :                 postprocess_result_function postfunc)
    1849                 : {
    1850 ECB             :     PID_TYPE    pid;
    1851                 :     instr_time  starttime;
    1852                 :     instr_time  stoptime;
    1853                 :     int         exit_status;
    1854 GIC         294 :     _stringlist *resultfiles = NULL;
    1855             294 :     _stringlist *expectfiles = NULL;
    1856             294 :     _stringlist *tags = NULL;
    1857 ECB             :     _stringlist *rl,
    1858                 :                *el,
    1859                 :                *tl;
    1860 CBC         294 :     bool        differ = false;
    1861                 : 
    1862 GIC         294 :     pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
    1863 CBC         294 :     INSTR_TIME_SET_CURRENT(starttime);
    1864 GIC         294 :     wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
    1865                 : 
    1866 ECB             :     /*
    1867                 :      * Advance over all three lists simultaneously.
    1868 EUB             :      *
    1869                 :      * Compare resultfiles[j] with expectfiles[j] always. Tags are optional
    1870                 :      * but if there are tags, the tag list has the same length as the other
    1871                 :      * two lists.
    1872                 :      */
    1873 CBC         294 :     for (rl = resultfiles, el = expectfiles, tl = tags;
    1874 GIC         590 :          rl != NULL;            /* rl and el have the same length */
    1875 GBC         296 :          rl = rl->next, el = el->next,
    1876 GIC         296 :          tl = tl ? tl->next : NULL)
    1877                 :     {
    1878                 :         bool        newdiff;
    1879 ECB             : 
    1880 GIC         296 :         if (postfunc)
    1881               3 :             (*postfunc) (rl->str);
    1882             296 :         newdiff = results_differ(test, rl->str, el->str);
    1883             296 :         if (newdiff && tl)
    1884 ECB             :         {
    1885 UNC           0 :             diag("tag: %s", tl->str);
    1886 ECB             :         }
    1887 CBC         296 :         differ |= newdiff;
    1888 ECB             :     }
    1889                 : 
    1890 GNC         294 :     INSTR_TIME_SUBTRACT(stoptime, starttime);
    1891                 : 
    1892             294 :     if (exit_status != 0)
    1893                 :     {
    1894 UNC           0 :         test_status_failed(test, false, INSTR_TIME_GET_MILLISEC(stoptime));
    1895               0 :         log_child_failure(exit_status);
    1896 ECB             :     }
    1897                 :     else
    1898                 :     {
    1899 GNC         294 :         if (differ)
    1900                 :         {
    1901 UNC           0 :             test_status_failed(test, false, INSTR_TIME_GET_MILLISEC(stoptime));
    1902                 :         }
    1903                 :         else
    1904                 :         {
    1905 GNC         294 :             test_status_ok(test, INSTR_TIME_GET_MILLISEC(stoptime), false);
    1906                 :         }
    1907                 :     }
    1908 CBC         294 : }
    1909 ECB             : 
    1910                 : /*
    1911                 :  * Create the summary-output files (making them empty if already existing)
    1912                 :  */
    1913                 : static void
    1914 CBC          84 : open_result_files(void)
    1915                 : {
    1916 ECB             :     char        file[MAXPGPATH];
    1917                 :     FILE       *difffile;
    1918                 : 
    1919                 :     /* create outputdir directory if not present */
    1920 GIC          84 :     if (!directory_exists(outputdir))
    1921               7 :         make_directory(outputdir);
    1922                 : 
    1923                 :     /* create the log file (copy of running status output) */
    1924              84 :     snprintf(file, sizeof(file), "%s/regression.out", outputdir);
    1925              84 :     logfilename = pg_strdup(file);
    1926              84 :     logfile = fopen(logfilename, "w");
    1927 CBC          84 :     if (!logfile)
    1928 ECB             :     {
    1929 UNC           0 :         bail("could not open file \"%s\" for writing: %s",
    1930                 :              logfilename, strerror(errno));
    1931                 :     }
    1932                 : 
    1933 ECB             :     /* create the diffs file as empty */
    1934 CBC          84 :     snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
    1935              84 :     difffilename = pg_strdup(file);
    1936              84 :     difffile = fopen(difffilename, "w");
    1937 GIC          84 :     if (!difffile)
    1938 EUB             :     {
    1939 UNC           0 :         bail("could not open file \"%s\" for writing: %s",
    1940                 :              difffilename, strerror(errno));
    1941                 :     }
    1942 ECB             :     /* we don't keep the diffs file open continuously */
    1943 GIC          84 :     fclose(difffile);
    1944 ECB             : 
    1945                 :     /* also create the results directory if not present */
    1946 GBC          84 :     snprintf(file, sizeof(file), "%s/results", outputdir);
    1947              84 :     if (!directory_exists(file))
    1948 GIC          84 :         make_directory(file);
    1949              84 : }
    1950                 : 
    1951 ECB             : static void
    1952 GIC           2 : drop_database_if_exists(const char *dbname)
    1953 EUB             : {
    1954 GIC           2 :     StringInfo  buf = psql_start_command();
    1955                 : 
    1956 ECB             :     /* Set warning level so we don't see chatter about nonexistent DB */
    1957 GIC           2 :     psql_add_command(buf, "SET client_min_messages = warning");
    1958               2 :     psql_add_command(buf, "DROP DATABASE IF EXISTS \"%s\"", dbname);
    1959 CBC           2 :     psql_end_command(buf, "postgres");
    1960 GIC           2 : }
    1961                 : 
    1962                 : static void
    1963              85 : create_database(const char *dbname)
    1964                 : {
    1965 CBC          85 :     StringInfo  buf = psql_start_command();
    1966                 :     _stringlist *sl;
    1967                 : 
    1968                 :     /*
    1969                 :      * We use template0 so that any installation-local cruft in template1 will
    1970                 :      * not mess up the tests.
    1971 ECB             :      */
    1972 GIC          85 :     if (encoding)
    1973               2 :         psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'%s", dbname, encoding,
    1974 CBC           2 :                          (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
    1975 ECB             :     else
    1976 CBC          83 :         psql_add_command(buf, "CREATE DATABASE \"%s\" TEMPLATE=template0%s", dbname,
    1977              83 :                          (nolocale) ? " LC_COLLATE='C' LC_CTYPE='C'" : "");
    1978 GIC          85 :     psql_add_command(buf,
    1979 EUB             :                      "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
    1980                 :                      "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
    1981                 :                      "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
    1982                 :                      "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
    1983                 :                      "ALTER DATABASE \"%s\" SET bytea_output TO 'hex';"
    1984 ECB             :                      "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
    1985                 :                      dbname, dbname, dbname, dbname, dbname, dbname);
    1986 CBC          85 :     psql_end_command(buf, "postgres");
    1987 ECB             : 
    1988                 :     /*
    1989 EUB             :      * Install any requested extensions.  We use CREATE IF NOT EXISTS so that
    1990                 :      * this will work whether or not the extension is preinstalled.
    1991                 :      */
    1992 GIC          90 :     for (sl = loadextension; sl != NULL; sl = sl->next)
    1993               5 :         psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
    1994 CBC          85 : }
    1995 ECB             : 
    1996                 : static void
    1997 UIC           0 : drop_role_if_exists(const char *rolename)
    1998                 : {
    1999 LBC           0 :     StringInfo  buf = psql_start_command();
    2000                 : 
    2001                 :     /* Set warning level so we don't see chatter about nonexistent role */
    2002 UIC           0 :     psql_add_command(buf, "SET client_min_messages = warning");
    2003 LBC           0 :     psql_add_command(buf, "DROP ROLE IF EXISTS \"%s\"", rolename);
    2004               0 :     psql_end_command(buf, "postgres");
    2005               0 : }
    2006 ECB             : 
    2007                 : static void
    2008 GIC           2 : create_role(const char *rolename, const _stringlist *granted_dbs)
    2009 ECB             : {
    2010 GIC           2 :     StringInfo  buf = psql_start_command();
    2011 ECB             : 
    2012 GIC           2 :     psql_add_command(buf, "CREATE ROLE \"%s\" WITH LOGIN", rolename);
    2013               6 :     for (; granted_dbs != NULL; granted_dbs = granted_dbs->next)
    2014                 :     {
    2015               4 :         psql_add_command(buf, "GRANT ALL ON DATABASE \"%s\" TO \"%s\"",
    2016               4 :                          granted_dbs->str, rolename);
    2017 ECB             :     }
    2018 CBC           2 :     psql_end_command(buf, "postgres");
    2019               2 : }
    2020                 : 
    2021 ECB             : static void
    2022 LBC           0 : help(void)
    2023 ECB             : {
    2024 UIC           0 :     printf(_("PostgreSQL regression test driver\n"));
    2025               0 :     printf(_("\n"));
    2026               0 :     printf(_("Usage:\n  %s [OPTION]... [EXTRA-TEST]...\n"), progname);
    2027               0 :     printf(_("\n"));
    2028               0 :     printf(_("Options:\n"));
    2029               0 :     printf(_("      --bindir=BINPATH          use BINPATH for programs that are run;\n"));
    2030               0 :     printf(_("                                if empty, use PATH from the environment\n"));
    2031 LBC           0 :     printf(_("      --config-auth=DATADIR     update authentication settings for DATADIR\n"));
    2032 UIC           0 :     printf(_("      --create-role=ROLE        create the specified role before testing\n"));
    2033               0 :     printf(_("      --dbname=DB               use database DB (default \"regression\")\n"));
    2034               0 :     printf(_("      --debug                   turn on debug mode in programs that are run\n"));
    2035               0 :     printf(_("      --dlpath=DIR              look for dynamic libraries in DIR\n"));
    2036               0 :     printf(_("      --encoding=ENCODING       use ENCODING as the encoding\n"));
    2037 UNC           0 :     printf(_("      --expecteddir=DIR         take expected files from DIR (default \".\")\n"));
    2038 LBC           0 :     printf(_("  -h, --help                    show this help, then exit\n"));
    2039               0 :     printf(_("      --inputdir=DIR            take input files from DIR (default \".\")\n"));
    2040               0 :     printf(_("      --launcher=CMD            use CMD as launcher of psql\n"));
    2041 UIC           0 :     printf(_("      --load-extension=EXT      load the named extension before running the\n"));
    2042               0 :     printf(_("                                tests; can appear multiple times\n"));
    2043 UBC           0 :     printf(_("      --max-connections=N       maximum number of concurrent connections\n"));
    2044 UIC           0 :     printf(_("                                (default is 0, meaning unlimited)\n"));
    2045 UBC           0 :     printf(_("      --max-concurrent-tests=N  maximum number of concurrent tests in schedule\n"));
    2046 UIC           0 :     printf(_("                                (default is 0, meaning unlimited)\n"));
    2047               0 :     printf(_("      --outputdir=DIR           place output files in DIR (default \".\")\n"));
    2048 UBC           0 :     printf(_("      --schedule=FILE           use test ordering schedule from FILE\n"));
    2049               0 :     printf(_("                                (can be used multiple times to concatenate)\n"));
    2050               0 :     printf(_("      --temp-instance=DIR       create a temporary instance in DIR\n"));
    2051               0 :     printf(_("      --use-existing            use an existing installation\n"));
    2052 UIC           0 :     printf(_("  -V, --version                 output version information, then exit\n"));
    2053               0 :     printf(_("\n"));
    2054 LBC           0 :     printf(_("Options for \"temp-instance\" mode:\n"));
    2055 UIC           0 :     printf(_("      --no-locale               use C locale\n"));
    2056 LBC           0 :     printf(_("      --port=PORT               start postmaster on PORT\n"));
    2057 UIC           0 :     printf(_("      --temp-config=FILE        append contents of FILE to temporary config\n"));
    2058 LBC           0 :     printf(_("\n"));
    2059               0 :     printf(_("Options for using an existing installation:\n"));
    2060 UIC           0 :     printf(_("      --host=HOST               use postmaster running on HOST\n"));
    2061 LBC           0 :     printf(_("      --port=PORT               use postmaster running at PORT\n"));
    2062               0 :     printf(_("      --user=USER               connect as USER\n"));
    2063 UIC           0 :     printf(_("\n"));
    2064 LBC           0 :     printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
    2065               0 :     printf(_("if the tests could not be run for some reason.\n"));
    2066 UIC           0 :     printf(_("\n"));
    2067               0 :     printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
    2068 UBC           0 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
    2069 UIC           0 : }
    2070 EUB             : 
    2071                 : int
    2072 GBC         303 : regression_main(int argc, char *argv[],
    2073 EUB             :                 init_function ifunc,
    2074                 :                 test_start_function startfunc,
    2075                 :                 postprocess_result_function postfunc)
    2076                 : {
    2077                 :     static struct option long_options[] = {
    2078                 :         {"help", no_argument, NULL, 'h'},
    2079                 :         {"version", no_argument, NULL, 'V'},
    2080                 :         {"dbname", required_argument, NULL, 1},
    2081                 :         {"debug", no_argument, NULL, 2},
    2082                 :         {"inputdir", required_argument, NULL, 3},
    2083                 :         {"max-connections", required_argument, NULL, 5},
    2084                 :         {"encoding", required_argument, NULL, 6},
    2085                 :         {"outputdir", required_argument, NULL, 7},
    2086                 :         {"schedule", required_argument, NULL, 8},
    2087                 :         {"temp-instance", required_argument, NULL, 9},
    2088                 :         {"no-locale", no_argument, NULL, 10},
    2089                 :         {"host", required_argument, NULL, 13},
    2090                 :         {"port", required_argument, NULL, 14},
    2091                 :         {"user", required_argument, NULL, 15},
    2092                 :         {"bindir", required_argument, NULL, 16},
    2093                 :         {"dlpath", required_argument, NULL, 17},
    2094                 :         {"create-role", required_argument, NULL, 18},
    2095                 :         {"temp-config", required_argument, NULL, 19},
    2096                 :         {"use-existing", no_argument, NULL, 20},
    2097                 :         {"launcher", required_argument, NULL, 21},
    2098                 :         {"load-extension", required_argument, NULL, 22},
    2099                 :         {"config-auth", required_argument, NULL, 24},
    2100                 :         {"max-concurrent-tests", required_argument, NULL, 25},
    2101                 :         {"expecteddir", required_argument, NULL, 26},
    2102                 :         {NULL, 0, NULL, 0}
    2103                 :     };
    2104                 : 
    2105                 :     bool        use_unix_sockets;
    2106                 :     _stringlist *sl;
    2107                 :     int         c;
    2108                 :     int         i;
    2109                 :     int         option_index;
    2110                 :     char        buf[MAXPGPATH * 4];
    2111                 :     char        buf2[MAXPGPATH * 4];
    2112                 : 
    2113 GBC         303 :     pg_logging_init(argv[0]);
    2114             303 :     progname = get_progname(argv[0]);
    2115             303 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_regress"));
    2116 EUB             : 
    2117 GIC         303 :     get_restricted_token();
    2118                 : 
    2119 CBC         303 :     atexit(stop_postmaster);
    2120                 : 
    2121                 : #if defined(WIN32)
    2122                 : 
    2123                 :     /*
    2124                 :      * We don't use Unix-domain sockets on Windows by default (see comment at
    2125                 :      * remove_temp() for a reason).  Override at your own risk.
    2126                 :      */
    2127                 :     use_unix_sockets = getenv("PG_TEST_USE_UNIX_SOCKETS") ? true : false;
    2128                 : #else
    2129 GIC         303 :     use_unix_sockets = true;
    2130                 : #endif
    2131                 : 
    2132             303 :     if (!use_unix_sockets)
    2133 UIC           0 :         hostname = "localhost";
    2134                 : 
    2135                 :     /*
    2136                 :      * We call the initialization function here because that way we can set
    2137                 :      * default parameters and let them be overwritten by the commandline.
    2138                 :      */
    2139 GIC         303 :     ifunc(argc, argv);
    2140                 : 
    2141             303 :     if (getenv("PG_REGRESS_DIFF_OPTS"))
    2142             303 :         pretty_diff_opts = getenv("PG_REGRESS_DIFF_OPTS");
    2143                 : 
    2144             920 :     while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
    2145                 :     {
    2146             617 :         switch (c)
    2147                 :         {
    2148 UIC           0 :             case 'h':
    2149               0 :                 help();
    2150               0 :                 exit(0);
    2151               0 :             case 'V':
    2152               0 :                 puts("pg_regress (PostgreSQL) " PG_VERSION);
    2153               0 :                 exit(0);
    2154 GIC          80 :             case 1:
    2155                 : 
    2156                 :                 /*
    2157 ECB             :                  * If a default database was specified, we need to remove it
    2158                 :                  * before we add the specified one.
    2159                 :                  */
    2160 GIC          80 :                 free_stringlist(&dblist);
    2161 CBC          80 :                 split_to_stringlist(optarg, ",", &dblist);
    2162 GIC          80 :                 break;
    2163 LBC           0 :             case 2:
    2164 UIC           0 :                 debug = true;
    2165               0 :                 break;
    2166 GIC          83 :             case 3:
    2167              83 :                 inputdir = pg_strdup(optarg);
    2168              83 :                 break;
    2169 UIC           0 :             case 5:
    2170               0 :                 max_connections = atoi(optarg);
    2171               0 :                 break;
    2172 GIC           2 :             case 6:
    2173 CBC           2 :                 encoding = pg_strdup(optarg);
    2174 GIC           2 :                 break;
    2175               9 :             case 7:
    2176 CBC           9 :                 outputdir = pg_strdup(optarg);
    2177 GBC           9 :                 break;
    2178 GIC           5 :             case 8:
    2179               5 :                 add_stringlist_item(&schedulelist, optarg);
    2180               5 :                 break;
    2181              82 :             case 9:
    2182              82 :                 temp_instance = make_absolute_path(optarg);
    2183 CBC          82 :                 break;
    2184 GIC           3 :             case 10:
    2185 CBC           3 :                 nolocale = true;
    2186               3 :                 break;
    2187 GIC           2 :             case 13:
    2188 CBC           2 :                 hostname = pg_strdup(optarg);
    2189 GIC           2 :                 break;
    2190 CBC           2 :             case 14:
    2191 GIC           2 :                 port = atoi(optarg);
    2192 GBC           2 :                 port_specified_by_user = true;
    2193               2 :                 break;
    2194               3 :             case 15:
    2195               3 :                 user = pg_strdup(optarg);
    2196               3 :                 break;
    2197              84 :             case 16:
    2198 ECB             :                 /* "--bindir=" means to use PATH */
    2199 GIC          84 :                 if (strlen(optarg))
    2200 UIC           0 :                     bindir = pg_strdup(optarg);
    2201                 :                 else
    2202 GIC          84 :                     bindir = NULL;
    2203              84 :                 break;
    2204 CBC           4 :             case 17:
    2205               4 :                 dlpath = pg_strdup(optarg);
    2206               4 :                 break;
    2207 GBC          20 :             case 18:
    2208              20 :                 split_to_stringlist(optarg, ",", &extraroles);
    2209              20 :                 break;
    2210 CBC          10 :             case 19:
    2211              10 :                 add_stringlist_item(&temp_configs, optarg);
    2212              10 :                 break;
    2213 UBC           0 :             case 20:
    2214               0 :                 use_existing = true;
    2215               0 :                 break;
    2216 LBC           0 :             case 21:
    2217               0 :                 launcher = pg_strdup(optarg);
    2218               0 :                 break;
    2219 CBC           5 :             case 22:
    2220               5 :                 add_stringlist_item(&loadextension, optarg);
    2221               5 :                 break;
    2222             219 :             case 24:
    2223             219 :                 config_auth_datadir = pg_strdup(optarg);
    2224             219 :                 break;
    2225               3 :             case 25:
    2226               3 :                 max_concurrent_tests = atoi(optarg);
    2227               3 :                 break;
    2228 GNC           1 :             case 26:
    2229               1 :                 expecteddir = pg_strdup(optarg);
    2230               1 :                 break;
    2231 LBC           0 :             default:
    2232 ECB             :                 /* getopt_long already emitted a complaint */
    2233 UNC           0 :                 pg_log_error_hint("Try \"%s --help\" for more information.",
    2234                 :                                   progname);
    2235 LBC           0 :                 exit(2);
    2236 ECB             :         }
    2237                 :     }
    2238                 : 
    2239                 :     /*
    2240                 :      * if we still have arguments, they are extra tests to run
    2241                 :      */
    2242 CBC         597 :     while (argc - optind >= 1)
    2243 ECB             :     {
    2244 CBC         294 :         add_stringlist_item(&extra_tests, argv[optind]);
    2245 GIC         294 :         optind++;
    2246 ECB             :     }
    2247 EUB             : 
    2248                 :     /*
    2249 ECB             :      * We must have a database to run the tests in; either a default name, or
    2250                 :      * one supplied by the --dbname switch.
    2251                 :      */
    2252 CBC         303 :     if (!(dblist && dblist->str && dblist->str[0]))
    2253 ECB             :     {
    2254 UNC           0 :         bail("no database name was specified");
    2255 ECB             :     }
    2256                 : 
    2257 CBC         303 :     if (config_auth_datadir)
    2258 EUB             :     {
    2259                 : #ifdef ENABLE_SSPI
    2260                 :         if (!use_unix_sockets)
    2261                 :             config_sspi_auth(config_auth_datadir, user);
    2262                 : #endif
    2263 GBC         219 :         exit(0);
    2264 ECB             :     }
    2265                 : 
    2266 CBC          84 :     if (temp_instance && !port_specified_by_user)
    2267 ECB             : 
    2268                 :         /*
    2269                 :          * To reduce chances of interference with parallel installations, use
    2270                 :          * a port number starting in the private range (49152-65535)
    2271                 :          * calculated from the version number.  This aids non-Unix socket mode
    2272                 :          * systems; elsewhere, the use of a private socket directory already
    2273                 :          * prevents interference.
    2274                 :          */
    2275 CBC          82 :         port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
    2276 EUB             : 
    2277 GIC          84 :     inputdir = make_absolute_path(inputdir);
    2278 GBC          84 :     outputdir = make_absolute_path(outputdir);
    2279 GNC          84 :     expecteddir = make_absolute_path(expecteddir);
    2280 GIC          84 :     dlpath = make_absolute_path(dlpath);
    2281 EUB             : 
    2282                 :     /*
    2283                 :      * Initialization
    2284                 :      */
    2285 GIC          84 :     open_result_files();
    2286                 : 
    2287              84 :     initialize_environment();
    2288 ECB             : 
    2289                 : #if defined(HAVE_GETRLIMIT)
    2290 CBC          84 :     unlimit_core_size();
    2291 ECB             : #endif
    2292                 : 
    2293 GIC          84 :     if (temp_instance)
    2294                 :     {
    2295                 :         FILE       *pg_conf;
    2296                 :         const char *env_wait;
    2297                 :         int         wait_seconds;
    2298 ECB             : 
    2299                 :         /*
    2300 EUB             :          * Prepare the temp instance
    2301                 :          */
    2302                 : 
    2303 CBC          82 :         if (directory_exists(temp_instance))
    2304                 :         {
    2305 UIC           0 :             if (!rmtree(temp_instance, true))
    2306                 :             {
    2307 UNC           0 :                 bail("could not remove temp instance \"%s\"", temp_instance);
    2308                 :             }
    2309 ECB             :         }
    2310                 : 
    2311                 :         /* make the temp instance top directory */
    2312 GIC          82 :         make_directory(temp_instance);
    2313                 : 
    2314                 :         /* and a directory for log files */
    2315              82 :         snprintf(buf, sizeof(buf), "%s/log", outputdir);
    2316 CBC          82 :         if (!directory_exists(buf))
    2317 GIC          82 :             make_directory(buf);
    2318 ECB             : 
    2319                 :         /* initdb */
    2320 CBC         328 :         snprintf(buf, sizeof(buf),
    2321                 :                  "\"%s%sinitdb\" -D \"%s/data\" --no-clean --no-sync%s%s > \"%s/log/initdb.log\" 2>&1",
    2322 GIC          82 :                  bindir ? bindir : "",
    2323              82 :                  bindir ? "/" : "",
    2324                 :                  temp_instance,
    2325 CBC          82 :                  debug ? " --debug" : "",
    2326 GIC          82 :                  nolocale ? " --no-locale" : "",
    2327 ECB             :                  outputdir);
    2328 GNC          82 :         fflush(NULL);
    2329 GIC          82 :         if (system(buf))
    2330                 :         {
    2331 UNC           0 :             bail("initdb failed\n"
    2332                 :                  "# Examine \"%s/log/initdb.log\" for the reason.\n"
    2333                 :                  "# Command was: %s",
    2334                 :                  outputdir, buf);
    2335                 :         }
    2336 ECB             : 
    2337                 :         /*
    2338                 :          * Adjust the default postgresql.conf for regression testing. The user
    2339                 :          * can specify a file to be appended; in any case we expand logging
    2340                 :          * and set max_prepared_transactions to enable testing of prepared
    2341                 :          * xacts.  (Note: to reduce the probability of unexpected shmmax
    2342                 :          * failures, don't set max_prepared_transactions any higher than
    2343                 :          * actually needed by the prepared_xacts regression test.)
    2344                 :          */
    2345 GIC          82 :         snprintf(buf, sizeof(buf), "%s/data/postgresql.conf", temp_instance);
    2346 CBC          82 :         pg_conf = fopen(buf, "a");
    2347 GIC          82 :         if (pg_conf == NULL)
    2348 EUB             :         {
    2349 UNC           0 :             bail("could not open \"%s\" for adding extra config: %s",
    2350                 :                  buf, strerror(errno));
    2351                 :         }
    2352 GIC          82 :         fputs("\n# Configuration added by pg_regress\n\n", pg_conf);
    2353              82 :         fputs("log_autovacuum_min_duration = 0\n", pg_conf);
    2354              82 :         fputs("log_checkpoints = on\n", pg_conf);
    2355 CBC          82 :         fputs("log_line_prefix = '%m %b[%p] %q%a '\n", pg_conf);
    2356 GIC          82 :         fputs("log_lock_waits = on\n", pg_conf);
    2357              82 :         fputs("log_temp_files = 128kB\n", pg_conf);
    2358 CBC          82 :         fputs("max_prepared_transactions = 2\n", pg_conf);
    2359 ECB             : 
    2360 CBC          92 :         for (sl = temp_configs; sl != NULL; sl = sl->next)
    2361                 :         {
    2362 GIC          10 :             char       *temp_config = sl->str;
    2363 ECB             :             FILE       *extra_conf;
    2364                 :             char        line_buf[1024];
    2365                 : 
    2366 CBC          10 :             extra_conf = fopen(temp_config, "r");
    2367 GIC          10 :             if (extra_conf == NULL)
    2368 ECB             :             {
    2369 UNC           0 :                 bail("could not open \"%s\" to read extra config: %s",
    2370                 :                      temp_config, strerror(errno));
    2371 ECB             :             }
    2372 CBC          32 :             while (fgets(line_buf, sizeof(line_buf), extra_conf) != NULL)
    2373 GIC          22 :                 fputs(line_buf, pg_conf);
    2374 GBC          10 :             fclose(extra_conf);
    2375                 :         }
    2376                 : 
    2377 GIC          82 :         fclose(pg_conf);
    2378                 : 
    2379                 : #ifdef ENABLE_SSPI
    2380                 :         if (!use_unix_sockets)
    2381                 :         {
    2382                 :             /*
    2383                 :              * Since we successfully used the same buffer for the much-longer
    2384                 :              * "initdb" command, this can't truncate.
    2385                 :              */
    2386                 :             snprintf(buf, sizeof(buf), "%s/data", temp_instance);
    2387                 :             config_sspi_auth(buf, NULL);
    2388 ECB             :         }
    2389                 : #endif
    2390 EUB             : 
    2391                 :         /*
    2392                 :          * Check if there is a postmaster running already.
    2393 ECB             :          */
    2394 CBC         164 :         snprintf(buf2, sizeof(buf2),
    2395 ECB             :                  "\"%s%spsql\" -X postgres <%s 2>%s",
    2396 CBC          82 :                  bindir ? bindir : "",
    2397              82 :                  bindir ? "/" : "",
    2398 ECB             :                  DEVNULL, DEVNULL);
    2399                 : 
    2400 GIC          82 :         for (i = 0; i < 16; i++)
    2401 ECB             :         {
    2402 GNC          82 :             fflush(NULL);
    2403 GIC          82 :             if (system(buf2) == 0)
    2404 ECB             :             {
    2405                 :                 char        s[16];
    2406                 : 
    2407 UIC           0 :                 if (port_specified_by_user || i == 15)
    2408 ECB             :                 {
    2409 UNC           0 :                     note("port %d apparently in use", port);
    2410 UIC           0 :                     if (!port_specified_by_user)
    2411 UNC           0 :                         note("could not determine an available port");
    2412               0 :                     bail("Specify an unused port using the --port option or shut down any conflicting PostgreSQL servers.");
    2413 ECB             :                 }
    2414                 : 
    2415 UNC           0 :                 note("port %d apparently in use, trying %d", port, port + 1);
    2416 UIC           0 :                 port++;
    2417               0 :                 sprintf(s, "%d", port);
    2418 LBC           0 :                 setenv("PGPORT", s, 1);
    2419                 :             }
    2420                 :             else
    2421 GIC          82 :                 break;
    2422                 :         }
    2423                 : 
    2424                 :         /*
    2425                 :          * Start the temp postmaster
    2426                 :          */
    2427             410 :         snprintf(buf, sizeof(buf),
    2428                 :                  "\"%s%spostgres\" -D \"%s/data\" -F%s "
    2429                 :                  "-c \"listen_addresses=%s\" -k \"%s\" "
    2430                 :                  "> \"%s/log/postmaster.log\" 2>&1",
    2431              82 :                  bindir ? bindir : "",
    2432              82 :                  bindir ? "/" : "",
    2433              82 :                  temp_instance, debug ? " -d 5" : "",
    2434 CBC         164 :                  hostname ? hostname : "", sockdir ? sockdir : "",
    2435                 :                  outputdir);
    2436              82 :         postmaster_pid = spawn_process(buf);
    2437              82 :         if (postmaster_pid == INVALID_PID)
    2438 UNC           0 :             bail("could not spawn postmaster: %s", strerror(errno));
    2439 ECB             : 
    2440                 :         /*
    2441                 :          * Wait till postmaster is able to accept connections; normally this
    2442                 :          * is only a second or so, but Cygwin is reportedly *much* slower, and
    2443 EUB             :          * test builds using Valgrind or similar tools might be too.  Hence,
    2444                 :          * allow the default timeout of 60 seconds to be overridden from the
    2445                 :          * PGCTLTIMEOUT environment variable.
    2446                 :          */
    2447 GBC          82 :         env_wait = getenv("PGCTLTIMEOUT");
    2448              82 :         if (env_wait != NULL)
    2449                 :         {
    2450 UIC           0 :             wait_seconds = atoi(env_wait);
    2451 UBC           0 :             if (wait_seconds <= 0)
    2452               0 :                 wait_seconds = 60;
    2453 EUB             :         }
    2454                 :         else
    2455 GIC          82 :             wait_seconds = 60;
    2456                 : 
    2457 CBC         164 :         for (i = 0; i < wait_seconds; i++)
    2458                 :         {
    2459                 :             /* Done if psql succeeds */
    2460 GNC         164 :             fflush(NULL);
    2461 GIC         164 :             if (system(buf2) == 0)
    2462              82 :                 break;
    2463                 : 
    2464 ECB             :             /*
    2465                 :              * Fail immediately if postmaster has exited
    2466                 :              */
    2467                 : #ifndef WIN32
    2468 CBC          82 :             if (waitpid(postmaster_pid, NULL, WNOHANG) == postmaster_pid)
    2469 ECB             : #else
    2470                 :             if (WaitForSingleObject(postmaster_pid, 0) == WAIT_OBJECT_0)
    2471                 : #endif
    2472                 :             {
    2473 UNC           0 :                 bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason",
    2474                 :                      outputdir);
    2475 EUB             :             }
    2476                 : 
    2477 GIC          82 :             pg_usleep(1000000L);
    2478                 :         }
    2479              82 :         if (i >= wait_seconds)
    2480                 :         {
    2481 UNC           0 :             diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason",
    2482                 :                  wait_seconds, outputdir);
    2483                 : 
    2484 ECB             :             /*
    2485                 :              * If we get here, the postmaster is probably wedged somewhere in
    2486                 :              * startup.  Try to kill it ungracefully rather than leaving a
    2487 EUB             :              * stuck postmaster that might interfere with subsequent test
    2488                 :              * attempts.
    2489                 :              */
    2490                 : #ifndef WIN32
    2491 UNC           0 :             if (kill(postmaster_pid, SIGKILL) != 0 && errno != ESRCH)
    2492               0 :                 bail("could not kill failed postmaster: %s", strerror(errno));
    2493                 : #else
    2494                 :             if (TerminateProcess(postmaster_pid, 255) == 0)
    2495                 :                 bail("could not kill failed postmaster: error code %lu",
    2496                 :                      GetLastError());
    2497 ECB             : #endif
    2498 UNC           0 :             bail("postmaster failed");
    2499                 :         }
    2500                 : 
    2501 GIC          82 :         postmaster_running = true;
    2502 ECB             : 
    2503                 : #ifdef _WIN64
    2504                 : /* need a series of two casts to convert HANDLE without compiler warning */
    2505                 : #define ULONGPID(x) (unsigned long) (unsigned long long) (x)
    2506                 : #else
    2507 EUB             : #define ULONGPID(x) (unsigned long) (x)
    2508                 : #endif
    2509 GNC          82 :         note("using temp instance on port %d with PID %lu",
    2510                 :              port, ULONGPID(postmaster_pid));
    2511 ECB             :     }
    2512                 :     else
    2513                 :     {
    2514                 :         /*
    2515 EUB             :          * Using an existing installation, so may need to get rid of
    2516                 :          * pre-existing database(s) and role(s)
    2517                 :          */
    2518 GIC           2 :         if (!use_existing)
    2519                 :         {
    2520               4 :             for (sl = dblist; sl; sl = sl->next)
    2521               2 :                 drop_database_if_exists(sl->str);
    2522               2 :             for (sl = extraroles; sl; sl = sl->next)
    2523 UIC           0 :                 drop_role_if_exists(sl->str);
    2524                 :         }
    2525 EUB             :     }
    2526                 : 
    2527                 :     /*
    2528                 :      * Create the test database(s) and role(s)
    2529                 :      */
    2530 GIC          84 :     if (!use_existing)
    2531                 :     {
    2532 GBC         169 :         for (sl = dblist; sl; sl = sl->next)
    2533 GIC          85 :             create_database(sl->str);
    2534              86 :         for (sl = extraroles; sl; sl = sl->next)
    2535 CBC           2 :             create_role(sl->str, dblist);
    2536                 :     }
    2537                 : 
    2538                 :     /*
    2539                 :      * Ready to run the tests
    2540                 :      */
    2541              89 :     for (sl = schedulelist; sl != NULL; sl = sl->next)
    2542                 :     {
    2543 GIC           5 :         run_schedule(sl->str, startfunc, postfunc);
    2544                 :     }
    2545                 : 
    2546             378 :     for (sl = extra_tests; sl != NULL; sl = sl->next)
    2547                 :     {
    2548             294 :         run_single_test(sl->str, startfunc, postfunc);
    2549                 :     }
    2550 ECB             : 
    2551                 :     /*
    2552                 :      * Shut down temp installation's postmaster
    2553                 :      */
    2554 CBC          84 :     if (temp_instance)
    2555 EUB             :     {
    2556 GIC          82 :         stop_postmaster();
    2557                 :     }
    2558                 : 
    2559                 :     /*
    2560                 :      * If there were no errors, remove the temp instance immediately to
    2561 ECB             :      * conserve disk space.  (If there were errors, we leave the instance in
    2562                 :      * place for possible manual investigation.)
    2563                 :      */
    2564 GNC          84 :     if (temp_instance && fail_count == 0)
    2565 ECB             :     {
    2566 GIC          82 :         if (!rmtree(temp_instance, true))
    2567 UNC           0 :             diag("could not remove temp instance \"%s\"",
    2568                 :                  temp_instance);
    2569                 :     }
    2570                 : 
    2571                 :     /*
    2572                 :      * Emit a TAP compliant Plan
    2573                 :      */
    2574 GNC          84 :     plan(fail_count + success_count);
    2575                 : 
    2576 ECB             :     /*
    2577                 :      * Emit nice-looking summary message
    2578                 :      */
    2579 GNC          84 :     if (fail_count == 0)
    2580              84 :         note("All %d tests passed.", success_count);
    2581                 :     else
    2582 UNC           0 :         diag("%d of %d tests failed.", fail_count, success_count + fail_count);
    2583                 : 
    2584 GIC          84 :     if (file_size(difffilename) > 0)
    2585 ECB             :     {
    2586 UNC           0 :         diag("The differences that caused some tests to fail can be viewed in the file \"%s\".",
    2587                 :              difffilename);
    2588               0 :         diag("A copy of the test summary that you see above is saved in the file \"%s\".",
    2589                 :              logfilename);
    2590 ECB             :     }
    2591                 :     else
    2592 EUB             :     {
    2593 GIC          84 :         unlink(difffilename);
    2594 GBC          84 :         unlink(logfilename);
    2595                 :     }
    2596                 : 
    2597 GNC          84 :     fclose(logfile);
    2598              84 :     logfile = NULL;
    2599                 : 
    2600 GIC          84 :     if (fail_count != 0)
    2601 UIC           0 :         exit(1);
    2602 ECB             : 
    2603 CBC          84 :     return 0;
    2604                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a