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\Task\System; |
||
22 | |||
23 | use Exception; |
||
24 | use Phing\Io\File; |
||
25 | use Phing\Io\FileUtils; |
||
26 | use Phing\Target; |
||
27 | use Phing\Task; |
||
28 | use Phing\Task\System\ApplyTask; |
||
29 | use Phing\Test\Support\BuildFileTest; |
||
30 | use Phing\UnknownElement; |
||
31 | use ReflectionException; |
||
32 | use ReflectionProperty; |
||
33 | |||
34 | /** |
||
35 | * Tests the Apply Task. |
||
36 | * |
||
37 | * @author Utsav Handa <handautsav at hotmail dot com> |
||
38 | */ |
||
39 | class ApplyTaskTest extends BuildFileTest |
||
40 | { |
||
41 | /** |
||
42 | * Whether test is being run on windows. |
||
43 | * |
||
44 | * @var bool |
||
45 | */ |
||
46 | protected $windows; |
||
47 | |||
48 | /** |
||
49 | * Setup the test. |
||
50 | */ |
||
51 | public function setUp(): void |
||
52 | { |
||
53 | // Tests definitions |
||
54 | $this->configureProject(PHING_TEST_BASE . '/etc/tasks/system/ApplyTest.xml'); |
||
55 | |||
56 | // Identifying the running environment |
||
57 | $this->windows = 'WIN' === strtoupper(substr(PHP_OS, 0, 3)); |
||
58 | } |
||
59 | |||
60 | // T E S T S |
||
61 | |||
62 | /** |
||
63 | * Tests the OS configuration setting. |
||
64 | */ |
||
65 | public function testPropertySetOs() |
||
66 | { |
||
67 | $this->assertAttributeIsSetTo('os', 'linux'); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Tests the dir configuration setting. |
||
72 | */ |
||
73 | public function testPropertySetDir() |
||
74 | { |
||
75 | $this->assertAttributeIsSetTo('dir', new File($this->project->getProperty('php.tmpdir'))); |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Tests the escape configuration setting. |
||
80 | */ |
||
81 | public function testPropertySetEscape() |
||
82 | { |
||
83 | $this->assertAttributeIsSetTo('escape', true); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Tests the pass-thru configuration setting. |
||
88 | */ |
||
89 | public function testPropertySetPassthru() |
||
90 | { |
||
91 | $this->assertAttributeIsSetTo('passthru', true); |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Tests the spawn configuration setting. |
||
96 | */ |
||
97 | public function testPropertySetSpawn() |
||
98 | { |
||
99 | $this->assertAttributeIsSetTo('spawn', true); |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * Tests the returnProperty configuration setting. |
||
104 | */ |
||
105 | public function testPropertySetReturnProperty() |
||
106 | { |
||
107 | $this->assertAttributeIsSetTo('returnProperty', 'retval'); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Tests the outputProperty configuration setting. |
||
112 | */ |
||
113 | public function testPropertySetOutputProperty() |
||
114 | { |
||
115 | $this->assertAttributeIsSetTo('outputProperty', 'outval'); |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Tests the checkReturn/failonerror configuration setting. |
||
120 | */ |
||
121 | public function testPropertySetCheckReturn() |
||
122 | { |
||
123 | $this->assertAttributeIsSetTo('checkreturn', true); |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Tests the output configuration setting. |
||
128 | */ |
||
129 | public function testPropertySetOutput() |
||
130 | { |
||
131 | $this->assertAttributeIsSetTo( |
||
132 | 'output', |
||
133 | new File($this->project->getProperty('php.tmpdir') . '/outputfilename') |
||
134 | ); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Tests the error configuration setting. |
||
139 | */ |
||
140 | public function testPropertySetError() |
||
141 | { |
||
142 | $this->assertAttributeIsSetTo( |
||
143 | 'error', |
||
144 | new File($this->project->getProperty('php.tmpdir') . '/errorfilename') |
||
145 | ); |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Tests the append configuration setting. |
||
150 | */ |
||
151 | public function testPropertySetAppend() |
||
152 | { |
||
153 | $this->assertAttributeIsSetTo('append', true, 'appendoutput'); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Tests the parallel configuration setting. |
||
158 | */ |
||
159 | public function testPropertySetParallel() |
||
160 | { |
||
161 | $this->assertAttributeIsSetTo('parallel', false); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * Tests the addsourcefile configuration setting. |
||
166 | */ |
||
167 | public function testPropertySetAddsourcefile() |
||
168 | { |
||
169 | $this->assertAttributeIsSetTo('addsourcefile', false); |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * Tests the relative configuration setting. |
||
174 | */ |
||
175 | public function testPropertySetRelative() |
||
176 | { |
||
177 | $this->assertAttributeIsSetTo('relative', false); |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Tests the forwardslash configuration setting. |
||
182 | */ |
||
183 | public function testPropertySetForwardslash() |
||
184 | { |
||
185 | $this->assertAttributeIsSetTo('forwardslash', true); |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Tests the maxparallel configuration setting. |
||
190 | */ |
||
191 | public function testPropertySetMaxparallel() |
||
192 | { |
||
193 | $this->assertAttributeIsSetTo('maxparallel', 10); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Tests the OS execution for the unspecified OS. |
||
198 | */ |
||
199 | public function testDoNotExecuteOnWrongOs() |
||
200 | { |
||
201 | // Process |
||
202 | $this->executeTarget(__FUNCTION__); |
||
203 | $this->assertInLogs('was not found in the specified list of valid OSes: unknownos'); |
||
204 | |||
205 | $this->assertStringNotContainsString('this should not be executed', $this->getOutput()); |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Tests the OS execution for the specified OS list. |
||
210 | */ |
||
211 | public function testExecuteOnCorrectOs() |
||
212 | { |
||
213 | $this->executeTarget(__FUNCTION__); |
||
214 | $this->assertInLogs('this should be executed'); |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Tests the dir changing on a non-existent directory. |
||
219 | */ |
||
220 | public function testFailOnNonExistingDir() |
||
221 | { |
||
222 | $nonExistentDir = $this->project->getProperty('php.tmpdir') . DIRECTORY_SEPARATOR |
||
223 | . 'non' . DIRECTORY_SEPARATOR |
||
224 | . 'existent' . DIRECTORY_SEPARATOR |
||
225 | . 'dir'; |
||
226 | |||
227 | return $this->expectBuildExceptionContaining( |
||
0 ignored issues
–
show
|
|||
228 | __FUNCTION__, |
||
229 | __FUNCTION__, |
||
230 | "'{$nonExistentDir}' is not a valid directory" |
||
231 | ); |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Tests the dir changing on an existent directory. |
||
236 | * |
||
237 | * @requires OS ^(?:(?!Win).)*$ |
||
238 | */ |
||
239 | public function testChangeToDir() |
||
240 | { |
||
241 | $this->executeTarget(__FUNCTION__); |
||
242 | $this->assertInLogs('Working directory change successful'); |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Tests the failonerror/checkreturn value for 'true'. |
||
247 | * |
||
248 | * @requires OS ^(?:(?!Win).)*$ |
||
249 | */ |
||
250 | public function testCheckreturnTrue() |
||
251 | { |
||
252 | $this->executeTarget(__FUNCTION__); |
||
253 | $this->assertTrue(true); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Tests the failonerror/checkreturn value for 'false'. |
||
258 | * |
||
259 | * @requires OS ^(?:(?!Win).)*$ |
||
260 | */ |
||
261 | public function testCheckreturnFalse() |
||
262 | { |
||
263 | return $this->expectBuildExceptionContaining(__FUNCTION__, __FUNCTION__, 'Task exited with code (1)'); |
||
0 ignored issues
–
show
Are you sure the usage of
$this->expectBuildExcept... exited with code (1)') targeting Phing\Test\Support\Build...ldExceptionContaining() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.
Loading history...
|
|||
264 | } |
||
265 | |||
266 | /** |
||
267 | * Tests the outputProperty setting. |
||
268 | */ |
||
269 | public function testOutputProperty() |
||
270 | { |
||
271 | $this->executeTarget(__FUNCTION__); |
||
272 | $this->assertInLogs('The output property\'s value is: "foo"'); |
||
273 | } |
||
274 | |||
275 | /** |
||
276 | * Tests the returnProperty setting. |
||
277 | */ |
||
278 | public function testReturnProperty() |
||
279 | { |
||
280 | $this->executeTarget(__FUNCTION__); |
||
281 | $this->assertInLogs('The return property\'s value is: "1"'); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * Tests the command escaping for execution. |
||
286 | */ |
||
287 | public function testEscape() |
||
288 | { |
||
289 | $this->executeTarget(__FUNCTION__); |
||
290 | $this->assertInLogs( |
||
291 | $this->windows |
||
292 | ? (escapeshellarg('echo') . ' ' . escapeshellarg('foo') . ' ' . escapeshellarg('|') . ' ' . escapeshellarg('cat')) |
||
293 | : ("'echo' 'foo' '|' 'cat'") |
||
294 | ); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Tests the command execution with 'passthru' function. |
||
299 | */ |
||
300 | public function testPassThru() |
||
301 | { |
||
302 | $this->executeTarget(__FUNCTION__); |
||
303 | $this->assertInLogs('Executing command:'); |
||
304 | } |
||
305 | |||
306 | /** |
||
307 | * Tests the output file functionality. |
||
308 | */ |
||
309 | public function testOutput() |
||
310 | { |
||
311 | // Getting a temp. file |
||
312 | $tempfile = tempnam(FileUtils::getTempDir(), 'phing-exectest-'); |
||
313 | |||
314 | // Setting the property |
||
315 | $this->project->setProperty('execTmpFile', $tempfile); |
||
316 | $this->executeTarget(__FUNCTION__); |
||
317 | |||
318 | // Validating the output |
||
319 | $output = @file_get_contents($tempfile); |
||
320 | @unlink($tempfile); |
||
321 | $this->assertEquals('outfoo', rtrim($output)); |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * Tests the error file functionality. |
||
326 | * |
||
327 | * @requires OS ^(?:(?!Win).)*$ |
||
328 | */ |
||
329 | public function testError() |
||
330 | { |
||
331 | // Getting a temp. file |
||
332 | $tempfile = tempnam(FileUtils::getTempDir(), 'phing-exectest-'); |
||
333 | |||
334 | $scriptFile = getcwd() . '/error_output.sh'; |
||
335 | file_put_contents($scriptFile, 'echo errfoo 1>&2'); |
||
336 | chmod($scriptFile, 0744); |
||
337 | |||
338 | // Setting the property |
||
339 | $this->project->setProperty('executable', $scriptFile); |
||
340 | $this->project->setProperty('execTmpFile', $tempfile); |
||
341 | $this->executeTarget(__FUNCTION__); |
||
342 | |||
343 | // Validating the output |
||
344 | $output = @file_get_contents($tempfile); |
||
345 | @unlink($tempfile); |
||
346 | @unlink($scriptFile); |
||
347 | $this->assertEquals('errfoo', rtrim($output)); |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * Tests the execution with the background process spawning. |
||
352 | * |
||
353 | * @requires OS ^(?:(?!Win).)*$ |
||
354 | */ |
||
355 | public function testSpawn() |
||
356 | { |
||
357 | // Process |
||
358 | $start = time(); |
||
359 | $this->executeTarget(__FUNCTION__); |
||
360 | $end = time(); |
||
361 | $this->assertLessThan( |
||
362 | 4, |
||
363 | ($end - $start), |
||
364 | 'Execution time should be lower than 4 seconds, otherwise spawning did not work' |
||
365 | ); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Tests the nested arguments specified for the execution. |
||
370 | */ |
||
371 | public function testNestedArgs() |
||
372 | { |
||
373 | $this->executeTarget(__FUNCTION__); |
||
374 | $this->assertInLogs('echo Hello World'); |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * Tests the missing/unspecified executable information. |
||
379 | */ |
||
380 | public function testMissingExecutable() |
||
381 | { |
||
382 | $this->expectBuildExceptionContaining(__FUNCTION__, __FUNCTION__, 'Please provide "executable" information'); |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Tests the escape functionality for special characters in argument. |
||
387 | */ |
||
388 | public function testEscapedArg() |
||
389 | { |
||
390 | $this->executeTarget(__FUNCTION__); |
||
391 | $this->assertPropertyEquals('outval', $this->windows ? 'abc$b3 SB' : 'abc$b3!SB'); |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Tests the relative source filenames functionality. |
||
396 | * |
||
397 | * @requires OS ^(?:(?!Win).)*$ |
||
398 | */ |
||
399 | public function testRelativeSourceFilenames() |
||
400 | { |
||
401 | $this->executeTarget(__FUNCTION__); |
||
402 | $this->assertNotInLogs('/etc/'); |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * Tests the source filename addition functionality. |
||
407 | * |
||
408 | * @requires OS ^(?:(?!Win).)*$ |
||
409 | */ |
||
410 | public function testSourceFilename() |
||
411 | { |
||
412 | $this->executeTarget(__FUNCTION__); |
||
413 | // As the addsourcefilename is 'off', only the executable should be processed in the execution |
||
414 | $this->assertInLogs('Executing command: ls'); |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * Tests the output file append functionality. |
||
419 | */ |
||
420 | public function testOutputAppend() |
||
421 | { |
||
422 | // Getting a temp. file |
||
423 | $tempfile = tempnam(FileUtils::getTempDir(), 'phing-exectest-'); |
||
424 | |||
425 | // Setting the property |
||
426 | $this->project->setProperty('execTmpFile', $tempfile); |
||
427 | $this->executeTarget(__FUNCTION__); |
||
428 | |||
429 | // Validating the output |
||
430 | $output = @file_get_contents($tempfile); |
||
431 | @unlink($tempfile); |
||
432 | $this->assertEquals($this->windows ? "Append OK \r\nAppend OK" : "Append OK\nAppend OK", rtrim($output)); |
||
433 | } |
||
434 | |||
435 | /** |
||
436 | * Tests the parallel configuration. |
||
437 | */ |
||
438 | public function testParallel() |
||
439 | { |
||
440 | $this->executeTarget(__FUNCTION__); |
||
441 | $messages = []; |
||
442 | foreach ($this->logBuffer as $log) { |
||
443 | $messages[] = $log['message']; |
||
444 | } |
||
445 | $this->assertEquals(1, substr_count(implode("\n", $messages), 'Executing command:')); |
||
446 | } |
||
447 | |||
448 | public function testMapperSupport() |
||
449 | { |
||
450 | // Getting a temp. file |
||
451 | $tempfile = tempnam(FileUtils::getTempDir(), 'phing-exectest-'); |
||
452 | |||
453 | // Setting the property |
||
454 | $this->project->setProperty('execTmpFile', $tempfile); |
||
455 | |||
456 | $this->executeTarget(__FUNCTION__); |
||
457 | $messages = []; |
||
458 | foreach ($this->logBuffer as $log) { |
||
459 | $messages[] = $log['message']; |
||
460 | } |
||
461 | $this->assertContains('Applied echo to 4 files and 0 directories.', $messages); |
||
462 | } |
||
463 | |||
464 | // H E L P E R M E T H O D S |
||
465 | |||
466 | /** |
||
467 | * @param string $name |
||
468 | * |
||
469 | * @return Target |
||
470 | * @throws Exception |
||
471 | */ |
||
472 | protected function getTargetByName(string $name): Target |
||
473 | { |
||
474 | foreach ($this->project->getTargets() as $target) { |
||
475 | if ($target->getName() == $name) { |
||
476 | return $target; |
||
477 | } |
||
478 | } |
||
479 | |||
480 | throw new Exception(sprintf('Target "%s" not found', $name)); |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * @param $target |
||
485 | * @param string $taskName |
||
486 | * @param int $pos |
||
487 | * |
||
488 | * @return Task |
||
489 | * @throws Exception |
||
490 | */ |
||
491 | protected function getTaskFromTarget($target, string $taskName, $pos = 0): Task |
||
492 | { |
||
493 | $rchildren = new ReflectionProperty(get_class($target), 'children'); |
||
494 | $rchildren->setAccessible(true); |
||
495 | $n = -1; |
||
496 | foreach ($rchildren->getValue($target) as $child) { |
||
497 | if ($child instanceof Task && ++$n == $pos) { |
||
498 | return $child; |
||
499 | } |
||
500 | } |
||
501 | |||
502 | throw new Exception(sprintf('%s #%d not found in task', $taskName, $pos)); |
||
503 | } |
||
504 | |||
505 | /** |
||
506 | * @param string $target |
||
507 | * @param string $task |
||
508 | * |
||
509 | * @return Task |
||
510 | * @throws Exception |
||
511 | */ |
||
512 | protected function getConfiguredTask(string $target, string $task): Task |
||
513 | { |
||
514 | $target = $this->getTargetByName($target); |
||
515 | $task = $this->getTaskFromTarget($target, $task); |
||
516 | $task->maybeConfigure(); |
||
517 | |||
518 | if ($task instanceof UnknownElement) { |
||
519 | return $task->getRuntimeConfigurableWrapper()->getProxy(); |
||
520 | } |
||
521 | |||
522 | return $task; |
||
523 | } |
||
524 | |||
525 | /** |
||
526 | * @param string $property |
||
527 | * @param mixed $value |
||
528 | * @param null $propertyName |
||
529 | * @throws ReflectionException |
||
530 | */ |
||
531 | protected function assertAttributeIsSetTo(string $property, $value, $propertyName = null) |
||
532 | { |
||
533 | $task = $this->getConfiguredTask('testPropertySet' . ucfirst($property), ApplyTask::class); |
||
534 | |||
535 | $propertyName = (null === $propertyName) ? $property : $propertyName; |
||
0 ignored issues
–
show
|
|||
536 | $rprop = new ReflectionProperty(ApplyTask::class, $propertyName); |
||
537 | $rprop->setAccessible(true); |
||
538 | $this->assertEquals($value, $rprop->getValue($task)); |
||
539 | } |
||
540 | } |
||
541 |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.