View Javadoc

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   * @since v1.6.0
27   */
28  public abstract class CalculateNextRunTimeTest {
29      protected abstract SchedulerService getSchedulerService();
30  
31      @Test
32      public void testRunImmediately() {
33          // We use a wide window here because Quartz's clock isn't pluggable and whether it adds the interval to
34          // the time or not seems to be a fairly random thing.
35          final long now = currentTimeMillis();
36          assertNextRunTime(forInterval(60000L, null), between(now - 100L, now + 61000L));
37      }
38  
39      @Test
40      public void testRunInThePast() {
41          // wide window again (see above)
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          // But here we're using an exact time and there shouldn't be any mismatch to it
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          //noinspection unchecked
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