File: ReflectionClosure6Test.php

package info (click to toggle)
php-opis-closure 3.6.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 576 kB
  • sloc: php: 3,313; xml: 41; makefile: 17; sh: 8
file content (117 lines) | stat: -rw-r--r-- 3,080 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
<?php declare(strict_types=1);

namespace Opis\Closure\Test;

use Closure;
use Opis\Closure\ReflectionClosure;

// Fake
use Opis\Closure\SerializableClosure;
use Some\ClassName as ClassAlias;

final class ReflectionClosure6Test extends \PHPUnit\Framework\TestCase
{
    protected function c(Closure $closure)
    {
        $r = new ReflectionClosure($closure);

        return $r->getCode();
    }

    protected function s($closure)
    {
        $closure = new SerializableClosure($closure);

        return unserialize(serialize($closure))->getClosure();
    }

    public function testUnionTypes()
    {
        $f1 = fn(): string|int|false|Bar|null => 1;
        $e1 = 'fn(): string|int|false|\Bar|null => 1';

        $f2 = fn(): \Foo|\Bar => 1;
        $e2 = 'fn(): \Foo|\Bar => 1';

        $f3 = fn(): int|false => false;
        $e3 = 'fn(): int|false => false';

        $f4 = function (): null|MyClass|ClassAlias|Relative\Ns\ClassName|\Absolute\Ns\ClassName { return null; };
        $e4 = 'function (): null|\MyClass|\Some\ClassName|\Relative\Ns\ClassName|\Absolute\Ns\ClassName { return null; }';

        $this->assertEquals($e1, $this->c($f1));
        $this->assertEquals($e2, $this->c($f2));
        $this->assertEquals($e3, $this->c($f3));
        $this->assertEquals($e4, $this->c($f4));

        self::assertTrue(true);
    }

    public function testMixedType()
    {
        $f1 = function (): mixed { return 42; };
        $e1 = 'function (): mixed { return 42; }';

        $this->assertEquals($e1, $this->c($f1));
    }

    public function testNullsafeOperator()
    {
        $f1 = function () { $obj = new \stdClass(); return $obj?->invalid(); };
        $e1 = 'function () { $obj = new \stdClass(); return $obj?->invalid(); }';

        $this->assertEquals($e1, $this->c($f1));
    }

    public function testTraillingComma()
    {
        $f1 = function (string $param,) {};
        $e1 = 'function (string $param,) {}';

        $this->assertEquals($e1, $this->c($f1));
    }

    public function testNamedParameter()
    {
        $f1 = function(string $firstName, string $lastName) { return $firstName . ' ' . $lastName;};

        $unserialized = $this->s($f1);

        $this->assertEquals('Marco Deleu', $unserialized(
            lastName: 'Deleu',
            firstName: 'Marco'
        ));
    }

    public function testConstructorPropertyPromotion()
    {
        $class = new PropertyPromotion('public', 'protected', 'private');

        $f1 = fn() => $class;

        $object = $this->s($f1)();

        $this->assertEquals('public', $object->public);
        $this->assertEquals('protected', $object->getProtected());
        $this->assertEquals('private', $object->getPrivate());
    }
}

class PropertyPromotion
{
    public function __construct(
        public string $public,
        protected string $protected,
        private string $private,
    ) {}

    public function getProtected(): string
    {
        return $this->protected;
    }

    public function getPrivate(): string
    {
        return $this->private;
    }
}