// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package util; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TimeMeasurementTest { private Clock mockedClock; @Before public void mockClock() { mockedClock = mock(SystemClock.class); } @After public void restoreDefaultClock() { Clock.restoreDefaultClock(); } @Test public void timeMeasurementShouldStartAtClockTime() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-2L); measurement.start(); assertThat(measurement.startedAt(), is(-2L)); } @Test public void elapsedTimeShouldReferenceClockTimeWhenNotStopped() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-3L, -1L); measurement.start(); assertThat(measurement.elapsed(), is(2L)); } @Test public void stopShouldReferenceClockTime() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-7L, -4L); measurement.start(); measurement.stop(); assertThat(measurement.stoppedAt(), is(-4L)); } @Test public void stopShouldFreezeElapsedTime() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-9L, -8L, -6L); measurement.start(); measurement.stop(); assertThat(measurement.elapsed(), is(1L)); assertThat(measurement.elapsed(), is(1L)); } @Test(expected=IllegalStateException.class) public void startedAtBeforeStartShouldThrowIllegalStateException() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); measurement.startedAt(); } @Test(expected=IllegalStateException.class) public void stoppedAtBeforeStopShouldThrowIllegalStateException() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); measurement.start(); measurement.stoppedAt(); } @Test public void callingStopMultipleTimesShouldHaveNoEffect() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-13L, -12L, -11L); measurement.start(); measurement.stop(); measurement.stop(); assertThat(measurement.elapsed(), is(1L)); } @Test public void stopStartShouldResetTheStartedAndStoppedAtTimes() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-17L, -16L, -15L, -14L); measurement.start(); assertThat(measurement.startedAt(), is(-17L)); measurement.stop(); assertThat(measurement.stoppedAt(), is(-16L)); measurement.start(); assertThat(measurement.startedAt(), is(-15L)); measurement.stop(); assertThat(measurement.stoppedAt(), is(-14L)); } @Test public void stopStartShouldAffectElapsedTimeCalculations() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-25L,-24L,-23L,-21L,-21L,-19L,-18L); measurement.start(); measurement.stop(); assertThat(measurement.elapsed(), is(1L)); measurement.start(); measurement.stop(); assertThat(measurement.elapsed(), is(2L)); measurement.start(); assertThat(measurement.elapsed(), is(2L)); measurement.stop(); assertThat(measurement.elapsed(), is(3L)); } @Test public void callingStartMultipleTimesShouldResetStartedAtAndElapsed() throws Exception { TimeMeasurement measurement = new TimeMeasurement(mockedClock); when(mockedClock.currentClockTimeInMillis()).thenReturn(-30L,-29L,-29L,-28L,-27L); measurement.start(); assertThat(measurement.startedAt(), is(-30L)); measurement.start(); assertThat(measurement.startedAt(), is(-29L)); assertThat(measurement.elapsed(), is(0L)); measurement.start(); assertThat(measurement.startedAt(), is(-28L)); assertThat(measurement.elapsed(), is(1L)); } @Test public void startShouldReturnSelfForCallChaining() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); assertThat(measurement.start(), is(sameInstance(measurement))); } @Test public void stopShouldReturnSelfForCallChaining() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); measurement.start(); assertThat(measurement.stop(), is(sameInstance(measurement))); } @Test public void startedAtDateShouldBeDateRepresentationOfStartedAt() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); assertThat(measurement.start().startedAtDate().getTime(), is(measurement.startedAt())); } @Test public void stoppedAtDateShouldBeDateRepresentationOfStoppedAt() throws Exception { TimeMeasurement measurement = new TimeMeasurement(); measurement.start(); assertThat(measurement.stop().stoppedAtDate().getTime(), is(measurement.stoppedAt())); } @Test public void elapsedSecondsShouldBeDoubleRepresentationOfElapsed() throws Exception { assertThat(timeMeasurementWithElapsedMillis(1).elapsedSeconds(), is(0.001d)); assertThat(timeMeasurementWithElapsedMillis(1000).elapsedSeconds(), is(1.0d)); assertThat(timeMeasurementWithElapsedMillis(2345).elapsedSeconds(), is(2.345d)); assertThat(timeMeasurementWithElapsedMillis(0).elapsedSeconds(), is(0d)); } private TimeMeasurement timeMeasurementWithElapsedMillis(final long millis) { return new TimeMeasurement() { @Override public long elapsed() { return millis; } }; } @Test public void alteringGlobalClockShouldNotAffectExistingTimeMeasurement() throws Exception { TimeMeasurement timeMeasurement = new TimeMeasurement(); DateAlteringClock globalClock = new DateAlteringClock(Clock.currentDate()).freeze(); TimeMeasurement frozentTimeMeasurement = new TimeMeasurement().start(); timeMeasurement.start(); SystemClock systemClock = new SystemClock(); long before = 0, after = 0; while (before == after) { after = systemClock.currentClockTimeInMillis(); if (before == 0) { before = after; } } assertThat(frozentTimeMeasurement.elapsed(), is(0L)); assertThat(timeMeasurement.elapsed(), is(not(0L))); } }