Completed
Push — master ( 9eae13...e56856 )
by Antonio
04:26
created

testEnqueDequeueWithDelay()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 45
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 45
rs 8.8571
cc 1
eloc 37
nc 1
nop 0
1
<?php
2
namespace Da\Mailer\Test\Queue\Backend\Redis;
3
4
use Da\Mailer\Model\MailMessage;
5
use Da\Mailer\Queue\Backend\Redis\RedisQueueStoreAdapter;
6
use Da\Mailer\Queue\Backend\Redis\RedisQueueStoreConnection;
7
use Da\Mailer\Test\Fixture\FixtureHelper;
8
use PHPUnit_Framework_TestCase;
9
use Mockery;
10
11
class RedisQueueStoreAdapterTest extends PHPUnit_Framework_TestCase
12
{
13
    private $mailJob;
14
    private $payload;
15
16
    protected function setUp()
17
    {
18
        parent::setUp();
19
        $this->mailJob = FixtureHelper::getRedisMailJob();
20
        $this->payload = json_encode([
21
            'id' => '123456789',
22
            'attempt' => $this->mailJob->getAttempt(),
23
            'message' => $this->mailJob->getMessage()
24
        ]);
25
    }
26
27
    public function testEnqueueDequeueAndAcknowledge()
28
    {
29
        $payload = $this->payload;
30
        $redisClient = Mockery::mock('\Predis\Client')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
31
            ->shouldReceive('zadd')
32
                ->andReturn(1)
33
            ->shouldReceive('rpush')
34
                ->andReturn(1)
35
            ->shouldReceive('llen')
36
                ->twice()
37
                ->andReturnUsing(
38
                    function (){
39
                        static $f = false;
40
                        return $f = !$f ? 1 : 0;
41
                    }
42
                )
43
            ->shouldReceive('zrem')
44
            ->andReturn(1)
45
            ->shouldReceive('lpop')
46
            ->with(Mockery::mustBe('mail_queue'))
47
            ->andReturnUsing(function() use ($payload) {
48
                static $f = false;
49
                return $f = !$f ? $payload : null;
50
            })
51
            ->shouldReceive('transaction')
52
            ->andReturn(1)
53
            ->getMock();
54
55
        $redisStoreConnection = Mockery::mock('\Da\Mailer\Queue\Backend\Redis\RedisQueueStoreConnection')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
56
            ->shouldReceive('connect')
57
            ->andReturnSelf()
58
            ->shouldReceive('getInstance')
59
            ->andReturn($redisClient)
60
            ->getMock();
61
62
        $redisQueueStore = new RedisQueueStoreAdapter($redisStoreConnection);
63
64
        $this->assertSame($redisQueueStore, $redisQueueStore->init());
65
        $this->assertTrue($redisQueueStore->enqueue($this->mailJob) === 1);
66
67
        $this->assertTrue($redisQueueStore->isEmpty() === false);
68
69
        $mailJob = $redisQueueStore->dequeue();
70
71
        $this->assertTrue($redisQueueStore->isEmpty() === true);
72
73
        $this->assertTrue(!empty($mailJob->getMessage()));
74
75
        $dequeuedMailMessage = MailMessage::fromArray(json_decode($mailJob->getMessage(), true));
76
77
        $this->assertEquals(FixtureHelper::getMailMessage(), $dequeuedMailMessage);
78
79
        $mailJob->markAsCompleted();
80
        $redisQueueStore->ack($mailJob);
0 ignored issues
show
Bug introduced by
It seems like $mailJob defined by $redisQueueStore->dequeue() on line 69 can be null; however, Da\Mailer\Queue\Backend\...ueueStoreAdapter::ack() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
81
82
        $this->assertTrue($redisQueueStore->dequeue() === null);
83
    }
84
85
    public function testEnqueDequeueWithDelay()
86
    {
87
        $time = time() + 2;
88
89
        $redisClient = Mockery::mock('\Predis\Client')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
            ->shouldReceive('zadd')
91
            ->with('mail_queue:delayed', $time)
92
            ->twice()
93
            ->withAnyArgs()
94
            ->andReturn(1)
95
            ->shouldReceive('rpush')
96
            ->andReturn(1)
97
            ->shouldReceive('llen')
98
            ->once()
99
            ->andReturn(0)
100
            ->shouldReceive('lpop')
101
            ->with(Mockery::mustBe('mail_queue'))
102
            ->andReturn($this->payload)
103
            ->shouldReceive('zrem')
104
            ->with('mail_queue:reserved', $this->payload)
105
            ->shouldReceive('transaction')
106
            ->andReturn(1)
107
            ->getMock();
108
109
        $redisStoreConnection = Mockery::mock('\Da\Mailer\Queue\Backend\Redis\RedisQueueStoreConnection')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
110
            ->shouldReceive('connect')
111
            ->andReturnSelf()
112
            ->shouldReceive('getInstance')
113
            ->andReturn($redisClient)
114
            ->getMock();
115
116
        $redisQueueStore = new RedisQueueStoreAdapter($redisStoreConnection);
117
118
        $mailJob = $this->mailJob;
119
        $mailJob->setTimeToSend($time);
120
        $this->assertTrue($redisQueueStore->enqueue($mailJob) === 1);
121
        $this->assertTrue($redisQueueStore->isEmpty() === true);
122
        sleep(3); // sleep three seconds to expire in delayed
123
        $mailJob = $redisQueueStore->dequeue(); // now it should have migrated
124
125
        $this->assertTrue(!empty($mailJob->getMessage()));
126
127
        $mailJob->markAsCompleted();
128
        $redisQueueStore->ack($mailJob);
0 ignored issues
show
Bug introduced by
It seems like $mailJob defined by $redisQueueStore->dequeue() on line 123 can be null; however, Da\Mailer\Queue\Backend\...ueueStoreAdapter::ack() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
129
    }
130
131
    public function testEnqueDequeueWithPossibleFailure()
132
    {
133
        $time = time() + 2;
0 ignored issues
show
Unused Code introduced by
$time 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...
134
        $redisClient = Mockery::mock('\Predis\Client')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
135
            ->shouldReceive('rpush')
136
            ->once()
137
            ->andReturn(1)
138
            ->shouldReceive('zadd')
139
            ->twice()
140
            ->withAnyArgs()
141
            ->andReturn(1)
142
            ->shouldReceive('llen')
143
            ->twice()
144
            ->andReturnUsing(
145
                function (){
146
                    static $f = false;
147
                    return $f = !$f ? 1 : 0;
148
                }
149
            )
150
            ->shouldReceive('lpop')
151
            ->with('queue')
152
            ->andReturn($this->payload)
153
            ->shouldReceive('zrem')
154
            ->with('queue:reserved', $this->payload)
155
            ->andReturn(1)
156
            ->shouldReceive('transaction')
157
            ->andReturn(1)
158
            ->getMock();
159
160
        $redisStoreConnection = Mockery::mock('\Da\Mailer\Queue\Backend\Redis\RedisQueueStoreConnection')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
161
            ->shouldReceive('connect')
162
            ->andReturnSelf()
163
            ->shouldReceive('getInstance')
164
            ->andReturn($redisClient)
165
            ->getMock();
166
167
        $redisQueueStore = new RedisQueueStoreAdapter($redisStoreConnection, 'queue', 2);
168
169
        $mailJob = FixtureHelper::getRedisMailJob();
170
        $this->assertSame($redisQueueStore, $redisQueueStore->init());
171
        $this->assertTrue($redisQueueStore->enqueue($mailJob) === 1);
172
173
        $this->assertTrue($redisQueueStore->isEmpty() === false);
174
175
        $mailJob = $redisQueueStore->dequeue(); // it should be in reserved
176
177
        sleep(3); // lets imagine we have a failure, wait 3 seconds
178
179
        $againMailJob = $redisQueueStore->dequeue(); // it should has come back and placed again in reserved
180
        $this->assertEquals($mailJob, $againMailJob);
181
182
        $mailJob->markAsCompleted();
183
        $redisQueueStore->ack($mailJob); // finish everything
0 ignored issues
show
Bug introduced by
It seems like $mailJob defined by $redisQueueStore->dequeue() on line 175 can be null; however, Da\Mailer\Queue\Backend\...ueueStoreAdapter::ack() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
184
185
        $this->assertTrue($redisQueueStore->isEmpty());
186
    }
187
188
    /**
189
     * @expectedException \Da\Mailer\Exception\InvalidCallException
190
     */
191
    public function testBadMethodCallExceptionOnAck()
192
    {
193
        $mailJob = FixtureHelper::getRedisMailJob();
194
        $connection = new RedisQueueStoreConnection([]);
195
        $redisQueueStore = new RedisQueueStoreAdapter($connection);
196
        $redisQueueStore->ack($mailJob);
197
    }
198
199
    public function testNonCompletedAck()
200
    {
201
        $payload = $this->payload;
202
        $redisClient = Mockery::mock('\Predis\Client')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
203
            ->shouldReceive('zadd')
204
            ->times(2)
205
            ->andReturn(1)
206
            ->shouldReceive('rpush')
207
            ->andReturn(1)
208
            ->shouldReceive('llen')
209
            ->twice()
210
            ->andReturnUsing(
211
                function (){
212
                    static $f = false;
213
                    return $f = !$f ? 1 : 0;
214
                }
215
            )
216
            ->shouldReceive('zrem')
217
            ->andReturn(1)
218
            ->shouldReceive('lpop')
219
            ->with(Mockery::mustBe('mail_queue'))
220
            ->andReturnUsing(function() use ($payload) {
221
                static $f = false;
222
                return $f = !$f ? $payload : null;
223
            })
224
            ->shouldReceive('transaction')
225
            ->andReturn(1)
226
            ->getMock();
227
228
        $redisStoreConnection = Mockery::mock('\Da\Mailer\Queue\Backend\Redis\RedisQueueStoreConnection')
0 ignored issues
show
Bug introduced by
The method shouldReceive() does not seem to exist on object<Mockery\Expectation>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
229
            ->shouldReceive('connect')
230
            ->andReturnSelf()
231
            ->shouldReceive('getInstance')
232
            ->andReturn($redisClient)
233
            ->getMock();
234
235
        $redisQueueStore = new RedisQueueStoreAdapter($redisStoreConnection);
236
237
        $this->assertSame($redisQueueStore, $redisQueueStore->init());
238
        $this->assertTrue($redisQueueStore->enqueue($this->mailJob) === 1);
239
240
        $this->assertTrue($redisQueueStore->isEmpty() === false);
241
242
        $mailJob = $redisQueueStore->dequeue();
243
244
        $this->assertTrue($redisQueueStore->isEmpty() === true);
245
246
        $this->assertTrue(!empty($mailJob->getMessage()));
247
248
        $dequeuedMailMessage = MailMessage::fromArray(json_decode($mailJob->getMessage(), true));
249
250
        $this->assertEquals(FixtureHelper::getMailMessage(), $dequeuedMailMessage);
251
        $redisQueueStore->ack($mailJob);
0 ignored issues
show
Bug introduced by
It seems like $mailJob defined by $redisQueueStore->dequeue() on line 242 can be null; however, Da\Mailer\Queue\Backend\...ueueStoreAdapter::ack() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
252
    }
253
}
254