From 1a908528910556e44b15afa68d8d55a122a56688 Mon Sep 17 00:00:00 2001 From: Christopher Szu Date: Fri, 29 Dec 2023 11:07:30 +0800 Subject: [PATCH] make test pass from both sides --- .github/workflows/actions.yml | 59 -------------------- lib/Recur/RRuleIterator.php | 13 ++++- tests/VObject/Recur/FastForwardToEndTest.php | 3 + tests/VObject/Recur/RRuleIteratorTest.php | 14 ++++- 4 files changed, 26 insertions(+), 63 deletions(-) delete mode 100644 .github/workflows/actions.yml diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml deleted file mode 100644 index d1c7c97b2..000000000 --- a/.github/workflows/actions.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Tests - -on: [push] - -jobs: - phpunit: - strategy: - matrix: - operating-system: [ubuntu-latest] - php-versions: ['7.4', '8.0', '8.1'] - - runs-on: ${{ matrix.operating-system }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: mbstring - coverage: pcov - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - # Use composer.json for key, if composer.lock is not committed. - # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code Analysis (PHP CS-Fixer) - if: matrix.code-analysis == 'yes' - run: php vendor/bin/php-cs-fixer fix --dry-run --diff - - - name: Code Analysis (PHPStan) - if: matrix.code-analysis == 'yes' - run: composer phpstan - - - name: Test with phpunit - run: vendor/bin/phpunit --configuration ./tests/phpunit.xml --coverage-text --coverage-clover=coverage.xml - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: ./coverage.xml - flags: tests - name: codecov-umbrella - fail_ci_if_error: true diff --git a/lib/Recur/RRuleIterator.php b/lib/Recur/RRuleIterator.php index 0b3140bb0..ecf1affeb 100644 --- a/lib/Recur/RRuleIterator.php +++ b/lib/Recur/RRuleIterator.php @@ -28,6 +28,8 @@ class RRuleIterator implements \Iterator */ public const dateUpperLimit = 253402300799; + private bool $yearlySkipUpperLimit; + /** * Creates the Iterator. * @@ -35,11 +37,12 @@ class RRuleIterator implements \Iterator * * @throws InvalidDataException */ - public function __construct($rrule, \DateTimeInterface $start) + public function __construct($rrule, \DateTimeInterface $start, bool $yearlySkipUpperLimit = true) { $this->startDate = $start; $this->parseRRule($rrule); $this->currentDate = clone $this->startDate; + $this->yearlySkipUpperLimit = $yearlySkipUpperLimit; } /* Implementation of the Iterator interface {{{ */ @@ -823,6 +826,14 @@ protected function nextYearly($amount = 1): void (int) $currentMonth, (int) $currentDayOfMonth ); + + // To prevent running this forever (better: until we hit the max date of DateTimeImmutable) we simply + // stop at 9999-12-31. Looks like the year 10000 problem is not solved in php .... + if (!$this->yearlySkipUpperLimit && ($this->currentDate->getTimestamp() > self::dateUpperLimit)) { + $this->currentDate = null; + + return; + } } // If we made it here, it means we got a valid occurrence diff --git a/tests/VObject/Recur/FastForwardToEndTest.php b/tests/VObject/Recur/FastForwardToEndTest.php index 1073a95df..0b94f3945 100644 --- a/tests/VObject/Recur/FastForwardToEndTest.php +++ b/tests/VObject/Recur/FastForwardToEndTest.php @@ -229,6 +229,9 @@ public function testFastForwardToEndUntilMonthly31thDay() $this->assertEquals($expected, $rrule->current()->getTimestamp()); } + /** + * @medium + */ public function testFastForwardToEndCountMonthlyAdvanced() { $startDate = new \DateTime('1970-01-31 00:00:00', new \DateTimeZone('America/New_York')); diff --git a/tests/VObject/Recur/RRuleIteratorTest.php b/tests/VObject/Recur/RRuleIteratorTest.php index 3384506f5..75222f217 100644 --- a/tests/VObject/Recur/RRuleIteratorTest.php +++ b/tests/VObject/Recur/RRuleIteratorTest.php @@ -1052,7 +1052,14 @@ public function testYearlyBySetPosLoop(): void 'FREQ=YEARLY;BYMONTH=5;BYSETPOS=3;BYMONTHDAY=3', '2022-03-03 15:45:00', [], - 'yearly', null, 1, null, '2022-05-01' + 'yearly', + null, + 1, + null, + '2022-05-01', + 'UTC', + false, + false, ); } @@ -1245,10 +1252,11 @@ public function parse( $expectedUntil = null, string $fastForward = null, string $tz = 'UTC', - bool $runTillTheEnd = false + bool $runTillTheEnd = false, + bool $yearlySkipUpperLimit = true ): void { $dt = new \DateTime($start, new \DateTimeZone($tz)); - $parser = new RRuleIterator($rule, $dt); + $parser = new RRuleIterator($rule, $dt, $yearlySkipUpperLimit); $this->assertEquals($expectedFreq, $parser->getFrequency()); $this->assertEquals($expectedCount, $parser->getCount());