To test software that depends on time, using the actual time is usually not feasable or even possible. To perform actons during a certain time period, a test can be speeded up if an accelerated time is used. Another example is software that acts on a specific date. To test such software the environment in which the program runs needs to set the date to that value instead of using the actual date. To facilitate testing of time dependent software, a virtual timebase is needed. This timebase will provide the virtual time to the system under test while the virtual time can be controlled by the test framework. When the time dependent software is not being tested but runs in actual operation the virtual time must be equal to the actual time.
Tachyon provides a virtual timebase with an interface that replaces system calls such as nanosleep(2) and time(2). Instead of using these system calls, a program would call Tachyon::nanosleep() and Tachyon::time().
Features of the Tachyon class include:
Functions to control the virtual timebase:
Example of performing an action every minute for 10 minutes:
Tachyon timebase; struct timespec interval; interval.tv_sec = 60; interval.tv_nsec = 0; std::cout << "Tachyon name is " << timebase.name() << "\n"; for (int i = 0; i < 10; i++) { timebase.nanosleep(interval); std::cout << "One minute.\n" }
Testing this in actual time would at least take 10 minutes. To speed up the test, the Tachyon object is instructed by a test program to accellerate time:
std::cin >> tachyon_name; Tachyon testtime(tachyon_name); testtime.accellerate(30); while (std::cin >> report) { std::cout << report; }
The virtual time is calculated by using an offset o and an acceleration factor a in a simple linear function:
Tv = T0 + a * (Ta - T0) + oT0 is the time at the moment of changing the accelleration. By default, the acceleration is 1.0 and the offset is 0, rendering the virtual time equal to the actual time. When the acceleration is unequal to 1.0, the virtual time starts to deviate from the actual time, i.e. run slower or faster. The difference or 'offset' will gruadually change as time progresses. At any point in time, Ta, the offset can be calculated with: o' = Tv - Ta = (1 - a) * T0 - (1 - a) * Ta + o If the acceleration, a, is changed, the offset is recalculated to reflect the change in acceleration and T0 is set to the time at which the acceleration is changed.
The nanosleep method will sleep for an interval of time, ts, in virtual time. This is a period of ts / a in actual time, unless the the accelleration or offset are changed during the sleep. If either of these parameters is changed, the time to sleep is recalculated from the moment of change to the moment the sleep period is supposed to end in virtual time. Receiving a message to change the accelleration or the virtual time interrupts a sleeping process. At that moment, the sleep will resume with a recalculated period in actual time. This is the diffrence bewteen at which the sleep ends and the current virtual time divided by the accelleration.
The nanosleep method calculates the virtual time at which the sleep ends and call the sleep_until method to perform the actual sleep by suspending the process. Interruptions of the sleep are handled by recalculating the sleep period from the possibly changed parameters and resuming the sleep if needed. The nanosleep(2) system call is used to perform the actual sleep. This system call may return for either one of four reasons.
To control the virtual time from an external process, a form of inter process communication (IPC) is used. The external process, usually a test program, can find the Tachyon object to control through a name which is assigned for that Tachyon object. Two or more Tachyon objects may exist, one of which holds the virtual time used by the time dependent software. The other Tachyon object(s) are used to control the virtual timebase and send the timebase parameters through a form of IPC.
struct timespec
. It is defined as follows:
struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
The parameters to control a Tachyon object are the accelleration factor and the time offset. These parameters are controlled by sending messages to the Tachyon object's message queue in ASCII format. A message starts with a single letter to select the parameter, followed by a number for the parameter's value. The letter can be 'A' for the accelleration or 'T' for the time. To set the accelleration the message is 'A', immediately followed by a number. This number can be a floating point number. For example, the message:
A2.5makes the virtaul time run 2.5 times faster. The virtual clock is set to a specific time by sending a 'T' followed by an integer number. The number is the number of seconds since the epoch (1970-01-01 00:00:00 +0000 (UTC)). For example:
T1563942575sets the time to Jul 24 06:29:35 CEST 2019.
tachyon [options] tachyon-name. Allowed options: -h [ --help ] produce help message --tachyon-name arg tachyon name -a [ --accelleration ] arg set time acceleration factor -t [ --time ] arg set time value in seconds