Passed
Pull Request — master (#76)
by Marco
04:42
created

testWillAllowSpecifyingGitRevision()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace RoaveE2ETest\BackwardCompatibility\Command;
6
7
use PHPUnit\Framework\TestCase;
8
use Symfony\Component\Process\Process;
9
10
/**
11
 * @coversNothing
12
 */
13
final class AssertBackwardsCompatibleTest extends TestCase
14
{
15
    private const COMPOSER_MANIFEST = <<<'JSON'
16
{
17
    "autoload": {
18
        "psr-4": {
19
            "TestArtifact\\": "src/"
20
        }
21
    },
22
    "repositories": [
23
        {
24
            "packagist.org": false
25
        }
26
    ]
27
}
28
29
JSON;
30
31
    private const CLASS_VERSIONS = [
32
        <<<'PHP'
33
<?php
34
35
namespace TestArtifact;
36
37
final class TheClass
38
{
39
    public function method(A $a)
40
    {
41
    }
42
}
43
44
PHP
45
        ,
46
        <<<'PHP'
47
<?php
48
49
namespace TestArtifact;
50
51
final class TheClass
52
{
53
    public function method(B $a)
54
    {
55
    }
56
}
57
58
PHP
59
        ,
60
        <<<'PHP'
61
<?php
62
63
namespace TestArtifact;
64
65
final class TheClass
66
{
67
    public function method(C $a)
68
    {
69
    }
70
}
71
72
PHP
73
        ,
74
        // The last version resets the class to its initial state
75
        <<<'PHP'
76
<?php
77
78
namespace TestArtifact;
79
80
final class TheClass
81
{
82
    public function method(A $a)
83
    {
84
    }
85
}
86
87
PHP
88
    ];
89
90
    /** @var string path to the sources that should be checked */
91
    private $sourcesRepository;
92
93
    /** @var string[] sha1 of the source versions */
94
    private $versions = [];
95
96
    protected function setUp() : void
97
    {
98
        parent::setUp();
99
100
        $this->sourcesRepository = tempnam(sys_get_temp_dir(), 'roave-backward-compatibility-e2e-test');
101
102
        self::assertInternalType('string', $this->sourcesRepository);
103
        self::assertNotEmpty($this->sourcesRepository);
104
        self::assertFileExists($this->sourcesRepository);
105
106
        unlink($this->sourcesRepository);
107
        mkdir($this->sourcesRepository);
108
        mkdir($this->sourcesRepository . '/src');
109
110
        self::assertDirectoryExists($this->sourcesRepository);
111
        self::assertDirectoryExists($this->sourcesRepository . '/src');
112
113
        (new Process('git init', $this->sourcesRepository))->mustRun();
114
115
        file_put_contents($this->sourcesRepository . '/composer.json', self::COMPOSER_MANIFEST);
116
117
        (new Process('git add -A', $this->sourcesRepository))->mustRun();
118
        (new Process('git commit -am "Initial commit with composer manifest"', $this->sourcesRepository))->mustRun();
119
120
        foreach (self::CLASS_VERSIONS as $key => $classCode) {
121
            file_put_contents($this->sourcesRepository . '/src/TheClass.php', $classCode);
122
123
            (new Process('git add -A', $this->sourcesRepository))->mustRun();
124
            (new Process(sprintf('git commit -am "Class sources v%d"', $key + 1), $this->sourcesRepository))->mustRun();
125
            $this->versions[$key] = trim((new Process('git rev-parse HEAD', $this->sourcesRepository))->mustRun()
126
                                                                                                      ->getOutput());
127
        }
128
    }
129
130
    protected function tearDown() : void
131
    {
132
        self::assertInternalType('string', $this->sourcesRepository);
133
        self::assertNotEmpty($this->sourcesRepository);
134
        self::assertDirectoryExists($this->sourcesRepository);
135
136
        // Need to be extremely careful with this stuff - skipping it for now
137
        (new Process(['rm', '-r', $this->sourcesRepository]))->mustRun();
138
139
        parent::tearDown();
140
    }
141
142
    public function testWillAllowSpecifyingGitRevision() : void
143
    {
144
        $check = new Process(
145
            [
146
                __DIR__ . '/../../../bin/roave-backward-compatibility-check',
147
                '--from=' . $this->versions[0],
148
                '--to=' . $this->versions[1],
149
            ],
150
            $this->sourcesRepository
151
        );
152
153
        self::assertSame(3, $check->run());
154
        self::assertStringEndsWith(
155
            <<<'EXPECTED'
156
[BC] CHANGED: The parameter $a of TestArtifact\TheClass#method() changed from TestArtifact\A to a non-contravariant TestArtifact\B
157
1 backwards-incompatible changes detected
158
159
EXPECTED
160
            ,
161
            $check->getErrorOutput() // @TODO https://github.com/Roave/BackwardCompatibilityCheck/issues/79 this looks like a symfony bug - we shouldn't check STDERR, but STDOUT
162
        );
163
    }
164
165
    public function testWillNotRunWithoutTagsNorSpecifiedVersions() : void
166
    {
167
        $check = new Process(
168
            __DIR__ . '/../../../bin/roave-backward-compatibility-check',
169
            $this->sourcesRepository
170
        );
171
172
        self::assertSame(212, $check->run());
173
        self::assertContains(
174
            'Could not detect any released versions for the given repository',
175
            $check->getErrorOutput()
176
        );
177
    }
178
179
    public function testWillRunSuccessfullyOnNoBcBreaks() : void
180
    {
181
        $check = new Process(
182
            [
183
                __DIR__ . '/../../../bin/roave-backward-compatibility-check',
184
                '--from=' . $this->versions[0],
185
                '--to=' . $this->versions[3],
186
            ],
187
            $this->sourcesRepository
188
        );
189
190
        self::assertSame(0, $check->run());
191
        self::assertContains(
192
            'No backwards-incompatible changes detected',
193
            $check->getErrorOutput()
194
        );
195
    }
196
197
    public function testWillPickTaggedVersionOnNoGivenFrom() : void
198
    {
199
        $this->tagOnVersion('1.2.3', 1);
200
201
        $check = new Process(
202
            [
203
                __DIR__ . '/../../../bin/roave-backward-compatibility-check',
204
                '--to=' . $this->versions[2],
205
            ],
206
            $this->sourcesRepository
207
        );
208
209
        self::assertSame(3, $check->run());
210
211
        $errorOutput = $check->getErrorOutput();
212
213
        self::assertContains('Detected last minor version: 1.2.3', $errorOutput);
214
        self::assertStringEndsWith(
215
            <<<'EXPECTED'
216
[BC] CHANGED: The parameter $a of TestArtifact\TheClass#method() changed from TestArtifact\B to a non-contravariant TestArtifact\C
217
1 backwards-incompatible changes detected
218
219
EXPECTED
220
            ,
221
            $errorOutput // @TODO https://github.com/Roave/BackwardCompatibilityCheck/issues/79 this looks like a symfony bug - we shouldn't check STDERR, but STDOUT
222
        );
223
    }
224
225
    public function testWillPickLatestTaggedVersionOnNoGivenFrom() : void
226
    {
227
        $this->tagOnVersion('2.2.3', 1);
228
        $this->tagOnVersion('1.2.3', 3);
229
230
        $check = new Process(
231
            [
232
                __DIR__ . '/../../../bin/roave-backward-compatibility-check',
233
                '--to=' . $this->versions[2],
234
            ],
235
            $this->sourcesRepository
236
        );
237
238
        self::assertSame(3, $check->run());
239
240
        $errorOutput = $check->getErrorOutput();
241
242
        self::assertContains('Detected last minor version: 2.2.3', $errorOutput);
243
        self::assertStringEndsWith(
244
            <<<'EXPECTED'
245
[BC] CHANGED: The parameter $a of TestArtifact\TheClass#method() changed from TestArtifact\B to a non-contravariant TestArtifact\C
246
1 backwards-incompatible changes detected
247
248
EXPECTED
249
            ,
250
            $errorOutput // @TODO https://github.com/Roave/BackwardCompatibilityCheck/issues/79 this looks like a symfony bug - we shouldn't check STDERR, but STDOUT
251
        );
252
    }
253
254
    private function tagOnVersion(string $tagName, int $version) : void
255
    {
256
        (new Process(
257
            [
258
                'git',
259
                'checkout',
260
                $this->versions[$version],
261
            ],
262
            $this->sourcesRepository
263
        ))->mustRun();
264
265
        (new Process(
266
            [
267
                'git',
268
                'tag',
269
                $tagName,
270
                '-m',
271
                'A tag for version ' . $version,
272
            ],
273
            $this->sourcesRepository
274
        ))->mustRun();
275
    }
276
}
277