Passed
Pull Request — master (#57)
by Matthew
07:36
created

BaseJobManagerTest   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 261
Duplicated Lines 13.41 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 35
lcom 1
cbo 4
dl 35
loc 261
rs 9
c 0
b 0
f 0

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Dtc\QueueBundle\Tests\Manager;
4
5
use Dtc\QueueBundle\Manager\JobManagerInterface;
6
use Dtc\QueueBundle\Manager\PriorityJobManager;
7
use Dtc\QueueBundle\Manager\RunManager;
8
use Dtc\QueueBundle\Model\BaseJob;
9
use Dtc\QueueBundle\Model\Worker;
10
use Dtc\QueueBundle\ODM\JobTimingManager;
11
use Dtc\QueueBundle\RabbitMQ\JobManager;
12
use PHPUnit\Framework\TestCase;
13
14
abstract class BaseJobManagerTest extends TestCase
15
{
16
    const PERFORMANCE_TOTAL_JOBS = 100;
17
18
    /** @var Worker */
19
    public static $worker;
20
21
    /** @var string */
22
    public static $jobClass;
23
24
    /** @var JobManagerInterface */
25
    public static $jobManager;
26
27
    /** @var RunManager */
28
    public static $runManager;
29
30
    /** @var JobTimingManager */
31
    public static $jobTimingManager;
32
33
    public static function setUpBeforeClass()
34
    {
35
        self::$jobClass = self::$jobManager->getJobClass();
36
        self::$worker->setJobManager(self::$jobManager);
37
    }
38
39
    protected function drain()
40
    {
41
        $limit = 10000;
42
        while ($limit && $job = self::$jobManager->getJob()) {
43
            --$limit;
44
            self::$jobManager->saveHistory($job);
45
        }
46
        self::assertGreaterThan(0, $limit);
47
    }
48
49
    public function testSaveJob()
50
    {
51
        $job = $this->getJob();
52
        $jobInQueue = self::$jobManager->getJob();
53
        self::assertNotNull($jobInQueue, 'There should be a job.');
54
        self::assertEquals(
55
            $job->getId(),
56
            $jobInQueue->getId(),
57
            'Job id returned by manager should be the same'
58
        );
59
        self::$jobManager->deleteJob($job);
60
    }
61
62
    protected function getJob()
63
    {
64
        $job = new self::$jobClass(self::$worker, false, null);
65
        $job->fibonacci(1);
66
        self::assertNotNull($job->getId(), 'Job id should be generated');
67
68
        return $job;
69
    }
70
71
    public function testGetJobByWorker()
72
    {
73
        $job = $this->getJob();
74
        $jobInQueue = self::$jobManager->getJob(self::$worker->getName());
75
        self::assertEquals(
76
            $job->getId(),
77
            $jobInQueue->getId(),
78
            'Job id returned by manager should be the same'
79
        );
80
    }
81
82
    public function testDeleteJob()
83
    {
84
        $this->drain();
85
86
        $job = $this->getJob();
87
        self::$jobManager->deleteJob($job);
88
89
        $nextJob = self::$jobManager->getJob();
90
        self::assertNull($nextJob, "Shouldn't be any jobs left in queue");
91
92
        return $job;
93
    }
94
95
    /**
96
     * Not all managers will support job priority.
97
     */
98
    public function testJobPriority()
99
    {
100
        $firstJob = new self::$jobClass(self::$worker, false, 12);
101
        $firstJob->fibonacci(1);
102
        self::assertNotNull($firstJob->getId(), 'Job id should be generated');
103
104
        $secondJob = new self::$jobClass(self::$worker, false, 1);
105
        $secondJob->fibonacci(1);
106
        self::assertNotNull($secondJob->getId(), 'Job id should be generated');
107
108
        $thirdJob = new self::$jobClass(self::$worker, false, 5);
109
        $thirdJob->fibonacci(1);
110
        self::assertNotNull($thirdJob->getId(), 'Job id should be generated');
111
112
        if (self::$jobManager instanceof PriorityJobManager && null !== self::$jobManager->getMaxPriority()) {
113
            $jobInQueue = self::$jobManager->getJob();
114
            self::assertNotNull($jobInQueue, 'There should be a job.');
115
            self::assertEquals(
116
                $secondJob->getId(),
117
                $jobInQueue->getId(),
118
                'Second job id should be returned - lower number unload first'
119
            );
120
121
            $jobInQueue = self::$jobManager->getJob();
122
            self::assertEquals(
123
                $thirdJob->getId(),
124
                $jobInQueue->getId(),
125
                'Third job id should be returned - lower number unload first'
126
            );
127
128
            $jobInQueue = self::$jobManager->getJob();
129
            self::assertEquals(
130
                $firstJob->getId(),
131
                $jobInQueue->getId(),
132
                'First job id should be returned - lower number unload first'
133
            );
134
        }
135
    }
136
137
    public function testResetExceptionJobs()
138
    {
139
        $this->expectingException('resetExceptionJobs');
140
    }
141
142
    public function testPruneExceptionJobs()
143
    {
144
        $this->expectingException('pruneExceptionJobs');
145
    }
146
147
    public function testPruneExpiredJobs()
148
    {
149
        $this->expectingException('pruneExpiredJobs');
150
    }
151
152
    public function testGetStatus()
153
    {
154
        $count = self::$jobManager->getWaitingJobCount();
155
        $status = self::$jobManager->getStatus();
156
157
        self::assertEquals($count, $status['all'][BaseJob::STATUS_NEW]);
158
    }
159
160
    public function testPruneArchivedJobs()
161
    {
162
        $failed = false;
163
        try {
164
            $time = time() - 86400;
165
            self::$jobManager->pruneArchivedJobs(new \DateTime("@$time"));
166
            $failed = true;
167
        } catch (\Exception $exception) {
168
            self::assertTrue(true);
169
        }
170
        self::assertFalse($failed);
171
    }
172
173
    /**
174
     * @param string $method
175
     */
176
    protected function expectingException($method)
177
    {
178
        $failed = false;
179
        try {
180
            self::$jobManager->$method();
181
            $failed = true;
182
        } catch (\Exception $exception) {
183
            self::assertTrue(true);
184
        }
185
        self::assertFalse($failed);
186
    }
187
188
    public function performanceEnqueue()
189
    {
190
        $jobsTotal = static::PERFORMANCE_TOTAL_JOBS;
191
        $start = microtime(true);
192
        for ($i = 0; $i < $jobsTotal; ++$i) {
193
            self::$worker->later()->fibonacci(1);
194
        }
195
196
        $total = microtime(true) - $start;
197
        echo "\nTotal of {$jobsTotal} jobs enqueued in {$total} seconds\n";
198
199
        try {
200
            // Have to add a sleep for RabbitMQ to catch up -
201
            $count = self::getWaitingJobCount($jobsTotal);
202
            self::assertEquals($jobsTotal, $count);
203
        } catch (\Exception $e) {
204
            if ('Unsupported' !== $e->getMessage()) {
205
                throw $e;
206
            }
207
        }
208
    }
209
210
    protected static function fudgeRabbitMQCount($count, $expected)
211
    {
212
        if ($expected !== $count) {
213
            sleep(1);
214
            $count = self::$jobManager->getWaitingJobCount();
215
            if ($expected !== $count && $expected > 10) {
216
                if ($expected >= $count - 10) { // 'fudge factor for RabbitMQ'
217
                    return $expected;
218
                }
219
            }
220
        }
221
222
        return $count;
223
    }
224
225
    protected static function getWaitingJobCount($expected)
226
    {
227
        $count = self::$jobManager->getWaitingJobCount();
228
        if (!self::$jobManager instanceof JobManager) {
229
            return $count;
230
        }
231
232
        return self::fudgeRabbitMQCount($count, $expected);
233
    }
234
235
    /**
236
     * @outputBuffering disabled
237
     */
238
    public function testPerformance()
239
    {
240
        echo "\n".static::class.": Testing Performance\n";
241
        flush();
242
        $reflection = new \ReflectionObject(self::$jobManager);
243
        if ($reflection->hasProperty('enableSorting')) {
244
            $oldEnableSorting = self::$jobManager->enableSorting;
245
            self::$jobManager->enableSorting = false; // Ignore priority
246
        }
247
248
        // Dequeue all outstanding jobs
249
        $this->drain();
250
251
        $this->performanceEnqueue();
252
        $this->performanceDequeue();
253
254
        if ($reflection->hasProperty('enableSorting')) {
255
            self::$jobManager->enableSorting = $oldEnableSorting; // Ignore priority
256
        }
257
    }
258
259
    public function performanceDequeue()
260
    {
261
        $jobsTotal = static::PERFORMANCE_TOTAL_JOBS;
262
        $start = microtime(true);
263
        $job = null;
264
        for ($i = 0; $i < $jobsTotal; ++$i) {
265
            $job = self::$jobManager->getJob();
266
        }
267
        $total = microtime(true) - $start;
268
        echo "Total of {$jobsTotal} jobs dequeued in {$total} seconds\n";
269
        self::assertNotNull($job, 'The last job in queue is null');
270
271
        $nextJob = self::$jobManager->getJob();
272
        self::assertNull($nextJob, "Shouldn't be any jobs left in queue");
273
    }
274
}
275