MongoQueueTest::testRelease()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 9.424
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace SfCod\QueueBundle\Tests\Queue;
4
5
use Helmich\MongoMock\MockDatabase;
6
use MongoDB\Database;
7
use PHPUnit\Framework\TestCase;
8
use SfCod\QueueBundle\Base\JobResolverInterface;
9
use SfCod\QueueBundle\Entity\Job;
10
use SfCod\QueueBundle\Job\JobContract;
11
use SfCod\QueueBundle\Job\JobContractInterface;
12
use SfCod\QueueBundle\Queue\MongoQueue;
13
use SfCod\QueueBundle\Service\MongoDriver;
14
15
/**
16
 * Class MongoQueueTest
17
 *
18
 * @author Virchenko Maksim <[email protected]>
19
 *
20
 * @package SfCod\QueueBundle\Tests\Queue
21
 */
22
class MongoQueueTest extends TestCase
23
{
24
    /**
25
     * Test pushing into database
26
     */
27
    public function testPush()
28
    {
29
        $collection = uniqid('collection_');
30
        $jobName = uniqid('job_');
31
        $data = range(1, 10);
32
33
        $database = new MockDatabase();
34
35
        $mongoQueue = $this->mockMongoQueue($database, $collection);
36
37
        $mongoQueue->push($jobName, $data);
38
39
        self::assertEquals(1, $database->selectCollection($collection)->count());
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
40
41
        $job = $database->selectCollection($collection)->findOne();
42
43
        $payload = json_decode($job->payload, true);
44
        self::assertEquals($jobName, $payload['job']);
45
        self::assertEquals($data, $payload['data']);
46
    }
47
48
    /**
49
     * Test pop from queue
50
     */
51
    public function testPop()
52
    {
53
        $collection = uniqid('collection_');
54
        $jobName = uniqid('job_');
55
        $data = range(1, 10);
56
57
        $database = new MockDatabase();
58
59
        $mongoQueue = $this->mockMongoQueue($database, $collection);
60
61
        $mongoQueue->push($jobName, $data);
62
63
        $job = $mongoQueue->pop();
64
        self::assertEquals($jobName, $job->getName());
65
        self::assertEquals($data, $job->payload()['data']);
66
    }
67
68
    /**
69
     * Test if job exists
70
     */
71
    public function testExists()
72
    {
73
        $collection = uniqid('collection_');
74
        $jobName = uniqid('job_');
75
        $data = range(1, 10);
76
77
        $database = new MockDatabase();
78
79
        $mongoQueue = $this->mockMongoQueue($database, $collection);
80
81
        $mongoQueue->push($jobName, $data);
82
83
        self::assertTrue($mongoQueue->exists($jobName, $data));
84
    }
85
86
    /**
87
     * Test pushing into database
88
     */
89
    public function testPushOn()
90
    {
91
        $collection = uniqid('collection_');
92
        $jobName = uniqid('job_');
93
        $data = range(1, 10);
94
95
        $database = new MockDatabase();
96
97
        $mongoQueue = $this->mockMongoQueue($database, $collection);
98
99
        $mongoQueue->pushOn('default', $jobName, $data);
100
101
        self::assertEquals(1, $database->selectCollection($collection)->count());
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
102
103
        $job = $database->selectCollection($collection)->findOne();
104
105
        $payload = json_decode($job->payload, true);
106
        self::assertEquals($jobName, $payload['job']);
107
        self::assertEquals($data, $payload['data']);
108
    }
109
110
    /**
111
     * Test pushing into database
112
     */
113
    public function testPushRaw()
114
    {
115
        $collection = uniqid('collection_');
116
        $jobName = uniqid('job_');
117
        $data = range(1, 10);
118
119
        $database = new MockDatabase();
120
121
        $mongoQueue = $this->mockMongoQueue($database, $collection);
122
123
        $mongoQueue->pushRaw(json_encode(['job' => $jobName, 'data' => $data]));
124
125
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
126
        self::assertEquals(1, $count);
127
128
        $job = $database->selectCollection($collection)->findOne();
129
130
        $payload = json_decode($job->payload, true);
131
        self::assertEquals($jobName, $payload['job']);
132
        self::assertEquals($data, $payload['data']);
133
    }
134
135
    /**
136
     * Test pushing job for later
137
     */
138
    public function testLater()
139
    {
140
        $collection = uniqid('collection_');
141
        $jobName = uniqid('job_');
142
        $data = range(1, 10);
143
        $delay = rand(60, 3600);
144
145
        $database = new MockDatabase();
146
147
        $mongoQueue = $this->mockMongoQueue($database, $collection);
148
149
        $mongoQueue->later($delay, $jobName, $data);
150
151
        $job = $database->selectCollection($collection)->findOne();
152
153
        $payload = json_decode($job->payload, true);
154
        self::assertEquals($jobName, $payload['job']);
155
        self::assertEquals($data, $payload['data']);
156
157
        self::assertGreaterThan(time() + $delay - 10, $job->available_at);
158
    }
159
160
    /**
161
     * Test pushing bulk
162
     */
163
    public function testBulk()
164
    {
165
        $collection = uniqid('collection_');
166
        $jobName = uniqid('job_');
167
        $data = range(1, 10);
168
        $delay = rand(60, 3600);
0 ignored issues
show
Unused Code introduced by
$delay is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
169
170
        $database = new MockDatabase();
171
172
        $mongoQueue = $this->mockMongoQueue($database, $collection);
173
174
        for ($i = 0; $i < 10; ++$i) {
175
            $jobs[] = $jobName . $i;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$jobs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $jobs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
176
        }
177
178
        $mongoQueue->bulk($jobs, $data);
0 ignored issues
show
Bug introduced by
The variable $jobs does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
179
180
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
181
182
        self::assertEquals(10, $count);
183
    }
184
185
    /**
186
     * Test release
187
     */
188
    public function testRelease()
189
    {
190
        $collection = uniqid('collection_');
191
        $jobName = uniqid('job_');
192
        $data = range(1, 10);
193
194
        $database = new MockDatabase();
195
196
        $mongoQueue = $this->mockMongoQueue($database, $collection);
197
198
        $mongoQueue->push($jobName, $data);
199
200
        $job = $database->selectCollection($collection)->findOne();
201
202
        $database->selectCollection($collection)->deleteMany([]);
203
204
        $jobToRelease = new Job();
205
        $jobToRelease->setId($job->_id);
206
        $jobToRelease->setQueue($job->queue);
207
        $jobToRelease->setAttempts($job->attempts);
208
209
        $jobResolver = $this->createMock(JobResolverInterface::class);
210
211
        $jobContract = new JobContract($jobResolver, $mongoQueue, $jobToRelease);
0 ignored issues
show
Documentation introduced by
$jobResolver is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<SfCod\QueueBundle...e\JobResolverInterface>.

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...
212
213
        $mongoQueue->release($jobContract, 0);
214
215
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
216
217
        self::assertEquals(1, $count);
218
    }
219
220
    /**
221
     * Test getting job by id
222
     */
223
    public function testGetJobById()
224
    {
225
        $collection = uniqid('collection_');
226
        $jobName = uniqid('job_');
227
        $data = range(1, 10);
228
229
        $database = new MockDatabase();
230
231
        $mongoQueue = $this->mockMongoQueue($database, $collection);
232
233
        $mongoQueue->push($jobName, $data);
234
235
        $job = $database->selectCollection($collection)->findOne();
236
237
        $jobContract = $mongoQueue->getJobById('default', $job->_id);
238
239
        self::assertInstanceOf(JobContractInterface::class, $jobContract);
240
        self::assertEquals($jobContract->getName(), $jobName);
241
    }
242
243
    /**
244
     * Test deleting reserved
245
     */
246
    public function testDeleteReserved()
247
    {
248
        $collection = uniqid('collection_');
249
        $jobName = uniqid('job_');
250
        $data = range(1, 10);
251
252
        $database = new MockDatabase();
253
254
        $mongoQueue = $this->mockMongoQueue($database, $collection);
255
256
        $mongoQueue->push($jobName, $data);
257
258
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
259
260
        self::assertEquals(1, $count);
261
262
        $job = $database->selectCollection($collection)->findOne();
263
        $result = $mongoQueue->deleteReserved($job->queue, $job->_id);
264
265
        self::assertTrue($result);
266
267
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
268
269
        self::assertEquals(0, $count);
270
    }
271
272
    /**
273
     * Test expire queue
274
     */
275
    public function testExpire()
276
    {
277
        $collection = uniqid('collection_');
278
        $expire = rand(1, 99999);
279
280
        $database = new MockDatabase();
281
282
        $mongoQueue = $this->mockMongoQueue($database, $collection);
283
284
        $mongoQueue->setExpire($expire);
285
286
        self::assertEquals($expire, $mongoQueue->getExpire());
287
    }
288
289
    /**
290
     * Test queue's size
291
     */
292
    public function testSize()
293
    {
294
        $collection = uniqid('collection_');
295
        $jobName = uniqid('job_');
296
        $data = range(1, 10);
297
298
        $database = new MockDatabase();
299
300
        $mongoQueue = $this->mockMongoQueue($database, $collection);
301
302
        for ($i = 0; $i < 10; ++$i) {
303
            $mongoQueue->push($jobName, $data);
304
        }
305
306
        $job = $database->selectCollection($collection)->findOne();
307
308
        $count = $database->selectCollection($collection)->count();
0 ignored issues
show
Deprecated Code introduced by
The method MongoDB\Collection::count() has been deprecated with message: 1.4

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
309
310
        self::assertEquals($count, $mongoQueue->size());
311
        self::assertEquals($count, $mongoQueue->size($job->queue));
312
    }
313
314
    /**
315
     * Test can run job
316
     */
317
    public function testCanRunJob()
318
    {
319
        $collection = uniqid('collection_');
320
        $jobName = uniqid('job_');
321
        $data = range(1, 10);
322
323
        $database = new MockDatabase();
324
325
        $mongoQueue = $this->mockMongoQueue($database, $collection);
326
327
        $mongoQueue->push($jobName, $data);
328
329
        $job = $database->selectCollection($collection)->findOne();
330
331
        /** @var JobContractInterface $jobContract */
332
        $jobContract = $mongoQueue->getJobById('default', $job->_id);
333
334
        $canRun = $mongoQueue->canRunJob($jobContract);
335
336
        self::assertTrue($canRun);
337
    }
338
339
    /**
340
     * Test mark job as reserved
341
     */
342
    public function testMarkJobAsReserved()
343
    {
344
        $collection = uniqid('collection_');
345
        $jobName = uniqid('job_');
346
        $data = range(1, 10);
347
348
        $database = new MockDatabase();
349
350
        $mongoQueue = $this->mockMongoQueue($database, $collection);
351
352
        $mongoQueue->push($jobName, $data);
353
354
        $job = $database->selectCollection($collection)->findOne();
355
        $attempts = $job->attempts;
356
357
        /** @var JobContractInterface $jobContract */
358
        $jobContract = $mongoQueue->getJobById('default', $job->_id);
359
360
        $mongoQueue->markJobAsReserved($jobContract);
361
362
        $reservedJob = $database->selectCollection($collection)->findOne();
363
364
        self::assertTrue((bool)$reservedJob->reserved);
365
        self::assertGreaterThan($attempts, $reservedJob->attempts);
366
        self::assertNotNull($reservedJob->reserved_at);
367
    }
368
369
    /**
370
     * Mock mongo queue
371
     *
372
     * @param Database $database
373
     * @param string $collection
374
     *
375
     * @return MongoQueue
376
     */
377
    private function mockMongoQueue(Database $database, string $collection): MongoQueue
378
    {
379
        $jobResolver = $this->createMock(JobResolverInterface::class);
380
        $mongo = $this->createMock(MongoDriver::class);
381
        $mongo
382
            ->expects(self::any())
383
            ->method('getDatabase')
384
            ->willReturn($database);
385
386
        $mongoQueue = new MongoQueue($jobResolver, $mongo, $collection);
0 ignored issues
show
Documentation introduced by
$jobResolver is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<SfCod\QueueBundle...e\JobResolverInterface>.

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...
Documentation introduced by
$mongo is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<SfCod\QueueBundle\Service\MongoDriver>.

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...
387
388
        return $mongoQueue;
389
    }
390
}
391