Improve pg_regress so that it reports the fact if any test process
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 May 2008 20:02:01 +0000 (20:02 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 May 2008 20:02:01 +0000 (20:02 +0000)
exits with nonzero status.  The Windows part of this is untested ...

src/test/regress/pg_regress.c

index 2fa64f1fb0a1ec9afc9e67fa326261d703497905..feaaf8f320200f6e6dde9004f7eb7af1bcaef998 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.44 2008/03/31 01:31:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.45 2008/05/17 20:02:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1305,14 +1305,15 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
 }
 
 /*
- * Wait for specified subprocesses to finish
+ * Wait for specified subprocesses to finish, and return their exit
+ * statuses into statuses[]
  *
- * If names isn't NULL, report each subprocess as it finishes
+ * If names isn't NULL, print each subprocess's name as it finishes
  *
  * Note: it's OK to scribble on the pids array, but not on the names array
  */
 static void
-wait_for_tests(PID_TYPE * pids, char **names, int num_tests)
+wait_for_tests(PID_TYPE *pids, int *statuses, char **names, int num_tests)
 {
        int                     tests_left;
        int                     i;
@@ -1327,9 +1328,10 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests)
        while (tests_left > 0)
        {
                PID_TYPE        p;
+               int                     exit_status;
 
 #ifndef WIN32
-               p = wait(NULL);
+               p = wait(&exit_status);
 
                if (p == INVALID_PID)
                {
@@ -1357,9 +1359,11 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests)
                        if (p == pids[i])
                        {
 #ifdef WIN32
+                               GetExitCodeProcess(pids[i], &exit_status);
                                CloseHandle(pids[i]);
 #endif
                                pids[i] = INVALID_PID;
+                               statuses[i] = exit_status;
                                if (names)
                                        status(" %s", names[i]);
                                tests_left--;
@@ -1373,6 +1377,35 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests)
 #endif
 }
 
+/*
+ * report nonzero exit code from a test process
+ */
+static void
+log_child_failure(int exitstatus)
+{
+       if (WIFEXITED(exitstatus))
+               status(_(" (test process exited with exit code %d)"),
+                          WEXITSTATUS(exitstatus));
+       else if (WIFSIGNALED(exitstatus))
+       {
+#if defined(WIN32)
+               status(_(" (test process was terminated by exception 0x%X)"),
+                          WTERMSIG(exitstatus));
+#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
+               status(_(" (test process was terminated by signal %d: %s)"),
+                          WTERMSIG(exitstatus),
+                          WTERMSIG(exitstatus) < NSIG ?
+                          sys_siglist[WTERMSIG(exitstatus)] : "(unknown))");
+#else
+               status(_(" (test process was terminated by signal %d)"),
+                          WTERMSIG(exitstatus));
+#endif
+       }
+       else
+               status(_(" (test process exited with unrecognized status %d)"),
+                          exitstatus);
+}
+
 /*
  * Run all the tests specified in one schedule file
  */
@@ -1385,6 +1418,7 @@ run_schedule(const char *schedule, test_function tfunc)
        _stringlist *expectfiles[MAX_PARALLEL_TESTS];
        _stringlist *tags[MAX_PARALLEL_TESTS];
        PID_TYPE        pids[MAX_PARALLEL_TESTS];
+       int                     statuses[MAX_PARALLEL_TESTS];
        _stringlist *ignorelist = NULL;
        char            scbuf[1024];
        FILE       *scf;
@@ -1486,7 +1520,7 @@ run_schedule(const char *schedule, test_function tfunc)
                {
                        status(_("test %-20s ... "), tests[0]);
                        pids[0] = (tfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
-                       wait_for_tests(pids, NULL, 1);
+                       wait_for_tests(pids, statuses, NULL, 1);
                        /* status line is finished below */
                }
                else if (max_connections > 0 && max_connections < num_tests)
@@ -1499,12 +1533,14 @@ run_schedule(const char *schedule, test_function tfunc)
                        {
                                if (i - oldest >= max_connections)
                                {
-                                       wait_for_tests(pids + oldest, tests + oldest, i - oldest);
+                                       wait_for_tests(pids + oldest, statuses + oldest,
+                                                                  tests + oldest, i - oldest);
                                        oldest = i;
                                }
                                pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
                        }
-                       wait_for_tests(pids + oldest, tests + oldest, i - oldest);
+                       wait_for_tests(pids + oldest, statuses + oldest,
+                                                  tests + oldest, i - oldest);
                        status_end();
                }
                else
@@ -1514,7 +1550,7 @@ run_schedule(const char *schedule, test_function tfunc)
                        {
                                pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
                        }
-                       wait_for_tests(pids, tests, num_tests);
+                       wait_for_tests(pids, statuses, tests, num_tests);
                        status_end();
                }
 
@@ -1543,7 +1579,7 @@ run_schedule(const char *schedule, test_function tfunc)
                                bool            newdiff;
 
                                if (tl)
-                                       tl = tl->next;          /* tl has the same lengt has rl and el
+                                       tl = tl->next;          /* tl has the same lengtas rl and el
                                                                                 * if it exists */
 
                                newdiff = results_differ(tests[i], rl->str, el->str);
@@ -1584,6 +1620,9 @@ run_schedule(const char *schedule, test_function tfunc)
                                success_count++;
                        }
 
+                       if (statuses[i] != 0)
+                               log_child_failure(statuses[i]);
+
                        status_end();
                }
        }
@@ -1598,6 +1637,7 @@ static void
 run_single_test(const char *test, test_function tfunc)
 {
        PID_TYPE        pid;
+       int                     exit_status;
        _stringlist *resultfiles = NULL;
        _stringlist *expectfiles = NULL;
        _stringlist *tags = NULL;
@@ -1608,7 +1648,7 @@ run_single_test(const char *test, test_function tfunc)
 
        status(_("test %-20s ... "), test);
        pid = (tfunc) (test, &resultfiles, &expectfiles, &tags);
-       wait_for_tests(&pid, NULL, 1);
+       wait_for_tests(&pid, &exit_status, NULL, 1);
 
        /*
         * Advance over all three lists simultaneously.
@@ -1624,7 +1664,7 @@ run_single_test(const char *test, test_function tfunc)
                bool            newdiff;
 
                if (tl)
-                       tl = tl->next;          /* tl has the same lengt has rl and el if it
+                       tl = tl->next;          /* tl has the same lengtas rl and el if it
                                                                 * exists */
 
                newdiff = results_differ(test, rl->str, el->str);
@@ -1645,6 +1685,10 @@ run_single_test(const char *test, test_function tfunc)
                status(_("ok"));
                success_count++;
        }
+
+       if (exit_status != 0)
+               log_child_failure(exit_status);
+
        status_end();
 }