Package org.eigenbase.test.concurrent

A framework for concurrent jdbc unit tests.


Interface Summary
ConcurrentTestCommand ConcurrentTestCommand represents a command, sequentially executed by ConcurrentTestCommandExecutor, during a concurrency test

Class Summary
ConcurrentTestCommandExecutor ConcurrentTestCommandExecutor is a thread that executes a sequence of commands on a JDBC connection.
ConcurrentTestCommandExecutor.Sync Synchronization object that allows multiple ConcurrentTestCommandExecutors to execute commands in lock-step.
ConcurrentTestCommandGenerator ConcurrentTestCommandGenerator creates instances of ConcurrentTestCommand that perform specific actions in a specific order and within the context of a test thread (ConcurrentTestCommandExecutor).
ConcurrentTestCommandGenerator.AbstractCommand abstract base to handle SQLExceptions
ConcurrentTestCommandGenerator.AutoSynchronizationCommand AutoSynchronizationCommand is idential to SynchronizationCommand, except that it is generated automatically by the test harness and is not counted when displaying the step number in which an error occurred.
ConcurrentTestCommandGenerator.CloseCommand CloseCommand closes a previously prepared statement.
ConcurrentTestCommandGenerator.CommitCommand CommitCommand commits pending transactions via Connection.commit().
ConcurrentTestCommandGenerator.DdlCommand DdlCommand executes DDL commands.
ConcurrentTestCommandGenerator.ExplainCommand ExplainCommand executes explain plan commands.
ConcurrentTestCommandGenerator.FailedThread Describes a thread that failed
ConcurrentTestCommandGenerator.FetchAndCompareCommand FetchAndCompareCommand executes a previously prepared statement stored in the ConcurrentTestCommandExecutor and then validates the returned rows against expected data.
ConcurrentTestCommandGenerator.InsertCommand InsertCommand exeutes an insert, update or delete SQL statement.
ConcurrentTestCommandGenerator.PrepareCommand PrepareCommand creates a PreparedStatement.
ConcurrentTestCommandGenerator.RollbackCommand RollbackCommand rolls back pending transactions via Connection.rollback().
ConcurrentTestCommandGenerator.SleepCommand SleepCommand causes the execution thread to wait for all other threads in the test before continuing.
ConcurrentTestCommandGenerator.SynchronizationCommand SynchronizationCommand causes the execution thread to wait for all other threads in the test before continuing.
ConcurrentTestCommandScript ConcurrentTestCommandScript creates instances of ConcurrentTestCommand that perform specific actions in a specific order and within the context of a test thread (ConcurrentTestCommandExecutor).
ConcurrentTestTimedCommandGenerator ConcurrentTestTimedCommandGenerator extends ConcurrentTestCommandGenerator and repeats the configured command sequence until a certain amount of time has elapsed.

Exception Summary
ConcurrentTestCommand.ShouldHaveFailedException Indicates that a command should have failed, but instead succeeded, which is a test error

Package org.eigenbase.test.concurrent Description

A framework for concurrent jdbc unit tests.

The class ConcurrentCommandGenerator providea a java API for constructing concurrent jdbc tests: an instance of the class represents a test case, which contains several sequences of SQL commands (abstracted as subclasses of ConcurrentCommand). Each sequence is run in its own thread as a separate jdbc client (ie a separate java.sql.Connection). There are facilties to synchronize these command threads. Only a simple command sequence is supported: no branching, no looping.

An alternative is to define a test by writing a test script in mtsql format, as described below. An instance of ConcurrentCommandScript parses and executes a script.

Revision $Id: //open/dev/farrago/src/org/eigenbase/test/concurrent/package.html#1 $
Copyright Copyright (C) 2005-2009 The Eigenbase Project
Copyright (C) 2005-2009 SQLstream, Inc.
Copyright (C) 2005-2009 LucidEra, Inc.
Author Stephan Zuercher

Script Format


The syntactic structure of an mtsql script is:

    <setup section>?
    <cleanup section>?
    <thread section>+

    <directive>         := @[no]lockstep | @enable | @disable
    <setup section>     := @setup <basic command>* @end 
    <cleanup section>   := @setup <basic command>* @end 
    <thread section>    := @thread <thread-name>? <command>* @end

    <command> := 
      <basic command> | 
      <command prefix>? <threadly command> | 
      <synchronization point>

Blank lines and comments are allowed anywhere. A comment starts with two hyphens and runs to the end of the line. Command names start with an '@'. Some commands run to the end of the line; but a command that contains SQL can span lines and ends with a semicolon.


Running a section means running its commands in sequence. First the setup section (if any) is run. Next all the thread sections are run at once, each in its own thread. When all these threads complete, the cleanup section (if any) is run.


The threads are synchronized by inserting synchronization points (@sync).

When a thread reaches a @sync, it waits until all threads are waiting on the same @sync: then all threads proceed. @sync points have no names. Clearly all thread sections must contain the same number of @sync points.

The directive @lockstep has the same effect as adding a @sync after each command in every thread section. Clearly it requires that all thread sections have the same number of commands. The default is the antonym @nolockstep.

The directive @disable means "skip this script". The deault is the antonym @enable.

Error handling:

When a command fails, the rest of its section is skipped. If this happens in a thread section, the thread stops, but the other threads continue (with one fewer partner to synchronize with), and finally the cleanup section runs. If the setup section fails, then only the cleanup section is run. (Note: Not sure this behavior is correct or desirable.)

Basic Commands (allowed in any section):

<SQL statement>;
  An SQL statement terminated by a semicolon. The statement can span lines.

@include FILE 
  Reads and executes the contents of FILE, another mtsql script.
  Inclusions may nest.

Threaded Commands (allowed only in a @thread section):

@sleep N        -- thread sleeps for N milliseconds
@echo MESSAGE   -- prints the message to stdout

<SQL statement> ';'             -- executes the SQL
@timeout N <SQL>  ';'    -- executes the SQL with the given timeout (msecs)
@rowlimit N <SQL> ';'    -- executes the SQL, stops fetching after N rows.
@err <SQL> ';'           -- executes the SQL, expecting it to fail.

@repeat N <command>+ @end
    Denotes a repeated block of commands, with repeat count = N.
    N must be positive. 
@prepare SQL-STATEMENT ';' 
    Prepares the sql. A thread has at most one prepared statement at a time.

@print FORMAT
    Sets the result-printing format for the current prepared statement.
    FORMAT is a sequence of the phrases:
        none             -- means print nothing
        all              -- means print all rows (the default)
        every N          -- means print the first row (row 0), then row N, 2N, etc.
        count            -- means print the row number before the row (starts with 0).
        time             -- means print the actual time the row was fetched
   (Sorry, no way yet to print selected columns, to print time in a special way, etc.)

@fetch <timeout>?
    Starts fetching and printing result rows, with an optional timeout (in msecs).
    Stop on EOD or on timeout.

    Closes the current prepared statement. However that an open prepared
    statement will be closed automatically at the end of its thread.

@shell <Shell Command>
    Runs the command in a spawned subshell, proceeds after it concludes, but quits if it fails.
    For @shell and @echo, the command or message runs to the end of the line in the script, 
    but can be continued if the line ends with a single '\'.

Substituted Variables

Needed mainly to pass arguments to the command of @shell, but also useful to parameterize SQL statements, timeout values etc.