Detect invalid permutations in isolationtester
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 14 Jan 2012 22:36:39 +0000 (19:36 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 14 Jan 2012 22:36:39 +0000 (19:36 -0300)
isolationtester is now able to continue running other permutations when
it detects that one of them is invalid, which is useful during initial
development of spec files.

Author: Alexander Shulgin

src/test/isolation/isolationtester.c

index b35e533b66c5143448c03e6748505dc6ed0cbac7..ab1ef036045f0888cd603df0a6f609615af8732c 100644 (file)
@@ -550,8 +550,53 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps)
    for (i = 0; i < nsteps; i++)
    {
        Step *step = steps[i];
+       PGconn *conn = conns[1 + step->session];
 
-       if (!PQsendQuery(conns[1 + step->session], step->sql))
+       if (waiting != NULL && step->session == waiting->session)
+       {
+           PGcancel *cancel;
+           PGresult *res;
+           int j;
+
+           /*
+            * This permutation is invalid: it can never happen in real life.
+            *
+            * A session is blocked on an earlier step (waiting) and no further
+            * steps from this session can run until it is unblocked, but it
+            * can only be unblocked by running steps from other sessions.
+            */
+           fprintf(stderr, "invalid permutation detected\n");
+
+           /* Cancel the waiting statement from this session. */
+           cancel = PQgetCancel(conn);
+           if (cancel != NULL)
+           {
+               char buf[256];
+
+               PQcancel(cancel, buf, sizeof(buf));
+
+               /* Be sure to consume the error message. */
+               while ((res = PQgetResult(conn)) != NULL)
+                   PQclear(res);
+
+               PQfreeCancel(cancel);
+           }
+
+           /*
+            * Now we really have to complete all the running transactions to
+            * make sure teardown doesn't block.
+            */
+           for (j = 1; j < nconns; j++)
+           {
+               res = PQexec(conns[j], "ROLLBACK");
+               if (res != NULL)
+                   PQclear(res);
+           }
+
+           goto teardown;
+       }
+
+       if (!PQsendQuery(conn, step->sql))
        {
            fprintf(stdout, "failed to send query for step %s: %s\n",
                    step->name, PQerrorMessage(conns[1 + step->session]));
@@ -590,6 +635,7 @@ run_permutation(TestSpec * testspec, int nsteps, Step ** steps)
        report_error_message(waiting);
    }
 
+teardown:
    /* Perform per-session teardown */
    for (i = 0; i < testspec->nsessions; i++)
    {