40
Daemon mode

!!! Warning !!! When run in daemon mode, QF-Test will accept connections from anyone that can access the host and port. No checking of user name and access rights is performed. Don't use this feature outside a secure environment.

In daemon mode (comparable, but not equivalent to a "service" on Windows) QF-Test listens to RMI connections and providing an interface for remote test execution. This is useful for simplifying test execution in a distributed load-testing scenario, but also for integration with existing test-management or test-execution tools.

There are two command line arguments both of which are available in batch and interactive mode:

When run in batch and daemon mode, QF-Test will not use a license. Licenses will be acquired during use as described below. In interactive daemon mode, QF-Test will be fully functional and thus use a license. In addition it will accept connections from the outside and use additional licenses during use, similar to batch mode. The latter scenario is useful during development of distributed tests.

Basically, the idea is that you can use QF-Test or some other tool to drive QF-Test based tests. The steps are quite simple:

For proper dependency management, including rollback of no longer required dependencies between 'Test-case' invocations, it is important to use the same DaemonRunContext for execution of each related 'Test-case'. The easiest way to achieve this is to use the shared TestRunDaemon and its shared DaemonRunContext each time you talk to a given Daemon.

The following sections provide a complete reference for the daemon API. Further explanations and examples are provided in section 16.2.

40.1
The DaemonLocator

The singleton class de.qfs.apps.qftest.daemon.DaemonLocator can be used to get hold of Daemon instances.

 
 
public static DaemonLocator instance()
Get the singleton instance.
ReturnsThe singleton instance.
 
public Daemon locateDaemon(String host, int port)
Get a Daemon from a specific host and port.
Parameters
host The target host, name or IP string.
port The target port.
ReturnsThe daemon or null if none can be found.
 
public Daemon[] locateDaemons(long timeout)
Get all known daemons.
Parameters
timeout The time in milliseconds to wait for daemons to react.
ReturnsThe known daemons.
 
 
40.2
The Daemon

The de.qfs.apps.qftest.daemon.Daemon interface is an envelope for various kinds of QF-Test daemons. Currently only the TestRunDaemon is available, but something like an SUTClientStarterDaemon is already planned and others may follow.

 
 
public void ping()
Test whether the Daemon is still alive.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getHost()
Get the host of the Daemon.
ReturnsThe host of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getIp()
Get the ip of the Daemon.
Returns The ip of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public int getPort()
Get the port of the Daemon.
Returns The port of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public TestRunDaemon getSharedTestRunDaemon()
Get the shared TestRunDaemon.
Returns The shared TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public TestRunDaemon createTestRunDaemon()
Get access to a TestRunDaemon.
Returns A TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public TestRunDaemon[] getTestRunDaemons()
Get all TestRunDaemons created by the Daemon that are still live.
Returns The set of live TestRunDaemons created by the Daemon. Does not include the shared TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public void terminate(int exitCode)
Terminate the daemon process by calling System.exit.
Parameters
exitCode The exit code for the daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
public void killClients()
Kill all clients that belong to the VM of the daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup()
Clean up all TestRunDaemons belonging to this Daemon and then kill all clients. The default timeout of 30 seconds is used to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup(long timeout)
Clean up all TestRunDaemons belonging to this Daemon and then kill all clients.
Parameters
timeout The maximum time in milliseconds to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
 
40.3
The TestRunDaemon

The de.qfs.apps.qftest.daemon.TestRunDaemon is the outer interface for test execution. It is used to define the environment for associated test-runs and create the DaemonRunContext instances that handle the actual test execution.

40.3.1
Miscellaneous
 
 
public Daemon getDaemon()
Get the Daemon to which the TestRunDaemon belongs.
Returns The Daemon of the TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
 
40.3.2
Global variable handling
 
 
public void setGlobal(String name, String value)
Set a global variable value.
Parameters
name The name of the global variable.
value The value of the global variable.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getGlobal(String name)
Get a global variable value.
Parameters
name The name of the global variable.
Returns The value of the global variable or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
public Properties getGlobals()
Get all global variable values.
Returns All global variable values.
Throws
RemoteException If something RMI specific goes wrong.
 
