Passed
Push — master ( 03c276...51d982 )
by Michiel
12:36
created

ExecTaskTest::testEnvVars()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
/**
21
 * Tests the Exec Task
22
 *
23
 * @author  Michiel Rook <[email protected]>
24
 * @package phing.tasks.system
25
 */
26
class ExecTaskTest extends BuildFileTest
27
{
28
    /**
29
     * Whether test is being run on windows
30
     * @var bool
31
     */
32
    protected $windows;
33
34
    public function setUp(): void
35
    {
36
        $this->configureProject(
37
            PHING_TEST_BASE . '/etc/tasks/system/ExecTest.xml'
38
        );
39
        $this->windows = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
40
    }
41
42
    protected function getTargetByName($name)
43
    {
44
        foreach ($this->project->getTargets() as $target) {
45
            if ($target->getName() == $name) {
46
                return $target;
47
            }
48
        }
49
        throw new Exception(sprintf('Target "%s" not found', $name));
50
    }
51
52
    protected function getTaskFromTarget($target, $taskname, $pos = 0)
53
    {
54
        $rchildren = new ReflectionProperty(get_class($target), 'children');
55
        $rchildren->setAccessible(true);
56
        $n = -1;
57
        foreach ($rchildren->getValue($target) as $child) {
58
            if ($child instanceof Task && ++$n == $pos) {
59
                return $child;
60
            }
61
        }
62
        throw new Exception(
63
            sprintf('%s #%d not found in task', $taskname, $pos)
64
        );
65
    }
66
67
    protected function getConfiguredTask($target, $task, $pos = 0)
0 ignored issues
show
Unused Code introduced by
The parameter $pos 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

67
    protected function getConfiguredTask($target, $task, /** @scrutinizer ignore-unused */ $pos = 0)

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...
68
    {
69
        $target = $this->getTargetByName($target);
70
        $task = $this->getTaskFromTarget($target, $task);
71
        $task->maybeConfigure();
72
73
        return $task;
74
    }
75
76
    protected function assertAttributeIsSetTo($property, $value, $propertyName = null)
77
    {
78
        $task = $this->getConfiguredTask(
79
            'testPropertySet' . ucfirst($property),
80
            'ExecTask'
81
        );
82
83
        if ($propertyName === null) {
84
            $propertyName = $property;
85
        }
86
87
        if ($task instanceof UnknownElement) {
88
            $task = $task->getRuntimeConfigurableWrapper()->getProxy();
89
        }
90
91
        $rprop = new ReflectionProperty('ExecTask', $propertyName);
92
        $rprop->setAccessible(true);
93
        $this->assertEquals($value, $rprop->getValue($task));
94
    }
95
96
    public function testPropertySetCommandline()
97
    {
98
        $this->assertAttributeIsSetTo('commandline', new Commandline("echo 'foo'"));
99
    }
100
101
    public function testPropertySetDir()
102
    {
103
        $this->assertAttributeIsSetTo(
104
            'dir',
105
            new PhingFile(
106
                realpath(__DIR__ . '/../../../../etc/tasks/system')
107
            )
108
        );
109
    }
110
111
    public function testPropertySetOs()
112
    {
113
        $this->assertAttributeIsSetTo('os', "linux");
114
    }
115
116
    public function testPropertySetEscape()
117
    {
118
        $this->assertAttributeIsSetTo('escape', true);
119
    }
120
121
    public function testPropertySetLogoutput()
122
    {
123
        $this->assertAttributeIsSetTo('logoutput', true, 'logOutput');
124
    }
125
126
    public function testPropertySetPassthru()
127
    {
128
        $this->assertAttributeIsSetTo('passthru', true);
129
    }
130
131
    public function testPropertySetSpawn()
132
    {
133
        $this->assertAttributeIsSetTo('spawn', true);
134
    }
135
136
    public function testPropertySetReturnProperty()
137
    {
138
        $this->assertAttributeIsSetTo('returnProperty', 'retval');
139
    }
140
141
    public function testPropertySetOutputProperty()
142
    {
143
        $this->assertAttributeIsSetTo('outputProperty', 'outval');
144
    }
145
146
    public function testPropertySetCheckReturn()
147
    {
148
        $this->assertAttributeIsSetTo('checkreturn', true);
149
    }
150
151
    public function testPropertySetOutput()
152
    {
153
        $this->assertAttributeIsSetTo(
154
            'output',
155
            new PhingFile(
156
                realpath(__DIR__ . '/../../../../etc/tasks/system')
157
                . '/outputfilename'
158
            )
159
        );
160
    }
161
162
    public function testPropertySetError()
163
    {
164
        $this->assertAttributeIsSetTo(
165
            'error',
166
            new PhingFile(
167
                realpath(__DIR__ . '/../../../../etc/tasks/system')
168
                . '/errorfilename'
169
            )
170
        );
171
    }
172
173
    public function testPropertySetLevelError()
174
    {
175
        $this->assertAttributeIsSetTo('levelError', Project::MSG_ERR, 'logLevel');
176
    }
177
178
    public function testPropertySetLevelWarning()
179
    {
180
        $this->assertAttributeIsSetTo('levelWarning', Project::MSG_WARN, 'logLevel');
181
    }
182
183
    public function testPropertySetLevelInfo()
184
    {
185
        $this->assertAttributeIsSetTo('levelInfo', Project::MSG_INFO, 'logLevel');
186
    }
187
188
    public function testPropertySetLevelVerbose()
189
    {
190
        $this->assertAttributeIsSetTo('levelVerbose', Project::MSG_VERBOSE, 'logLevel');
191
    }
192
193
    public function testPropertySetLevelDebug()
194
    {
195
        $this->assertAttributeIsSetTo('levelDebug', Project::MSG_DEBUG, 'logLevel');
196
    }
197
198
    public function testPropertySetLevelUnknown()
199
    {
200
        $this->expectException(BuildException::class);
201
        $this->expectExceptionMessage('Unknown log level "unknown"');
202
203
        $this->getConfiguredTask('testPropertySetLevelUnknown', 'ExecTask');
204
    }
205
206
    public function testDoNotExecuteOnWrongOs()
207
    {
208
        $this->executeTarget(__FUNCTION__);
209
        $this->assertInLogs('not found in the specified list of valid OSes: unknownos');
210
        $this->assertStringNotContainsString(
211
            'this should not be executed',
212
            $this->getOutput()
213
        );
214
    }
215
216
    public function testDoNotExecuteOnWrongOsFamily()
217
    {
218
        $this->expectBuildException(__FUNCTION__, "Don't know how to detect os family 'unknownos'");
219
    }
220
221
    public function testExecuteOnCorrectOs()
222
    {
223
        $this->executeTarget(__FUNCTION__);
224
        $this->assertInLogs('this should be executed');
225
    }
226
227
    public function testExecuteOnCorrectOsFamily()
228
    {
229
        $this->executeTarget(__FUNCTION__);
230
        $this->assertInLogs('this should be executed');
231
    }
232
233
    public function testFailOnNonExistingDir()
234
    {
235
        $this->expectException(BuildException::class);
236
        $this->expectExceptionMessageMatches('/' . preg_quote(str_replace('/', DIRECTORY_SEPARATOR, "'/this/dir/does/not/exist' does not exist"), '/') . '/');
237
238
//        try {
239
//            $this->executeTarget(__FUNCTION__);
240
//            $this->fail('Expected BuildException was not thrown');
241
//        } catch (BuildException $e) {
242
//            $this->assertContains(
243
//                str_replace('/', DIRECTORY_SEPARATOR, "'/this/dir/does/not/exist' does not exist"),
244
//                $e->getMessage()
245
//            );
246
//        }
247
248
        $this->executeTarget(__FUNCTION__);
249
    }
250
251
    /**
252
     * @requires OS ^(?:(?!Win).)*$
253
     */
254
    public function testChangeToDir()
255
    {
256
        $this->executeTarget(__FUNCTION__);
257
        $this->assertInLogs('ExecTaskTest.php');
258
    }
259
260
    public function testCheckreturnTrue()
261
    {
262
        if (FileSystem::getFileSystem()->which('true') === false) {
0 ignored issues
show
introduced by
The condition FileSystem::getFileSyste...which('true') === false is always false.
Loading history...
263
            $this->markTestSkipped("'true' not found.");
264
        }
265
        $this->executeTarget(__FUNCTION__);
266
        $this->assertTrue(true);
267
    }
268
269
    public function testCheckreturnFalse()
270
    {
271
        if (FileSystem::getFileSystem()->which('false') === false) {
0 ignored issues
show
introduced by
The condition FileSystem::getFileSyste...hich('false') === false is always false.
Loading history...
272
            $this->markTestSkipped("'false' not found.");
273
        }
274
275
        $this->expectException(BuildException::class);
276
        $this->expectExceptionMessage('exec returned: 1');
277
278
        $this->executeTarget(__FUNCTION__);
279
    }
280
281
    public function testOutputProperty()
282
    {
283
        $this->executeTarget(__FUNCTION__);
284
        $this->assertInLogs('The output property\'s value is: "foo"');
285
    }
286
287
    public function testReturnProperty()
288
    {
289
        $this->executeTarget(__FUNCTION__);
290
        $this->assertInLogs('The return property\'s value is: "1"');
291
    }
292
293
    public function testEscape()
294
    {
295
        $this->executeTarget(__FUNCTION__);
296
        $this->assertInLogs($this->windows ? '"foo" "|" "cat"' : 'foo | cat');
297
    }
298
299
    public function testPassthru()
300
    {
301
        ob_start();
302
        $this->executeTarget(__FUNCTION__);
303
        $out = ob_get_clean();
304
        $this->assertEquals("foo", rtrim($out, " \r\n"));
305
        //foo should not be in logs, except for the logged command
306
        $this->assertInLogs('echo foo');
307
        $this->assertNotContains('foo', $this->logBuffer);
308
    }
309
310
    public function testOutput()
311
    {
312
        $file = tempnam(FileUtils::getTempDir(), 'phing-exectest-');
313
        $this->project->setProperty('execTmpFile', $file);
314
        $this->executeTarget(__FUNCTION__);
315
        $this->assertStringContainsString('outfoo', file_get_contents($file));
316
        unlink($file);
317
    }
318
319
    public function testError()
320
    {
321
        $file = tempnam(FileUtils::getTempDir(), 'phing-exectest-');
322
        $this->project->setProperty('execTmpFile', $file);
323
        $this->executeTarget(__FUNCTION__);
324
        $this->assertStringContainsString('errfoo', file_get_contents($file));
325
        unlink($file);
326
    }
327
328
    public function testSpawn()
329
    {
330
        $start = time();
331
        $this->executeTarget(__FUNCTION__);
332
        $end = time();
333
        $this->assertLessThan(
334
            4,
335
            $end - $start,
336
            'Time between start and end should be lower than 4 seconds'
337
            . ' - otherwise it looks as spawning did not work'
338
        );
339
    }
340
341
    public function testNestedArg()
342
    {
343
        $this->executeTarget(__FUNCTION__);
344
        $this->assertInLogs($this->windows ? 'nested-arg "b  ar"' : 'nested-arg b  ar');
345
    }
346
347
    public function testMissingExecutableAndCommand()
348
    {
349
        $this->expectException(BuildException::class);
350
        $this->expectExceptionMessage('ExecTask: Please provide "executable"');
351
352
        $this->executeTarget(__FUNCTION__);
353
    }
354
355
    /**
356
     * Inspired by {@link http://www.phing.info/trac/ticket/833}
357
     */
358
    public function testEscapedArg()
359
    {
360
        $this->executeTarget(__FUNCTION__);
361
        $this->assertPropertyEquals('outval', $this->windows ? 'abc$b3 SB' : 'abc$b3!SB');
362
    }
363
364
    public function testEscapedArgWithoutWhitespace()
365
    {
366
        $arg = 'foo|bar';
0 ignored issues
show
Unused Code introduced by
The assignment to $arg is dead and can be removed.
Loading history...
367
        $this->executeTarget(__FUNCTION__);
368
        $this->assertInLogs($this->windows ? '"echo" "foo|bar" 2>&1' : '\'echo\' \'foo|bar\' 2>&1');
369
        $this->assertNotInLogs($this->windows ? 'echo " foo|bar " 2>&1' : 'echo \' foo|bar \' 2>&1');
370
    }
371
372
    public function testNestedEnv()
373
    {
374
        $this->executeTarget(__FUNCTION__);
375
        $this->assertStringStartsWith('phploc', $this->getProject()->getProperty('envtest'));
376
    }
377
378
    public function testEnvVars(): void
379
    {
380
        if ($this->windows) {
381
            $this->markTestSkipped('Setting environment variables for command is not supported on windows.');
382
        }
383
        $this->expectPropertySet(__FUNCTION__, 'hello', 'world');
384
    }
385
}
386