View Javadoc

1   package com.atlassian.scheduler.core.util;
2   
3   import org.junit.Test;
4   
5   import java.util.regex.Matcher;
6   import java.util.regex.Pattern;
7   
8   import static com.atlassian.scheduler.core.util.CronExpressionQuantizer.Randomize.ALWAYS;
9   import static com.atlassian.scheduler.core.util.CronExpressionQuantizer.Randomize.AS_NEEDED;
10  import static com.atlassian.scheduler.core.util.CronExpressionQuantizer.Randomize.NEVER;
11  import static com.atlassian.scheduler.core.util.CronExpressionQuantizer.quantizeSecondsField;
12  import static org.hamcrest.Matchers.equalTo;
13  import static org.junit.Assert.assertThat;
14  import static org.junit.Assert.fail;
15  
16  /**
17   * @since v1.0
18   */
19  @SuppressWarnings("ConstantConditions")
20  public class CronExpressionQuantizerTest {
21      private static final Pattern SIMPLE_SECONDS_FIELD = Pattern.compile("^([1-5]?\\d) (.*)$");
22  
23      // How certain we want to be that we didn't get a spurious pass from a fortunate random number.
24      private static final int ATTEMPTS = 100;
25  
26      @Test
27      public void testNullOrIncompleteExpression() {
28          verifyNullOrIncompleteExpression(null);
29          verifyNullOrIncompleteExpression("");
30          verifyNullOrIncompleteExpression("0");
31          verifyNullOrIncompleteExpression("a");
32          verifyNullOrIncompleteExpression("*");
33          verifyNullOrIncompleteExpression("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
34      }
35  
36      @Test
37      public void testRandomizedNever() {
38          assertZeroed("x * * * * ?", NEVER);
39          assertZeroed("0 * * * * ?", NEVER);
40          assertNoChange("42 * * * * ?", NEVER);
41          assertZeroed("60 * * * * ?", NEVER);
42          assertZeroed("*/5 * * * * ?", NEVER);
43          assertZeroed("7,12 * * * * ?", NEVER);
44          assertZeroed("x * * * * ?", NEVER);
45          assertZeroed("a b c", NEVER);
46      }
47  
48      @Test
49      public void testRandomizedAsNeededByNullArgument() {
50          assertRandomized("x * * * * ?", null);
51          assertNoChange("0 * * * * ?", null);
52          assertNoChange("42 * * * * ?", null);
53          assertRandomized("60 * * * * ?", null);
54          assertRandomized("*/5 * * * * ?", null);
55          assertRandomized("7,12 * * * * ?", null);
56          assertRandomized("x * * * * ?", null);
57          assertRandomized("a b c", null);
58      }
59  
60      @Test
61      public void testRandomizedAsNeededByDefault() {
62          assertRandomized("x * * * * ?");
63          assertNoChange("0 * * * * ?");
64          assertNoChange("42 * * * * ?");
65          assertRandomized("60 * * * * ?");
66          assertRandomized("*/5 * * * * ?");
67          assertRandomized("7,12 * * * * ?");
68          assertRandomized("x * * * * ?");
69          assertRandomized("a b c");
70      }
71  
72      @Test
73      public void testRandomizedAsNeeded() {
74          assertRandomized("x * * * * ?", AS_NEEDED);
75          assertZeroed("0 * * * * ?", AS_NEEDED);
76          assertNoChange("42 * * * * ?", AS_NEEDED);
77          assertRandomized("60 * * * * ?", AS_NEEDED);
78          assertRandomized("*/5 * * * * ?", AS_NEEDED);
79          assertRandomized("7,12 * * * * ?", AS_NEEDED);
80          assertRandomized("x * * * * ?", AS_NEEDED);
81          assertRandomized("a b c", AS_NEEDED);
82      }
83  
84      @Test
85      public void testRandomizedAlways() {
86          assertRandomized("x * * * * ?", ALWAYS);
87          assertRandomized("0 * * * * ?", ALWAYS);
88          assertRandomized("42 * * * * ?", ALWAYS);
89          assertRandomized("60 * * * * ?", ALWAYS);
90          assertRandomized("*/5 * * * * ?", ALWAYS);
91          assertRandomized("7,12 * * * * ?", ALWAYS);
92          assertRandomized("x * * * * ?", ALWAYS);
93          assertRandomized("a b c", ALWAYS);
94      }
95  
96  
97      private static void verifyNullOrIncompleteExpression(final String cronExpression) {
98          assertNoChange(cronExpression, null);
99          assertNoChange(cronExpression, NEVER);
100         assertNoChange(cronExpression, AS_NEEDED);
101         assertNoChange(cronExpression, ALWAYS);
102     }
103 
104     private static void assertRandomized(final String cronExpression) {
105         String s = null;
106         final String expectedRest = cronExpression.substring(cronExpression.indexOf(' ') + 1);
107         for (int i = 0; i < ATTEMPTS; ++i) {
108             s = quantizeSecondsField(cronExpression);
109             if (looksRandomized(expectedRest, s)) {
110                 return;
111             }
112         }
113         fail("Did not get a randomized seconds field using cron expression '" + cronExpression +
114                 "' with randomize=unspecified (should default to AS_NEEDED); last result was: '" + s + '\'');
115     }
116 
117     private static void assertRandomized(final String cronExpression, final CronExpressionQuantizer.Randomize randomize) {
118         String s = null;
119         final String expectedRest = cronExpression.substring(cronExpression.indexOf(' ') + 1);
120         for (int i = 0; i < ATTEMPTS; ++i) {
121             s = quantizeSecondsField(cronExpression, randomize);
122             if (looksRandomized(expectedRest, s)) {
123                 return;
124             }
125         }
126         fail("Did not get a randomized seconds field using cron expression '" + cronExpression +
127                 "' with randomize=" + randomize + "; last result was: '" + s + '\'');
128     }
129 
130     private static boolean looksRandomized(String expectedRest, String cronExpression) {
131         final Matcher matcher = SIMPLE_SECONDS_FIELD.matcher(cronExpression);
132         if (!matcher.find() || !expectedRest.equals(matcher.group(2))) {
133             return false;
134         }
135         final int seconds = Integer.parseInt(matcher.group(1));
136         return seconds > 0 && seconds <= 59 && seconds != 42;
137     }
138 
139     private static void assertZeroed(final String cronExpression, final CronExpressionQuantizer.Randomize randomize) {
140         final String expectedRest = cronExpression.substring(cronExpression.indexOf(' ') + 1);
141         for (int i = 0; i < ATTEMPTS; ++i) {
142             final String s = quantizeSecondsField(cronExpression, randomize);
143             if (!looksZeroed(expectedRest, s)) {
144                 fail("Did not get a zeroed seconds field using cron expression '" + cronExpression +
145                         "' with randomize=" + randomize + "; attempt i=" + i + " result was: '" + s + '\'');
146             }
147         }
148     }
149 
150     private static boolean looksZeroed(String expectedRest, String cronExpression) {
151         final Matcher matcher = SIMPLE_SECONDS_FIELD.matcher(cronExpression);
152         return matcher.find() && "0".equals(matcher.group(1)) && expectedRest.equals(matcher.group(2));
153     }
154 
155 
156     private static void assertNoChange(final String cronExpression) {
157         for (int i = 0; i < ATTEMPTS; ++i) {
158             assertThat(quantizeSecondsField(cronExpression), equalTo(cronExpression));
159         }
160     }
161 
162     private static void assertNoChange(final String cronExpression, final CronExpressionQuantizer.Randomize randomize) {
163         for (int i = 0; i < ATTEMPTS; ++i) {
164             assertThat(quantizeSecondsField(cronExpression, randomize), equalTo(cronExpression));
165         }
166     }
167 }