serializable isolation level; but tests for other sorts of concurrent
behaviors have been added as well.
-To run the tests, you need to have a server running at the default port
-expected by libpq. (You can set PGPORT and so forth in your environment
-to control this.) Then run
+You can run the tests against the current build tree by typing
+ make check
+Alternatively, you can run against an existing installation by typing
make installcheck
-To run just specific test(s), you can do something like
+(This will contact a server at the default port expected by libpq.
+You can set PGPORT and so forth in your environment to control this.)
+
+To run just specific test(s) against an installed server,
+you can do something like
./pg_isolation_regress fk-contention fk-deadlock
(look into the specs/ subdirectory to see the available tests).
The prepared-transactions test requires the server's
max_prepared_transactions parameter to be set to at least 3; therefore it
is not run by default. To include it in the test run, use
+ make check-prepared-txns
+or
make installcheck-prepared-txns
+after making sure the server configuration is correct (see TEMP_CONFIG
+to adjust this in the "check" case).
To define tests with overlapping transactions, we use test specification
files with a custom syntax, which is described in the next section. To add
psql to execute a test, it uses isolationtester. It accepts all the same
command-line arguments as pg_regress.
+By default, isolationtester will wait at most 300 seconds (5 minutes)
+for any one test step to complete. If you need to adjust this, set
+the environment variable PGISOLATIONTIMEOUT to the desired timeout
+in seconds.
+
Test specification
==================
deadlock). A test that uses this ability must manually specify valid
permutations, i.e. those that would not expect a blocked session to execute a
command. If a test fails to follow that rule, isolationtester will cancel it
-after 180 seconds. If the cancel doesn't work, isolationtester will exit
-uncleanly after a total of 200 seconds of wait time. Testing invalid
-permutations should be avoided because they can make the isolation tests take
-a very long time to run, and they serve no useful testing purpose.
+after PGISOLATIONTIMEOUT seconds. If the cancel doesn't work, isolationtester
+will exit uncleanly after a total of twice PGISOLATIONTIMEOUT. Testing
+invalid permutations should be avoided because they can make the isolation
+tests take a very long time to run, and they serve no useful testing purpose.
Note that isolationtester recognizes that a command has blocked by looking
to see if it is shown as waiting in the pg_locks view; therefore, only
static const char **backend_pid_strs = NULL;
static int nconns = 0;
+/* Maximum time to wait before giving up on a step (in usec) */
+static int64 max_step_wait = 300 * USECS_PER_SEC;
+
+
static void run_testspec(TestSpec *testspec);
static void run_all_permutations(TestSpec *testspec);
static void run_all_permutations_recurse(TestSpec *testspec, int nsteps,
main(int argc, char **argv)
{
const char *conninfo;
+ const char *env_wait;
TestSpec *testspec;
int i,
j;
else
conninfo = "dbname = postgres";
+ /*
+ * If PGISOLATIONTIMEOUT is set in the environment, adopt its value (given
+ * in seconds) as the max time to wait for any one step to complete.
+ */
+ env_wait = getenv("PGISOLATIONTIMEOUT");
+ if (env_wait != NULL)
+ max_step_wait = ((int64) atoi(env_wait)) * USECS_PER_SEC;
+
/* Read the test spec from stdin */
spec_yyparse();
testspec = &parseresult;
td += (int64) current_time.tv_usec - (int64) start_time.tv_usec;
/*
- * After 180 seconds, try to cancel the query.
+ * After max_step_wait microseconds, try to cancel the query.
*
* If the user tries to test an invalid permutation, we don't want
* to hang forever, especially when this is running in the
* failing, but remaining permutations and tests should still be
* OK.
*/
- if (td > 180 * USECS_PER_SEC && !canceled)
+ if (td > max_step_wait && !canceled)
{
PGcancel *cancel = PQgetCancel(conn);
char buf[256];
if (PQcancel(cancel, buf, sizeof(buf)))
+ {
+ /*
+ * print to stdout not stderr, as this should appear
+ * in the test case's results
+ */
+ printf("isolationtester: canceling step %s after %d seconds\n",
+ step->name, (int) (td / USECS_PER_SEC));
canceled = true;
+ }
else
fprintf(stderr, "PQcancel failed: %s\n", buf);
PQfreeCancel(cancel);
}
/*
- * After 200 seconds, just give up and die.
+ * After twice max_step_wait, just give up and die.
*
* Since cleanup steps won't be run in this case, this may cause
* later tests to fail. That stinks, but it's better than waiting
* forever for the server to respond to the cancel.
*/
- if (td > 200 * USECS_PER_SEC)
+ if (td > 2 * max_step_wait)
{
- fprintf(stderr, "step %s timed out after 200 seconds\n",
- step->name);
+ fprintf(stderr, "step %s timed out after %d seconds\n",
+ step->name, (int) (td / USECS_PER_SEC));
exit(1);
}
}