]> granicus.if.org Git - postgresql/commitdiff
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++)
        {