File: LoopTest.php

package info (click to toggle)
php-malkusch-lock 2.3.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 440 kB
  • sloc: php: 2,124; makefile: 19
file content (147 lines) | stat: -rw-r--r-- 3,799 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php

declare(strict_types=1);

namespace malkusch\lock\Tests\util;

use malkusch\lock\exception\TimeoutException;
use malkusch\lock\util\Loop;
use phpmock\environment\SleepEnvironmentBuilder;
use phpmock\MockEnabledException;
use phpmock\phpunit\PHPMock;
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\TestCase;

class LoopTest extends TestCase
{
    use PHPMock;

    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();

        $sleepBuilder = new SleepEnvironmentBuilder();
        $sleepBuilder->addNamespace(__NAMESPACE__);
        $sleepBuilder->addNamespace('malkusch\lock\util');
        $sleep = $sleepBuilder->build();
        try {
            $sleep->enable();
            $this->registerForTearDown($sleep);
        } catch (MockEnabledException $e) {
            // workaround for burn testing
            \assert($e->getMessage() === 'microtime is already enabled.Call disable() on the existing mock.');
        }
    }

    /**
     * Test an invalid timeout.
     */
    public function testInvalidTimeout(): void
    {
        $this->expectException(\LengthException::class);

        new Loop(0);
    }

    /**
     * Tests execution within the timeout.
     *
     * @doesNotPerformAssertions
     */
    #[DoesNotPerformAssertions]
    public function testExecutionWithinTimeout(): void
    {
        $loop = new Loop(0.5);
        $loop->execute(static function () use ($loop): void {
            usleep(499 * 1000);
            $loop->end();
        });
    }

    /**
     * Tests execution within the timeout without calling end().
     */
    public function testExecutionWithinTimeoutWithoutExplicitEnd(): void
    {
        $this->expectException(TimeoutException::class);
        $this->expectExceptionMessage('Timeout of 0.5 seconds exceeded');

        $loop = new Loop(0.5);
        $loop->execute(static function (): void {
            usleep(10 * 1000);
        });
    }

    /**
     * Tests exceeding the execution timeout.
     *
     * @doesNotPerformAssertions
     */
    #[DoesNotPerformAssertions]
    public function testExceedTimeoutIsAcceptableIfEndWasCalled(): void
    {
        $loop = new Loop(0.5);
        $loop->execute(static function () use ($loop): void {
            usleep(501 * 1000);
            $loop->end();
        });
    }

    /**
     * Tests exceeding the execution timeout without calling end().
     */
    public function testExceedTimeoutWithoutExplicitEnd(): void
    {
        $this->expectException(TimeoutException::class);
        $this->expectExceptionMessage('Timeout of 0.5 seconds exceeded');

        $loop = new Loop(0.5);
        $loop->execute(static function (): void {
            usleep(501 * 1000);
        });
    }

    /**
     * Tests that an exception would stop any further iteration.
     */
    public function testExceptionStopsIteration(): void
    {
        $this->expectException(\DomainException::class);

        $loop = new Loop();
        $loop->execute(static function () {
            throw new \DomainException();
        });
    }

    /**
     * Tests end() will stop the iteration and return the result.
     */
    public function testEnd(): void
    {
        $i = 0;
        $loop = new Loop();
        $loop->execute(static function () use ($loop, &$i) {
            ++$i;
            $loop->end();
        });
        self::assertSame(1, $i);
    }

    /**
     * Tests that the code is executed more times.
     */
    public function testIteration(): void
    {
        $i = 0;
        $loop = new Loop();
        $loop->execute(static function () use ($loop, &$i): void {
            ++$i;
            if ($i > 1) {
                $loop->end();
            }
        });
        self::assertSame(2, $i);
    }
}