1 package com.atlassian.scheduler.core.tests;
2
3 import org.hamcrest.Matcher;
4 import org.joda.time.DateTime;
5 import org.joda.time.DateTimeZone;
6
7 import java.util.ArrayList;
8 import java.util.Date;
9 import java.util.List;
10
11 import static com.atlassian.scheduler.core.tests.CronFactory.CronExpressionAdapter;
12 import static java.util.concurrent.TimeUnit.MILLISECONDS;
13 import static org.hamcrest.Matchers.allOf;
14 import static org.hamcrest.Matchers.contains;
15 import static org.junit.Assert.assertThat;
16 import static org.junit.Assert.fail;
17
18
19
20
21 public abstract class AbstractCronExpressionTest {
22 protected final CronFactory cronFactory;
23
24 protected AbstractCronExpressionTest(final CronFactory cronFactory) {
25 this.cronFactory = cronFactory;
26 }
27
28 @SuppressWarnings("unchecked")
29 protected void assertCron(final String message, final String cronExpression, final Matcher... matchers) {
30 assertThat(message, cronFactory.parse(cronExpression), allOf(matchers));
31 }
32
33 protected void assertQuartzBug(final String whyQuartzIsWrong, final String cronExpression, final Matcher<?> matcher) {
34 final CronExpressionAdapter cron = cronFactory.parse(cronExpression);
35 if (matcher.matches(cron)) {
36 fail("Expected a Quartz bug to cause a mismatch between <" + cronExpression + "> and <" + matcher +
37 "> because " + whyQuartzIsWrong + " -- Maybe this bug has been fixed, now?");
38 } else {
39 System.err.println("Quartz failed to match <" + cronExpression + "> with <" + matcher +
40 "> due to known bug: " + whyQuartzIsWrong);
41 }
42 }
43
44 protected void assertRunTimes(final String message, final String cronExpression, final DateTime startingAfter,
45 final Matcher... matchers) {
46 final CronExpressionAdapter cron = cronFactory.parse(cronExpression, startingAfter.getZone());
47 assertRunTimes(message, cron, startingAfter, matchers);
48 }
49
50 protected void assertRunTimes(final String message, final CronExpressionAdapter cron, final DateTime startingAfter,
51 final Matcher... matchers) {
52 final List<Date> list = generateNextRunTimes(cron, startingAfter, matchers.length);
53 boolean ok = false;
54 try {
55 assertThat(message, list, contains(matchers));
56 ok = true;
57 } finally {
58 if (!ok) {
59 final DateTimeZone zone = startingAfter.getZone();
60 System.err.println("Debug info for run times of '" + cron + "':");
61 System.err.println("\t" + startingAfter.getMillis() + " = " + startingAfter + " (T = starting point)");
62 for (Date date : list) {
63 System.err.println("\t" + date.getTime() + " = " + new DateTime(date, zone) + " (T + " +
64 MILLISECONDS.toMinutes(date.getTime() - startingAfter.getMillis()) + " min)");
65 }
66 }
67 }
68 }
69
70 protected List<Date> generateNextRunTimes(final CronExpressionAdapter adapter,
71 final DateTime startingAfter, final int maximumResults) {
72 final List<Date> list = new ArrayList<Date>(maximumResults);
73 Date current = startingAfter.toDate();
74 for (int i = 0; i < maximumResults && current != null; ++i) {
75 current = adapter.nextRunTime(current);
76 list.add(current);
77 }
78 return list;
79 }
80 }