xref: /template/strap/vendor/dragonmantank/cron-expression/tests/Cron/CronExpressionTest.php (revision 37748cd8654635afbeca80942126742f0f4cc346)
1*37748cd8SNickeau<?php
2*37748cd8SNickeau
3*37748cd8SNickeaunamespace Cron\Tests;
4*37748cd8SNickeau
5*37748cd8SNickeauuse Cron\CronExpression;
6*37748cd8SNickeauuse DateTime;
7*37748cd8SNickeauuse DateTimeZone;
8*37748cd8SNickeauuse InvalidArgumentException;
9*37748cd8SNickeauuse PHPUnit_Framework_TestCase;
10*37748cd8SNickeau
11*37748cd8SNickeau/**
12*37748cd8SNickeau * @author Michael Dowling <mtdowling@gmail.com>
13*37748cd8SNickeau */
14*37748cd8SNickeauclass CronExpressionTest extends PHPUnit_Framework_TestCase
15*37748cd8SNickeau{
16*37748cd8SNickeau    /**
17*37748cd8SNickeau     * @covers Cron\CronExpression::factory
18*37748cd8SNickeau     */
19*37748cd8SNickeau    public function testFactoryRecognizesTemplates()
20*37748cd8SNickeau    {
21*37748cd8SNickeau        $this->assertEquals('0 0 1 1 *', CronExpression::factory('@annually')->getExpression());
22*37748cd8SNickeau        $this->assertEquals('0 0 1 1 *', CronExpression::factory('@yearly')->getExpression());
23*37748cd8SNickeau        $this->assertEquals('0 0 * * 0', CronExpression::factory('@weekly')->getExpression());
24*37748cd8SNickeau    }
25*37748cd8SNickeau
26*37748cd8SNickeau    /**
27*37748cd8SNickeau     * @covers Cron\CronExpression::__construct
28*37748cd8SNickeau     * @covers Cron\CronExpression::getExpression
29*37748cd8SNickeau     * @covers Cron\CronExpression::__toString
30*37748cd8SNickeau     */
31*37748cd8SNickeau    public function testParsesCronSchedule()
32*37748cd8SNickeau    {
33*37748cd8SNickeau        // '2010-09-10 12:00:00'
34*37748cd8SNickeau        $cron = CronExpression::factory('1 2-4 * 4,5,6 */3');
35*37748cd8SNickeau        $this->assertEquals('1', $cron->getExpression(CronExpression::MINUTE));
36*37748cd8SNickeau        $this->assertEquals('2-4', $cron->getExpression(CronExpression::HOUR));
37*37748cd8SNickeau        $this->assertEquals('*', $cron->getExpression(CronExpression::DAY));
38*37748cd8SNickeau        $this->assertEquals('4,5,6', $cron->getExpression(CronExpression::MONTH));
39*37748cd8SNickeau        $this->assertEquals('*/3', $cron->getExpression(CronExpression::WEEKDAY));
40*37748cd8SNickeau        $this->assertEquals('1 2-4 * 4,5,6 */3', $cron->getExpression());
41*37748cd8SNickeau        $this->assertEquals('1 2-4 * 4,5,6 */3', (string) $cron);
42*37748cd8SNickeau        $this->assertNull($cron->getExpression('foo'));
43*37748cd8SNickeau
44*37748cd8SNickeau        try {
45*37748cd8SNickeau            $cron = CronExpression::factory('A 1 2 3 4');
46*37748cd8SNickeau            $this->fail('Validation exception not thrown');
47*37748cd8SNickeau        } catch (InvalidArgumentException $e) {
48*37748cd8SNickeau        }
49*37748cd8SNickeau    }
50*37748cd8SNickeau
51*37748cd8SNickeau    /**
52*37748cd8SNickeau     * @covers Cron\CronExpression::__construct
53*37748cd8SNickeau     * @covers Cron\CronExpression::getExpression
54*37748cd8SNickeau     * @dataProvider scheduleWithDifferentSeparatorsProvider
55*37748cd8SNickeau     */
56*37748cd8SNickeau    public function testParsesCronScheduleWithAnySpaceCharsAsSeparators($schedule, array $expected)
57*37748cd8SNickeau    {
58*37748cd8SNickeau        $cron = CronExpression::factory($schedule);
59*37748cd8SNickeau        $this->assertEquals($expected[0], $cron->getExpression(CronExpression::MINUTE));
60*37748cd8SNickeau        $this->assertEquals($expected[1], $cron->getExpression(CronExpression::HOUR));
61*37748cd8SNickeau        $this->assertEquals($expected[2], $cron->getExpression(CronExpression::DAY));
62*37748cd8SNickeau        $this->assertEquals($expected[3], $cron->getExpression(CronExpression::MONTH));
63*37748cd8SNickeau        $this->assertEquals($expected[4], $cron->getExpression(CronExpression::WEEKDAY));
64*37748cd8SNickeau        $this->assertEquals($expected[5], $cron->getExpression(CronExpression::YEAR));
65*37748cd8SNickeau    }
66*37748cd8SNickeau
67*37748cd8SNickeau    /**
68*37748cd8SNickeau     * Data provider for testParsesCronScheduleWithAnySpaceCharsAsSeparators
69*37748cd8SNickeau     *
70*37748cd8SNickeau     * @return array
71*37748cd8SNickeau     */
72*37748cd8SNickeau    public static function scheduleWithDifferentSeparatorsProvider()
73*37748cd8SNickeau    {
74*37748cd8SNickeau        return array(
75*37748cd8SNickeau            array("*\t*\t*\t*\t*\t*", array('*', '*', '*', '*', '*', '*')),
76*37748cd8SNickeau            array("*  *  *  *  *  *", array('*', '*', '*', '*', '*', '*')),
77*37748cd8SNickeau            array("* \t * \t * \t * \t * \t *", array('*', '*', '*', '*', '*', '*')),
78*37748cd8SNickeau            array("*\t \t*\t \t*\t \t*\t \t*\t \t*", array('*', '*', '*', '*', '*', '*')),
79*37748cd8SNickeau        );
80*37748cd8SNickeau    }
81*37748cd8SNickeau
82*37748cd8SNickeau    /**
83*37748cd8SNickeau     * @covers Cron\CronExpression::__construct
84*37748cd8SNickeau     * @covers Cron\CronExpression::setExpression
85*37748cd8SNickeau     * @covers Cron\CronExpression::setPart
86*37748cd8SNickeau     * @expectedException InvalidArgumentException
87*37748cd8SNickeau     */
88*37748cd8SNickeau    public function testInvalidCronsWillFail()
89*37748cd8SNickeau    {
90*37748cd8SNickeau        // Only four values
91*37748cd8SNickeau        $cron = CronExpression::factory('* * * 1');
92*37748cd8SNickeau    }
93*37748cd8SNickeau
94*37748cd8SNickeau    /**
95*37748cd8SNickeau     * @covers Cron\CronExpression::setPart
96*37748cd8SNickeau     * @expectedException InvalidArgumentException
97*37748cd8SNickeau     */
98*37748cd8SNickeau    public function testInvalidPartsWillFail()
99*37748cd8SNickeau    {
100*37748cd8SNickeau        // Only four values
101*37748cd8SNickeau        $cron = CronExpression::factory('* * * * *');
102*37748cd8SNickeau        $cron->setPart(1, 'abc');
103*37748cd8SNickeau    }
104*37748cd8SNickeau
105*37748cd8SNickeau    /**
106*37748cd8SNickeau     * Data provider for cron schedule
107*37748cd8SNickeau     *
108*37748cd8SNickeau     * @return array
109*37748cd8SNickeau     */
110*37748cd8SNickeau    public function scheduleProvider()
111*37748cd8SNickeau    {
112*37748cd8SNickeau        return array(
113*37748cd8SNickeau            array('*/2 */2 * * *', '2015-08-10 21:47:27', '2015-08-10 22:00:00', false),
114*37748cd8SNickeau            array('* * * * *', '2015-08-10 21:50:37', '2015-08-10 21:50:00', true),
115*37748cd8SNickeau            array('* 20,21,22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true),
116*37748cd8SNickeau            // Handles CSV values
117*37748cd8SNickeau            array('* 20,22 * * *', '2015-08-10 21:50:00', '2015-08-10 22:00:00', false),
118*37748cd8SNickeau            // CSV values can be complex
119*37748cd8SNickeau            array('* 5,21-22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true),
120*37748cd8SNickeau            array('7-9 * */9 * *', '2015-08-10 22:02:33', '2015-08-18 00:07:00', false),
121*37748cd8SNickeau            // 15th minute, of the second hour, every 15 days, in January, every Friday
122*37748cd8SNickeau            array('1 * * * 7', '2015-08-10 21:47:27', '2015-08-16 00:01:00', false),
123*37748cd8SNickeau            // Test with exact times
124*37748cd8SNickeau            array('47 21 * * *', strtotime('2015-08-10 21:47:30'), '2015-08-10 21:47:00', true),
125*37748cd8SNickeau            // Test Day of the week (issue #1)
126*37748cd8SNickeau            // According cron implementation, 0|7 = sunday, 1 => monday, etc
127*37748cd8SNickeau            array('* * * * 0', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
128*37748cd8SNickeau            array('* * * * 7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
129*37748cd8SNickeau            array('* * * * 1', strtotime('2011-06-15 23:09:00'), '2011-06-20 00:00:00', false),
130*37748cd8SNickeau            // Should return the sunday date as 7 equals 0
131*37748cd8SNickeau            array('0 0 * * MON,SUN', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
132*37748cd8SNickeau            array('0 0 * * 1,7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
133*37748cd8SNickeau            array('0 0 * * 0-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
134*37748cd8SNickeau            array('0 0 * * 7-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
135*37748cd8SNickeau            array('0 0 * * 4-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
136*37748cd8SNickeau            array('0 0 * * 7-3', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
137*37748cd8SNickeau            array('0 0 * * 3-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
138*37748cd8SNickeau            array('0 0 * * 3-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
139*37748cd8SNickeau            // Test lists of values and ranges (Abhoryo)
140*37748cd8SNickeau            array('0 0 * * 2-7', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
141*37748cd8SNickeau            array('0 0 * * 0,2-6', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
142*37748cd8SNickeau            array('0 0 * * 2-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
143*37748cd8SNickeau            array('0 0 * * 4-7', strtotime('2011-07-19 00:00:00'), '2011-07-21 00:00:00', false),
144*37748cd8SNickeau            // Test increments of ranges
145*37748cd8SNickeau            array('0-12/4 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
146*37748cd8SNickeau            array('4-59/2 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
147*37748cd8SNickeau            array('4-59/2 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:06:00', true),
148*37748cd8SNickeau            array('4-59/3 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:07:00', false),
149*37748cd8SNickeau            //array('0 0 * * 0,2-6', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
150*37748cd8SNickeau            // Test Day of the Week and the Day of the Month (issue #1)
151*37748cd8SNickeau            array('0 0 1 1 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
152*37748cd8SNickeau            array('0 0 1 JAN 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
153*37748cd8SNickeau            array('0 0 1 * 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
154*37748cd8SNickeau            array('0 0 L * *', strtotime('2011-07-15 00:00:00'), '2011-07-31 00:00:00', false),
155*37748cd8SNickeau            // Test the W day of the week modifier for day of the month field
156*37748cd8SNickeau            array('0 0 2W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
157*37748cd8SNickeau            array('0 0 1W * *', strtotime('2011-05-01 00:00:00'), '2011-05-02 00:00:00', false),
158*37748cd8SNickeau            array('0 0 1W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
159*37748cd8SNickeau            array('0 0 3W * *', strtotime('2011-07-01 00:00:00'), '2011-07-04 00:00:00', false),
160*37748cd8SNickeau            array('0 0 16W * *', strtotime('2011-07-01 00:00:00'), '2011-07-15 00:00:00', false),
161*37748cd8SNickeau            array('0 0 28W * *', strtotime('2011-07-01 00:00:00'), '2011-07-28 00:00:00', false),
162*37748cd8SNickeau            array('0 0 30W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
163*37748cd8SNickeau            array('0 0 31W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
164*37748cd8SNickeau            // Test the year field
165*37748cd8SNickeau            array('* * * * * 2012', strtotime('2011-05-01 00:00:00'), '2012-01-01 00:00:00', false),
166*37748cd8SNickeau            // Test the last weekday of a month
167*37748cd8SNickeau            array('* * * * 5L', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
168*37748cd8SNickeau            array('* * * * 6L', strtotime('2011-07-01 00:00:00'), '2011-07-30 00:00:00', false),
169*37748cd8SNickeau            array('* * * * 7L', strtotime('2011-07-01 00:00:00'), '2011-07-31 00:00:00', false),
170*37748cd8SNickeau            array('* * * * 1L', strtotime('2011-07-24 00:00:00'), '2011-07-25 00:00:00', false),
171*37748cd8SNickeau            array('* * * * TUEL', strtotime('2011-07-24 00:00:00'), '2011-07-26 00:00:00', false),
172*37748cd8SNickeau            array('* * * 1 5L', strtotime('2011-12-25 00:00:00'), '2012-01-27 00:00:00', false),
173*37748cd8SNickeau            // Test the hash symbol for the nth weekday of a given month
174*37748cd8SNickeau            array('* * * * 5#2', strtotime('2011-07-01 00:00:00'), '2011-07-08 00:00:00', false),
175*37748cd8SNickeau            array('* * * * 5#1', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
176*37748cd8SNickeau            array('* * * * 3#4', strtotime('2011-07-01 00:00:00'), '2011-07-27 00:00:00', false),
177*37748cd8SNickeau        );
178*37748cd8SNickeau    }
179*37748cd8SNickeau
180*37748cd8SNickeau    /**
181*37748cd8SNickeau     * @covers Cron\CronExpression::isDue
182*37748cd8SNickeau     * @covers Cron\CronExpression::getNextRunDate
183*37748cd8SNickeau     * @covers Cron\DayOfMonthField
184*37748cd8SNickeau     * @covers Cron\DayOfWeekField
185*37748cd8SNickeau     * @covers Cron\MinutesField
186*37748cd8SNickeau     * @covers Cron\HoursField
187*37748cd8SNickeau     * @covers Cron\MonthField
188*37748cd8SNickeau     * @covers Cron\YearField
189*37748cd8SNickeau     * @covers Cron\CronExpression::getRunDate
190*37748cd8SNickeau     * @dataProvider scheduleProvider
191*37748cd8SNickeau     */
192*37748cd8SNickeau    public function testDeterminesIfCronIsDue($schedule, $relativeTime, $nextRun, $isDue)
193*37748cd8SNickeau    {
194*37748cd8SNickeau        $relativeTimeString = is_int($relativeTime) ? date('Y-m-d H:i:s', $relativeTime) : $relativeTime;
195*37748cd8SNickeau
196*37748cd8SNickeau        // Test next run date
197*37748cd8SNickeau        $cron = CronExpression::factory($schedule);
198*37748cd8SNickeau        if (is_string($relativeTime)) {
199*37748cd8SNickeau            $relativeTime = new DateTime($relativeTime);
200*37748cd8SNickeau        } elseif (is_int($relativeTime)) {
201*37748cd8SNickeau            $relativeTime = date('Y-m-d H:i:s', $relativeTime);
202*37748cd8SNickeau        }
203*37748cd8SNickeau        $this->assertEquals($isDue, $cron->isDue($relativeTime));
204*37748cd8SNickeau        $next = $cron->getNextRunDate($relativeTime, 0, true);
205*37748cd8SNickeau        $this->assertEquals(new DateTime($nextRun), $next);
206*37748cd8SNickeau    }
207*37748cd8SNickeau
208*37748cd8SNickeau    /**
209*37748cd8SNickeau     * @covers Cron\CronExpression::isDue
210*37748cd8SNickeau     */
211*37748cd8SNickeau    public function testIsDueHandlesDifferentDates()
212*37748cd8SNickeau    {
213*37748cd8SNickeau        $cron = CronExpression::factory('* * * * *');
214*37748cd8SNickeau        $this->assertTrue($cron->isDue());
215*37748cd8SNickeau        $this->assertTrue($cron->isDue('now'));
216*37748cd8SNickeau        $this->assertTrue($cron->isDue(new DateTime('now')));
217*37748cd8SNickeau        $this->assertTrue($cron->isDue(date('Y-m-d H:i')));
218*37748cd8SNickeau    }
219*37748cd8SNickeau
220*37748cd8SNickeau    /**
221*37748cd8SNickeau     * @covers Cron\CronExpression::isDue
222*37748cd8SNickeau     */
223*37748cd8SNickeau    public function testIsDueHandlesDifferentTimezones()
224*37748cd8SNickeau    {
225*37748cd8SNickeau        $cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00
226*37748cd8SNickeau        $date = '2014-01-01 15:00'; //Wednesday
227*37748cd8SNickeau        $utc = new DateTimeZone('UTC');
228*37748cd8SNickeau        $amsterdam =  new DateTimeZone('Europe/Amsterdam');
229*37748cd8SNickeau        $tokyo = new DateTimeZone('Asia/Tokyo');
230*37748cd8SNickeau
231*37748cd8SNickeau        date_default_timezone_set('UTC');
232*37748cd8SNickeau        $this->assertTrue($cron->isDue(new DateTime($date, $utc)));
233*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam)));
234*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $tokyo)));
235*37748cd8SNickeau
236*37748cd8SNickeau        date_default_timezone_set('Europe/Amsterdam');
237*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $utc)));
238*37748cd8SNickeau        $this->assertTrue($cron->isDue(new DateTime($date, $amsterdam)));
239*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $tokyo)));
240*37748cd8SNickeau
241*37748cd8SNickeau        date_default_timezone_set('Asia/Tokyo');
242*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $utc)));
243*37748cd8SNickeau        $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam)));
244*37748cd8SNickeau        $this->assertTrue($cron->isDue(new DateTime($date, $tokyo)));
245*37748cd8SNickeau    }
246*37748cd8SNickeau
247*37748cd8SNickeau    /**
248*37748cd8SNickeau     * @covers Cron\CronExpression::getPreviousRunDate
249*37748cd8SNickeau     */
250*37748cd8SNickeau    public function testCanGetPreviousRunDates()
251*37748cd8SNickeau    {
252*37748cd8SNickeau        $cron = CronExpression::factory('* * * * *');
253*37748cd8SNickeau        $next = $cron->getNextRunDate('now');
254*37748cd8SNickeau        $two = $cron->getNextRunDate('now', 1);
255*37748cd8SNickeau        $this->assertEquals($next, $cron->getPreviousRunDate($two));
256*37748cd8SNickeau
257*37748cd8SNickeau        $cron = CronExpression::factory('* */2 * * *');
258*37748cd8SNickeau        $next = $cron->getNextRunDate('now');
259*37748cd8SNickeau        $two = $cron->getNextRunDate('now', 1);
260*37748cd8SNickeau        $this->assertEquals($next, $cron->getPreviousRunDate($two));
261*37748cd8SNickeau
262*37748cd8SNickeau        $cron = CronExpression::factory('* * * */2 *');
263*37748cd8SNickeau        $next = $cron->getNextRunDate('now');
264*37748cd8SNickeau        $two = $cron->getNextRunDate('now', 1);
265*37748cd8SNickeau        $this->assertEquals($next, $cron->getPreviousRunDate($two));
266*37748cd8SNickeau    }
267*37748cd8SNickeau
268*37748cd8SNickeau    /**
269*37748cd8SNickeau     * @covers Cron\CronExpression::getMultipleRunDates
270*37748cd8SNickeau     */
271*37748cd8SNickeau    public function testProvidesMultipleRunDates()
272*37748cd8SNickeau    {
273*37748cd8SNickeau        $cron = CronExpression::factory('*/2 * * * *');
274*37748cd8SNickeau        $this->assertEquals(array(
275*37748cd8SNickeau            new DateTime('2008-11-09 00:00:00'),
276*37748cd8SNickeau            new DateTime('2008-11-09 00:02:00'),
277*37748cd8SNickeau            new DateTime('2008-11-09 00:04:00'),
278*37748cd8SNickeau            new DateTime('2008-11-09 00:06:00')
279*37748cd8SNickeau        ), $cron->getMultipleRunDates(4, '2008-11-09 00:00:00', false, true));
280*37748cd8SNickeau    }
281*37748cd8SNickeau
282*37748cd8SNickeau    /**
283*37748cd8SNickeau     * @covers Cron\CronExpression::getMultipleRunDates
284*37748cd8SNickeau     * @covers Cron\CronExpression::setMaxIterationCount
285*37748cd8SNickeau     */
286*37748cd8SNickeau    public function testProvidesMultipleRunDatesForTheFarFuture() {
287*37748cd8SNickeau        // Fails with the default 1000 iteration limit
288*37748cd8SNickeau        $cron = CronExpression::factory('0 0 12 1 * */2');
289*37748cd8SNickeau        $cron->setMaxIterationCount(2000);
290*37748cd8SNickeau        $this->assertEquals(array(
291*37748cd8SNickeau            new DateTime('2016-01-12 00:00:00'),
292*37748cd8SNickeau            new DateTime('2018-01-12 00:00:00'),
293*37748cd8SNickeau            new DateTime('2020-01-12 00:00:00'),
294*37748cd8SNickeau            new DateTime('2022-01-12 00:00:00'),
295*37748cd8SNickeau            new DateTime('2024-01-12 00:00:00'),
296*37748cd8SNickeau            new DateTime('2026-01-12 00:00:00'),
297*37748cd8SNickeau            new DateTime('2028-01-12 00:00:00'),
298*37748cd8SNickeau            new DateTime('2030-01-12 00:00:00'),
299*37748cd8SNickeau            new DateTime('2032-01-12 00:00:00'),
300*37748cd8SNickeau        ), $cron->getMultipleRunDates(9, '2015-04-28 00:00:00', false, true));
301*37748cd8SNickeau    }
302*37748cd8SNickeau
303*37748cd8SNickeau    /**
304*37748cd8SNickeau     * @covers Cron\CronExpression
305*37748cd8SNickeau     */
306*37748cd8SNickeau    public function testCanIterateOverNextRuns()
307*37748cd8SNickeau    {
308*37748cd8SNickeau        $cron = CronExpression::factory('@weekly');
309*37748cd8SNickeau        $nextRun = $cron->getNextRunDate("2008-11-09 08:00:00");
310*37748cd8SNickeau        $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
311*37748cd8SNickeau
312*37748cd8SNickeau        // true is cast to 1
313*37748cd8SNickeau        $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", true, true);
314*37748cd8SNickeau        $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
315*37748cd8SNickeau
316*37748cd8SNickeau        // You can iterate over them
317*37748cd8SNickeau        $nextRun = $cron->getNextRunDate($cron->getNextRunDate("2008-11-09 00:00:00", 1, true), 1, true);
318*37748cd8SNickeau        $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
319*37748cd8SNickeau
320*37748cd8SNickeau        // You can skip more than one
321*37748cd8SNickeau        $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 2, true);
322*37748cd8SNickeau        $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
323*37748cd8SNickeau        $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 3, true);
324*37748cd8SNickeau        $this->assertEquals($nextRun, new DateTime("2008-11-30 00:00:00"));
325*37748cd8SNickeau    }
326*37748cd8SNickeau
327*37748cd8SNickeau    /**
328*37748cd8SNickeau     * @covers Cron\CronExpression::getRunDate
329*37748cd8SNickeau     */
330*37748cd8SNickeau    public function testSkipsCurrentDateByDefault()
331*37748cd8SNickeau    {
332*37748cd8SNickeau        $cron = CronExpression::factory('* * * * *');
333*37748cd8SNickeau        $current = new DateTime('now');
334*37748cd8SNickeau        $next = $cron->getNextRunDate($current);
335*37748cd8SNickeau        $nextPrev = $cron->getPreviousRunDate($next);
336*37748cd8SNickeau        $this->assertEquals($current->format('Y-m-d H:i:00'), $nextPrev->format('Y-m-d H:i:s'));
337*37748cd8SNickeau    }
338*37748cd8SNickeau
339*37748cd8SNickeau    /**
340*37748cd8SNickeau     * @covers Cron\CronExpression::getRunDate
341*37748cd8SNickeau     * @ticket 7
342*37748cd8SNickeau     */
343*37748cd8SNickeau    public function testStripsForSeconds()
344*37748cd8SNickeau    {
345*37748cd8SNickeau        $cron = CronExpression::factory('* * * * *');
346*37748cd8SNickeau        $current = new DateTime('2011-09-27 10:10:54');
347*37748cd8SNickeau        $this->assertEquals('2011-09-27 10:11:00', $cron->getNextRunDate($current)->format('Y-m-d H:i:s'));
348*37748cd8SNickeau    }
349*37748cd8SNickeau
350*37748cd8SNickeau    /**
351*37748cd8SNickeau     * @covers Cron\CronExpression::getRunDate
352*37748cd8SNickeau     */
353*37748cd8SNickeau    public function testFixesPhpBugInDateIntervalMonth()
354*37748cd8SNickeau    {
355*37748cd8SNickeau        $cron = CronExpression::factory('0 0 27 JAN *');
356*37748cd8SNickeau        $this->assertEquals('2011-01-27 00:00:00', $cron->getPreviousRunDate('2011-08-22 00:00:00')->format('Y-m-d H:i:s'));
357*37748cd8SNickeau    }
358*37748cd8SNickeau
359*37748cd8SNickeau    public function testIssue29()
360*37748cd8SNickeau    {
361*37748cd8SNickeau        $cron = CronExpression::factory('@weekly');
362*37748cd8SNickeau        $this->assertEquals(
363*37748cd8SNickeau            '2013-03-10 00:00:00',
364*37748cd8SNickeau            $cron->getPreviousRunDate('2013-03-17 00:00:00')->format('Y-m-d H:i:s')
365*37748cd8SNickeau        );
366*37748cd8SNickeau    }
367*37748cd8SNickeau
368*37748cd8SNickeau    /**
369*37748cd8SNickeau     * @see https://github.com/mtdowling/cron-expression/issues/20
370*37748cd8SNickeau     */
371*37748cd8SNickeau    public function testIssue20() {
372*37748cd8SNickeau        $e = CronExpression::factory('* * * * MON#1');
373*37748cd8SNickeau        $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
374*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-14 00:00:00')));
375*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-21 00:00:00')));
376*37748cd8SNickeau
377*37748cd8SNickeau        $e = CronExpression::factory('* * * * SAT#2');
378*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-05 00:00:00')));
379*37748cd8SNickeau        $this->assertTrue($e->isDue(new DateTime('2014-04-12 00:00:00')));
380*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-19 00:00:00')));
381*37748cd8SNickeau
382*37748cd8SNickeau        $e = CronExpression::factory('* * * * SUN#3');
383*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-13 00:00:00')));
384*37748cd8SNickeau        $this->assertTrue($e->isDue(new DateTime('2014-04-20 00:00:00')));
385*37748cd8SNickeau        $this->assertFalse($e->isDue(new DateTime('2014-04-27 00:00:00')));
386*37748cd8SNickeau    }
387*37748cd8SNickeau
388*37748cd8SNickeau    /**
389*37748cd8SNickeau     * @covers Cron\CronExpression::getRunDate
390*37748cd8SNickeau     */
391*37748cd8SNickeau    public function testKeepOriginalTime()
392*37748cd8SNickeau    {
393*37748cd8SNickeau        $now = new \DateTime;
394*37748cd8SNickeau        $strNow = $now->format(DateTime::ISO8601);
395*37748cd8SNickeau        $cron = CronExpression::factory('0 0 * * *');
396*37748cd8SNickeau        $cron->getPreviousRunDate($now);
397*37748cd8SNickeau        $this->assertEquals($strNow, $now->format(DateTime::ISO8601));
398*37748cd8SNickeau    }
399*37748cd8SNickeau
400*37748cd8SNickeau    /**
401*37748cd8SNickeau     * @covers Cron\CronExpression::__construct
402*37748cd8SNickeau     * @covers Cron\CronExpression::factory
403*37748cd8SNickeau     * @covers Cron\CronExpression::isValidExpression
404*37748cd8SNickeau     * @covers Cron\CronExpression::setExpression
405*37748cd8SNickeau     * @covers Cron\CronExpression::setPart
406*37748cd8SNickeau     */
407*37748cd8SNickeau    public function testValidationWorks()
408*37748cd8SNickeau    {
409*37748cd8SNickeau        // Invalid. Only four values
410*37748cd8SNickeau        $this->assertFalse(CronExpression::isValidExpression('* * * 1'));
411*37748cd8SNickeau        // Valid
412*37748cd8SNickeau        $this->assertTrue(CronExpression::isValidExpression('* * * * 1'));
413*37748cd8SNickeau    }
414*37748cd8SNickeau}
415