Completed
Push — master ( 8ffdf8...f67228 )
by Matthew
08:43
created

JobManagerTest::testSaveJob()   C

Complexity

Conditions 7
Paths 72

Size

Total Lines 74
Code Lines 56

Duplication

Lines 74
Ratio 100 %

Importance

Changes 0
Metric Value
dl 74
loc 74
rs 6.6374
c 0
b 0
f 0
nc 72
cc 7
eloc 56
nop 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A JobManagerTest::testGetStatus() 0 9 1
A JobManagerTest::getBaseStatus() 21 21 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Dtc\QueueBundle\Tests\Redis;
4
5
use Dtc\QueueBundle\Model\BaseJob;
6
use Dtc\QueueBundle\Model\Job;
7
use Dtc\QueueBundle\Model\JobTiming;
8
use Dtc\QueueBundle\Manager\JobTimingManager;
9
use Dtc\QueueBundle\Model\RetryableJob;
10
use Dtc\QueueBundle\Model\Run;
11
use Dtc\QueueBundle\Manager\RunManager;
12
use Dtc\QueueBundle\Redis\JobManager;
13
use Dtc\QueueBundle\Redis\Predis;
14
use Dtc\QueueBundle\Tests\FibonacciWorker;
15
use Dtc\QueueBundle\Tests\Manager\AutoRetryTrait;
16
use Dtc\QueueBundle\Tests\Manager\BaseJobManagerTest;
17
use Dtc\QueueBundle\Tests\Manager\PriorityTestTrait;
18
use Dtc\QueueBundle\Tests\Manager\RetryableTrait;
19
use Dtc\QueueBundle\Tests\Manager\SaveJobTrait;
20
use Dtc\QueueBundle\Util\Util;
21
use Predis\Client;
22
23
/**
24
 * @author David
25
 *
26
 * This test requires local beanstalkd running
27
 */
