1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.time;
18
19 import static org.hamcrest.MatcherAssert.assertThat;
20 import static org.hamcrest.Matchers.allOf;
21 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
22 import static org.hamcrest.Matchers.lessThan;
23 import static org.hamcrest.Matchers.lessThanOrEqualTo;
24 import static org.hamcrest.Matchers.not;
25 import static org.hamcrest.Matchers.startsWith;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertFalse;
28 import static org.junit.jupiter.api.Assertions.assertNotEquals;
29 import static org.junit.jupiter.api.Assertions.assertNull;
30 import static org.junit.jupiter.api.Assertions.assertThrows;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32
33 import java.time.Duration;
34 import java.time.Instant;
35 import java.util.concurrent.TimeUnit;
36
37 import org.apache.commons.lang3.AbstractLangTest;
38 import org.apache.commons.lang3.ThreadUtils;
39 import org.apache.commons.lang3.reflect.FieldUtils;
40 import org.junit.jupiter.api.Test;
41
42
43
44
45 public class StopWatchTest extends AbstractLangTest {
46
47 private static final Duration MILLIS_200 = Duration.ofMillis(200);
48 private static final Duration MILLIS_550 = Duration.ofMillis(550);
49 private static final String MESSAGE = "Baking cookies";
50 private static final Duration MIN_SLEEP = Duration.ofMillis(20);
51 private static final String ZERO_HOURS_PREFIX = "00:";
52 private static final String ZERO_TIME_ELAPSED = "00:00:00.000";
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 private StopWatch createMockStopWatch(final long nanos) {
74 final StopWatch watch = StopWatch.createStarted();
75 watch.suspend();
76 return set(watch, nanos);
77 }
78
79 private StopWatch set(final StopWatch watch, final long nanos) {
80 try {
81 final long currentNanos = System.nanoTime();
82 FieldUtils.writeField(watch, "startTimeNanos", currentNanos - nanos, true);
83 FieldUtils.writeField(watch, "stopTimeNanos", currentNanos, true);
84 } catch (final IllegalAccessException e) {
85 return null;
86 }
87 return watch;
88 }
89
90 private void sleep(final Duration duration) throws InterruptedException {
91 ThreadUtils.sleep(duration);
92 }
93
94
95
96
97 @Test
98 public void testBadStates() {
99 final StopWatch watch = new StopWatch();
100 assertThrows(IllegalStateException.class, watch::stop,
101 "Calling stop on an unstarted StopWatch should throw an exception. ");
102
103 assertThrows(IllegalStateException.class, watch::suspend,
104 "Calling suspend on an unstarted StopWatch should throw an exception. ");
105
106 assertThrows(IllegalStateException.class, watch::split,
107 "Calling split on a non-running StopWatch should throw an exception. ");
108
109 assertThrows(IllegalStateException.class, watch::unsplit,
110 "Calling unsplit on an unsplit StopWatch should throw an exception. ");
111
112 assertThrows(IllegalStateException.class, watch::resume,
113 "Calling resume on an unsuspended StopWatch should throw an exception. ");
114
115 watch.start();
116
117 assertThrows(IllegalStateException.class, watch::start,
118 "Calling start on a started StopWatch should throw an exception. ");
119
120 assertThrows(IllegalStateException.class, watch::unsplit,
121 "Calling unsplit on an unsplit StopWatch should throw an exception. ");
122
123 assertThrows(IllegalStateException.class, watch::getSplitTime,
124 "Calling getSplitTime on an unsplit StopWatch should throw an exception. ");
125
126 assertThrows(IllegalStateException.class, watch::getSplitDuration,
127 "Calling getSplitTime on an unsplit StopWatch should throw an exception. ");
128
129 assertThrows(IllegalStateException.class, watch::resume,
130 "Calling resume on an unsuspended StopWatch should throw an exception. ");
131
132 watch.stop();
133
134 assertThrows(IllegalStateException.class, watch::start,
135 "Calling start on a stopped StopWatch should throw an exception as it needs to be reset. ");
136 }
137
138 @Test
139 public void testBooleanStates() {
140 final StopWatch watch = new StopWatch();
141 assertFalse(watch.isStarted());
142 assertFalse(watch.isSuspended());
143 assertTrue(watch.isStopped());
144
145 watch.start();
146 assertTrue(watch.isStarted());
147 assertFalse(watch.isSuspended());
148 assertFalse(watch.isStopped());
149
150 watch.suspend();
151 assertTrue(watch.isStarted());
152 assertTrue(watch.isSuspended());
153 assertFalse(watch.isStopped());
154
155 watch.stop();
156 assertFalse(watch.isStarted());
157 assertFalse(watch.isSuspended());
158 assertTrue(watch.isStopped());
159 }
160
161 @Test
162 public void testFormatSplitTime() {
163 final StopWatch watch = StopWatch.createStarted();
164 ThreadUtils.sleepQuietly(MIN_SLEEP);
165 watch.split();
166 final String formatSplitTime = watch.formatSplitTime();
167 assertNotEquals(ZERO_TIME_ELAPSED, formatSplitTime);
168 assertThat("formatSplitTime", formatSplitTime, startsWith(ZERO_HOURS_PREFIX));
169 }
170
171 @Test
172 public void testFormatSplitTimeWithMessage() {
173 final StopWatch watch = new StopWatch(MESSAGE);
174 watch.start();
175 ThreadUtils.sleepQuietly(MIN_SLEEP);
176 watch.split();
177 final String formatSplitTime = watch.formatSplitTime();
178 assertThat("formatSplitTime", formatSplitTime, not(startsWith(MESSAGE)));
179 assertThat("formatSplitTime", formatSplitTime, startsWith(ZERO_HOURS_PREFIX));
180 }
181
182 @Test
183 public void testFormatTime() {
184 final StopWatch watch = StopWatch.create();
185 final String formatTime = watch.formatTime();
186 assertEquals(ZERO_TIME_ELAPSED, formatTime);
187 assertThat("formatTime", formatTime, startsWith(ZERO_HOURS_PREFIX));
188 }
189
190 @Test
191 public void testFormatTimeWithMessage() {
192 final StopWatch watch = new StopWatch(MESSAGE);
193 final String formatTime = watch.formatTime();
194 assertThat("formatTime", formatTime, not(startsWith(MESSAGE)));
195 }
196
197 @Test
198 public void testGetDuration() throws InterruptedException {
199 final StopWatch watch = new StopWatch();
200 assertEquals(Duration.ZERO, watch.getDuration());
201 assertEquals(ZERO_TIME_ELAPSED, watch.toString());
202 watch.start();
203 sleep(MILLIS_550);
204 assertThat("watch.getDuration()", watch.getDuration().toMillis(), lessThan(2000L));
205 }
206
207 @Test
208 public void testGetSplitDuration() {
209
210
211 final StopWatch watch = StopWatch.createStarted();
212 watch.split();
213 set(watch, 123456);
214
215 assertEquals(Duration.ofNanos(123456), watch.getSplitDuration());
216 }
217
218 @Test
219 public void testGetStartInstant() {
220 final long beforeStopWatchMillis = System.currentTimeMillis();
221 final StopWatch watch = new StopWatch();
222 assertThrows(IllegalStateException.class, watch::getStartInstant, "Calling getStartInstant on an unstarted StopWatch should throw an exception");
223 watch.start();
224
225 watch.getStartInstant();
226 assertThat("getStartInstant", watch.getStartInstant(), greaterThanOrEqualTo(Instant.ofEpochMilli(beforeStopWatchMillis)));
227
228 watch.reset();
229 assertThrows(IllegalStateException.class, watch::getStartInstant,
230 "Calling getStartInstant on a reset, but unstarted StopWatch should throw an exception");
231 }
232
233 @Test
234 public void testGetStartTime() {
235 final long beforeStopWatchMillis = System.currentTimeMillis();
236 final StopWatch watch = new StopWatch();
237 assertThrows(IllegalStateException.class, watch::getStartTime, "Calling getStartTime on an unstarted StopWatch should throw an exception");
238 watch.start();
239
240 watch.getStartTime();
241 assertThat("getStartTime", watch.getStartTime(), greaterThanOrEqualTo(beforeStopWatchMillis));
242
243 watch.reset();
244 assertThrows(IllegalStateException.class, watch::getStartTime, "Calling getStartTime on a reset, but unstarted StopWatch should throw an exception");
245 }
246
247 @Test
248 public void testGetTime() throws InterruptedException {
249 final StopWatch watch = new StopWatch();
250 assertEquals(0, watch.getTime());
251 assertEquals(ZERO_TIME_ELAPSED, watch.toString());
252 watch.start();
253 sleep(MILLIS_550);
254 assertThat("watch.getTime()", watch.getTime(), lessThan(2000L));
255 }
256
257 @Test
258 public void testGetWithTimeUnit() {
259
260
261 final StopWatch watch = createMockStopWatch(
262 TimeUnit.HOURS.toNanos(2)
263 + TimeUnit.MINUTES.toNanos(59)
264 + TimeUnit.SECONDS.toNanos(1)
265 + TimeUnit.MILLISECONDS.toNanos(999));
266
267 assertEquals(2L, watch.getTime(TimeUnit.HOURS));
268 assertEquals(179L, watch.getTime(TimeUnit.MINUTES));
269 assertEquals(10741L, watch.getTime(TimeUnit.SECONDS));
270 assertEquals(10741999L, watch.getTime(TimeUnit.MILLISECONDS));
271 }
272
273 @Test
274 public void testLang315() throws InterruptedException {
275 final StopWatch watch = StopWatch.createStarted();
276 sleep(MILLIS_200);
277 watch.suspend();
278 final long suspendTime = watch.getTime();
279 final Duration suspendDuration = watch.getDuration();
280 sleep(MILLIS_200);
281 watch.stop();
282 final long totalTime = watch.getTime();
283 final Duration totalDuration = watch.getDuration();
284 assertEquals(suspendTime, totalTime);
285 assertEquals(suspendDuration, totalDuration);
286 }
287
288 @Test
289 public void testMessage() {
290 assertNull(StopWatch.create().getMessage());
291 final StopWatch stopWatch = new StopWatch(MESSAGE);
292 assertEquals(MESSAGE, stopWatch.getMessage());
293 assertThat("stopWatch.toString", stopWatch.toString(), startsWith(MESSAGE));
294 stopWatch.start();
295 stopWatch.split();
296 assertThat("stopWatch.toSplitString", stopWatch.toSplitString(), startsWith(MESSAGE));
297 }
298
299 @Test
300 public void testSimple() throws InterruptedException {
301 final StopWatch watch = StopWatch.createStarted();
302 sleep(MILLIS_550);
303 watch.stop();
304 final long time = watch.getTime();
305 final Duration duration = watch.getDuration();
306 assertEquals(time, watch.getTime());
307 assertEquals(duration, watch.getDuration());
308 assertThat("time", time, allOf(greaterThanOrEqualTo(500L), lessThan(2000L)));
309 assertThat("duration", duration.toMillis(), allOf(greaterThanOrEqualTo(500L), lessThan(2000L)));
310 watch.reset();
311 assertEquals(0, watch.getTime());
312 assertEquals(Duration.ZERO, watch.getDuration());
313 }
314
315 @Test
316 public void testSplit() throws InterruptedException {
317 final StopWatch watch = StopWatch.createStarted();
318 sleep(MILLIS_550);
319
320 watch.split();
321 final long splitTime = watch.getSplitTime();
322 final Duration splitDuration = watch.getSplitDuration();
323 assertEquals(splitTime, watch.getSplitDuration().toMillis());
324 assertEquals(12, watch.toSplitString().length(), "Formatted split string not the correct length");
325 sleep(MILLIS_550);
326
327 watch.unsplit();
328 sleep(MILLIS_550);
329
330 watch.stop();
331 final long totalTime = watch.getTime();
332 final Duration totalDuration = watch.getDuration();
333 assertThat("splitTime", splitTime, allOf(greaterThanOrEqualTo(500L), lessThan(1000L)));
334 assertThat("splitDuration", splitDuration.toMillis(), allOf(greaterThanOrEqualTo(500L), lessThan(1000L)));
335 assertThat("totalTime", totalTime, allOf(greaterThanOrEqualTo(1500L), lessThan(2100L)));
336 assertThat("totalDuration", totalDuration.toMillis(), allOf(greaterThanOrEqualTo(1500L), lessThan(2100L)));
337 }
338
339 @Test
340 public void testStatic() {
341 final StopWatch watch = StopWatch.createStarted();
342 assertTrue(watch.isStarted());
343 }
344
345 @Test
346 public void testStopInstantSimple() throws InterruptedException {
347 final StopWatch watch = StopWatch.createStarted();
348 final long testStartMillis = System.currentTimeMillis();
349 sleep(MILLIS_550);
350 watch.stop();
351 final long testEndMillis = System.currentTimeMillis();
352 final Instant stopTime = watch.getStopInstant();
353 assertEquals(stopTime, watch.getStopInstant());
354 assertThat("stopTime", stopTime,
355 allOf(greaterThanOrEqualTo(Instant.ofEpochMilli(testStartMillis)), lessThanOrEqualTo(Instant.ofEpochMilli(testEndMillis))));
356 }
357
358 @Test
359 public void testStopTimeSimple() throws InterruptedException {
360 final StopWatch watch = StopWatch.createStarted();
361 final long testStartMillis = System.currentTimeMillis();
362 sleep(MILLIS_550);
363 watch.stop();
364 final long testEndMillis = System.currentTimeMillis();
365 final long stopTime = watch.getStopTime();
366 assertEquals(stopTime, watch.getStopTime());
367 assertThat("stopTime", stopTime, allOf(greaterThanOrEqualTo(testStartMillis), lessThanOrEqualTo(testEndMillis)));
368 }
369
370 @Test
371 public void testSuspend() throws InterruptedException {
372
373 final StopWatch watch = StopWatch.createStarted();
374 final long testStartMillis = System.currentTimeMillis();
375 final long testStartNanos = System.nanoTime();
376 final Instant testStartInstant = Instant.ofEpochMilli(testStartMillis);
377 sleep(MILLIS_550);
378 watch.suspend();
379 final long testSuspendMillis = System.currentTimeMillis();
380 final long testSuspendNanos = System.nanoTime();
381 final long testSuspendTimeNanos = testSuspendNanos - testStartNanos;
382 final Duration testSuspendDuration = Duration.ofNanos(testSuspendTimeNanos);
383 final long suspendTimeFromNanos = watch.getTime();
384 final Duration suspendDuration = watch.getDuration();
385 final long stopTimeMillis = watch.getStopTime();
386 final Instant stopInstant = watch.getStopInstant();
387
388 assertThat("testStartMillis <= stopTimeMillis", testStartMillis, lessThanOrEqualTo(stopTimeMillis));
389 assertThat("testStartInstant <= stopInstant", testStartInstant, lessThanOrEqualTo(stopInstant));
390 assertThat("testSuspendMillis <= stopTimeMillis", testSuspendMillis, lessThanOrEqualTo(stopTimeMillis));
391 assertThat("testSuspendMillis <= stopInstant", testSuspendMillis, lessThanOrEqualTo(stopInstant.toEpochMilli()));
392
393 sleep(MILLIS_550);
394 watch.resume();
395 sleep(MILLIS_550);
396 watch.stop();
397 final long totalTimeFromNanos = watch.getTime();
398 final Duration totalDuration = watch.getDuration();
399
400 assertThat("suspendTimeFromNanos", suspendTimeFromNanos, greaterThanOrEqualTo(500L));
401 assertThat("suspendDuration", suspendDuration, greaterThanOrEqualTo(Duration.ofMillis(500L)));
402 assertThat("suspendTimeFromNanos <= testSuspendTimeNanos", suspendTimeFromNanos, lessThanOrEqualTo(testSuspendTimeNanos));
403 assertThat("suspendDuration <= testSuspendDuration", suspendDuration, lessThanOrEqualTo(testSuspendDuration));
404 assertThat("totalTimeFromNanos", totalTimeFromNanos, greaterThanOrEqualTo(1000L));
405 assertThat("totalDuration", totalDuration, greaterThanOrEqualTo(Duration.ofMillis(1000L)));
406
407 assertThat("totalTimeFromNanos", totalTimeFromNanos, lessThan(2500L));
408 assertThat("totalDuration", totalDuration, lessThan(Duration.ofMillis(2500L)));
409 }
410
411 @Test
412 public void testToSplitString() throws InterruptedException {
413 final StopWatch watch = StopWatch.createStarted();
414 sleep(MILLIS_550);
415 watch.split();
416 final String splitStr = watch.toSplitString();
417 assertEquals(12, splitStr.length(), "Formatted split string not the correct length");
418 }
419
420 @Test
421 public void testToSplitStringWithMessage() throws InterruptedException {
422 final StopWatch watch = new StopWatch(MESSAGE);
423 watch.start();
424 sleep(MILLIS_550);
425 watch.split();
426 final String splitStr = watch.toSplitString();
427 assertEquals(12 + MESSAGE.length() + 1, splitStr.length(), "Formatted split string not the correct length");
428 }
429
430 @Test
431 public void testToString() throws InterruptedException {
432
433 final StopWatch watch = StopWatch.createStarted();
434 sleep(MILLIS_550);
435 watch.split();
436 final String splitStr = watch.toString();
437 assertEquals(12, splitStr.length(), "Formatted split string not the correct length");
438 }
439
440 @Test
441 public void testToStringWithMessage() throws InterruptedException {
442 assertThat("message", new StopWatch(MESSAGE).toString(), startsWith(MESSAGE));
443
444 final StopWatch watch = new StopWatch(MESSAGE);
445 watch.start();
446 sleep(MILLIS_550);
447 watch.split();
448 final String splitStr = watch.toString();
449 assertEquals(12 + MESSAGE.length() + 1, splitStr.length(), "Formatted split string not the correct length");
450 }
451 }