views:

333

answers:

5

I have a Java app that runs on linux that has a lots of events and business logic that revolve around times and dates.

For testing, is it possible to tweak something into time going faster. Let's say, make a whole computer-year finish in one hour wall time?

+2  A: 

If you are system calls to get the system time (i.e. System.currentTimeMillis()), presumably, you can speed up time by changing the system time. This should reflect on the time you see in your application.

If you are using other ways to calculate time (elapsed time from JVM start (i.e. System.nanoTime()), net time servers, etc...) then the answer is that it is not possible.


I can't stress enough that I am just explaining how to do what you asked, and this is good only for integration testing, when you take into considerations anything else you are affecting on said machine.

This should not come as a replacement whatsoever for proper and extensive unit-testing.

Yuval A
If anyone else is using the machine, they will not be happy. If the simulation crashes, your machine's clock is wrong. If you create files during the simulation, their timestamps will be in the future afterwards.
Jonathan Leffler
@Jonathan, well put, I updated my answer with a disclaimer
Yuval A
A: 

I have no idea if this is possible but how about running the entire thing in a virtual machine, maybe virtualbox, wmware, qemu or similar.

Maybe you can set those to ignore the real time/world....? If it is possible it would be kind off cool anyway ;-)

/Johan

Johan
+6  A: 

You can write a wrapper interface for your time/date calls. Have one real implementation that does real system calls, and a test implementation that can do whatever you want (run faster, slower, fake dates, etc).

patros
A: 

You have to design your system so that you can 'reschedule' the clock during testing. For some classes of system, there is an event queue, which stores scheduled events in time order. At any point in the simulation, the next event is the first item in the queue; you can pull it off the queue, and adjust the effective time so that it matches the time when that event occurs. As new events are scheduled, they're added to the queue. Thus, you can process the events as quickly as the system allows, rather than having to wait for actual time to elapse. But you have to design your system to allow such a mechanism to work.

Jonathan Leffler
+6  A: 

One approach that works best for unit testing is to abstract the way the current time is accessed in your code.

Instead of calling System.currentTimeMillis() directly you can provide your own implementation.

Something like this (pseudo-code):

class MyTime {
   private static TimeInterface CurrentTimeInterface = new DefaultTimeImpl();

   public setTimeInterface(TimeInterface timeInterface) {
      CurrentTimeInterface = timeInterface;
   }

   public int getTime() { CurrentTimeInterface.getTime(); }

}

class DefaultTimeImpl implements TimeInterface {
   public int getTime() { return System.currentTimeMillis(); }
}

class TestTimeImpl implements TimeInterface {
   private int CurrentTimeMillis = 0;
   public int getTime() { return CurrentTimeMillis; }
   public void setTime(int timeMillis) { CurrentTimeMillis = timeMillis}
   public void sleep(int millis) { CurrentTimeMillis += millis; }
}

Then, everywhere you would have called System.getTimeMillis() instead call MyTime.getTime(). When you're testing your code simply create a TestTimeImpl and call MyTime.setTimeInterface(testTimeImpl). Then when you want time to advance call testTimeImpl.sleep() or testTimeImpl.setTime().

This allows you to simulate any time down to the millisecond.

Tom