public final class InterProcessConcurrencyTester
extends java.lang.Object
This class is used to check whether or not a set of processes violate a concurrency contract (e.g., whether they run concurrently when they are not allowed to, or vice versa).
The usage and implementation of this class resemble those of ConcurrencyTester
, except
that ConcurrencyTester
supports concurrency testing for threads within the same process
whereas this class supports concurrency testing for different processes.
The following is a usage scenario of this class. Suppose we have a class whose main() method executes an action (some piece of code) exactly once. When several processes are concurrently calling the main() method (possibly with different parameter values), the class under test may make a contract that all the processes can execute the corresponding actions concurrently, or it may make a contract that all the processes cannot execute the actions concurrently. To check whether the class under test meets the concurrency contract, we can write a test as follows.
InterProcessConcurrencyTester tester = new InterProcessConcurrencyTester();
for (...) {
tester.addClassInvocationFromNewProcess(ClassUnderTest.class, new String[] {...});
}
In the class under test's main() method, before calling the action under test, it needs to
notify InterProcessConcurrencyTester
when the process has started and when the action is
running as follows (so that the tester can perform necessary concurrency checks on these events):
// The server socket port is added to the list of arguments by InterProcessConcurrencyTester for
// the client process to communicate with the main process
int serverSocketPort = Integer.valueOf(args[args.length - 1]);
InterProcessConcurrencyTester.MainProcessNotifier notifier =
new InterProcessConcurrencyTester.MainProcessNotifier(serverSocketPort);
notifier.processStarted(); // Notify the main process that it has started execution
... // Start of the synchronized region (e.g., lock.lock())
notifier.actionStarted(); // Notify that it starts executing the action under test
... // The action under test (which has a concurrency requirement)
... // End of the synchronized region (e.g., lock.unlock())
Then, if the actions are allowed to run concurrently, we can make the following assertion:
tester.assertThatActionsCanRunConcurrently();
If the actions are not allowed to run concurrently, we can make the following assertion:
tester.assertThatActionsCannotRunConcurrently();
Modifier and Type | Class and Description |
---|---|
static class |
InterProcessConcurrencyTester.MainProcessNotifier
Class to be used by client processes (which are executing the actions under test) to notify
the main process of events happening in the client processes.
|
Constructor and Description |
---|
InterProcessConcurrencyTester() |
Modifier and Type | Method and Description |
---|---|
void |
addClassInvocationFromNewProcess(java.lang.Class classUnderTest,
java.lang.String[] args)
Adds a new invocation of the class under test's main() method to this
InterProcessConcurrencyTester instance. |
void |
assertThatActionsCannotRunConcurrently()
Executes the invocations of the class under test's main() method in separate processes and
asserts that all the actions ran sequentially.
|
void |
assertThatActionsCanRunConcurrently()
Executes the invocations of the class under test's main() method in separate processes and
asserts that all the actions ran concurrently.
|
public void addClassInvocationFromNewProcess(@NonNull java.lang.Class classUnderTest, @NonNull java.lang.String[] args)
InterProcessConcurrencyTester
instance. The InterProcessConcurrencyTester
will
execute each invocation in a separate process and check whether the corresponding actions
under test meet the concurrency requirement.classUnderTest
- the class under test whose main() method will be executed from a new
processargs
- the arguments for the class under test's main() methodpublic void assertThatActionsCanRunConcurrently() throws java.io.IOException
java.io.IOException
public void assertThatActionsCannotRunConcurrently() throws java.io.IOException
java.io.IOException