Passed
Pull Request — master (#18)
by Harry
01:55
created

ProcessRunTest::testOnFailure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
dl 0
loc 23
rs 9.7666
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * This file is part of graze/parallel-process.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/parallel-process
12
 */
13
14
namespace Graze\ParallelProcess\Test\Unit;
15
16
use Graze\ParallelProcess\Event\RunEvent;
17
use Graze\ParallelProcess\ProcessRun;
18
use Graze\ParallelProcess\RunInterface;
19
use Graze\ParallelProcess\Test\TestCase;
20
use Mockery;
21
use Symfony\Component\Process\Process;
22
23
class ProcessRunTest extends TestCase
24
{
25
    public function testRunImplementsRunInterface()
26
    {
27
        $process = Mockery::mock(Process::class);
28
        $process->shouldReceive('stop');
29
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

29
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
30
        $this->assertInstanceOf(RunInterface::class, $run);
31
    }
32
33
    public function testInitialState()
34
    {
35
        $process = Mockery::mock(Process::class);
36
        $process->shouldReceive('stop');
37
38
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

38
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
39
40
        $this->assertSame($process, $run->getProcess());
41
42
        $process->shouldReceive('isRunning')
43
                ->andReturn(false);
44
        $process->shouldReceive('isStarted')
45
                ->andReturn(false);
46
        $process->shouldReceive('isSuccessful')
47
                ->andReturn(false);
48
49
        $this->assertFalse($run->isRunning(), 'should not be running');
50
        $this->assertFalse($run->hasStarted(), 'should not have started');
51
        $this->assertFalse($run->isSuccessful(), 'should not be successful');
52
        $this->assertTrue($run->isUpdateOnPoll(), 'update on poll should be on by deafult');
53
        $this->assertTrue($run->isUpdateOnProcessOutput(), 'update on poll should be on by deafult');
54
        $this->assertEquals([], $run->getExceptions(), 'no exceptions should be returned');
55
    }
56
57
    public function testUpdateOnPoll()
58
    {
59
        $process = Mockery::mock(Process::class);
60
        $process->shouldReceive('stop');
61
62
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

62
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
63
64
        $this->assertTrue($run->isUpdateOnPoll());
65
        $this->assertSame($run, $run->setUpdateOnPoll(false));
66
        $this->assertFalse($run->isUpdateOnPoll());
67
    }
68
69
    public function testUpdateOnProcessOutput()
70
    {
71
        $process = Mockery::mock(Process::class);
72
        $process->shouldReceive('stop');
73
74
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

74
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
75
76
        $this->assertTrue($run->isUpdateOnProcessOutput());
77
        $this->assertSame($run, $run->setUpdateOnProcessOutput(false));
78
        $this->assertFalse($run->isUpdateOnProcessOutput());
79
    }
80
81
    public function testProcessRunning()
82
    {
83
        $process = Mockery::mock(Process::class);
84
        $process->shouldReceive('stop');
85
86
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

86
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
87
88
        $process->shouldReceive('isRunning')
89
                ->andReturn(true); // check
90
        $process->shouldReceive('start');
91
92
        $process->shouldReceive('isStarted')
93
                ->andReturn(false, true); // start, check
94
95
        $run->start();
96
97
        $this->assertTrue($run->isRunning());
98
        $this->assertTrue($run->hasStarted());
99
        $this->assertFalse($run->isSuccessful());
100
    }
101
102
    public function testRun()
103
    {
104
        $process = Mockery::mock(Process::class);
105
        $process->shouldReceive('stop');
106
107
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

107
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
108
109
        $process->shouldReceive('isRunning')->andReturn(true, false);
110
        $process->shouldReceive('start');
111
        $process->shouldReceive('isStarted')->andReturn(false, true);
112
113
        $run->start();
114
115
        $process->shouldReceive('isSuccessful')->andReturn(true);
116
117
        $this->assertTrue($run->poll());
118
        $this->assertFalse($run->poll());
119
        $this->assertTrue($run->isSuccessful());
120
        $this->assertTrue($run->hasStarted());
121
    }
122
123
    public function testOnStart()
124
    {
125
        $process = Mockery::mock(Process::class);
126
        $process->shouldReceive('stop');
127
128
        $hit = false;
129
130
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

130
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
131
        $run->addListener(
132
            RunEvent::STARTED,
133
            function (RunEvent $event) use (&$run, &$hit) {
134
                $this->assertSame($event->getRun(), $run);
135
                $hit = true;
136
            }
137
        );
138
139
        $process->shouldReceive('start')->once();
140
        $process->shouldReceive('isStarted')->andReturn(false, true);
141
        $process->shouldReceive('isRunning')->andReturn(false);
142
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
143
144
        $run->start();
145
        $this->assertFalse($run->poll());
146
    }
147
148
    public function testOnSuccess()
149
    {
150
        $process = Mockery::mock(Process::class);
151
        $process->shouldReceive('stop');
152
153
        $hit = false;
154
155
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

155
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
156
        $run->addListener(
157
            RunEvent::COMPLETED,
158
            function (RunEvent $event) use (&$run, &$hit) {
159
                $this->assertSame($event->getRun(), $run);
160
                $hit = true;
161
            }
162
        );
163
164
        $process->shouldReceive('start')->once();
165
        $process->shouldReceive('isStarted')->andReturn(false, true);
166
        $process->shouldReceive('isRunning')->andReturn(false);
167
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
168
169
        $run->start();
170
        $this->assertFalse($run->poll());
171
    }
172
173
    public function testOnFailure()
174
    {
175
        $process = Mockery::mock(Process::class);
176
        $process->shouldReceive('stop');
177
178
        $hit = false;
179
180
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

180
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
181
        $run->addListener(
182
            RunEvent::FAILED,
183
            function (RunEvent $event) use (&$run, &$hit) {
184
                $this->assertSame($event->getRun(), $run);
185
                $hit = true;
186
            }
187
        );
188
189
        $process->shouldReceive('start')->once();
190
        $process->shouldReceive('isStarted')->andReturn(false, true);
191
        $process->shouldReceive('isRunning')->andReturn(false);
192
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
193
194
        $run->start();
195
        $this->assertFalse($run->poll());
196
    }
197
198
    public function testOnProgress()
199
    {
200
        $process = Mockery::mock(Process::class);
201
        $process->shouldReceive('stop');
202
203
        $hit = false;
204
205
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

205
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
206
        $run->addListener(
207
            RunEvent::UPDATED,
208
            function (RunEvent $event) use (&$run, &$hit) {
209
                $this->assertSame($event->getRun(), $run);
210
                $hit = true;
211
            }
212
        );
213
214
        $process->shouldReceive('start')->once();
215
        $process->shouldReceive('isStarted')->andReturn(false, true);
216
        $process->shouldReceive('isRunning')->andReturn(true, false);
217
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
218
219
        $run->start();
220
        $this->assertTrue($run->poll());
221
        $this->assertFalse($run->poll());
222
    }
223
224
    public function testStartingAfterStartedWillDoNothing()
225
    {
226
        $process = Mockery::mock(Process::class);
227
        $process->shouldReceive('stop');
228
229
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

229
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
230
231
        $process->shouldReceive('isStarted')
232
                ->andReturn(true);
233
234
        $this->assertSame($run, $run->start());
235
    }
236
237
    public function testEventsProvideDurationAndLastMessage()
238
    {
239
        $process = Mockery::mock(Process::class);
240
        $process->shouldReceive('stop');
241
242
        $process->shouldReceive('start')
243
                ->with(
244
                    Mockery::on(
245
                        function (callable $fn) {
246
                            $this->assertNotNull($fn);
247
                            $fn(Process::OUT, 'some text');
248
                            return true;
249
                        }
250
                    )
251
                )
252
                ->once();
253
254
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

254
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
255
        $run->addListener(
256
            RunEvent::UPDATED,
257
            function (RunEvent $event) use (&$run, &$hits) {
258
                $this->assertSame($event->getRun(), $run);
259
                $this->assertInternalType('float', $run->getDuration());
260
                $this->assertEquals('some text', $run->getLastMessage());
261
                $this->assertEquals(Process::OUT, $run->getLastMessageType());
262
                $hits++;
263
            }
264
        );
265
266
        $process->shouldReceive('isStarted')->andReturn(false, true);
267
        $process->shouldReceive('isRunning')->andReturn(false);
268
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
269
270
        $run->start();
271
        $this->assertFalse($run->poll());
272
    }
273
274
    public function testLastMessageHavingMultipleLinesReturnsOnePerLine()
275
    {
276
        $process = Mockery::mock(Process::class);
277
        $process->shouldReceive('stop');
278
279
        $process->shouldReceive('start')
280
                ->with(
281
                    Mockery::on(
282
                        function (callable $fn) {
283
                            $this->assertNotNull($fn);
284
                            $fn(Process::OUT, "line 1\n\nline 2");
285
                            return true;
286
                        }
287
                    )
288
                )
289
                ->once();
290
291
        $hits = 0;
292
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

292
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
293
        $run->addListener(
294
            RunEvent::UPDATED,
295
            function (RunEvent $event) use (&$run, &$hits) {
296
                $this->assertSame($event->getRun(), $run);
297
                $this->assertInternalType('float', $run->getDuration());
298
                $this->assertContains($run->getLastMessage(), ['line 1', 'line 2']);
299
                $this->assertEquals(Process::OUT, $run->getLastMessageType());
300
                $hits++;
301
            }
302
        );
303
304
        $process->shouldReceive('isStarted')->andReturn(false, true);
305
        $process->shouldReceive('isRunning')->andReturn(false);
306
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
307
308
        $run->start();
309
        $this->assertFalse($run->poll());
310
        $this->assertEquals(2, $hits);
311
    }
312
313
    public function testUpdateOnPollOffDoesNotUpdateOnPoll()
314
    {
315
        $process = Mockery::mock(Process::class);
316
        $process->shouldReceive('stop');
317
318
        $process->shouldReceive('start')->once();
319
320
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

320
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
321
        $run->addListener(
322
            RunEvent::UPDATED,
323
            function () {
324
                $this->fail('onProgress should not be called');
325
            }
326
        );
327
        $run->setUpdateOnPoll(false);
328
329
        $process->shouldReceive('isStarted')->andReturn(false, true);
330
        $process->shouldReceive('isRunning')->andReturn(true, false);
331
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
332
333
        $run->start();
334
        $this->assertTrue($run->poll());
335
        $this->assertFalse($run->poll());
336
    }
337
338
    public function testUpdateOnOutputOffDoesNotCallUpdateOnOutput()
339
    {
340
        $process = Mockery::mock(Process::class);
341
        $process->shouldReceive('stop');
342
343
        $process->shouldReceive('start')
344
                ->with(
345
                    Mockery::on(
346
                        function (callable $fn) {
347
                            $this->assertNotNull($fn);
348
                            $fn(Process::STDOUT, 'some text');
349
                            return true;
350
                        }
351
                    )
352
                )
353
                ->once();
354
355
        $run = new ProcessRun($process);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

355
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process);
Loading history...
356
        $run->addListener(
357
            RunEvent::UPDATED,
358
            function () {
359
                $this->fail('onProgress should not be called');
360
            }
361
        );
362
        $run->setUpdateOnProcessOutput(false);
363
364
        $process->shouldReceive('isStarted')->andReturn(false, true);
365
        $process->shouldReceive('isRunning')->andReturn(false);
366
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
367
368
        $run->start();
369
        $this->assertFalse($run->poll());
370
    }
371
372
    public function testGetPriority()
373
    {
374
        $process = Mockery::mock(Process::class);
375
        $process->shouldReceive('stop');
376
        $run = new ProcessRun($process, [], 1.5);
0 ignored issues
show
Bug introduced by
$process of type Mockery\MockInterface is incompatible with the type Symfony\Component\Process\Process expected by parameter $process of Graze\ParallelProcess\ProcessRun::__construct(). ( Ignorable by Annotation )

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

376
        $run = new ProcessRun(/** @scrutinizer ignore-type */ $process, [], 1.5);
Loading history...
377
378
        $this->assertEquals(1.5, $run->getPriority());
379
        $this->assertSame($run, $run->setPriority(2));
380
        $this->assertEquals(2, $run->getPriority());
381
    }
382
}
383