28
class JobManagerTest extends BaseJobManagerTest
29
{
30
    use PriorityTestTrait;
31
    use AutoRetryTrait;
32
    use RetryableTrait;
33
    use SaveJobTrait;
34
    public static $connection;
35
36
    public static function setUpBeforeClass()
37
    {
38
        if (self::$jobManager) {
39
            parent::setUpBeforeClass();
40
41
            return;
42
        }
43
44
        $host = getenv('REDIS_HOST');
45
        $port = getenv('REDIS_PORT') ?: 6379;
46
        $jobTimingClass = JobTiming::class;
47
        $runClass = Run::class;
48
        $predisClient = new Client(['scheme' => 'tcp', 'host' => $host, 'port' => $port]);
49
        $predisClient->flushall();
50
        $predis = new Predis($predisClient);
51
52
        self::$jobTimingManager = new JobTimingManager($jobTimingClass, false);
53
        self::$runManager = new RunManager($runClass);
54
        self::$jobManager = new JobManager(self::$runManager, self::$jobTimingManager, \Dtc\QueueBundle\Redis\Job::class, 'test_cache_key');
55
        self::$jobManager->setRedis($predis);
56
        self::$jobManager->setMaxPriority(255);
57
        self::$worker = new FibonacciWorker();
58
        parent::setUpBeforeClass();
59
    }
60
61 View Code Duplication
    public function testConstructor()
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...
62
    {
63
        $test = null;
64
        try {
65
            $test = new JobManager(self::$runManager, self::$jobTimingManager, Job::class, 'something');
66
        } catch (\Exception $exception) {
67
            self::fail("shouldn't get here");
68
        }
69
        self::assertNotNull($test);
70
    }
71
72 View Code Duplication
    public function testGetJobByWorker()
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...
73
    {
74
        $failed = false;
75
        try {
76
            self::$jobManager->getJob(self::$worker->getName());
77
            $failed = true;
78
        } catch (\Exception $exception) {
79
            self::assertTrue(true);
80
        }
81
        self::assertFalse($failed);
82
    }
83
84 View Code Duplication
    public function testExpiredJob()
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...
85
    {
86
        $this->drain();
87
        $job = new self::$jobClass(self::$worker, false, null);
88
        $time = time() - 1;
89
        $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(1);
90
        self::assertNotNull($job->getId(), 'Job id should be generated');
91
92
        $jobInQueue = self::$jobManager->getJob();
93
        self::assertNull($jobInQueue, 'The job should have been dropped...');
94
95
        $job = new self::$jobClass(self::$worker, false, null);
96
        $time = time() - 1;
97
        $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(1);
98
99
        $job = new self::$jobClass(self::$worker, false, null);
100
        $time = time() - 1;
101
        $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(5);
102
103
        $job = new self::$jobClass(self::$worker, false, null);
104
        $time = time() - 1;
105
        $job->setExpiresAt(new \DateTime("@$time"))->fibonacci(2);
106
107
        $job = new self::$jobClass(self::$worker, false, null);
108
        $job->fibonacci(1);
109
        $jobInQueue = self::$jobManager->getJob();
110
        self::assertNotNull($jobInQueue, 'There should be a job.');
111
        self::assertEquals(
112
            $job->getId(),
113
            $jobInQueue->getId(),
114
            'Job id returned by manager should be the same'
115
        );
116
    }
117
118
    public function testInvalidReset()
119
    {
120
        $job = new \Dtc\QueueBundle\RabbitMQ\Job();
121
        $failure = false;
122
        try {
123
            self::$jobManager->resetJob($job);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Dtc\QueueBundle\Manager\JobManagerInterface as the method resetJob() does only exist in the following implementations of said interface: Dtc\QueueBundle\Beanstalkd\JobManager, Dtc\QueueBundle\Doctrine\BaseDoctrineJobManager, Dtc\QueueBundle\Doctrine\DoctrineJobManager, Dtc\QueueBundle\Manager\ArchivableJobManager, Dtc\QueueBundle\Manager\PriorityJobManager, Dtc\QueueBundle\Manager\RetryableJobManager, Dtc\QueueBundle\Manager\StallableJobManager, Dtc\QueueBundle\ODM\JobManager, Dtc\QueueBundle\ORM\JobManager, Dtc\QueueBundle\RabbitMQ\JobManager, Dtc\QueueBundle\Redis\BaseJobManager, Dtc\QueueBundle\Redis\JobManager, Dtc\QueueBundle\Tests\StubJobManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
124
            $failure = true;
125
        } catch (\InvalidArgumentException $exception) {
126
            self::assertTrue(true);
127
        }
128
        self::assertFalse($failure);
129
    }
130
131
    public function testBatchJobs()
132
    {
133
        $this->drain();
134
135
        /** @var JobManager|\Dtc\QueueBundle\ORM\JobManager $jobManager */
136
        $worker = self::$worker;
137
        $job1 = $worker->later()->fibonacci(1);
138
        $job2 = $worker->batchLater()->fibonacci(1);
139
140
        self::assertEquals($job1->getId(), $job2->getId());
141
142
        $job = self::$jobManager->getJob();
143
        self::assertEquals($job1->getId(), $job->getId());
144
        self::assertEquals($job1->getPriority(), $job->getPriority());
145
146
        $job = self::$jobManager->getJob();
147
        self::assertNull($job);
148
149
        if (null !== self::$jobManager->getMaxPriority()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Dtc\QueueBundle\Manager\JobManagerInterface as the method getMaxPriority() does only exist in the following implementations of said interface: Dtc\QueueBundle\Doctrine\BaseDoctrineJobManager, Dtc\QueueBundle\Doctrine\DoctrineJobManager, Dtc\QueueBundle\Manager\ArchivableJobManager, Dtc\QueueBundle\Manager\PriorityJobManager, Dtc\QueueBundle\Manager\StallableJobManager, Dtc\QueueBundle\ODM\JobManager, Dtc\QueueBundle\ORM\JobManager, Dtc\QueueBundle\RabbitMQ\JobManager, Dtc\QueueBundle\Redis\BaseJobManager, Dtc\QueueBundle\Redis\JobManager, Dtc\QueueBundle\Tests\StubJobManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
150
            $job1 = $worker->later()->fibonacci(1);
151
            $job2 = $worker->batchLater()->setPriority(3)->fibonacci(1);
152
            self::assertEquals($job1->getId(), $job2->getId());
153
            self::assertNotEquals($job1->getPriority(), $job2->getPriority());
154
155
            $job = self::$jobManager->getJob();
156
            self::assertNotNull($job);
157
            self::assertEquals($job1->getId(), $job->getId());
158
            self::assertEquals($job->getPriority(), $job2->getPriority());
159
160
            $job = self::$jobManager->getJob();
161
            self::assertNull($job);
162
        }
163
164
        $job1 = $worker->later(100)->fibonacci(1);
165
        $time1 = new \DateTime('@'.time());
166
        $job2 = $worker->batchLater(0)->fibonacci(1);
167
        $time2 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal());
168
169
        self::assertEquals($job1->getId(), $job2->getId());
170
        self::assertGreaterThanOrEqual($time1, $job2->getWhenAt());
171
        self::assertLessThanOrEqual($time2, $job2->getWhenAt());
172
173
        $job = self::$jobManager->getJob();
174
        self::assertNotNull($job);
175
        self::assertEquals($job1->getId(), $job->getId());
176
        if (null !== self::$jobManager->getMaxPriority()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Dtc\QueueBundle\Manager\JobManagerInterface as the method getMaxPriority() does only exist in the following implementations of said interface: Dtc\QueueBundle\Doctrine\BaseDoctrineJobManager, Dtc\QueueBundle\Doctrine\DoctrineJobManager, Dtc\QueueBundle\Manager\ArchivableJobManager, Dtc\QueueBundle\Manager\PriorityJobManager, Dtc\QueueBundle\Manager\StallableJobManager, Dtc\QueueBundle\ODM\JobManager, Dtc\QueueBundle\ORM\JobManager, Dtc\QueueBundle\RabbitMQ\JobManager, Dtc\QueueBundle\Redis\BaseJobManager, Dtc\QueueBundle\Redis\JobManager, Dtc\QueueBundle\Tests\StubJobManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
177
            self::assertNotNull($job->getPriority());
178
        } else {
179
            self::assertNull($job->getPriority());
180
        }
181
        self::assertGreaterThanOrEqual($time1, $job->getWhenAt());
182
        self::assertLessThanOrEqual($time2, $job->getWhenAt());
183
184
        if (null !== self::$jobManager->getMaxPriority()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Dtc\QueueBundle\Manager\JobManagerInterface as the method getMaxPriority() does only exist in the following implementations of said interface: Dtc\QueueBundle\Doctrine\BaseDoctrineJobManager, Dtc\QueueBundle\Doctrine\DoctrineJobManager, Dtc\QueueBundle\Manager\ArchivableJobManager, Dtc\QueueBundle\Manager\PriorityJobManager, Dtc\QueueBundle\Manager\StallableJobManager, Dtc\QueueBundle\ODM\JobManager, Dtc\QueueBundle\ORM\JobManager, Dtc\QueueBundle\RabbitMQ\JobManager, Dtc\QueueBundle\Redis\BaseJobManager, Dtc\QueueBundle\Redis\JobManager, Dtc\QueueBundle\Tests\StubJobManager.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
185
            $job1 = $worker->later(100)->setPriority(3)->fibonacci(1);
186
            $priority1 = $job1->getPriority();
187
            $time1 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal());
188
            $job2 = $worker->batchLater(0)->setPriority(1)->fibonacci(1);
189
            $time2 = Util::getDateTimeFromDecimalFormat(Util::getMicrotimeDecimal());
190
            self::assertEquals($job1->getId(), $job2->getId());
191
            self::assertNotEquals($priority1, $job2->getPriority());
192
193
            self::assertGreaterThanOrEqual($time1, $job2->getWhenAt());
194
            self::assertLessThanOrEqual($time2, $job2->getWhenAt());
195
        }
