Completed
Pull Request — master (#12)
by Harry
01:54
created

PoolTest::testPoolAddingProcess()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of graze/parallel-process.
5
 *
6
 * Copyright (c) 2017 Nature Delivered Ltd. <https://www.graze.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
12
 * @link    https://github.com/graze/parallel-process
13
 */
14
15
namespace Graze\ParallelProcess\Test\Unit;
16
17
use Graze\DataStructure\Collection\CollectionInterface;
18
use Graze\ParallelProcess\Pool;
19
use Graze\ParallelProcess\Run;
20
use Graze\ParallelProcess\RunInterface;
21
use Graze\ParallelProcess\Test\TestCase;
22
use Mockery;
23
use Symfony\Component\Process\Process;
24
25
class PoolTest extends TestCase
26
{
27
    /** @var mixed */
28
    private $process;
29
30 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...
31
    {
32
        parent::setUp();
33
34
        $this->process = Mockery::mock(Process::class);
35
        $this->process->shouldReceive('stop');
36
        $this->process->shouldReceive('isStarted')->andReturn(false);
37
        $this->process->shouldReceive('isRunning')->andReturn(false);
38
    }
39
40
    public function testPoolIsARunInterface()
41
    {
42
        $pool = new Pool();
43
        $this->assertInstanceOf(RunInterface::class, $pool);
44
    }
45
46
    public function testPoolIsACollectionOfRuns()
47
    {
48
        $pool = new Pool();
49
        $this->assertInstanceOf(CollectionInterface::class, $pool);
50
51
        $this->assertSame($pool, $pool->add($this->process));
52
53
        $runs = $pool->getAll();
54
        $this->assertCount(1, $runs);
55
56
        $this->assertInstanceOf(Run::class, reset($runs));
57
    }
58
59
    public function testPoolInitialStateWithProcess()
60
    {
61
        $pool = new Pool();
62
        $pool->add($this->process);
63
64
        $this->assertFalse($pool->isSuccessful());
65
        $this->assertFalse($pool->isRunning());
66
        $this->assertFalse($pool->hasStarted());
67
    }
68
69
    public function testPoolConstructor()
70
    {
71
        $runs = [];
72
        for ($i = 0; $i < 2; $i++) {
73
            $runs[] = Mockery::mock(RunInterface::class)
74
                             ->shouldReceive('isRunning')
75
                             ->andReturn(false)
76
                             ->getMock()
77
                             ->shouldReceive('hasStarted')
78
                             ->andReturn(false)
79
                             ->getMock();
80
        }
81
82
        $pool = new Pool($runs);
83
84
        $this->assertEquals(2, $pool->count());
85
    }
86
87
    /**
88
     * @expectedException \InvalidArgumentException
89
     */
90
    public function testAddingNonRunInterfaceWillThrowException()
91
    {
92
        $nope = Mockery::mock();
93
        $pool = new Pool();
94
        $pool->add($nope);
95
    }
96
97
    public function testPoolInitialStateWithNoRuns()
98
    {
99
        $pool = new Pool();
100
101
        $this->assertFalse($pool->isSuccessful(), 'should not be successful');
102
        $this->assertFalse($pool->isRunning(), 'should not be running');
103
        $this->assertFalse($pool->hasStarted(), 'should not be started');
104
    }
105
106
    public function testPoolAddingRun()
107
    {
108
        $run = Mockery::mock(RunInterface::class);
109
        $run->shouldReceive('hasStarted')
110
            ->andReturn(false);
111
        $run->shouldReceive('isRunning')
112
            ->andReturn(false);
113
        $pool = new Pool();
114
        $pool->add($run);
115
116
        $this->assertEquals(1, $pool->count());
117
    }
118
119
    public function testPoolAddingProcess()
120
    {
121
        $pool = new Pool();
122
        $pool->add($this->process);
123
124
        $this->assertEquals(1, $pool->count());
125
        $runs = $pool->getAll();
126
        $run = reset($runs);
127
128
        $this->assertEquals($this->process, $run->getProcess());
129
    }
130
131 View Code Duplication
    public function testSuccessfulRun()
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...
132
    {
133
        $run = Mockery::mock(RunInterface::class);
134
        $run->shouldReceive('isRunning')
135
            ->andReturn(false);
136
        $run->shouldReceive('poll')
137
            ->andReturn(true, false);
138
        $run->shouldReceive('hasStarted')
139
            ->andReturn(true);
140
        $run->shouldReceive('isSuccessful')
141
            ->andReturn(true);
142
143
        $pool = new Pool([$run]);
0 ignored issues
show
Documentation introduced by
array($run) is of type array<integer,object<Moc...kery\\MockInterface>"}>, but the function expects a array<integer,object<Gra...onent\Process\Process>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
144
145
        $run->shouldReceive('start');
146
        $pool->run(0);
147
148
        $this->assertTrue($pool->hasStarted());
149
        $this->assertFalse($pool->isRunning());
150
        $this->assertTrue($pool->isSuccessful());
151
    }
152
153
    /**
154
     * @expectedException \Graze\ParallelProcess\Exceptions\NotRunningException
155
     */
156
    public function testPoolUnableToAddRunningProcessWhenPoolHasNotStarted()
157
    {
158
        $run = Mockery::mock(RunInterface::class);
159
        $run->shouldReceive('isRunning')
160
            ->andReturn(true);
161
162
        $pool = new Pool();
163
164
        $pool->add($run);
165
    }
166
167
    public function testPoolAbleToAddRunningProcessWhenPoolHasStarted()
168
    {
169
        $run = Mockery::mock(RunInterface::class);
170
        $run->shouldReceive('isRunning')
171
            ->andReturn(false);
172
        $run->shouldReceive('hasStarted')
173
            ->andReturn(false);
174
        $run->shouldReceive('start');
175
        $pool = new Pool([$run]);
0 ignored issues
show
Documentation introduced by
array($run) is of type array<integer,object<Moc...kery\\MockInterface>"}>, but the function expects a array<integer,object<Gra...onent\Process\Process>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
        $pool->start();
177
178
        $run2 = Mockery::mock(RunInterface::class);
179
        $run2->shouldReceive('isRunning')
180
             ->andReturn(true);
181
        $run2->shouldReceive('start');
182
        $pool->add($run2);
183
184
        $this->assertEquals(2, $pool->count());
185
        $this->assertTrue($pool->isRunning());
186
    }
187
188 View Code Duplication
    public function testOnSuccessIsCalledOnSuccessfulProcess()
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...
189
    {
190
        $process = Mockery::mock(Process::class);
191
        $process->shouldReceive('stop');
192
        $process->shouldReceive('isStarted')->andReturn(true);
193
        $process->shouldReceive('isRunning')->andReturn(false);
194
        $process->shouldReceive('start')->atLeast()->once();
195
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
196
197
        $hit = false;
198
199
        $pool = new Pool(
200
            [],
201
            function ($proc) use ($process, &$hit) {
202
                $this->assertSame($proc, $process);
203
                $hit = true;
204
            }
205
        );
206
207
        $pool->add($process);
208
209
        $pool->run(0);
210
211
        $this->assertTrue($hit);
212
    }
213
214 View Code Duplication
    public function testOnFailureIsCalledForErroredProcess()
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...
215
    {
216
        $process = Mockery::mock(Process::class);
217
        $process->shouldReceive('stop');
218
        $process->shouldReceive('isStarted')->andReturn(true);
219
        $process->shouldReceive('isRunning')->andReturn(false);
220
        $process->shouldReceive('start')->atLeast()->once();
221
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
222
223
        $hit = false;
224
225
        $pool = new Pool(
226
            [],
227
            null,
228
            function ($proc) use ($process, &$hit) {
229
                $this->assertEquals($proc, $process);
230
                $hit = true;
231
            }
232
        );
233
234
        $pool->add($process);
235
236
        $pool->run(0);
237
238
        $this->assertTrue($hit);
239
    }
240
241
    public function testOnProgressIsCalledDuringProcessRun()
242
    {
243
        $process = Mockery::mock(Process::class);
244
        $process->shouldReceive('stop');
245
        $process->shouldReceive('isStarted')->andReturn(true);
246
        $process->shouldReceive('isRunning')->andReturn(false, false, true, false);
247
        $process->shouldReceive('start')->atLeast()->once();
248
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
249
250
        $hit = false;
251
252
        $pool = new Pool(
253
            [],
254
            null,
255
            null,
256
            function ($proc) use ($process, &$hit) {
257
                $this->assertEquals($proc, $process);
258
                $hit = true;
259
            }
260
        );
261
262
        $pool->add($process);
263
264
        $pool->run(0);
265
266
        $this->assertTrue($hit);
267
    }
268
269 View Code Duplication
    public function testOnSuccessSetterIsCalledOnSuccessfulProcess()
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...
270
    {
271
        $process = Mockery::mock(Process::class);
272
        $process->shouldReceive('stop');
273
        $process->shouldReceive('isStarted')->andReturn(true);
274
        $process->shouldReceive('isRunning')->andReturn(false);
275
        $process->shouldReceive('start')->atLeast()->once();
276
        $process->shouldReceive('isSuccessful')->once()->andReturn(true);
277
278
        $hit = false;
279
280
        $pool = new Pool();
281
        $this->assertSame(
282
            $pool,
283
            $pool->setOnSuccess(function ($proc) use ($process, &$hit) {
284
                $this->assertEquals($proc, $process);
285
                $hit = true;
286
            })
287
        );
288
289
        $pool->add($process);
290
291
        $pool->run(0);
292
293
        $this->assertTrue($hit);
294
    }
295
296 View Code Duplication
    public function testOnFailureSetterIsCalledForErroredProcess()
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...
297
    {
298
        $process = Mockery::mock(Process::class);
299
        $process->shouldReceive('stop');
300
        $process->shouldReceive('isStarted')->andReturn(true);
301
        $process->shouldReceive('isRunning')->andReturn(false);
302
        $process->shouldReceive('poll')->andReturn(false);
303
        $process->shouldReceive('start')->atLeast()->once();
304
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
305
306
        $hit = false;
307
308
        $pool = new Pool();
309
        $this->assertSame(
310
            $pool,
311
            $pool->setOnFailure(function ($proc) use ($process, &$hit) {
312
                $this->assertEquals($proc, $process);
313
                $hit = true;
314
            })
315
        );
316
317
        $pool->add($process);
318
319
        $pool->run(0);
320
321
        $this->assertTrue($hit);
322
    }
323
324 View Code Duplication
    public function testOnProgressSetterIsCalledDuringProcessRun()
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...
325
    {
326
        $process = Mockery::mock(Process::class);
327
        $process->shouldReceive('stop');
328
        $process->shouldReceive('isStarted')->andReturn(true);
329
        $process->shouldReceive('isRunning')->andReturn(false, false, true, false);
330
        $process->shouldReceive('start')->atLeast()->once();
331
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
332
333
        $hit = false;
334
335
        $pool = new Pool();
336
        $this->assertSame(
337
            $pool,
338
            $pool->setOnProgress(function ($proc) use ($process, &$hit) {
339
                $this->assertEquals($proc, $process);
340
                $hit = true;
341
            })
342
        );
343
344
        $pool->add($process);
345
346
        $pool->run(0);
347
348
        $this->assertTrue($hit);
349
    }
350
351 View Code Duplication
    public function testOnStartSetterIsCalledDuringProcessRun()
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...
352
    {
353
        $process = Mockery::mock(Process::class);
354
        $process->shouldReceive('stop');
355
        $process->shouldReceive('isStarted')->andReturn(true);
356
        $process->shouldReceive('isRunning')->andReturn(false, false, true, false);
357
        $process->shouldReceive('start')->atLeast()->once();
358
        $process->shouldReceive('isSuccessful')->once()->andReturn(false);
359
360
        $hit = false;
361
362
        $pool = new Pool();
363
        $this->assertSame(
364
            $pool,
365
            $pool->setOnStart(function ($proc) use ($process, &$hit) {
366
                $this->assertEquals($proc, $process);
367
                $hit = true;
368
            })
369
        );
370
371
        $pool->add($process);
372
373
        $pool->run(0);
374
375
        $this->assertTrue($hit);
376
    }
377
}
378