Passed
Push — main ( edb315...b4ea7c )
by Siad
05:13
created

BuildFileTest::getResource()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Test\Support;
22
23
use Phing\Exception\BuildException;
24
use Phing\Io\File;
25
use Phing\Io\IOException;
26
use Phing\Parser\ProjectConfigurator;
27
use Phing\Project;
28
use PHPUnit\Framework\TestCase;
29
30
/**
31
 * A BuildFileTest is a TestCase which executes targets from a Phing buildfile
32
 * for testing.
33
 *
34
 * This class provides a number of utility methods for particular build file
35
 * tests which extend this class.
36
 *
37
 * @author Nico Seessle <[email protected]>
38
 * @author Conor MacNeill
39
 * @author Victor Farazdagi <[email protected]>
40
 */
41
abstract class BuildFileTest extends TestCase
42
{
43
    /**
44
     * @var array array of log BuildEvent objects
45
     */
46
    public $logBuffer = [];
47
    /** @var Project */
48
    protected $project;
49
50
    /**
51
     * @var array
52
     */
53
    private $outBuffer;
54
55
    /**
56
     * @var array
57
     */
58
    private $errBuffer;
59
60
    /**
61
     * @var BuildException
62
     */
63
    private $buildException;
64
65
    public function assertFileSizeAtLeast(string $filepath, int $bytes)
66
    {
67
        $actualSize = filesize($filepath);
68
69
        if (!is_int($actualSize)) {
0 ignored issues
show
introduced by
The condition is_int($actualSize) is always true.
Loading history...
70
            $this->fail("Error while reading file '{$filepath}'");
71
        }
72
73
        $this->assertGreaterThanOrEqual($bytes, $actualSize);
74
    }
75
76
    /**
77
     * Asserts that the log buffer contains specified message at specified priority.
78
     *
79
     * @param string $expected Message subsctring
80
     * @param null $priority Message priority (default: any)
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $priority is correct as it would always require null to be passed?
Loading history...
81
     * @param string $errormsg the error message to display
82
     */
83
    protected function assertInLogs(string $expected, $priority = null, $errormsg = "Expected to find '%s' in logs: %s")
84
    {
85
        $found = false;
86
        foreach ($this->logBuffer as $log) {
87
            if (false !== stripos($log['message'], $expected)) {
88
                $this->assertEquals(1, 1); // increase number of positive assertions
89
                if (null === $priority) {
90
                    return;
91
                }
92
                if ($priority >= $log['priority']) {
93
                    $found = true;
94
                }
95
            }
96
            if ($found) {
97
                return;
98
            }
99
        }
100
        $representation = [];
101
        foreach ($this->logBuffer as $log) {
102
            $representation[] = "[msg=\"{$log['message']}\",priority={$log['priority']}]";
103
        }
104
        $this->fail(sprintf($errormsg, $expected, var_export($representation, true)));
105
    }
106
107
    /**
108
     * Asserts that the log buffer contains specified message at specified priority.
109
     *
110
     * @param string $expected Message subsctring
111
     * @param null $priority Message priority (default: any)
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $priority is correct as it would always require null to be passed?
Loading history...
112
     * @param string $errormsg the error message to display
113
     */
114
    protected function assertLogLineContaining(
115
        string $expected,
116
        $priority = null,
117
        $errormsg = "Expected to find a log line that starts with '%s': %s"
118
    ) {
119
        $found = false;
120
        foreach ($this->logBuffer as $log) {
121
            if (false !== strpos($log['message'], $expected)) {
122
                $this->assertEquals(1, 1); // increase number of positive assertions
123
                if (null === $priority) {
124
                    return;
125
                }
126
                if ($priority >= $log['priority']) {
127
                    $found = true;
128
                }
129
            }
130
            if ($found) {
131
                return;
132
            }
133
        }
134
        $representation = [];
135
        foreach ($this->logBuffer as $log) {
136
            $representation[] = "[msg=\"{$log['message']}\",priority={$log['priority']}]";
137
        }
138
        $this->fail(sprintf($errormsg, $expected, var_export($representation, true)));
139
    }
140
141
    /**
142
     * Asserts that the log buffer does NOT contain specified message at specified priority.
143
     *
144
     * @param string $message Message subsctring
145
     * @param null $priority Message priority (default: any)
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $priority is correct as it would always require null to be passed?
Loading history...
146
     * @param string $errormsg the error message to display
147
     */
148
    protected function assertNotInLogs(
149
        string $message,
150
        $priority = null,
0 ignored issues
show
Unused Code introduced by
The parameter $priority is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

150
        /** @scrutinizer ignore-unused */ $priority = null,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
151
        $errormsg = "Unexpected string '%s' found in logs: %s"
152
    ) {
153
        foreach ($this->logBuffer as $log) {
154
            if (false !== stripos($log['message'], $message)) {
155
                $representation = [];
156
                foreach ($this->logBuffer as $log) {
0 ignored issues
show
Comprehensibility Bug introduced by
$log is overwriting a variable from outer foreach loop.
Loading history...
157
                    $representation[] = "[msg=\"{$log['message']}\",priority={$log['priority']}]";
158
                }
159
                $this->fail(sprintf($errormsg, $message, var_export($representation, true)));
160
            }
161
        }
162
163
        $this->assertEquals(1, 1); // increase number of positive assertions
164
    }
165
166
    /**
167
     *  run a target, expect for any build exception.
168
     *
169
     * @param string $target target to run
170
     * @param string $cause information string to reader of report
171
     */
172
    protected function expectBuildException(string $target, string $cause)
173
    {
174
        $this->expectSpecificBuildException($target, $cause, null);
175
    }
176
177
    /**
178
     * Assert that only the given message has been logged with a
179
     * priority &gt;= INFO when running the given target.
180
     *
181
     * @param mixed $target
182
     * @param mixed $log
183
     */
184
    protected function expectLog($target, $log)
185
    {
186
        $this->executeTarget($target);
187
        $this->assertInLogs($log);
188
    }
189
190
    /**
191
     * Assert that the given message has been logged with a priority
192
     * &gt;= INFO when running the given target.
193
     *
194
     * @param mixed $target
195
     * @param mixed $log
196
     */
197
    protected function expectLogContaining($target, $log)
198
    {
199
        $this->executeTarget($target);
200
        $this->assertInLogs($log);
201
    }
202
203
    /**
204
     * Assert that the given message has been logged with a priority
205
     * &gt;= DEBUG when running the given target.
206
     *
207
     * @param mixed $target
208
     * @param mixed $log
209
     */
210
    protected function expectDebuglog($target, $log)
211
    {
212
        $this->executeTarget($target);
213
        $this->assertInLogs($log, Project::MSG_DEBUG);
214
    }
215
216
    /**
217
     *  execute the target, verify output matches expectations.
218
     *
219
     * @param string $target target to execute
220
     * @param string $output output to look for
221
     */
222
    protected function expectOutput(string $target, string $output)
223
    {
224
        $this->executeTarget($target);
225
        $realOutput = $this->getOutput();
226
        $this->assertEquals($output, $realOutput);
227
    }
228
229
    /**
230
     *  execute the target, verify output matches expectations
231
     *  and that we got the named error at the end.
232
     *
233
     * @param string $target target to execute
234
     * @param string $output output to look for
235
     * @param string $error Description of Parameter
236
     */
237
    protected function expectOutputAndError(string $target, string $output, string $error)
238
    {
239
        $this->executeTarget($target);
240
        $realOutput = $this->getOutput();
241
        $this->assertEquals($output, $realOutput);
242
        $realError = $this->getError();
243
        $this->assertEquals($error, $realError);
244
    }
245
246
    protected function getOutput(): string
247
    {
248
        return $this->cleanBuffer($this->outBuffer);
249
    }
250
251
    protected function getError(): string
252
    {
253
        return $this->cleanBuffer($this->errBuffer);
254
    }
255
256
    protected function getBuildException(): BuildException
257
    {
258
        return $this->buildException;
259
    }
260
261
    /**
262
     *  set up to run the named project.
263
     *
264
     * @param string $filename name of project file to run
265
     *
266
     * @throws BuildException
267
     * @throws IOException
268
     */
269
    protected function configureProject(string $filename)
270
    {
271
        $this->logBuffer = [];
272
        $this->project = new Project();
273
        $this->project->init();
274
        $f = new File($filename);
275
        $this->project->setUserProperty('phing.file', $f->getAbsolutePath());
276
        $this->project->setUserProperty('phing.dir', dirname($f->getAbsolutePath()));
277
        $this->project->addBuildListener(new PhingTestListener($this));
278
        ProjectConfigurator::configureProject($this->project, new File($filename));
279
    }
280
281
    /**
282
     *  execute a target we have set up.
283
     *
284
     * @pre configureProject has been called
285
     *
286
     * @param string $targetName target to run
287
     */
288
    protected function executeTarget(string $targetName)
289
    {
290
        if (empty($this->project)) {
291
            return;
292
        }
293
294
        $this->outBuffer = '';
0 ignored issues
show
Documentation Bug introduced by
It seems like '' of type string is incompatible with the declared type array of property $outBuffer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
295
        $this->errBuffer = '';
0 ignored issues
show
Documentation Bug introduced by
It seems like '' of type string is incompatible with the declared type array of property $errBuffer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
296
        $this->logBuffer = [];
297
        $this->buildException = null;
298
        $this->project->executeTarget($targetName);
299
    }
300
301
    /**
302
     * Get the project which has been configured for a test.
303
     *
304
     * @return Project the Project instance for this test
305
     */
306
    protected function getProject(): Project
307
    {
308
        return $this->project;
309
    }
310
311
    /**
312
     * get the directory of the project.
313
     *
314
     * @return File the base dir of the project
315
     */
316
    protected function getProjectDir(): File
317
    {
318
        return $this->project->getBasedir();
319
    }
320
321
    /**
322
     *  run a target, wait for a build exception.
323
     *
324
     * @param string $target target to run
325
     * @param string $cause information string to reader of report
326
     * @param string|null $msg the message value of the build exception we are waiting for
327
     *                       set to null for any build exception to be valid
328
     */
329
    protected function expectSpecificBuildException(string $target, string $cause, ?string $msg): void
330
    {
331
        try {
332
            $this->executeTarget($target);
333
        } catch (BuildException $ex) {
334
            $this->buildException = $ex;
335
            if ((null !== $msg) && ($ex->getMessage() !== $msg)) {
336
                $this->fail(
337
                    "Should throw BuildException because '" . $cause
338
                    . "' with message '" . $msg
339
                    . "' (actual message '" . $ex->getMessage() . "' instead)"
340
                );
341
            }
342
            $this->assertEquals(1, 1); // increase number of positive assertions
343
344
            return;
345
        }
346
        $this->fail('Should throw BuildException because: ' . $cause);
347
    }
348
349
    /**
350
     *  run a target, expect an exception string
351
     *  containing the substring we look for (case sensitive match).
352
     *
353
     * @param string $target target to run
354
     * @param string $cause information string to reader of report
355
     * @param string $contains substring of the build exception to look for
356
     */
357
    protected function expectBuildExceptionContaining(string $target, string $cause, string $contains)
358
    {
359
        try {
360
            $this->executeTarget($target);
361
        } catch (BuildException $ex) {
362
            $this->buildException = $ex;
363
            $found = false;
364
            while ($ex) {
365
                $msg = $ex->getMessage();
366
                if (false !== strpos($ex->getMessage(), $contains)) {
367
                    $found = true;
368
                }
369
                $ex = $ex->getPrevious();
370
            }
371
372
            if (!$found) {
373
                $this->fail(
374
                    "Should throw BuildException because '" . $cause . "' with message containing '" . $contains
375
                    . "' (actual message '" . $msg . "' instead)"
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $msg does not seem to be defined for all execution paths leading up to this point.
Loading history...
376
                );
377
            }
378
379
            $this->assertEquals(1, 1); // increase number of positive assertions
380
381
            return;
382
        }
383
        $this->fail('Should throw BuildException because: ' . $cause);
384
    }
385
386
    /**
387
     * call a target, verify property is as expected.
388
     *
389
     * @param string $target build file target
390
     * @param string $property property name
391
     * @param string $value expected value
392
     */
393
    protected function expectPropertySet(string $target, string $property, $value = 'true')
394
    {
395
        $this->executeTarget($target);
396
        $this->assertPropertyEquals($property, $value);
397
    }
398
399
    /**
400
     * assert that a property equals a value; comparison is case sensitive.
401
     *
402
     * @param string $property property name
403
     * @param string|null $value expected value
404
     */
405
    protected function assertPropertyEquals(string $property, ?string $value)
406
    {
407
        $result = $this->project->getProperty($property);
408
        $this->assertEquals($value, $result, 'property ' . $property);
409
    }
410
411
    /**
412
     * assert that a property equals &quot;true&quot;.
413
     *
414
     * @param string $property property name
415
     */
416
    protected function assertPropertySet(string $property)
417
    {
418
        $this->assertPropertyEquals($property, 'true');
419
    }
420
421
    /**
422
     * assert that a property is null.
423
     *
424
     * @param string $property property name
425
     */
426
    protected function assertPropertyUnset(string $property)
427
    {
428
        $this->assertPropertyEquals($property, null);
429
    }
430
431
    /**
432
     * call a target, verify property is null.
433
     *
434
     * @param string $target build file target
435
     * @param string $property property name
436
     */
437
    protected function expectPropertyUnset(string $target, string $property)
438
    {
439
        $this->expectPropertySet($target, $property, null);
440
    }
441
442
    protected function rmdir($dir): bool
443
    {
444
        if (!file_exists($dir)) {
445
            return true;
446
        }
447
        if (!is_dir($dir)) {
448
            return unlink($dir);
449
        }
450
        foreach (scandir($dir) as $item) {
451
            if ('.' === $item || '..' === $item) {
452
                continue;
453
            }
454
            if (!$this->rmdir($dir . DIRECTORY_SEPARATOR . $item)) {
455
                return false;
456
            }
457
        }
458
459
        return rmdir($dir);
460
    }
461
462
    /**
463
     * Get relative date.
464
     *
465
     * @param int $timestamp Timestamp to us as pin-point
466
     * @param string $type Whether 'fulldate' or 'time'
467
     *
468
     * @return string
469
     */
470
    protected function getRelativeDate(int $timestamp, $type = 'fulldate'): string
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

470
    protected function getRelativeDate(int $timestamp, /** @scrutinizer ignore-unused */ $type = 'fulldate'): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
471
    {
472
        // calculate the diffrence
473
        $timediff = time() - $timestamp;
474
475
        if ($timediff < 3600) {
476
            if ($timediff < 120) {
477
                $returndate = '1 minute ago';
478
            } else {
479
                $returndate = ceil($timediff / 60) . ' minutes ago';
480
            }
481
        } else {
482
            if ($timediff < 7200) {
483
                $returndate = '1 hour ago.';
484
            } else {
485
                if ($timediff < 86400) {
486
                    $returndate = ceil($timediff / 3600) . ' hours ago';
487
                } else {
488
                    if ($timediff < 172800) {
489
                        $returndate = '1 day ago.';
490
                    } else {
491
                        if ($timediff < 604800) {
492
                            $returndate = ceil($timediff / 86400) . ' days ago';
493
                        } else {
494
                            if ($timediff < 1209600) {
495
                                $returndate = ceil($timediff / 86400) . ' days ago';
496
                            } else {
497
                                if ($timediff < 2629744) {
498
                                    $returndate = ceil($timediff / 86400) . ' days ago';
499
                                } else {
500
                                    if ($timediff < 3024000) {
501
                                        $returndate = ceil($timediff / 604900) . ' weeks ago';
502
                                    } else {
503
                                        if ($timediff > 5259486) {
504
                                            $returndate = ceil($timediff / 2629744) . ' months ago';
505
                                        } else {
506
                                            $returndate = ceil($timediff / 604900) . ' weeks ago';
507
                                        }
508
                                    }
509
                                }
510
                            }
511
                        }
512
                    }
513
                }
514
            }
515
        }
516
517
        return $returndate;
518
    }
519
520
    private function cleanBuffer($buffer): string
521
    {
522
        $cleanedBuffer = '';
523
        $cr = false;
524
        for ($i = 0, $bufflen = strlen($buffer); $i < $bufflen; ++$i) {
525
            $ch = $buffer[$i];
526
            if ("\r" === $ch) {
527
                $cr = true;
528
529
                continue;
530
            }
531
532
            if (!$cr) {
533
                $cleanedBuffer .= $ch;
534
            } else {
535
                if ("\n" === $ch) {
536
                    $cleanedBuffer .= $ch;
537
                } else {
538
                    $cleanedBuffer .= "\r" . $ch;
539
                }
540
            }
541
        }
542
543
        return $cleanedBuffer;
544
    }
545
}
546