196
197
        $this->drain();
198
    }
199
200
    public function testGetStatus()
201
    {
202
        list(, $status1) = $this->getBaseStatus();
203
        list(, $status2) = $this->getBaseStatus();
204
        $fibonacciStatus1 = $status1['fibonacci->fibonacci()'];
205
        $fibonacciStatus2 = $status2['fibonacci->fibonacci()'];
206
207
        self::assertEquals($fibonacciStatus1[BaseJob::STATUS_NEW] + 1, $fibonacciStatus2[BaseJob::STATUS_NEW]);
208
    }
209
210 View Code Duplication
    protected function getBaseStatus()
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...
211
    {
212
        /** @var JobManager|\Dtc\QueueBundle\ORM\JobManager $jobManager */
213
        $jobManager = self::$jobManager;
214
        $job = new self::$jobClass(self::$worker, false, null);
215
        $job->fibonacci(1);
216
        $status = $jobManager->getStatus();
217
        self::assertArrayHasKey('fibonacci->fibonacci()', $status);
218
        $fibonacciStatus = $status['fibonacci->fibonacci()'];
219
220
        self::assertArrayHasKey(BaseJob::STATUS_NEW, $fibonacciStatus);
221
        self::assertArrayHasKey(BaseJob::STATUS_EXCEPTION, $fibonacciStatus);
222
        self::assertArrayHasKey(BaseJob::STATUS_RUNNING, $fibonacciStatus);
223
        self::assertArrayHasKey(BaseJob::STATUS_SUCCESS, $fibonacciStatus);
224
        self::assertArrayHasKey(Job::STATUS_EXPIRED, $fibonacciStatus);
225
        self::assertArrayHasKey(RetryableJob::STATUS_MAX_EXCEPTIONS, $fibonacciStatus);
226
        self::assertArrayHasKey(RetryableJob::STATUS_MAX_FAILURES, $fibonacciStatus);
227
        self::assertArrayHasKey(RetryableJob::STATUS_MAX_RETRIES, $fibonacciStatus);
228
229
        return [$job, $status];
230
    }
231
}
232