public void clearGlobals()
Clear all global variables.
Throws
RemoteException If something RMI specific goes wrong.
 
 
40.3.3
Test execution
 
 
public void setRootDirectory(String directory)
Set the test-suite root directory for new created daemon run-contexts.
Parameters
directory The new root directory.
Throws
RemoteException If something RMI specific goes wrong.
 
public DaemonRunContext getSharedContext()
Get the shared daemon run-context. Needs to acquire a license if the shared context must be created first.
Returns The shared context or null if no license can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
public DaemonRunContext createContext()
Create a single daemon run-context. Needs to acquire a license.
Returns The context or null if no license can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
public DaemonRunContext[] createContexts(int threads)
Create daemon run-contexts for multiple threads. Needs to acquire one license per thread.
Parameters
threads The number of threads for the contexts.
Returns The contexts or null if not enough licenses can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
public DaemonRunContext[] getContexts()
Get all DaemonRunContexts created by the TestRunDaemon that are still live and have not been released.
Returns The set of live DaemonRunContexts created by the TestRunDaemon. Does not include the shared DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup()
Clean up and release all contexts belonging to this TestRunDaemon. The default timeout of 30 seconds is used to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup(long timeout)
Clean up and release all contexts belonging to this TestRunDaemon.
Parameters
timeout The maximum time in milliseconds to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
 
40.3.4
Identification
 
 
public void setIdentifier(String identifier)
Set an identifier for the TestRunDaemon. This can be useful in identifying a TestRunDaemon retrieved via Daemon.getTestRunDaemons().
Parameters
identifier The identifier to set.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getIdentifier()
Get the identifier for the TestRunDaemon. If no identifier was previously set with setIdentifier(), a default identifier is created from the name of the Daemon, to which the TestRunDaemon belongs, and a counter.
Returns The identifier for the TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
 
40.4
The DaemonRunContext

The de.qfs.apps.qftest.daemon.DaemonRunContext interface is in charge of the actual test execution.

Following run states are defined:

State Value Description
STATE_INVALID -1 Invalid after release - cannot be reactivated.
STATE_IDLE 0 No run scheduled.
STATE_SCHEDULED 1 Run scheduled but not started.
STATE_RUNNING 2 Running.
STATE_PAUSED 3 Running but paused.
STATE_FINISHED 4 Run finished, result and run-log available.
Table 40.1:  The run state
 
 
public TestRunDaemon getTestRunDaemon()
Get the TestRunDaemon to which the DaemonRunContext belongs.
Returns The TestRunDaemon of the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
public int getNumThreads()
Get the number of threads in the group to which the DaemonRunContext belongs.
Returns The number of threads of the DaemonRunContext's group.
Throws
RemoteException If something RMI specific goes wrong.
 
public int getThreadNum()
Get the thread index of the DaemonRunContext.
Parameters
Returns The thread index of the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
public int getRunState()
Get the current run state of the context. One of STATE_IDLE, STATE_SCHEDULED, STATE_RUNNING, STATE_PAUSED, STATE_FINISHED.
Returns The current run state.
Throws
RemoteException If something RMI specific goes wrong.
 
public boolean waitForRunState(int state, long timeout)
Wait for the context to reach a given state.
Parameters
state The state to wait for.
timeout Maximum time in milliseconds to wait.
Returns True if the state was reached, false if timed out.
Throws
RemoteException If something RMI specific goes wrong.
 
public void setRootDirectory(String directory)
Set the test-suite root directory for the next test-run.
Parameters
directory The new root directory.
Throws
RemoteException If something RMI specific goes wrong.
 
