1 package com.atlassian.scheduler.core.tests;
2
3 import com.atlassian.scheduler.SchedulerService;
4 import com.atlassian.scheduler.SchedulerServiceException;
5 import com.atlassian.scheduler.config.Schedule;
6 import org.hamcrest.Matcher;
7 import org.joda.time.DateTime;
8 import org.junit.Test;
9
10 import java.util.Date;
11
12 import static com.atlassian.scheduler.config.Schedule.forCronExpression;
13 import static com.atlassian.scheduler.config.Schedule.forInterval;
14 import static java.lang.System.currentTimeMillis;
15 import static org.hamcrest.Matchers.allOf;
16 import static org.hamcrest.Matchers.containsString;
17 import static org.hamcrest.Matchers.equalTo;
18 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
19 import static org.hamcrest.Matchers.lessThanOrEqualTo;
20 import static org.hamcrest.Matchers.not;
21 import static org.hamcrest.Matchers.nullValue;
22 import static org.junit.Assert.assertThat;
23 import static org.junit.Assert.fail;
24
25
26
27
28 public abstract class CalculateNextRunTimeTest {
29 protected abstract SchedulerService getSchedulerService();
30
31 @Test
32 public void testRunImmediately() {
33
34
35 final long now = currentTimeMillis();
36 assertNextRunTime(forInterval(60000L, null), between(now - 100L, now + 61000L));
37 }
38
39 @Test
40 public void testRunInThePast() {
41
42 final long now = currentTimeMillis();
43 assertNextRunTime(forInterval(60000L, new Date(now - 120000L)), between(now - 100L, now + 61000L));
44 }
45
46 @Test
47 public void testRunLater() {
48
49 final long now = currentTimeMillis();
50 assertNextRunTime(forInterval(60000L, new Date(now + 15000L)), now + 15000L);
51 }
52
53 @Test
54 public void testCronEveryFiveMinutes() {
55 final Date nextRunTime = calculateNextRunTime(forCronExpression("0 */5 * * * ?"));
56 assertThat(nextRunTime, not(nullValue()));
57
58 final DateTime dateTime = new DateTime(nextRunTime);
59 if (dateTime.getMillisOfSecond() != 0
60 || dateTime.getSecondOfMinute() != 0
61 || (dateTime.getMinuteOfHour() % 5) != 0) {
62 fail("Should have fallen on a 5 minute boundary: " + dateTime);
63 }
64 }
65
66 @Test
67 public void testFebruaryThirtyFirst() {
68 assertNeverRuns(forCronExpression("0 0 2 31 2 ?"));
69 }
70
71 @Test
72 public void testInvalidCronExpression() {
73 assertException(forCronExpression("0 0 2 31 2 *"), "must use '?'");
74 }
75
76
77 Matcher<Date> between(long min, long max) {
78
79 return allOf(greaterThanOrEqualTo(new Date(min)), lessThanOrEqualTo(new Date(max)));
80 }
81
82 Date calculateNextRunTime(Schedule schedule) {
83 try {
84 return getSchedulerService().calculateNextRunTime(schedule);
85 } catch (SchedulerServiceException sse) {
86 final AssertionError err = new AssertionError("Unexpected exception finding first run time for "
87 + schedule);
88 err.initCause(sse);
89 throw err;
90 }
91 }
92
93 void assertNextRunTime(Schedule schedule, long value) {
94 assertNextRunTime(schedule, equalTo(new Date(value)));
95 }
96
97 void assertNextRunTime(Schedule schedule, Matcher<? super Date> matcher) {
98 assertThat(calculateNextRunTime(schedule), matcher);
99 }
100
101 void assertNeverRuns(Schedule schedule) {
102 assertThat(calculateNextRunTime(schedule), nullValue(Date.class));
103 }
104
105 void assertException(Schedule schedule, String substring) {
106 final SchedulerService schedulerService = getSchedulerService();
107 try {
108 final Date nextRunTime = schedulerService.calculateNextRunTime(schedule);
109 fail("Got first run time <" + nextRunTime + "> when exception containing <" + substring +
110 "> was expected for <" + schedule + '>');
111 } catch (SchedulerServiceException sse) {
112 assertThat(sse.getMessage(), containsString(substring));
113 }
114 }
115 }
116