1<?php 2 3namespace Sabre\VObject\Recur\EventIterator; 4 5use DateTimeImmutable; 6use DateTimeZone; 7use Sabre\VObject\Component\VCalendar; 8use Sabre\VObject\Recur; 9 10class InfiniteLoopProblemTest extends \PHPUnit_Framework_TestCase { 11 12 function setUp() { 13 14 $this->vcal = new VCalendar(); 15 16 } 17 18 /** 19 * This bug came from a Fruux customer. This would result in a never-ending 20 * request. 21 */ 22 function testFastForwardTooFar() { 23 24 $ev = $this->vcal->createComponent('VEVENT'); 25 $ev->UID = 'foobar'; 26 $ev->DTSTART = '20090420T180000Z'; 27 $ev->RRULE = 'FREQ=WEEKLY;BYDAY=MO;UNTIL=20090704T205959Z;INTERVAL=1'; 28 29 $this->assertFalse($ev->isInTimeRange(new DateTimeImmutable('2012-01-01 12:00:00'), new DateTimeImmutable('3000-01-01 00:00:00'))); 30 31 } 32 33 /** 34 * Different bug, also likely an infinite loop. 35 */ 36 function testYearlyByMonthLoop() { 37 38 $ev = $this->vcal->createComponent('VEVENT'); 39 $ev->UID = 'uuid'; 40 $ev->DTSTART = '20120101T154500'; 41 $ev->DTSTART['TZID'] = 'Europe/Berlin'; 42 $ev->RRULE = 'FREQ=YEARLY;INTERVAL=1;UNTIL=20120203T225959Z;BYMONTH=2;BYSETPOS=1;BYDAY=SU,MO,TU,WE,TH,FR,SA'; 43 $ev->DTEND = '20120101T164500'; 44 $ev->DTEND['TZID'] = 'Europe/Berlin'; 45 46 // This recurrence rule by itself is a yearly rule that should happen 47 // every february. 48 // 49 // The BYDAY part expands this to every day of the month, but the 50 // BYSETPOS limits this to only the 1st day of the month. Very crazy 51 // way to specify this, and could have certainly been a lot easier. 52 $this->vcal->add($ev); 53 54 $it = new Recur\EventIterator($this->vcal, 'uuid'); 55 $it->fastForward(new DateTimeImmutable('2012-01-29 23:00:00', new DateTimeZone('UTC'))); 56 57 $collect = []; 58 59 while ($it->valid()) { 60 $collect[] = $it->getDtStart(); 61 if ($it->getDtStart() > new DateTimeImmutable('2013-02-05 22:59:59', new DateTimeZone('UTC'))) { 62 break; 63 } 64 $it->next(); 65 66 } 67 68 $this->assertEquals( 69 [new DateTimeImmutable('2012-02-01 15:45:00', new DateTimeZone('Europe/Berlin'))], 70 $collect 71 ); 72 73 } 74 75 /** 76 * Something, somewhere produced an ics with an interval set to 0. Because 77 * this means we increase the current day (or week, month) by 0, this also 78 * results in an infinite loop. 79 * 80 * @expectedException \Sabre\VObject\InvalidDataException 81 * @return void 82 */ 83 function testZeroInterval() { 84 85 $ev = $this->vcal->createComponent('VEVENT'); 86 $ev->UID = 'uuid'; 87 $ev->DTSTART = '20120824T145700Z'; 88 $ev->RRULE = 'FREQ=YEARLY;INTERVAL=0'; 89 $this->vcal->add($ev); 90 91 $it = new Recur\EventIterator($this->vcal, 'uuid'); 92 $it->fastForward(new DateTimeImmutable('2013-01-01 23:00:00', new DateTimeZone('UTC'))); 93 94 // if we got this far.. it means we are no longer infinitely looping 95 96 } 97 98} 99