]> granicus.if.org Git - postgresql/blob - src/test/regress/pg_regress.c
Remove hard-wired lists of timezone abbreviations in favor of providing
[postgresql] / src / test / regress / pg_regress.c
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-2006, PostgreSQL Global Development Group
12  * Portions Copyright (c) 1994, Regents of the University of California
13  *
14  * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.15 2006/07/25 03:51:22 tgl Exp $
15  *
16  *-------------------------------------------------------------------------
17  */
18
19 #include "postgres_fe.h"
20
21 #include <ctype.h>
22 #include <sys/stat.h>
23 #include <sys/wait.h>
24 #include <signal.h>
25 #include <unistd.h>
26
27 #include "getopt_long.h"
28 #include "pg_config_paths.h"
29
30 #ifndef WIN32
31 #define PID_TYPE pid_t
32 #define INVALID_PID (-1)
33 #else
34 #define PID_TYPE HANDLE
35 #define INVALID_PID INVALID_HANDLE_VALUE
36 #endif
37
38
39 /* simple list of strings */
40 typedef struct _stringlist
41 {
42         char *str;
43         struct _stringlist *next;
44 } _stringlist;
45
46 /* for resultmap we need a list of pairs of strings */
47 typedef struct _resultmap
48 {
49         char *test;
50         char *resultfile;
51         struct _resultmap *next;
52 } _resultmap;
53
54 /*
55  * Values obtained from pg_config_paths.h and Makefile.  The PG installation
56  * paths are only used in temp_install mode: we use these strings to find
57  * out where "make install" will put stuff under the temp_install directory.
58  * In non-temp_install mode, the only thing we need is the location of psql,
59  * which we expect to find in psqldir, or in the PATH if psqldir isn't given.
60  */
61 static char *bindir = PGBINDIR;
62 static char *libdir = LIBDIR;
63 static char *datadir = PGSHAREDIR;
64 static char *host_platform = HOST_TUPLE;
65 static char *makeprog = MAKEPROG;
66 #ifndef WIN32                                   /* not used in WIN32 case */
67 static char *shellprog = SHELLPROG;
68 #endif
69
70 /* currently we can use the same diff switches on all platforms */
71 static const char *basic_diff_opts = "-w";
72 static const char *pretty_diff_opts = "-w -C3";
73
74 /* options settable from command line */
75 static char *dbname = "regression";
76 static bool debug = false;
77 static char *inputdir = ".";
78 static char *outputdir = ".";
79 static _stringlist *loadlanguage = NULL;
80 static int max_connections = 0;
81 static char *encoding = NULL;
82 static _stringlist *schedulelist = NULL;
83 static _stringlist *extra_tests = NULL;
84 static char *temp_install = NULL;
85 static char *top_builddir = NULL;
86 static int temp_port = 65432;
87 static bool nolocale = false;
88 static char *psqldir = NULL;
89 static char *hostname = NULL;
90 static int port = -1;
91 static char *user = NULL;
92
93 /* internal variables */
94 static const char *progname;
95 static char *logfilename;
96 static FILE *logfile;
97 static char *difffilename;
98
99 static _resultmap *resultmap = NULL;
100
101 static PID_TYPE postmaster_pid = INVALID_PID;
102 static bool postmaster_running = false;
103
104 static int success_count = 0;
105 static int fail_count = 0;
106 static int fail_ignore_count = 0;
107
108 static void
109 header(const char *fmt,...)
110 /* This extension allows gcc to check the format string for consistency with
111    the supplied arguments. */
112 __attribute__((format(printf, 1, 2)));
113 static void
114 status(const char *fmt,...)
115 /* This extension allows gcc to check the format string for consistency with
116    the supplied arguments. */
117 __attribute__((format(printf, 1, 2)));
118 static void
119 psql_command(const char *database, const char *query, ...)
120 /* This extension allows gcc to check the format string for consistency with
121    the supplied arguments. */
122 __attribute__((format(printf, 2, 3)));
123
124
125 /*
126  * Add an item at the end of a stringlist.
127  */
128 static void
129 add_stringlist_item(_stringlist **listhead, const char *str)
130 {
131         _stringlist *newentry = malloc(sizeof(_stringlist));
132         _stringlist *oldentry;
133
134         newentry->str = strdup(str);
135         newentry->next = NULL;
136         if (*listhead == NULL)
137                 *listhead = newentry;
138         else
139         {
140                 for (oldentry = *listhead; oldentry->next; oldentry = oldentry->next)
141                         /*skip*/;
142                 oldentry->next = newentry;
143         }
144 }
145
146 /*
147  * Print a progress banner on stdout.
148  */
149 static void
150 header(const char *fmt,...)
151 {
152         char            tmp[64];
153         va_list         ap;
154
155         va_start(ap, fmt);
156         vsnprintf(tmp, sizeof(tmp), fmt, ap);
157         va_end(ap);
158
159         fprintf(stdout, "============== %-38s ==============\n", tmp);
160         fflush(stdout);
161 }
162
163 /*
164  * Print "doing something ..." --- supplied text should not end with newline
165  */
166 static void
167 status(const char *fmt,...)
168 {
169         va_list         ap;
170
171         va_start(ap, fmt);
172         vfprintf(stdout, fmt, ap);
173         fflush(stdout);
174         va_end(ap);
175
176         if (logfile)
177         {
178                 va_start(ap, fmt);
179                 vfprintf(logfile, fmt, ap);
180                 va_end(ap);
181         }
182 }
183
184 /*
185  * Done "doing something ..."
186  */
187 static void
188 status_end(void)
189 {
190         fprintf(stdout, "\n");
191         fflush(stdout);
192         if (logfile)
193                 fprintf(logfile, "\n");
194 }
195
196 /*
197  * shut down temp postmaster
198  */
199 static void
200 stop_postmaster(void)
201 {
202         if (postmaster_running)
203         {
204                 /* We use pg_ctl to issue the kill and wait for stop */
205                 char buf[MAXPGPATH * 2];
206
207                 /* On Windows, system() seems not to force fflush, so... */
208                 fflush(stdout);
209                 fflush(stderr);
210
211                 snprintf(buf, sizeof(buf),
212                                  SYSTEMQUOTE "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast" SYSTEMQUOTE,
213                                  bindir, temp_install);
214                 system(buf);                    /* ignore exit status */
215                 postmaster_running = false;
216         }
217 }
218
219 /*
220  * Always exit through here, not through plain exit(), to ensure we make
221  * an effort to shut down a temp postmaster
222  */
223 static void
224 exit_nicely(int code)
225 {
226         stop_postmaster();
227         exit(code);
228 }
229
230 /*
231  * Check whether string matches pattern
232  *
233  * In the original shell script, this function was implemented using expr(1),
234  * which provides basic regular expressions restricted to match starting at
235  * the string start (in conventional regex terms, there's an implicit "^"
236  * at the start of the pattern --- but no implicit "$" at the end).
237  *
238  * For now, we only support "." and ".*" as non-literal metacharacters,
239  * because that's all that anyone has found use for in resultmap.  This
240  * code could be extended if more functionality is needed.
241  */
242 static bool
243 string_matches_pattern(const char *str, const char *pattern)
244 {
245         while (*str && *pattern)
246         {
247                 if (*pattern == '.' && pattern[1] == '*')
248                 {
249                         pattern += 2;
250                         /* Trailing .* matches everything. */
251                         if (*pattern == '\0')
252                                 return true;
253
254                         /*
255                          * Otherwise, scan for a text position at which we can match the
256                          * rest of the pattern.
257                          */
258                         while (*str)
259                         {
260                                 /*
261                                  * Optimization to prevent most recursion: don't recurse
262                                  * unless first pattern char might match this text char.
263                                  */
264                                 if (*str == *pattern || *pattern == '.')
265                                 {
266                                         if (string_matches_pattern(str, pattern))
267                                                 return true;
268                                 }
269
270                                 str++;
271                         }
272
273                         /*
274                          * End of text with no match.
275                          */
276                         return false;
277                 }
278                 else if (*pattern != '.' && *str != *pattern)
279                 {
280                         /*
281                          * Not the single-character wildcard and no explicit match? Then
282                          * time to quit...
283                          */
284                         return false;
285                 }
286
287                 str++;
288                 pattern++;
289         }
290
291         if (*pattern == '\0')
292                 return true;                    /* end of pattern, so declare match */
293
294         /* End of input string.  Do we have matching pattern remaining? */
295         while (*pattern == '.' && pattern[1] == '*')
296                 pattern += 2;
297         if (*pattern == '\0')
298                 return true;                    /* end of pattern, so declare match */
299
300         return false;
301 }
302
303 /*
304  * Scan resultmap file to find which platform-specific expected files to use.
305  *
306  * The format of each line of the file is
307  *         testname/hostplatformpattern=substitutefile
308  * where the hostplatformpattern is evaluated per the rules of expr(1),
309  * namely, it is a standard regular expression with an implicit ^ at the start.
310  * (We currently support only a very limited subset of regular expressions,
311  * see string_matches_pattern() above.)  What hostplatformpattern will be
312  * matched against is the config.guess output.  (In the shell-script version,
313  * we also provided an indication of whether gcc or another compiler was in
314  * use, but that facility isn't used anymore.)
315  */
316 static void
317 load_resultmap(void)
318 {
319         char buf[MAXPGPATH];
320         FILE *f;
321
322         /* scan the file ... */
323         snprintf(buf, sizeof(buf), "%s/resultmap", inputdir);
324         f = fopen(buf,"r");
325         if (!f)
326         {
327                 /* OK if it doesn't exist, else complain */
328                 if (errno == ENOENT)
329                         return;
330                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
331                                 progname, buf, strerror(errno));
332                 exit_nicely(2);
333         }
334
335         while (fgets(buf, sizeof(buf), f))
336         {
337                 char *platform;
338                 char *expected;
339                 int i;
340
341                 /* strip trailing whitespace, especially the newline */
342                 i = strlen(buf);
343                 while (i > 0 && isspace((unsigned char) buf[i-1]))
344                         buf[--i] = '\0';
345
346                 /* parse out the line fields */
347                 platform = strchr(buf, '/');
348                 if (!platform)
349                 {
350                         fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
351                                         buf);
352                         exit_nicely(2);
353                 }
354                 *platform++ = '\0';
355                 expected = strchr(platform, '=');
356                 if (!expected)
357                 {
358                         fprintf(stderr, _("incorrectly formatted resultmap entry: %s\n"),
359                                         buf);
360                         exit_nicely(2);
361                 }
362                 *expected++ = '\0';
363
364                 /*
365                  * if it's for current platform, save it in resultmap list.
366                  * Note: by adding at the front of the list, we ensure that in
367                  * ambiguous cases, the last match in the resultmap file is used.
368                  * This mimics the behavior of the old shell script.
369                  */
370                 if (string_matches_pattern(host_platform, platform))
371                 {
372                         _resultmap *entry = malloc(sizeof(_resultmap));
373
374                         entry->test = strdup(buf);
375                         entry->resultfile = strdup(expected);
376                         entry->next = resultmap;
377                         resultmap = entry;
378                 }
379         }
380         fclose(f);
381 }
382
383 /*
384  * Handy subroutine for setting an environment variable "var" to "val"
385  */
386 static void
387 doputenv(const char *var, const char *val)
388 {
389         char *s = malloc(strlen(var)+strlen(val)+2);
390
391         sprintf(s, "%s=%s", var, val);
392         putenv(s);
393 }
394
395 /*
396  * Set the environment variable "pathname", prepending "addval" to its
397  * old value (if any).
398  */
399 static void
400 add_to_path(const char *pathname, char separator, const char *addval)
401 {
402         char *oldval = getenv(pathname);
403         char *newval;
404
405         if (!oldval || !oldval[0])
406         {
407                 /* no previous value */
408                 newval = malloc(strlen(pathname) + strlen(addval) + 2);
409                 sprintf(newval, "%s=%s", pathname, addval);
410         }
411         else
412         {
413                 newval = malloc(strlen(pathname) + strlen(addval) + strlen(oldval) + 3);
414                 sprintf(newval,"%s=%s%c%s",pathname,addval,separator,oldval);
415         }
416         putenv(newval);
417 }
418
419 /*
420  * Prepare environment variables for running regression tests
421  */
422 static void
423 initialize_environment(void)
424 {
425         char *tmp;
426
427         /*
428          * Clear out any non-C locale settings
429          */
430         unsetenv("LC_COLLATE");
431         unsetenv("LC_CTYPE");
432         unsetenv("LC_MONETARY");
433         unsetenv("LC_MESSAGES");
434         unsetenv("LC_NUMERIC");
435         unsetenv("LC_TIME");
436         unsetenv("LC_ALL");
437         unsetenv("LANG");
438         unsetenv("LANGUAGE");
439         /* On Windows the default locale may not be English, so force it */
440 #if defined(WIN32) || defined(__CYGWIN__)
441         putenv("LANG=en");
442 #endif
443
444         /*
445          * Set multibyte as requested
446          */
447         if (encoding)
448                 doputenv("PGCLIENTENCODING", encoding);
449         else
450                 unsetenv("PGCLIENTENCODING");
451
452         /*
453          * Set timezone and datestyle for datetime-related tests
454          */
455         putenv("PGTZ=PST8PDT");
456         putenv("PGDATESTYLE=Postgres, MDY");
457
458         if (temp_install)
459         {
460                 /*
461                  * Clear out any environment vars that might cause psql to connect
462                  * to the wrong postmaster, or otherwise behave in nondefault ways.
463                  * (Note we also use psql's -X switch consistently, so that ~/.psqlrc
464                  * files won't mess things up.)  Also, set PGPORT to the temp port,
465                  * and set or unset PGHOST depending on whether we are using TCP or
466                  * Unix sockets.
467                  */
468                 unsetenv("PGDATABASE");
469                 unsetenv("PGUSER");
470                 unsetenv("PGSERVICE");
471                 unsetenv("PGSSLMODE");
472                 unsetenv("PGREQUIRESSL");
473                 unsetenv("PGCONNECT_TIMEOUT");
474                 unsetenv("PGDATA");
475                 if (hostname != NULL)
476                         doputenv("PGHOST", hostname);
477                 else
478                         unsetenv("PGHOST");
479                 unsetenv("PGHOSTADDR");
480                 if (port != -1)
481                 {
482                         char s[16];
483
484                         sprintf(s,"%d",port);
485                         doputenv("PGPORT",s);
486                 }
487
488                 /*
489                  * Adjust path variables to point into the temp-install tree
490                  */
491                 tmp = malloc(strlen(temp_install) + 32 + strlen(bindir));
492                 sprintf(tmp, "%s/install/%s", temp_install, bindir);
493                 bindir = tmp;
494
495                 tmp = malloc(strlen(temp_install) + 32 + strlen(libdir));
496                 sprintf(tmp, "%s/install/%s", temp_install, libdir);
497                 libdir = tmp;
498
499                 tmp = malloc(strlen(temp_install) + 32 + strlen(datadir));
500                 sprintf(tmp, "%s/install/%s", temp_install, datadir);
501                 datadir = tmp;
502
503                 /* psql will be installed into temp-install bindir */
504                 psqldir = bindir;
505
506                 /*
507                  * Set up shared library paths to include the temp install.
508                  *
509                  * LD_LIBRARY_PATH covers many platforms.  DYLD_LIBRARY_PATH works on
510                  * Darwin, and maybe other Mach-based systems.  Windows needs shared
511                  * libraries in PATH.  (Only those linked into executables, not
512                  * dlopen'ed ones)  Feel free to account for others as well.
513                  */
514                 add_to_path("LD_LIBRARY_PATH", ':', libdir);
515                 add_to_path("DYLD_LIBRARY_PATH", ':', libdir);
516 #if defined(WIN32) || defined(__CYGWIN__)
517                 add_to_path("PATH", ';', libdir);
518 #endif
519         }
520         else
521         {
522                 const char *pghost;
523                 const char *pgport;
524
525                 /*
526                  * When testing an existing install, we honor existing environment
527                  * variables, except if they're overridden by command line options.
528                  */
529                 if (hostname != NULL)
530                 {
531                         doputenv("PGHOST", hostname);
532                         unsetenv("PGHOSTADDR");
533                 }
534                 if (port != -1)
535                 {
536                         char s[16];
537
538                         sprintf(s,"%d",port);
539                         doputenv("PGPORT",s);
540                 }
541                 if (user != NULL)
542                         doputenv("PGUSER", user);
543
544                 /*
545                  * Report what we're connecting to
546                  */
547                 pghost = getenv("PGHOST");
548                 pgport = getenv("PGPORT");
549 #ifndef HAVE_UNIX_SOCKETS
550                 if (!pghost)
551                         pghost = "localhost";
552 #endif
553
554                 if (pghost && pgport)
555                         printf(_("(using postmaster on %s, port %s)\n"), pghost, pgport);
556                 if (pghost && !pgport)
557                         printf(_("(using postmaster on %s, default port)\n"), pghost);
558                 if (!pghost && pgport)
559                         printf(_("(using postmaster on Unix socket, port %s)\n"), pgport);
560                 if (!pghost && !pgport)
561                         printf(_("(using postmaster on Unix socket, default port)\n"));
562         }
563
564         load_resultmap();
565 }
566
567 /*
568  * Issue a command via psql, connecting to the specified database
569  *
570  * Since we use system(), this doesn't return until the operation finishes
571  */
572 static void
573 psql_command(const char *database, const char *query, ...)
574 {
575         char query_formatted[1024];
576         char query_escaped[2048];
577         char psql_cmd[MAXPGPATH + 2048];
578         va_list args;
579         char *s;
580         char *d;
581
582         /* Generate the query with insertion of sprintf arguments */
583         va_start(args, query);
584         vsnprintf(query_formatted, sizeof(query_formatted), query, args);
585         va_end(args);
586
587         /* Now escape any shell double-quote metacharacters */
588         d = query_escaped;
589         for (s = query_formatted; *s; s++)
590         {
591                 if (strchr("\\\"$`", *s))
592                         *d++ = '\\';
593                 *d++ = *s;
594         }
595         *d = '\0';
596
597         /* And now we can build and execute the shell command */
598         snprintf(psql_cmd, sizeof(psql_cmd),
599                          SYSTEMQUOTE "\"%s%spsql\" -X -c \"%s\" \"%s\"" SYSTEMQUOTE,
600                          psqldir ? psqldir : "",
601                          psqldir ? "/" : "",
602                          query_escaped,
603                          database);
604
605         if (system(psql_cmd) != 0)
606         {
607                 /* psql probably already reported the error */
608                 fprintf(stderr, _("command failed: %s\n"), psql_cmd);
609                 exit_nicely(2);
610         }
611 }
612
613 /*
614  * Spawn a process to execute the given shell command; don't wait for it
615  *
616  * Returns the process ID so we can wait for it later
617  */
618 static PID_TYPE
619 spawn_process(const char *cmdline)
620 {
621 #ifndef WIN32
622         pid_t pid;
623
624         /*
625          * Must flush I/O buffers before fork.  Ideally we'd use fflush(NULL) here
626          * ... does anyone still care about systems where that doesn't work?
627          */
628         fflush(stdout);
629         fflush(stderr);
630         if (logfile)
631                 fflush(logfile);
632
633         pid = fork();
634         if (pid == -1)
635         {
636                 fprintf(stderr, _("%s: could not fork: %s\n"),
637                                 progname, strerror(errno));
638                 exit_nicely(2);
639         }
640         if (pid == 0)
641         {
642                 /*
643                  * In child
644                  *
645                  * Instead of using system(), exec the shell directly, and tell it
646                  * to "exec" the command too.  This saves two useless processes
647                  * per parallel test case.
648                  */
649                 char *cmdline2 = malloc(strlen(cmdline) + 6);
650
651                 sprintf(cmdline2, "exec %s", cmdline);
652                 execl(shellprog, shellprog, "-c", cmdline2, NULL);
653                 fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
654                                 progname, shellprog, strerror(errno));
655                 exit(1);                                /* not exit_nicely here... */
656         }
657         /* in parent */
658         return pid;
659 #else
660         char *cmdline2;
661         STARTUPINFO si;
662         PROCESS_INFORMATION pi;
663
664         ZeroMemory(&si, sizeof(si));
665         si.cb = sizeof(si);
666
667         cmdline2 = malloc(strlen(cmdline) + 8);
668         sprintf(cmdline2, "cmd /c %s", cmdline);
669
670         if (!CreateProcess(NULL, cmdline2, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
671         {
672                 fprintf(stderr, _("could not start process for \"%s\": %lu\n"),
673                                 cmdline2, GetLastError());
674                 exit_nicely(2);
675         }
676         free(cmdline2);
677
678         CloseHandle(pi.hThread);
679         return pi.hProcess;
680 #endif
681 }
682
683 /*
684  * start a psql test process for specified file (including redirection),
685  * and return process ID
686  */
687 static PID_TYPE
688 psql_start_test(const char *testname)
689 {
690         PID_TYPE pid;
691         char infile[MAXPGPATH];
692         char outfile[MAXPGPATH];
693         char psql_cmd[MAXPGPATH * 3];
694
695         snprintf(infile, sizeof(infile), "%s/sql/%s.sql",
696                          inputdir, testname);
697         snprintf(outfile, sizeof(outfile), "%s/results/%s.out",
698                          outputdir, testname);
699
700         snprintf(psql_cmd, sizeof(psql_cmd),
701                          SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
702                          psqldir ? psqldir : "",
703                          psqldir ? "/" : "",
704                          dbname,
705                          infile,
706                          outfile);
707
708         pid = spawn_process(psql_cmd);
709
710         if (pid == INVALID_PID)
711         {
712                 fprintf(stderr, _("could not start process for test %s\n"),
713                                 testname);
714                 exit_nicely(2);
715         }
716
717         return pid;
718 }
719
720 /*
721  * Count bytes in file
722  */
723 static long
724 file_size(const char *file)
725 {
726         long r;
727         FILE *f = fopen(file,"r");
728
729         if (!f)
730         {
731                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
732                                 progname, file, strerror(errno));
733                 return -1;
734         }
735         fseek(f, 0, SEEK_END);
736         r = ftell(f);
737         fclose(f);
738         return r;
739 }
740
741 /*
742  * Count lines in file
743  */
744 static int
745 file_line_count(const char *file)
746 {
747         int c;
748         int l = 0;
749         FILE *f = fopen(file,"r");
750
751         if (!f)
752         {
753                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
754                                 progname, file, strerror(errno));
755                 return -1;
756         }
757         while ((c = fgetc(f)) != EOF)
758         {
759                 if (c == '\n')
760                         l++;
761         }
762         fclose(f);
763         return l;
764 }
765
766 static bool
767 file_exists(const char *file)
768 {
769         FILE *f = fopen(file, "r");
770
771         if (!f)
772                 return false;
773         fclose(f);
774         return true;
775 }
776
777 static bool
778 directory_exists(const char *dir)
779 {
780         struct stat st;
781
782         if (stat(dir, &st) != 0)
783                 return false;
784         if (st.st_mode & S_IFDIR)
785                 return true;
786         return false;
787 }
788
789 /* Create a directory */
790 static void
791 make_directory(const char *dir)
792 {
793         if (mkdir(dir, S_IRWXU) < 0)
794         {
795                 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
796                                 progname, dir, strerror(errno));
797                 exit_nicely(2);
798         }
799 }
800
801 /*
802  * Run a "diff" command and check that it didn't crash
803  */
804 static void
805 run_diff(const char *cmd)
806 {
807         int r;
808
809         r = system(cmd);
810         /*
811          * XXX FIXME: it appears that include/port/win32.h's definitions of
812          * WIFEXITED and related macros may be wrong.  They certainly don't
813          * work for inspecting the results of system().  For the moment,
814          * hard-wire the check on Windows.
815          */
816 #ifndef WIN32
817         if (!WIFEXITED(r) || WEXITSTATUS(r) > 1)
818 #else
819         if (r != 0 && r != 1)
820 #endif
821         {
822                 fprintf(stderr, _("diff command failed with status %d: %s\n"), r, cmd);
823                 exit_nicely(2);
824         }
825 }
826
827 /*
828  * Check the actual result file for the given test against expected results
829  *
830  * Returns true if different (failure), false if correct match found.
831  * In the true case, the diff is appended to the diffs file.
832  */
833 static bool
834 results_differ(const char *testname)
835 {
836         const char *expectname;
837         char resultsfile[MAXPGPATH];
838         char expectfile[MAXPGPATH];
839         char diff[MAXPGPATH];
840         char cmd[MAXPGPATH * 3];
841         char best_expect_file[MAXPGPATH];
842         _resultmap *rm;
843         FILE *difffile;
844         int best_line_count;
845         int i;
846         int l;
847
848         /* Check in resultmap if we should be looking at a different file */
849         expectname = testname;
850         for (rm = resultmap; rm != NULL; rm = rm->next)
851         {
852                 if (strcmp(testname, rm->test) == 0)
853                 {
854                         expectname = rm->resultfile;
855                         break;
856                 }
857         }
858
859         /* Name of test results file */
860         snprintf(resultsfile, sizeof(resultsfile), "%s/results/%s.out",
861                          outputdir, testname);
862
863         /* Name of expected-results file */
864         snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
865                          inputdir, expectname);
866
867         /* Name to use for temporary diff file */
868         snprintf(diff, sizeof(diff), "%s/results/%s.diff",
869                          outputdir, testname);
870
871         /* OK, run the diff */
872         snprintf(cmd, sizeof(cmd),
873                          SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
874                          basic_diff_opts, expectfile, resultsfile, diff);
875         run_diff(cmd);
876
877         /* Is the diff file empty? */
878         if (file_size(diff) == 0)
879         {
880                 /* No diff = no changes = good */
881                 unlink(diff);
882                 return false;
883         }
884
885         /* There may be secondary comparison files that match better */
886         best_line_count = file_line_count(diff);
887         strcpy(best_expect_file, expectfile);
888
889         for (i = 0; i <= 9; i++)
890         {
891                 snprintf(expectfile, sizeof(expectfile), "%s/expected/%s_%d.out",
892                                  inputdir, expectname, i);
893                 if (!file_exists(expectfile))
894                         continue;
895
896                 snprintf(cmd, sizeof(cmd),
897                                  SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
898                                  basic_diff_opts, expectfile, resultsfile, diff);
899                 run_diff(cmd);
900
901                 if (file_size(diff) == 0)
902                 {
903                         /* No diff = no changes = good */
904                         unlink(diff);
905                         return false;
906                 }
907
908                 l = file_line_count(diff);
909                 if (l < best_line_count)
910                 {
911                         /* This diff was a better match than the last one */
912                         best_line_count = l;
913                         strcpy(best_expect_file, expectfile);
914                 }
915         }
916
917         /*
918          * Use the best comparison file to generate the "pretty" diff, which
919          * we append to the diffs summary file.
920          */
921         snprintf(cmd, sizeof(cmd),
922                          SYSTEMQUOTE "diff %s \"%s\" \"%s\" >> \"%s\"" SYSTEMQUOTE,
923                          pretty_diff_opts, best_expect_file, resultsfile, difffilename);
924         run_diff(cmd);
925
926         /* And append a separator */
927         difffile = fopen(difffilename, "a");
928         if (difffile)
929         {
930                 fprintf(difffile,
931                                 "\n======================================================================\n\n");
932                 fclose(difffile);
933         }
934
935         unlink(diff);
936         return true;
937 }
938
939 /*
940  * Wait for specified subprocesses to finish
941  *
942  * If names isn't NULL, report each subprocess as it finishes
943  *
944  * Note: it's OK to scribble on the pids array, but not on the names array
945  */
946 static void
947 wait_for_tests(PID_TYPE *pids, char **names, int num_tests)
948 {
949         int tests_left;
950         int i;
951
952 #ifdef WIN32
953         PID_TYPE *active_pids = malloc(num_tests * sizeof(PID_TYPE));
954
955         memcpy(active_pids, pids, num_tests * sizeof(PID_TYPE));
956 #endif
957
958         tests_left = num_tests;
959         while (tests_left > 0)
960         {
961                 PID_TYPE p;
962
963 #ifndef WIN32
964                 p = wait(NULL);
965
966                 if (p == INVALID_PID)
967                 {
968                         fprintf(stderr, _("failed to wait for subprocesses: %s\n"),
969                                         strerror(errno));
970                         exit_nicely(2);
971                 }
972 #else
973                 int r;
974
975                 r = WaitForMultipleObjects(tests_left, active_pids, FALSE, INFINITE);
976                 if (r < WAIT_OBJECT_0 || r >= WAIT_OBJECT_0 + tests_left)
977                 {
978                         fprintf(stderr, _("failed to wait for subprocesses: %lu\n"),
979                                         GetLastError());
980                         exit_nicely(2);
981                 }
982                 p = active_pids[r - WAIT_OBJECT_0];
983                 /* compact the active_pids array */
984                 active_pids[r - WAIT_OBJECT_0] = active_pids[tests_left - 1];
985 #endif /* WIN32 */
986
987                 for (i=0; i < num_tests; i++)
988                 {
989                         if (p == pids[i])
990                         {
991 #ifdef WIN32
992                                 CloseHandle(pids[i]);
993 #endif
994                                 pids[i] = INVALID_PID;
995                                 if (names)
996                                         status(" %s", names[i]);
997                                 tests_left--;
998                                 break;
999                         }
1000                 }
1001         }
1002
1003 #ifdef WIN32
1004         free(active_pids);
1005 #endif
1006 }
1007
1008 /*
1009  * Run all the tests specified in one schedule file
1010  */
1011 static void
1012 run_schedule(const char *schedule)
1013 {
1014 #define MAX_PARALLEL_TESTS 100
1015         char *tests[MAX_PARALLEL_TESTS];
1016         PID_TYPE pids[MAX_PARALLEL_TESTS];
1017         _stringlist *ignorelist = NULL;
1018         char scbuf[1024];
1019         FILE *scf;
1020         int line_num = 0;
1021
1022         scf = fopen(schedule, "r");
1023         if (!scf)
1024         {
1025                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1026                                 progname, schedule, strerror(errno));
1027                 exit_nicely(2);
1028         }
1029
1030         while (fgets(scbuf, sizeof(scbuf), scf))
1031         {
1032                 char *test = NULL;
1033                 char *c;
1034                 int num_tests;
1035                 bool inword;
1036                 int i;
1037
1038                 line_num++;
1039
1040                 /* strip trailing whitespace, especially the newline */
1041                 i = strlen(scbuf);
1042                 while (i > 0 && isspace((unsigned char) scbuf[i-1]))
1043                         scbuf[--i] = '\0';
1044
1045                 if (scbuf[0] == '\0' || scbuf[0] == '#')
1046                         continue;
1047                 if (strncmp(scbuf, "test: ", 6) == 0)
1048                         test = scbuf + 6;
1049                 else if (strncmp(scbuf, "ignore: ", 8) == 0)
1050                 {
1051                         c = scbuf + 8;
1052                         while (*c && isspace((unsigned char) *c))
1053                                 c++;
1054                         add_stringlist_item(&ignorelist, c);
1055                         /*
1056                          * Note: ignore: lines do not run the test, they just say that
1057                          * failure of this test when run later on is to be ignored.
1058                          * A bit odd but that's how the shell-script version did it.
1059                          */
1060                         continue;
1061                 }
1062                 else
1063                 {
1064                         fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1065                                         schedule, line_num, scbuf);
1066                         exit_nicely(2);
1067                 }
1068
1069                 num_tests = 0;
1070                 inword = false;
1071                 for (c = test; *c; c++)
1072                 {
1073                         if (isspace((unsigned char) *c))
1074                         {
1075                                 *c = '\0';
1076                                 inword = false;
1077                         }
1078                         else if (!inword)
1079                         {
1080                                 if (num_tests >= MAX_PARALLEL_TESTS)
1081                                 {
1082                                         /* can't print scbuf here, it's already been trashed */
1083                                         fprintf(stderr, _("too many parallel tests in schedule file \"%s\", line %d\n"),
1084                                                         schedule, line_num);
1085                                         exit_nicely(2);
1086                                 }
1087                                 tests[num_tests] = c;
1088                                 num_tests++;
1089                                 inword = true;
1090                         }
1091                 }
1092
1093                 if (num_tests == 0)
1094                 {
1095                         fprintf(stderr, _("syntax error in schedule file \"%s\" line %d: %s\n"),
1096                                         schedule, line_num, scbuf);
1097                         exit_nicely(2);
1098                 }
1099
1100                 if (num_tests == 1)
1101                 {
1102                         status(_("test %-20s ... "), tests[0]);
1103                         pids[0] = psql_start_test(tests[0]);
1104                         wait_for_tests(pids, NULL, 1);
1105                         /* status line is finished below */
1106                 }
1107                 else if (max_connections > 0 && max_connections < num_tests)
1108                 {
1109                         int oldest = 0;
1110
1111                         status(_("parallel group (%d tests, in groups of %d): "),
1112                                    num_tests, max_connections);
1113                         for (i = 0; i < num_tests; i++)
1114                         {
1115                                 if (i - oldest >= max_connections)
1116                                 {
1117                                         wait_for_tests(pids + oldest, tests + oldest, i - oldest);
1118                                         oldest = i;
1119                                 }
1120                                 pids[i] = psql_start_test(tests[i]);
1121                         }
1122                         wait_for_tests(pids + oldest, tests + oldest, i - oldest);
1123                         status_end();
1124                 }
1125                 else
1126                 {
1127                         status(_("parallel group (%d tests): "), num_tests);
1128                         for (i = 0; i < num_tests; i++)
1129                         {
1130                                 pids[i] = psql_start_test(tests[i]);
1131                         }
1132                         wait_for_tests(pids, tests, num_tests);
1133                         status_end();
1134                 }
1135
1136                 /* Check results for all tests */
1137                 for (i = 0; i < num_tests; i++)
1138                 {
1139                         if (num_tests > 1)
1140                                 status(_("     %-20s ... "), tests[i]);
1141
1142                         if (results_differ(tests[i]))
1143                         {
1144                                 bool ignore = false;
1145                                 _stringlist *sl;
1146
1147                                 for (sl = ignorelist; sl != NULL; sl = sl->next)
1148                                 {
1149                                         if (strcmp(tests[i], sl->str) == 0)
1150                                         {
1151                                                 ignore = true;
1152                                                 break;
1153                                         }
1154                                 }
1155                                 if (ignore)
1156                                 {
1157                                         status(_("failed (ignored)"));
1158                                         fail_ignore_count++;
1159                                 }
1160                                 else
1161                                 {
1162                                         status(_("FAILED"));
1163                                         fail_count++;
1164                                 }
1165                         }
1166                         else
1167                         {
1168                                 status(_("ok"));
1169                                 success_count++;
1170                         }
1171
1172                         status_end();
1173                 }
1174         }
1175
1176         fclose(scf);
1177 }
1178
1179 /*
1180  * Run a single test
1181  */
1182 static void
1183 run_single_test(const char *test)
1184 {
1185         PID_TYPE pid;
1186
1187         status(_("test %-20s ... "), test);
1188         pid = psql_start_test(test);
1189         wait_for_tests(&pid, NULL, 1);
1190
1191         if (results_differ(test))
1192         {
1193                 status(_("FAILED"));
1194                 fail_count++;
1195         }
1196         else
1197         {
1198                 status(_("ok"));
1199                 success_count++;
1200         }
1201         status_end();
1202 }
1203
1204 /*
1205  * Create the summary-output files (making them empty if already existing)
1206  */
1207 static void
1208 open_result_files(void)
1209 {
1210         char file[MAXPGPATH];
1211         FILE *difffile;
1212
1213         /* create the log file (copy of running status output) */
1214         snprintf(file, sizeof(file), "%s/regression.out", outputdir);
1215         logfilename = strdup(file);
1216         logfile = fopen(logfilename, "w");
1217         if (!logfile)
1218         {
1219                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1220                                 progname, logfilename, strerror(errno));
1221                 exit_nicely(2);
1222         }
1223
1224         /* create the diffs file as empty */
1225         snprintf(file, sizeof(file), "%s/regression.diffs", outputdir);
1226         difffilename = strdup(file);
1227         difffile = fopen(difffilename, "w");
1228         if (!difffile)
1229         {
1230                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1231                                 progname, difffilename, strerror(errno));
1232                 exit_nicely(2);
1233         }
1234         /* we don't keep the diffs file open continuously */
1235         fclose(difffile);
1236
1237         /* also create the output directory if not present */
1238         snprintf(file, sizeof(file), "%s/results", outputdir);
1239         if (!directory_exists(file))
1240                 make_directory(file);
1241 }
1242
1243 static void
1244 help(void)
1245 {
1246         printf(_("PostgreSQL regression test driver\n"));
1247         printf(_("\n"));
1248         printf(_("Usage: %s [options...] [extra tests...]\n"), progname);
1249         printf(_("\n"));
1250         printf(_("Options:\n"));
1251         printf(_("  --dbname=DB               use database DB (default \"regression\")\n"));
1252         printf(_("  --debug                   turn on debug mode in programs that are run\n"));
1253         printf(_("  --inputdir=DIR            take input files from DIR (default \".\")\n"));
1254         printf(_("  --load-language=lang      load the named language before running the\n"));
1255         printf(_("                            tests; can appear multiple times\n"));
1256         printf(_("  --max-connections=N       maximum number of concurrent connections\n"));
1257         printf(_("                            (default is 0 meaning unlimited)\n"));
1258         printf(_("  --multibyte=ENCODING      use ENCODING as the multibyte encoding\n"));
1259         printf(_("  --outputdir=DIR           place output files in DIR (default \".\")\n"));
1260         printf(_("  --schedule=FILE           use test ordering schedule from FILE\n"));
1261         printf(_("                            (may be used multiple times to concatenate)\n"));
1262         printf(_("  --temp-install=DIR        create a temporary installation in DIR\n"));
1263         printf(_("  --no-locale               use C locale\n"));
1264         printf(_("\n"));
1265         printf(_("Options for \"temp-install\" mode:\n"));
1266         printf(_("  --top-builddir=DIR        (relative) path to top level build directory\n"));
1267         printf(_("  --temp-port=PORT          port number to start temp postmaster on\n"));
1268         printf(_("\n"));
1269         printf(_("Options for using an existing installation:\n"));
1270         printf(_("  --host=HOST               use postmaster running on HOST\n"));
1271         printf(_("  --port=PORT               use postmaster running at PORT\n"));
1272         printf(_("  --user=USER               connect as USER\n"));
1273         printf(_("  --psqldir=DIR             use psql in DIR (default: find in PATH)\n"));
1274         printf(_("\n"));
1275         printf(_("The exit status is 0 if all tests passed, 1 if some tests failed, and 2\n"));
1276         printf(_("if the tests could not be run for some reason.\n"));
1277         printf(_("\n"));
1278         printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
1279 }
1280
1281 int
1282 main(int argc, char *argv[])
1283 {
1284         _stringlist *sl;
1285         int c;
1286         int i;
1287         int option_index;
1288         char buf[MAXPGPATH * 4];
1289
1290         static struct option long_options[] = {
1291                 {"help", no_argument, NULL, 'h'},
1292                 {"version", no_argument, NULL, 'V'},
1293                 {"dbname", required_argument, NULL, 1},
1294                 {"debug", no_argument, NULL, 2},
1295                 {"inputdir", required_argument, NULL, 3},
1296                 {"load-language", required_argument, NULL, 4},
1297                 {"max-connections", required_argument, NULL, 5},
1298                 {"multibyte", required_argument, NULL, 6},
1299                 {"outputdir", required_argument, NULL, 7},
1300                 {"schedule", required_argument, NULL, 8},
1301                 {"temp-install", required_argument, NULL, 9},
1302                 {"no-locale", no_argument, NULL, 10},
1303                 {"top-builddir", required_argument, NULL, 11},
1304                 {"temp-port", required_argument, NULL, 12},
1305                 {"host", required_argument, NULL, 13},
1306                 {"port", required_argument, NULL, 14},
1307                 {"user", required_argument, NULL, 15},
1308                 {"psqldir", required_argument, NULL, 16},
1309                 {NULL, 0, NULL, 0}
1310         };
1311
1312         progname = get_progname(argv[0]);
1313         set_pglocale_pgservice(argv[0], "pg_regress");
1314
1315 #ifndef HAVE_UNIX_SOCKETS
1316         /* no unix domain sockets available, so change default */
1317         hostname = "localhost";
1318 #endif
1319
1320         while ((c = getopt_long(argc, argv, "hV", long_options, &option_index)) != -1)
1321         {
1322                 switch (c)
1323                 {
1324                         case 'h':
1325                                 help();
1326                                 exit_nicely(0);
1327                         case 'V':
1328                                 printf("pg_regress (PostgreSQL %s)\n", PG_VERSION);
1329                                 exit_nicely(0);
1330                         case 1:
1331                                 dbname = strdup(optarg);
1332                                 break;
1333                         case 2:
1334                                 debug = true;
1335                                 break;
1336                         case 3:
1337                                 inputdir = strdup(optarg);
1338                                 break;
1339                         case 4:
1340                                 add_stringlist_item(&loadlanguage, optarg);
1341                                 break;
1342                         case 5:
1343                                 max_connections = atoi(optarg);
1344                                 break;
1345                         case 6:
1346                                 encoding = strdup(optarg);
1347                                 break;
1348                         case 7:
1349                                 outputdir = strdup(optarg);
1350                                 break;
1351                         case 8:
1352                                 add_stringlist_item(&schedulelist, optarg);
1353                                 break;
1354                         case 9:
1355                                 /* temp_install must be absolute path */
1356                                 if (is_absolute_path(optarg))
1357                                         temp_install = strdup(optarg);
1358                                 else
1359                                 {
1360                                         char cwdbuf[MAXPGPATH];
1361
1362                                         if (!getcwd(cwdbuf, sizeof(cwdbuf)))
1363                                         {
1364                                                 fprintf(stderr, _("could not get current working directory: %s\n"), strerror(errno));
1365                                                 exit_nicely(2);
1366                                         }
1367                                         temp_install = malloc(strlen(cwdbuf) + strlen(optarg) + 2);
1368                                         sprintf(temp_install,"%s/%s", cwdbuf, optarg);
1369                                 }
1370                                 canonicalize_path(temp_install);
1371                                 break;
1372                         case 10:
1373                                 nolocale = true;
1374                                 break;
1375                         case 11:
1376                                 top_builddir = strdup(optarg);
1377                                 break;
1378                         case 12:
1379                                 {
1380                                         int p = atoi(optarg);
1381
1382                                         /* Since Makefile isn't very bright, check port range */
1383                                         if (p >= 1024 && p <= 65535)
1384                                                 temp_port = p;
1385                                 }
1386                                 break;
1387                         case 13:
1388                                 hostname = strdup(optarg);
1389                                 break;
1390                         case 14:
1391                                 port = atoi(optarg);
1392                                 break;
1393                         case 15:
1394                                 user = strdup(optarg);
1395                                 break;
1396                         case 16:
1397                                 /* "--psqldir=" should mean to use PATH */
1398                                 if (strlen(optarg))
1399                                         psqldir = strdup(optarg);
1400                                 break;
1401                         default:
1402                                 /* getopt_long already emitted a complaint */
1403                                 fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
1404                                                 progname);
1405                                 exit_nicely(2);
1406                 }
1407         }
1408
1409         /*
1410          * if we still have arguments, they are extra tests to run
1411          */
1412         while (argc - optind >= 1)
1413         {
1414                 add_stringlist_item(&extra_tests, argv[optind]);
1415                 optind++;
1416         }
1417
1418         if (temp_install)
1419                 port = temp_port;
1420
1421         /*
1422          * Initialization
1423          */
1424         open_result_files();
1425
1426         initialize_environment();
1427
1428         if (temp_install)
1429         {
1430                 /*
1431                  * Prepare the temp installation
1432                  */
1433                 if (!top_builddir)
1434                 {
1435                         fprintf(stderr, _("--top-builddir must be specified when using --temp-install\n"));
1436                         exit_nicely(2);
1437                 }
1438
1439                 if (directory_exists(temp_install))
1440                 {
1441                         header(_("removing existing temp installation"));
1442                         rmtree(temp_install,true);
1443                 }
1444
1445                 header(_("creating temporary installation"));
1446
1447                 /* make the temp install top directory */
1448                 make_directory(temp_install);
1449
1450                 /* and a directory for log files */
1451                 snprintf(buf, sizeof(buf), "%s/log", outputdir);
1452                 if (!directory_exists(buf))
1453                         make_directory(buf);
1454
1455                 /* "make install" */
1456                 snprintf(buf, sizeof(buf),
1457                                  SYSTEMQUOTE "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install with_perl=no with_python=no > \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
1458                                  makeprog, top_builddir, temp_install, outputdir);
1459                 if (system(buf))
1460                 {
1461                         fprintf(stderr, _("\n%s: installation failed\nExamine %s/log/install.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
1462                         exit_nicely(2);
1463                 }
1464
1465                 /* initdb */
1466                 header(_("initializing database system"));
1467                 snprintf(buf, sizeof(buf),
1468                                  SYSTEMQUOTE "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean%s%s > \"%s/log/initdb.log\" 2>&1" SYSTEMQUOTE,
1469                                  bindir, temp_install, datadir,
1470                                  debug ? " --debug" : "",
1471                                  nolocale ? " --no-locale" : "",
1472                                  outputdir);
1473                 if (system(buf))
1474                 {
1475                         fprintf(stderr, _("\n%s: initdb failed\nExamine %s/log/initdb.log for the reason.\nCommand was: %s\n"), progname, outputdir, buf);
1476                         exit_nicely(2);
1477                 }
1478
1479                 /*
1480                  * Start the temp postmaster
1481                  */
1482                 header(_("starting postmaster"));
1483                 snprintf(buf, sizeof(buf),
1484                                  SYSTEMQUOTE "\"%s/postmaster\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
1485                                  bindir, temp_install,
1486                                  debug ? " -d 5" : "",
1487                                  hostname ? hostname : "",
1488                                  outputdir);
1489                 postmaster_pid = spawn_process(buf);
1490                 if (postmaster_pid == INVALID_PID)
1491                 {
1492                         fprintf(stderr, _("\n%s: could not spawn postmaster: %s\n"),
1493                                         progname, strerror(errno));
1494                         exit_nicely(2);
1495                 }
1496
1497                 /*
1498                  * Wait till postmaster is able to accept connections (normally only
1499                  * a second or so, but Cygwin is reportedly *much* slower).  Don't
1500                  * wait forever, however.
1501                  */
1502                 snprintf(buf, sizeof(buf),
1503                                  SYSTEMQUOTE "\"%s/psql\" -X postgres <%s 2>%s" SYSTEMQUOTE,
1504                                  bindir, DEVNULL, DEVNULL);
1505                 for (i = 0; i < 60; i++)
1506                 {
1507                         /* Done if psql succeeds */
1508                         if (system(buf) == 0)
1509                                 break;
1510
1511                         /*
1512                          * Fail immediately if postmaster has exited
1513                          *
1514                          * XXX is there a way to do this on Windows?
1515                          */
1516 #ifndef WIN32
1517                         if (kill(postmaster_pid, 0) != 0)
1518                         {
1519                                 fprintf(stderr, _("\n%s: postmaster failed\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
1520                                 exit_nicely(2);
1521                         }
1522 #endif
1523
1524                         pg_usleep(1000000L);
1525                 }
1526                 if (i == 60)
1527                 {
1528                         fprintf(stderr, _("\n%s: postmaster did not start within 60 seconds\nExamine %s/log/postmaster.log for the reason\n"), progname, outputdir);
1529                         exit_nicely(2);
1530                 }
1531
1532                 postmaster_running = true;
1533
1534                 printf(_("running on port %d with pid %lu\n"),
1535                            temp_port, (unsigned long) postmaster_pid);
1536         }
1537         else
1538         {
1539                 /*
1540                  * Using an existing installation, so may need to get rid of
1541                  * pre-existing database.
1542                  */
1543                 header(_("dropping database \"%s\""), dbname);
1544                 psql_command("postgres","DROP DATABASE IF EXISTS \"%s\"", dbname);
1545         }
1546
1547         /*
1548          * Create the test database
1549          *
1550          * We use template0 so that any installation-local cruft in template1
1551          * will not mess up the tests.
1552          */
1553         header(_("creating database \"%s\""), dbname);
1554         if (encoding)
1555                 psql_command("postgres",
1556                                          "CREATE DATABASE \"%s\" TEMPLATE=template0 ENCODING='%s'",
1557                                          dbname, encoding);
1558         else                                            /* use installation default */
1559                 psql_command("postgres",
1560                                          "CREATE DATABASE \"%s\" TEMPLATE=template0",
1561                                          dbname);
1562
1563         psql_command(dbname,
1564                                  "ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
1565                                  "ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
1566                                  "ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
1567                                  "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
1568                                  "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
1569                                  dbname, dbname, dbname, dbname, dbname);
1570
1571         /*
1572          * Install any requested PL languages
1573          */
1574         for (sl = loadlanguage; sl != NULL; sl = sl->next)
1575         {
1576                 header(_("installing %s"), sl->str);
1577                 psql_command(dbname, "CREATE LANGUAGE \"%s\"", sl->str);
1578         }
1579
1580         /*
1581          * Ready to run the tests
1582          */
1583         header(_("running regression test queries"));
1584
1585         for (sl = schedulelist; sl != NULL; sl = sl->next)
1586         {
1587                 run_schedule(sl->str);
1588         }
1589
1590         for (sl = extra_tests; sl != NULL; sl = sl->next)
1591         {
1592                 run_single_test(sl->str);
1593         }
1594
1595         /*
1596          * Shut down temp installation's postmaster
1597          */
1598         if (temp_install)
1599         {
1600                 header(_("shutting down postmaster"));
1601                 stop_postmaster();
1602         }
1603
1604         fclose(logfile);
1605
1606         /*
1607          * Emit nice-looking summary message
1608          */
1609         if (fail_count == 0 && fail_ignore_count == 0)
1610                 snprintf(buf, sizeof(buf),
1611                                  _(" All %d tests passed. "),
1612                                  success_count);
1613         else if (fail_count == 0) /* fail_count=0, fail_ignore_count>0 */
1614                 snprintf(buf, sizeof(buf),
1615                                  _(" %d of %d tests passed, %d failed test(s) ignored. "),
1616                                  success_count,
1617                                  success_count + fail_ignore_count,
1618                                  fail_ignore_count);
1619         else if (fail_ignore_count == 0) /* fail_count>0 && fail_ignore_count=0 */
1620                 snprintf(buf, sizeof(buf),
1621                                  _(" %d of %d tests failed. "),
1622                                  fail_count,
1623                                  success_count+fail_count);
1624         else /* fail_count>0 && fail_ignore_count>0 */
1625                 snprintf(buf, sizeof(buf),
1626                                  _(" %d of %d tests failed, %d of these failures ignored. "),
1627                                  fail_count+fail_ignore_count,
1628                                  success_count + fail_count+fail_ignore_count,
1629                                  fail_ignore_count);
1630
1631         putchar('\n');
1632         for (i = strlen(buf); i > 0; i--)
1633                 putchar('=');
1634         printf("\n%s\n", buf);
1635         for (i = strlen(buf); i > 0; i--)
1636                 putchar('=');
1637         putchar('\n');
1638         putchar('\n');
1639
1640         if (file_size(difffilename) > 0)
1641         {
1642                 printf(_("The differences that caused some tests to fail can be viewed in the\n"
1643                                  "file \"%s\".  A copy of the test summary that you see\n"
1644                                  "above is saved in the file \"%s\".\n\n"),
1645                            difffilename, logfilename);
1646         }
1647         else
1648         {
1649                 unlink(difffilename);
1650                 unlink(logfilename);
1651         }
1652
1653         if (fail_count != 0)
1654                 exit_nicely(1);
1655
1656         return 0;
1657 }