Improve pg_regress so that it reports the fact if any test process
authorTom Lane
Sat, 17 May 2008 20:02:01 +0000 (20:02 +0000)
committerTom Lane
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();
 }