IncreasingTime { public static synchronized long currentTimeMillis() { long now = System.currentTimeMillis(); if (now > last) { last = now; } else { last++; } return last; }  static synchronized long currentTimeMillis(); static void advanceTime(int inc); static void catchUp();  }
@Test public void currentTimeMillisReturnsEverIncreasingTime() { List<Long> times = new ArrayList<>(NUM_ITERATIONS); for (int i = 0; i < NUM_ITERATIONS; i++) { times.add(IncreasingTime.currentTimeMillis()); } assertIncreasingTimes(NUM_ITERATIONS, times); }
@Test public void currentTimeMillisReturnsTimeGreaterThanSystemTime() { for (int i = 0; i < NUM_ITERATIONS; i++) { long systemTime = System.currentTimeMillis(); long increasedTime = IncreasingTime.currentTimeMillis(); assertTrue(increasedTime > systemTime); } }
@Test public void currentTimeMillisReturnsEverIncreasingTimeAcrossConcurrentThreads() throws Exception { final List<Long> times = Collections.synchronizedList(new ArrayList<Long>(NUM_ITERATIONS)); final List<Thread> threads = new ArrayList<>(); for (int i = 0; i < NUM_THREADS; i++) { Thread thread = new Thread(new Runnable() { public void run() { for (int i = 0; i < NUM_ITERATIONS; i++) { times.add(IncreasingTime.currentTimeMillis()); } } }); threads.add(thread); thread.start(); } for (Thread thread : threads) { thread.join(5000); } Collections.sort(times); assertIncreasingTimes(NUM_THREADS * NUM_ITERATIONS, times); }