public boolean runTest(String test, Properties bindings=None)
Run a test in the run-context.
Parameters
test The test to run, of the form Suite#Test where #Test is optional and Test is the fully qualified name of a 'Test-set' or 'Test-case' or just ".". The latter is equivalent to specifying just Suite and causes the whole test-suite to be executed. Examples:
MySuite     Runs whole test-suite MySuite.
MySuite#.     Runs whole test-suite MySuite.
MySuite#MyTestSet     Runs test-set MyTestSet in test-suite MySuite.
MySuite#MyTestSet.MyTestCase     Runs test-case MyTestCase located in test-set MyTestSet in test-suiteMySuite.
bindings An optional set of variable bindings. These variables have higher precedence than the globals or any bindings on the fallback stack.
Returns True if the test was started, false if suite or test could not be found.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
public boolean callProcedure(String procedure, Properties bindings=None)
Call a procedure in the run-context.
Parameters
procedure The procedure to run, of the form Suite#Procedure where Procedure is the fully qualified name of the 'Procedure'.
bindings An optional set of variable bindings. These variables have higher precedence than the globals or any bindings on the fallback stack.
Returns True if the procedure call was started, false if suite or procedure could not be found.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
public String getLastTest()
Get the name of the test that is currently running or was last run on this DaemonRunContext.
Returns The name of the currently running or most recently executed test.
Throws
RemoteException If something RMI specific goes wrong.
 
public void stopRun()
Stop the test-run.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run was scheduled.
 
public int getResult()
Get the result of the test run.
Returns 0, 1, 2, 3 for OK, warning, error, exception.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If the state isn't STATE_FINISHED.
 
public byte[] getRunLog()
Get the run-log of the test run.
Returns The run-log dumped into a byte array.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If the state isn't STATE_FINISHED.
 
void rollbackDependencies()
Roll back the dependencies for this DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
public void release()
Release the DaemonRunContext and return its license. If a test is running, stop it.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no DaemonRunContext was allocated.
 
public void setIdentifier(String identifier)
Set an identifier for the DaemonRunContext. This can be useful in identifying a DaemonRunContext retrieved via TestRunDaemon.getContexts().
Parameters
identifier The identifier to set.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getIdentifier()
Get the identifier for the DaemonRunContext. If no identifier was previously set with setIdentifier(), a default identifier is created from the name of the TestRunDaemon, to which the DaemonRunContext belongs, and a counter.
Returns The identifier for the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getGlobal(String name)
Retrieve the value of a global variable from the DaemonRunContext.
Parameters
nameThe name of the variable.
Returns The value of the variable or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
public Properties getGlobals()
Retrieve all global variables from the DaemonRunContext.
Returns The global variables.
Throws
RemoteException If something RMI specific goes wrong.
 
public String getProperty(String group, String name)
Retrieve the value of a property or resource from the DaemonRunContext.
Parameters
nameThe name of the property or resource group.
nameThe name of the property.
Returns The value of the property or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
public Properties getProperties(String group)
Retrieve all properties from a property or resource group from the DaemonRunContext.
Parameters
nameThe name of the property or resource group.
Returns The properties or null if no such group exists.
Throws
RemoteException If something RMI specific goes wrong.
 
void addTestRunListener(DaemonTestRunListener listener, boolean synchronous, long timeout)
Add a DaemonTestRunListener to the DaemonRunContext.
Parameters
listenerThe listener to add.
synchronous Whether the listener should get notified synchronously, in which case the test-run will be blocked while the listener is processing the event.
timeout Timeout in milliseconds for callbacks to the listener. If the listener does not reply within that time the listener is automatically unregistered to prevent further problems. In case of a synchronous listener the test-run will then continue. A value of 0 means no timeout which is dangerous but may be useful.
 
void removeTestRunListener(DaemonTestRunListener listener)
Remove a DaemonTestRunListener from the DaemonRunContext.
Parameters
listenerThe listener to remove.
 
void clearTestRunListeners()
Remove all DaemonTestRunListeners from the DaemonRunContext.
 
 
3.1+40.5
The DaemonTestRunListener

The de.qfs.apps.qftest.daemon.DaemonTestRunListener interface is identical to the interface de.qfs.apps.qftest.extensions.qftest.TestRunListener described in section 39.5, except that its methods can throw a RemoteException on RMI failure. When implementing this interface you must derive your class from java.rmi.server.UnicastRemoteObject.

You can register the listener with a DaemonRunContext via its addTestRunListener method described in the previous section.