Completed
Pull Request — master (#30)
by Matthew
23:29 queued 08:10
created

BaseJobManagerTest::testDeleteJob()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
namespace Dtc\QueueBundle\Tests\Manager;
4
5
use Dtc\QueueBundle\Manager\JobManagerInterface;
6
use Dtc\QueueBundle\Manager\RunManager;
7
use Dtc\QueueBundle\Model\Worker;
8
use Dtc\QueueBundle\ODM\JobTimingManager;
9
use PHPUnit\Framework\TestCase;
10
11
abstract class BaseJobManagerTest extends TestCase
12
{
13
    const PERFORMANCE_TOTAL_JOBS = 100;
14
15
    /** @var Worker */
16
    public static $worker;
17
18
    /** @var string */
19
    public static $jobClass;
20
21
    /** @var JobManagerInterface */
22
    public static $jobManager;
23
24
    /** @var RunManager */
25
    public static $runManager;
26
27
    /** @var JobTimingManager */
28
    public static $jobTimingManager;
29
30
    public static function setUpBeforeClass()
31
    {
32
        self::$jobClass = self::$jobManager->getJobClass();
33
        self::$worker->setJobManager(self::$jobManager);
34
    }
35
36
    public function testSaveJob()
37
    {
38
        $job = $this->getJob();
39
        $jobInQueue = self::$jobManager->getJob();
40
        self::assertNotNull($jobInQueue, 'There should be a job.');
41
        self::assertEquals(
42
            $job->getId(),
43
            $jobInQueue->getId(),
44
            'Job id returned by manager should be the same'
45
        );
46
        self::$jobManager->deleteJob($job);
47
    }
48
49
    protected function getJob()
50
    {
51
        $job = new self::$jobClass(self::$worker, false, null);
52
        $job->fibonacci(1);
53
        self::assertNotNull($job->getId(), 'Job id should be generated');
54
55
        return $job;
56
    }
57
58
    public function testGetJobByWorker()
59
    {
60
        $job = $this->getJob();
61
        $jobInQueue = self::$jobManager->getJob(self::$worker->getName());
62
        self::assertEquals(
63
            $job->getId(),
64
            $jobInQueue->getId(),
65
            'Job id returned by manager should be the same'
66
        );
67
    }
68
69
    public function testDeleteJob()
70
    {
71
        $job = $this->getJob();
72
        self::$jobManager->deleteJob($job);
73
74
        $nextJob = self::$jobManager->getJob();
75
        self::assertNull($nextJob, "Shouldn't be any jobs left in queue");
76
77
        return $job;
78
    }
79
80
    /**
81
     * Not all managers will support job priority.
82
     */
83
    public function testJobPriority()
84
    {
85
        $firstJob = new self::$jobClass(self::$worker, false, 12);
86
        $firstJob->fibonacci(1);
87
        self::assertNotNull($firstJob->getId(), 'Job id should be generated');
88
89
        $secondJob = new self::$jobClass(self::$worker, false, 1);
90
        $secondJob->fibonacci(1);
91
        self::assertNotNull($secondJob->getId(), 'Job id should be generated');
92
93
        $thirdJob = new self::$jobClass(self::$worker, false, 5);
94
        $thirdJob->fibonacci(1);
95
        self::assertNotNull($thirdJob->getId(), 'Job id should be generated');
96
97
        $jobInQueue = self::$jobManager->getJob();
98
        self::assertNotNull($jobInQueue, 'There should be a job.');
99
        self::assertEquals(
100
            $secondJob->getId(),
101
            $jobInQueue->getId(),
102
            'Second job id should be returned - lower number unload first'
103
        );
104
105
        $jobInQueue = self::$jobManager->getJob();
106
        self::assertEquals(
107
            $thirdJob->getId(),
108
            $jobInQueue->getId(),
109
            'Third job id should be returned - lower number unload first'
110
        );
111
112
        $jobInQueue = self::$jobManager->getJob();
113
        self::assertEquals(
114
            $firstJob->getId(),
115
            $jobInQueue->getId(),
116
            'First job id should be returned - lower number unload first'
117
        );
118
    }
119
120
    public function testResetExceptionJobs()
121
    {
122
        $this->expectingException('resetExceptionJobs');
123
    }
124
125
    public function testResetStalledJobs()
126
    {
127
        $this->expectingException('resetStalledJobs');
128
    }
129
130
    public function testPruneStalledJobs()
131
    {
132
        $this->expectingException('pruneStalledJobs');
133
    }
134
135
    public function testPruneExceptionJobs()
136
    {
137
        $this->expectingException('pruneExceptionJobs');
138
    }
139
140
    public function testPruneExpiredJobs()
141
    {
142
        $this->expectingException('pruneExpiredJobs');
143
    }
144
145
    public function testGetStatus()
146
    {
147
        $this->expectingException('getStatus');
148
    }
149
150
    public function testPruneArchivedJobs()
151
    {
152
        $failed = false;
153
        try {
154
            $time = time() - 86400;
155
            self::$jobManager->pruneArchivedJobs(new \DateTime("@$time"));
156
            $failed = true;
157
        } catch (\Exception $exception) {
158
            self::assertTrue(true);
159
        }
160
        self::assertFalse($failed);
161
    }
162
163
    /**
164
     * @param string $method
165
     */
166 View Code Duplication
    protected function expectingException($method)
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...
167
    {
168
        $failed = false;
169
        try {
170
            self::$jobManager->$method();
171
            $failed = true;
172
        } catch (\Exception $exception) {
173
            self::assertTrue(true);
174
        }
175
        self::assertFalse($failed);
176
    }
177
178
    public function performanceEnqueue()
179
    {
180
        $jobsTotal = static::PERFORMANCE_TOTAL_JOBS;
181
        $start = microtime(true);
182
        for ($i = 0; $i < $jobsTotal; ++$i) {
183
            self::$worker->later()->fibonacci(1);
184
        }
185
186
        $total = microtime(true) - $start;
187
        echo "\nTotal of {$jobsTotal} jobs enqueued in {$total} seconds\n";
188
189
        try {
190
            $count = self::$jobManager->getJobCount();
191
            self::assertEquals($jobsTotal, $count);
192
        } catch (\Exception $e) {
193
            if ('Unsupported' !== $e->getMessage()) {
194
                throw $e;
195
            }
196
        }
197
    }
198
199
    /**
200
     * @outputBuffering disabled
201
     */
202
    public function testPerformance()
203
    {
204
        echo "\n".static::class.": Testing Performance\n";
205
        flush();
206
        $reflection = new \ReflectionObject(self::$jobManager);
207
        if ($reflection->hasProperty('enableSorting')) {
208
            $oldEnableSorting = self::$jobManager->enableSorting;
0 ignored issues
show
Bug introduced by
Accessing enableSorting on the interface Dtc\QueueBundle\Manager\JobManagerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
209
            self::$jobManager->enableSorting = false; // Ignore priority
0 ignored issues
show
Bug introduced by
Accessing enableSorting on the interface Dtc\QueueBundle\Manager\JobManagerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
210
        }
211
212
        // Dequeue all outstanding jobs
213
        $limit = 10000;
214
        while ($job = self::$jobManager->getJob() && $limit) {
0 ignored issues
show
Unused Code introduced by
$job 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...
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: $job = (self::$jobManager->getJob() && $limit), Probably Intended Meaning: ($job = self::$jobManager->getJob()) && $limit
Loading history...
215
            $limit -= 1;
216
        }
217
        self::assertGreaterThan(0, $limit);
218
219
        $this->performanceEnqueue();
220
        $this->performanceDequeue();
221
222
        if ($reflection->hasProperty('enableSorting')) {
223
            self::$jobManager->enableSorting = $oldEnableSorting; // Ignore priority
0 ignored issues
show
Bug introduced by
Accessing enableSorting on the interface Dtc\QueueBundle\Manager\JobManagerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
The variable $oldEnableSorting 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...
224
        }
225
    }
226
227
    public function performanceDequeue()
228
    {
229
        $jobsTotal = static::PERFORMANCE_TOTAL_JOBS;
230
        $start = microtime(true);
231
        $job = null;
232
        for ($i = 0; $i < $jobsTotal; ++$i) {
233
            $job = self::$jobManager->getJob();
234
        }
235
        $total = microtime(true) - $start;
236
        echo "Total of {$jobsTotal} jobs dequeued in {$total} seconds\n";
237
        self::assertNotNull($job, 'The last job in queue is null');
238
239
        $nextJob = self::$jobManager->getJob();
240
        self::assertNull($nextJob, "Shouldn't be any jobs left in queue");
241
    }
242
}
243