From 20249e4adc4abaf3c81cd864331508cf68b8777b Mon Sep 17 00:00:00 2001 From: OHTAKE Tomohiro Date: Tue, 10 Jan 2012 18:29:52 +0900 Subject: [PATCH] [FIXED JENKINS-12357] Crontab#ceil may stuck in an infinite loop or may return an incorrect value if day of week is 7 (=0, Sunday) To use @Test(timeout), inheritance from TestCase should be removed --- .../main/java/hudson/scheduler/CronTab.java | 4 +- .../scheduler/CronTabDayOfWeekLocaleTest.java | 64 ++++++++++++++++++- .../java/hudson/scheduler/CronTabTest.java | 15 ++++- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/hudson/scheduler/CronTab.java b/core/src/main/java/hudson/scheduler/CronTab.java index 9da5ae4f98..8ca60e76cc 100644 --- a/core/src/main/java/hudson/scheduler/CronTab.java +++ b/core/src/main/java/hudson/scheduler/CronTab.java @@ -89,8 +89,10 @@ public final class CronTab { spec = format; parser.startRule(this); - if((dayOfWeek&(1<<7))!=0) + if((dayOfWeek&(1<<7))!=0) { dayOfWeek |= 1; // copy bit 7 over to bit 0 + dayOfWeek &= ~(1<<7); // clear bit 7 or CalendarField#ceil will return an invalid value 7 + } } diff --git a/core/src/test/java/hudson/scheduler/CronTabDayOfWeekLocaleTest.java b/core/src/test/java/hudson/scheduler/CronTabDayOfWeekLocaleTest.java index 854a152de7..e777a3d49f 100644 --- a/core/src/test/java/hudson/scheduler/CronTabDayOfWeekLocaleTest.java +++ b/core/src/test/java/hudson/scheduler/CronTabDayOfWeekLocaleTest.java @@ -13,6 +13,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import org.jvnet.hudson.test.Bug; import org.jvnet.hudson.test.For; import org.jvnet.hudson.test.Url; @@ -273,7 +274,68 @@ public class CronTabDayOfWeekLocaleTest { expected.set(2011, 0, 9, 1, 0, 0); compare(expected, actual); } - + + @Test + @Bug(12357) + public void isSundayAndNextRunIsNextSunday7() throws Exception { + final Calendar cal = Calendar.getInstance(locale); + cal.set(2011, 0, 16, 1, 0, 0); // Sunday, Jan 16th 2011, 01:00 + final String cronStr = "0 0 * * 7"; // Sundays(7 not 0) @00:00 + + final CronTab cron = new CronTab(cronStr); + final Calendar actual = cron.ceil(cal); + + final Calendar expected = Calendar.getInstance(); + // Expected next: Sunday, Jan 22th 2011, 00:00 + expected.set(2011, 0, 23, 0, 0, 0); + compare(expected, actual); + } + + @Test + public void isSundayAndPreviousRunIsPreviousSunday7() throws Exception { + final Calendar cal = Calendar.getInstance(locale); + cal.set(2011, 0, 16, 0, 0, 0); // Sunday, Jan 16th 2011, 00:00 + final String cronStr = "0 1 * * 7"; // Sundays(7 not 0) @01:00 + + final CronTab cron = new CronTab(cronStr); + final Calendar actual = cron.floor(cal); + + final Calendar expected = Calendar.getInstance(); + // Expected next: Sunday, Jan 9th 2011, 01:00 + expected.set(2011, 0, 9, 1, 0, 0); + compare(expected, actual); + } + + @Test + public void isSaturdayAndNextRunIsSundayAsterisk() throws Exception { + final Calendar cal = Calendar.getInstance(locale); + cal.set(2011, 0, 15, 1, 0, 0); // Saturday, Jan 15th 2011, 01:00 + final String cronStr = "0 0 * * *"; // Everyday @00:00 + + final CronTab cron = new CronTab(cronStr); + final Calendar actual = cron.ceil(cal); + + final Calendar expected = Calendar.getInstance(); + // Expected next: Sunday, Jan 16th 2011, 00:00 + expected.set(2011, 0, 16, 0, 0, 0); + compare(expected, actual); + } + + @Test + public void isSundayAndPreviousRunIsSaturdayAsterisk() throws Exception { + final Calendar cal = Calendar.getInstance(locale); + cal.set(2011, 0, 16, 0, 0, 0); // Sunday, Jan 16th 2011, 00:00 + final String cronStr = "0 23 * * *"; // Everyday @23:00 + + final CronTab cron = new CronTab(cronStr); + final Calendar actual = cron.floor(cal); + + final Calendar expected = Calendar.getInstance(); + // Expected next: Saturday, Jan 15th 2011, 23:00 + expected.set(2011, 0, 15, 23, 0, 0); + compare(expected, actual); + } + private void compare(final Calendar expected, final Calendar actual) { final DateFormat f = DateFormat.getDateTimeInstance(); final String msg = "Locale: " + locale + " FirstDayOfWeek: " + actual.getFirstDayOfWeek() + " Expected: " diff --git a/core/src/test/java/hudson/scheduler/CronTabTest.java b/core/src/test/java/hudson/scheduler/CronTabTest.java index 76b0eb8629..8a3f2ef625 100644 --- a/core/src/test/java/hudson/scheduler/CronTabTest.java +++ b/core/src/test/java/hudson/scheduler/CronTabTest.java @@ -29,7 +29,8 @@ import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Locale; -import junit.framework.TestCase; +import static org.junit.Assert.*; +import org.junit.Test; import org.jvnet.hudson.test.Bug; import org.jvnet.hudson.test.Url; @@ -38,7 +39,7 @@ import static java.util.Calendar.MONDAY; /** * @author Kohsuke Kawaguchi */ -public class CronTabTest extends TestCase { +public class CronTabTest { public void test1() throws ANTLRException { new CronTab("@yearly"); new CronTab("@weekly"); @@ -72,6 +73,16 @@ public class CronTabTest extends TestCase { compare(new GregorianCalendar(2010,7,1,0,0),x.ceil(c)); } + @Test(timeout = 1000) + @Bug(12357) + public void testCeil3_DoW7() throws Exception { + // similar to testCeil3, but DoW=7 may stuck in an infinite loop + CronTab x = new CronTab("0 0 1 * 7"); + Calendar c = new GregorianCalendar(2010,0,1,15,55); + // the first such day in 2010 is Aug 1st + compare(new GregorianCalendar(2010, 7, 1, 0, 0), x.ceil(c)); + } + /** * Verifies that HUDSON-8656 never crops up again. */ -- GitLab