Completed
Pull Request — master (#12)
by Harry
02:36
created

TableTest::testShowSummary()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
namespace Graze\ParallelProcess\Test\Unit;
4
5
use Graze\ParallelProcess\Pool;
6
use Graze\ParallelProcess\Table;
7
use Graze\ParallelProcess\Test\BufferDiffOutput;
8
use Graze\ParallelProcess\Test\TestCase;
9
use Mockery;
10
use Symfony\Component\Console\Output\ConsoleOutputInterface;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use Symfony\Component\Process\Exception\ProcessFailedException;
13
use Symfony\Component\Process\Process;
14
15
class TableTest extends TestCase
16
{
17
    /** @var BufferDiffOutput */
18
    private $bufferOutput;
19
    /** @var mixed */
20
    private $pool;
21
    /** @var Table */
22
    private $table;
23
24 View Code Duplication
    public function setUp()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
25
    {
26
        mb_internal_encoding("UTF-8");
27
        $this->bufferOutput = new BufferDiffOutput();
28
        $this->pool = Mockery::mock(Pool::class)->makePartial();
29
        $this->table = new Table($this->bufferOutput, $this->pool);
30
    }
31
32
    public function testConstructWithNonBufferedOutput()
33
    {
34
        $output = Mockery::mock(ConsoleOutputInterface::class);
35
        $table = new Table($output);
36
37
        $this->assertInstanceOf(Table::class, $table);
38
    }
39
40 View Code Duplication
    public function testShowOutput()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
41
    {
42
        $output = Mockery::mock(ConsoleOutputInterface::class);
43
        $table = new Table($output);
44
45
        $this->assertTrue($table->isShowOutput());
46
47
        $this->assertSame($table, $table->setShowOutput(false));
48
49
        $this->assertFalse($table->isShowOutput());
50
    }
51
52 View Code Duplication
    public function testShowSummary()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
53
    {
54
        $output = Mockery::mock(ConsoleOutputInterface::class);
55
        $table = new Table($output);
56
57
        $this->assertTrue($table->isShowSummary());
58
59
        $this->assertSame($table, $table->setShowSummary(false));
60
61
        $this->assertFalse($table->isShowSummary());
62
    }
63
64
    public function testSpinnerLoop()
65
    {
66
        $this->table->setShowSummary(false);
67
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
68
69
        $process = Mockery::mock(Process::class);
70
        $process->shouldReceive('stop');
71
        $process->shouldReceive('start')->once();
72
        $process->shouldReceive('isStarted')->andReturn(true);
73
        $process->shouldReceive('isRunning')->andReturn(
74
            false, // add
75
            false, // start
76
            true,  // check
77
            true,  // ...
78
            true,
79
            true,
80
            true,
81
            true,
82
            true,
83
            true,
84
            true,
85
            true,
86
            true,
87
            false // complete
88
        );
89
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
90
91
        $this->table->add($process, ['key' => 'value']);
92
93
        $this->table->run(0);
94
95
        $expected = [
96
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %'],
97
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
98
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠙%'],
99
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠹%'],
100
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠸%'],
101
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠼%'],
102
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠴%'],
103
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠦%'],
104
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠧%'],
105
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠇%'],
106
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠏%'],
107
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
108
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
109
        ];
110
111
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
112
    }
113
114
    public function testValueDataArrayDoesNotShowTheKey()
115
    {
116
        $this->table->setShowSummary(false);
117
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
118
119
        $process = Mockery::mock(Process::class);
120
        $process->shouldReceive('stop');
121
        $process->shouldReceive('start')->once();
122
        $process->shouldReceive('isStarted')->andReturn(true);
123
        $process->shouldReceive('isRunning')->andReturn(
124
            false, // add
125
            false, // start
126
            true,  // check
127
            false // complete
128
        );
129
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
130
131
        $this->table->add($process, ['value', 'value2']);
132
133
        $this->table->run(0);
134
135
        $expected = [
136
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) %'],
137
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
138
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
139
        ];
140
141
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
142
    }
143
144
    public function testSummaryIsWaitingBeforeTheProcessStarts()
145
    {
146
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
147
        $this->table->setShowOutput(true);
148
        $this->table->setShowSummary(true);
149
150
        $oneFails = false;
151
152
        $process = Mockery::mock(Process::class);
153
        $process->shouldReceive('stop');
154
        $process->shouldReceive('start')->with(Mockery::on(function ($closure) {
155
            call_user_func($closure, Process::OUT, 'some text');
156
            return true;
157
        }))->once();
158
        $process->shouldReceive('isStarted')->andReturn(false, true);
159
        $process->shouldReceive('isRunning')->andReturn(false, false, true, false); // add, start, check, check
160
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
161
        $process->shouldReceive('getOutput')->andReturn('some text');
162
163
        $this->table->add($process, ['key' => 'value']);
164
165
        try {
166
            $this->table->run(0);
167
        } catch (\Exception $e) {
168
            if (!$oneFails || !$e instanceof ProcessFailedException) {
169
                throw $e;
170
            }
171
        }
172
173
        $expected = [
174
            [
175
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %',
176
                '%waiting...%',
177
            ],
178
            [
179
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %',
180
                '%<comment>Total</comment>:  1, <comment>Running</comment>:  1, <comment>Waiting</comment>:  0%',
181
            ],
182
            [
183
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
184
                '%<comment>Total</comment>:  1, <comment>Running</comment>:  1, <comment>Waiting</comment>:  0%',
185
            ],
186
            [
187
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
188
                '%^$%',
189
            ],
190
        ];
191
192
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
193
    }
194
195
    /**
196
     * Runs a series of processes, each doing initial state, single on progress run, single complete entry
197
     *
198
     * @dataProvider outputData
199
     *
200
     * @param int        $verbosity     OutputInterface::VERBOSITY_*
201
     * @param bool       $showOutput    Should it display some output text
202
     * @param bool       $showSummary   Should we show a summary
203
     * @param bool[]     $processStates an entry for each process to run, true = success, false = failure
204
     * @param string[][] $outputs       Regex patterns for the output string
205
     *
206
     * @throws \Exception
207
     */
208
    public function testOutput($verbosity, $showOutput, $showSummary, array $processStates, array $outputs)
209
    {
210
        $this->bufferOutput->setVerbosity($verbosity);
211
        $this->table->setShowOutput($showOutput);
212
        $this->table->setShowSummary($showSummary);
213
214
        $oneFails = false;
215
216
        for ($i = 0; $i < count($processStates); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
217
            $process = Mockery::mock(Process::class);
218
            $process->shouldReceive('stop');
219
            $process->shouldReceive('start')->with(Mockery::on(function ($closure) {
220
                call_user_func($closure, Process::OUT, 'some text');
221
                return true;
222
            }))->once();
223
            $process->shouldReceive('isStarted')->andReturn(true);
224
            $process->shouldReceive('isRunning')->andReturn(false, false, true, false); // add, start, check, check
225
            $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn($processStates[$i]);
226
            $process->shouldReceive('getOutput')->andReturn('some text');
227
228
            if (!$processStates[$i]) {
229
                $process->shouldReceive('getCommandLine')->andReturn('test');
230
                $process->shouldReceive('getExitCode')->andReturn(1);
231
                $process->shouldReceive('getExitCodeText')->andReturn('failed');
232
                $process->shouldReceive('getWorkingDirectory')->andReturn('/tmp');
233
                $process->shouldReceive('isOutputDisabled')->andReturn(false);
234
                $process->shouldReceive('getErrorOutput')->andReturn('some error text');
235
                $oneFails = true;
236
            }
237
238
            $this->table->add($process, ['key' => 'value', 'run' => $i]);
239
        }
240
241
        try {
242
            $this->table->run(0);
243
        } catch (\Exception $e) {
244
            if (!$oneFails || !$e instanceof ProcessFailedException) {
245
                throw $e;
246
            }
247
        }
248
249
        $this->compareOutputs($outputs, $this->bufferOutput->getWritten());
250
    }
251
252
    /**
253
     * @return array
254
     */
255
    public function outputData()
256
    {
257
        return [
258
            [ // verbose with single valid run
259
                OutputInterface::VERBOSITY_VERBOSE,
260
                false,
261
                false,
262
                [true],
263
                [
264
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
265
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%'],
266
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
267
                ],
268
            ],
269
            [ // normal verbosity only writes a single line
270
                OutputInterface::VERBOSITY_NORMAL,
271
                false,
272
                false,
273
                [true],
274
                [
275
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
276
                ],
277
            ],
278
            [
279
                OutputInterface::VERBOSITY_NORMAL,
280
                false,
281
                false,
282
                [true, true],
283
                [
284
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
285
                    ['%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
286
                ],
287
            ],
288
            [ // multiple runs with verbosity will update each item one at a time
289
                OutputInterface::VERBOSITY_VERBOSE,
290
                false,
291
                false,
292
                [true, true],
293
                [
294
                    [
295
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
296
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
297
                    ],
298
                    [
299
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
300
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
301
                    ],
302
                    [
303
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
304
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
305
                    ],
306
                    [
307
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
308
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
309
                    ],
310
                    [
311
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
312
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
313
                    ],
314
                ],
315
            ],
316
            [ // errors will display an error
317
                OutputInterface::VERBOSITY_VERBOSE,
318
                false,
319
                false,
320
                [false],
321
                [
322
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
323
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%'],
324
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%'],
325
                    [
326
                        <<<DOC
327
%The command "test" failed.
328
329
Exit Code: 1\(failed\)
330
331
Working directory: /tmp
332
333
Output:
334
================
335
some text
336
337
Error Output:
338
================
339
some error text%
340
DOC
341
                        ,
342
                    ],
343
                ],
344
            ],
345
            [ // errors will display an error
346
                OutputInterface::VERBOSITY_NORMAL,
347
                false,
348
                false,
349
                [false],
350
                [
351
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%'],
352
                    [
353
                        <<<DOC
354
%The command "test" failed.
355
356
Exit Code: 1\(failed\)
357
358
Working directory: /tmp
359
360
Output:
361
================
362
some text
363
364
Error Output:
365
================
366
some error text%
367
DOC
368
                        ,
369
                    ],
370
                ],
371
            ],
372
            [ // multiple runs with verbosity will update each item one at a time
373
                OutputInterface::VERBOSITY_VERBOSE,
374
                false,
375
                false,
376
                [true, false],
377
                [
378
                    [
379
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
380
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
381
                    ],
382
                    [
383
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
384
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
385
                    ],
386
                    [
387
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
388
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
389
                    ],
390
                    [
391
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
392
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
393
                    ],
394
                    [
395
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
396
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%',
397
                    ],
398
                    [
399
                        <<<DOC
400
%The command "test" failed.
401
402
Exit Code: 1\(failed\)
403
404
Working directory: /tmp
405
406
Output:
407
================
408
some text
409
410
Error Output:
411
================
412
some error text%
413
DOC
414
                        ,
415
                    ],
416
                ],
417
            ],
418
            [ // include output
419
                OutputInterface::VERBOSITY_VERBOSE,
420
                true,
421
                false,
422
                [true],
423
                [
424
                    ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
425
                    ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]  some text%'],
426
                    ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>  some text%'],
427
                ],
428
            ],
429
            [ // include a summary
430
                OutputInterface::VERBOSITY_VERBOSE,
431
                false,
432
                true,
433
                [true, true],
434
                [
435
                    [
436
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
437
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
438
                        '%^$%',
439
                    ],
440
                    [
441
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
442
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
443
                        '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
444
                    ],
445
                    [
446
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
447
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
448
                        '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
449
                    ],
450
                    [
451
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
452
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
453
                        '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
454
                    ],
455
                    [
456
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
457
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
458
                        '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
459
                    ],
460
                    [
461
                        '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
462
                        '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
463
                        '%^$%',
464
                    ],
465
                ],
466
            ],
467
        ];
468
    }
469
}
470