From a18b0152df2d91b9d5eaab47cb2417e2a89d2382 Mon Sep 17 00:00:00 2001 From: depristo Date: Sun, 22 May 2011 19:45:31 +0000 Subject: [PATCH] Contracts for SimpleTimer, as well as UnitTests git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@5841 348d0f76-0448-11de-a6fe-93d51630548a --- .../sting/utils/SimpleTimer.java | 76 ++++++++++++++++++- .../sting/utils/SimpleTimerUnitTest.java | 54 +++++++++++++ 2 files changed, 126 insertions(+), 4 deletions(-) create mode 100755 java/test/org/broadinstitute/sting/utils/SimpleTimerUnitTest.java diff --git a/java/src/org/broadinstitute/sting/utils/SimpleTimer.java b/java/src/org/broadinstitute/sting/utils/SimpleTimer.java index 2d45f04fa..a59c5134a 100644 --- a/java/src/org/broadinstitute/sting/utils/SimpleTimer.java +++ b/java/src/org/broadinstitute/sting/utils/SimpleTimer.java @@ -1,52 +1,120 @@ package org.broadinstitute.sting.utils; import java.io.PrintStream; +import com.google.java.contract.*; /** - * A useful simple system for timing code. + * A useful simple system for timing code. This code is not thread safe! * * User: depristo * Date: Dec 10, 2010 * Time: 9:07:44 AM */ +@Invariant({ + "elapsed >= 0", + "startTime >= 0", + "name != null", + "! running || startTime > 0"}) public class SimpleTimer { - private String name = ""; + final private String name; private long elapsed = 0l; - private long startTime = -1l; + private long startTime = 0l; boolean running = false; + /** + * Creates an anonymous simple timer + */ + @Ensures("name != null && name.equals(\"Anonymous\")") + public SimpleTimer() { + this("Anonymous"); + } + + /** + * Creates a simple timer named name + * @param name of the timer, must not be null + */ + @Requires("name != null") + @Ensures("this.name != null && this.name.equals(name)") public SimpleTimer(String name) { this.name = name; } + /** + * @return the name associated with this timer + */ + @Ensures("result != null") public String getName() { return name; } + /** + * Starts the timer running, and sets the elapsed time to 0. This is equivalent to + * resetting the time to have no history at all. + * + * @return this object, for programming convenience + */ + @Requires("running == false") + @Ensures({"result != null", "elapsed == 0l"}) public SimpleTimer start() { elapsed = 0l; restart(); return this; } + /** + * Starts the timer running, without reseting the elapsed time. This function may be + * called without first calling start(). The only difference between start and restart + * is that start resets the elapsed time, while restart does not. + * + * @return this object, for programming convenience + */ + @Requires("running == false") + @Ensures("result != null") public SimpleTimer restart() { running = true; startTime = currentTime(); return this; } + /** + * @return is this timer running? + */ + public boolean isRunning() { + return running; + } + + /** + * @return A convenience function to obtain the current time in milliseconds from this timer + */ public long currentTime() { return System.currentTimeMillis(); } + /** + * Stops the timer. Increases the elapsed time by difference between start and now. The + * timer must be running in order to call stop + * + * @return this object, for programming convenience + */ + @Requires("running == true") + @Ensures({"result != null", "elapsed >= old(elapsed)", "running == false"}) public SimpleTimer stop() { running = false; elapsed += currentTime() - startTime; return this; } + /** + * Returns the total elapsed time of all start/stops of this timer. If the timer is currently + * running, includes the difference from currentTime() and the start as well + * + * @return this time, in seconds + */ + @Ensures({ + "result >= (elapsed/1000.0)", + "result >= 0"}) public double getElapsedTime() { - return (running ? (currentTime() - startTime) : elapsed) / 1000.0; + return (running ? (currentTime() - startTime + elapsed) : elapsed) / 1000.0; } diff --git a/java/test/org/broadinstitute/sting/utils/SimpleTimerUnitTest.java b/java/test/org/broadinstitute/sting/utils/SimpleTimerUnitTest.java new file mode 100755 index 000000000..3f5d05e66 --- /dev/null +++ b/java/test/org/broadinstitute/sting/utils/SimpleTimerUnitTest.java @@ -0,0 +1,54 @@ +package org.broadinstitute.sting.utils; + +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; + +public class SimpleTimerUnitTest extends BaseTest { + private final static String NAME = "unit.test.timer"; + + @Test + public void testSimpleTimer() { + SimpleTimer t = new SimpleTimer(NAME); + Assert.assertEquals(t.getName(), NAME, "Name is not the provided one"); + Assert.assertFalse(t.isRunning(), "Initial state of the timer is running"); + Assert.assertEquals(t.getElapsedTime(), 0.0, "New timer elapsed time should be 0"); + + t.start(); + Assert.assertTrue(t.isRunning(), "Started timer isn't running"); + Assert.assertTrue(t.getElapsedTime() >= 0.0, "Elapsed time should be >= 0"); + double t1 = t.getElapsedTime(); + idleLoop(); // idle loop to wait a tiny bit of time + double t2 = t.getElapsedTime(); + Assert.assertTrue(t2 >= t1, "T2 >= T1 for a running time"); + + t.stop(); + Assert.assertFalse(t.isRunning(), "Stopped timer still running"); + double t3 = t.getElapsedTime(); + idleLoop(); // idle loop to wait a tiny bit of time + double t4 = t.getElapsedTime(); + Assert.assertTrue(t4 == t3, "Elapsed times for two calls of stop timer not the same"); + + t.restart(); + idleLoop(); // idle loop to wait a tiny bit of time + double t5 = t.getElapsedTime(); + Assert.assertTrue(t.isRunning(), "Restarted timer should be running"); + idleLoop(); // idle loop to wait a tiny bit of time + double t6 = t.getElapsedTime(); + Assert.assertTrue(t5 >= t4, "Restarted timer elapsed time should be after elapsed time preceding the restart"); + Assert.assertTrue(t6 >= t5, "Second elapsed time not after the first in restarted timer"); + + t.stop().start(); + Assert.assertTrue(t.isRunning(), "second started timer isn't running"); + Assert.assertTrue(t.getElapsedTime() >= 0.0, "elapsed time should have been reset"); + Assert.assertTrue(t.getElapsedTime() < t6, "elapsed time isn't less than time before start call"); // we should have effective no elapsed time + } + + private final static void idleLoop() { + for ( int i = 0; i < 100000; i++ ) ; // idle loop to wait a tiny bit of time + } +} \ No newline at end of file