Wright Flyer Test Client API
Comments to Kyle Jennings (jennings@cmu.edu)
Abstract: This document describes the application programmer’s interface that Wright Flyer federates
must use to interact with the Wright Flyer Interactive Test Program (ITP).
Overview: The Wright Flyer ITP (“ITP”) is a graphical front end useful for testing components of the
Wright Flyer simulator. It includes all of the functionality of the DMSO’s TestFederateNT program, as
well as additional functionality to:
- View and sort trace messages.
- Monitor all events going across the RTI bus.
- Automate complex, multi-machine tests.
- Support examining the internal state of federates.
There is at most one ITP per federation execution. Additionally, there is one Test Server on each machine
involved in a federation execution. It is the conduit through which individual executables communicate
with the ITP across the network. Interactions with the Test Server are encapsulated within the Test Client
API, described in this document.
One of the most basic features of the ITP is the ability to display and coordinate trace messages from
multiple machines. A trace message is essentially a string that indicates the occurrence of a certain event
within a program. Trace messages take the place of random “printfs” that programmers typically
intersperse throughout their programs to facilitate debugging. In addition to their actual message, traces
carry the source machine, executable, federate and federate instance ID (optional), wall clock time sent, and
simulation time sent. Each message is placed in a different message class. All messages of a certain class
can be turned on and off individually. If a message is turned off, the message is never sent across the
network.
The ITP can also be used to send non-HLA stimuli to individual executables or federates. In the most basic
case, a federate might wait to perform a particular action until it receives the go-ahead from a test script,
executed by the ITP. This feature supports writing complex, automated tests.
The ITP also facilitates state dumps. Each executable must register a state dump handler, which is
responsible for producing the state dump.
The Test Client API, when invoked, spins off a separate thread that handles all communication with the
Test Server. Therefore, there is no need to insert function calls like the RTI’s “tick.”
The remainder of this document is divided into sections that discuss:
- The connection API.
- The assert API.
- The message API.
- The stimulus API.
- The state dump API.
Connection API: The connection API is how the program connects to the Test Server. The program
may connect to the Test Server at any point during its lifetime, but must connect before any of its other
calls (including state dump calls, and excepting assert calls) have an effect. (Assert calls continue to check
the conditions, but do not communicate failures to the ITP.) The connection API also includes functions to
allocate handles for federation name/instance pairs.
namespace TestClient {
bool ConnectToServer(void);
bool DetachFromServer(void);
FEDID AllocateFedID(char *szFedName, int nFedInstance);
}
void TestClient::ConnectToServer(void)
Description Attempt to connect to the Test Server running on the current machine. Start a Test
Client thread in this process.
Preconditions There is a Test Server process running on this machine.
This process is not currently connected to the Test Server.
Postconditions This process is connected to the Test Server.
Parameters None.
Return Values None.
Exceptions class TestClient::eNoTestServer {} – There is no test server running on this machine.
class TestClient::eAlreadyConnected {} – This process is already connected to the test
server.
void TestClient::DetachFromServer(void)
Description Detach from the Test Server, killing the Test Client thread. This should be done before
the program exits.
Preconditions This process is currently connected to the Test Server.
Postconditions This process is not connected to the Test Server.
Parameters None.
Return Values None.
Exceptions class TestClient::eNotConnected {} – The process is not connected to the Test Server.
FEDID TestClient::AllocateFedID(char *szFedName, int nFedInstance)
Description Return a new or existing numeric handle that can be used to identify federates with the
name szFedName and instance number nFedInstance in all future message and assert
calls.
Preconditions This process is currently connected to the Test Server.
szFedName is a valid character string.
Postconditions The return value is a valid federate identifier.
Parameters char *szFedName – the name of the federate instance being identified.
int nFedInstance – the instance number of the federate instance being identified.
Return Values (FEDID) A federation ID identifying the named federate instance.
Exceptions class TestClient::eNotConnected {} – The process is not connected to the Test Server.
class TestClient::eLostConnection {} – The connection with the Test Server was lost.
Assert API: The assert API allows programs to test certain conditions during execution. If the conditions
are not satisfied, the program terminates. Using asserts to test assumptions is a powerful way to quickly
find logical errors in a program. If an assertion fails and the program is connected to the Test Server, the
assertion failure message will be transmitted to the Test Server.
namespace TestClient {
void assert(FEDID, bool);
void assertf(FEDID, bool, char *, …);
void assertv(FEDID, bool, char *, varg *);
}
#define DECLARE_ASSERT_WRAPPERS(prefix, fedid) \
inline void prefix##_assert(bool b) { TestClient::assert(fedid, b); } \
inline void prefix##_assertf(bool b, char *szFormat, …) { \
varg *v; \
va_start(v, szFormat); \
TestClient::assertv(fedid, b, szFormat, v); \
va_end(v); \
}
void TestClient::assert(FEDID fedid, bool fCondition)
Description Check that fCondition is true. If not, exit the program with a diagnostic message.
Preconditions None.
Postconditions fCondition is true, or the program has terminated.
Parameters FEDID fedid – The handle of this federate and federate instance as assigned by the Test
Server. May be NULL.
bool fCondition – Condition to check.
Return Values None.
Exceptions None.
void TestClient::assertf(FEDID fedid, bool fCondition, char *szFormat, …)
Description Check that fCondition is true. If not, exit the program with a diagnostic message. Also,
print the message in szFormat, which is structured as with a call to printf().
Preconditions None.
Postconditions fCondition is true, or the program has terminated and the message in szFormat has
been displayed.
Parameters FEDID fedid – The handle of this federate and federate instance as assigned by the Test
Server. May be NULL.
bool fCondition – Condition to check.
char *szFormat – The message to display if fCondition is false.
… – additional arguments as dictated by szFormat.
Return Values None.
Exceptions None.
void TestClient::assertv(FEDID fedid, bool fCondition, char *szFormat, varg *v)
Description Check that fCondition is true. If not, exit the program with a diagnostic message. Also,
print the message in szFormat, which is structured as with a call to vprintf().
Preconditions None.
Postconditions fCondition is true, or the program has terminated and the message in szFormat has
been displayed.
Parameters FEDID fedid – The handle of this federate and federate instance as assigned by the Test
Server. May be NULL.
bool fCondition – Condition to check.
char *szFormat – The message to display if fCondition is false.
varg *v – additional arguments as dictated by szFormat.
Return Values None.
Exceptions None.
When an assert kills the program, the program is safely disconnected from the Test Server.
Message API: The message API allows programs to send diagnostic messages to the ITP. Messages are
divided into classes that indicate the meaning of the message.
The message classes include:
- Entered function.
- Left function.
- Sent event.
- Received event.
- Made RTI call.
- Returned from RTI call.
- Warning.
- Non-fatal error.
- Caught exception.
- Handled exception.
- Assertion failure. (Never sent by a user call.)
- Program terminated. (Never sent by a user call.)
- Program connected to Test Server. (Never sent by a user call.)
- Program disconnected from Test Server. (Never sent by a user call.)
- Trace.
namespace TestClient {
void trace(FEDID, MSGCLS, char *, …);
void tracev(FEDID, MSGCLS, char *, varg *);
}
#define DECLARE_TRACE_WRAPPERS(prefix, fedid) \
inline void prefix##_trace(MSGCLS msgcls, char *szFormat, …) { \
varg *v; \
va_start(v, szFormat); \
TestClient::tracev(fedid, msgcls, szFormat, v); \
va_end(v); \
}
void TestClient::trace(FEDID fedid, MSGCLS msgcls, char *szFormat, …)
Description Display a trace messsage from fedid of class msgcls described by szFormat and …,
which are like the arguments to printf.
Preconditions msgcls is a valid message class identifier.
szFormat is not NULL.
Postconditions If the program is connected to the Test Server, then the message identified by
msgcls, szFormat, and … has been sent to the Test Server.
Parameters FEDID fedid – The handle of this federate and federate instance as assigned by the Test
Server. May be NULL.
MSGCLS msgcls – Condition to check.
char *szFormat – The message to display.
… – additional arguments as dictated by szFormat.
Return Values None.
Exceptions None.
void TestClient::tracev(FEDID fedid, MSGCLS msgcls, char *szFormat, varg *v)
Description Display a trace messsage from fedid of class msgcls described by szFormat and v,
which are like the arguments to vprintf.
Preconditions msgcls is a valid message class identifier.
szFormat is not NULL.
Postconditions If the program is connected to the Test Server, then the message identified by
msgcls, szFormat, and v has been sent to the Test Server.
Parameters FEDID fedid – The handle of this federate and federate instance as assigned by the Test
Server. May be NULL.
MSGCLS msgcls – Condition to check.
char *szFormat – The message to display.
varg *v – additional arguments as dictated by szFormat.
Return Values None.
Exceptions None.
Stimulus API: The stimulus API allows a program to wait for a specific message from the ITP. There
are two variants on this wait. In the first variant, a stimulus is counted as having been received if it was
received before or after the wait call. In the second variant, the stimulus must be received after the wait
call in order to be counted.
Stimuli are identified by strings, and stimuli themselves are data. Thus, this mechanism is obviously not
intended for fast communication. Instead it is intended to facilitate automated testing.
namespace TestClient {
char * WaitForStimulus(char *szStimulusID, bool fRetroactive);
}
char * TestClient::WaitForStimulus(char *szStimulusID, bool fRetroactive)
Description Wait for the stimulus identified by szStimulusID. If fRetroactive is true, then count the
stimulus as having been received if the Test Server received the stimulus between when
or before the program connected to the Test Server, and when this call was made. If this
is the case, return the most recently-received value. Always look for receipt after this
call.
Preconditions This process is currently connected to the Test Server.
szStimulusID is a valid character string.
Postconditions The stimulus identified by szStimulusID has been received.
The return value is a valid character string that becomes the responsibility of the
caller, or is alternately NULL.
Parameters char *szStimulusID – the name of the stimulus to wait for.
bool fRetroactive – whether to count receipt before the call as valid.
Return Values (char *) The value sent with the stimulus.
Exceptions class TestClient::eNotConnected {} – The process is not connected to the Test Server.
class TestClient::eLostConnection {} – The connection with the Test Server was lost.
State Dump API: The ITP coordinates collection of state information from the programs that it is
interested in at the user’s request. This includes the value of attributes, and internal state information.
Each program can register a state dump callback that dumps the state for that program when the Test Server
requests it. This callback is called asynchronously from the Test Client thread, and thus must be thread-
safe.
To be determined….