Completed
Push — master ( 3d7ddc...730db5 )
by Marco
13:55
created

GearmanLockTest::setUp()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 17
nc 2
nop 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Functional\Locking;
4
5
use Doctrine\Tests\Models\CMS\CmsArticle;
6
use Doctrine\DBAL\LockMode;
7
use Doctrine\Tests\OrmFunctionalTestCase;
8
9
/**
10
 * @group locking_functional
11
 */
12
class GearmanLockTest extends OrmFunctionalTestCase
13
{
14
    private $gearman = null;
15
    private $maxRunTime = 0;
16
    private $articleId;
17
18
    protected function setUp()
19
    {
20
        if (!class_exists('GearmanClient', false)) {
21
            $this->markTestSkipped('pecl/gearman is required for this test to run.');
22
        }
23
24
        $this->useModelSet('cms');
25
        parent::setUp();
26
        $this->tasks = [];
27
28
        $this->gearman = new \GearmanClient();
29
        $this->gearman->addServer(
30
            isset($_SERVER['GEARMAN_HOST']) ? $_SERVER['GEARMAN_HOST'] : null,
31
            isset($_SERVER['GEARMAN_PORT']) ? $_SERVER['GEARMAN_PORT'] : 4730        
32
        );
33
        $this->gearman->setCompleteCallback([$this, "gearmanTaskCompleted"]);
34
35
        $article = new CmsArticle();
36
        $article->text = "my article";
37
        $article->topic = "Hello";
38
39
        $this->_em->persist($article);
40
        $this->_em->flush();
41
42
        $this->articleId = $article->id;
43
    }
44
45
    public function gearmanTaskCompleted($task)
46
    {
47
        $this->maxRunTime = max($this->maxRunTime, $task->data());
48
    }
49
50
    public function testFindWithLock()
51
    {
52
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
53
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
54
55
        $this->assertLockWorked();
56
    }
57
58
    public function testFindWithWriteThenReadLock()
59
    {
60
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
61
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_READ);
62
63
        $this->assertLockWorked();
64
    }
65
66
    public function testFindWithReadThenWriteLock()
67
    {
68
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_READ);
69
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
70
71
        $this->assertLockWorked();
72
    }
73
74
    public function testFindWithOneLock()
75
    {
76
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
77
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::NONE);
78
79
        $this->assertLockDoesNotBlock();
80
    }
81
82
    public function testDqlWithLock()
83
    {
84
        $this->asyncDqlWithLock('SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a', [], LockMode::PESSIMISTIC_WRITE);
85
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
86
87
        $this->assertLockWorked();
88
    }
89
90
    public function testLock()
91
    {
92
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
93
        $this->asyncLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
94
95
        $this->assertLockWorked();
96
    }
97
98
    public function testLock2()
99
    {
100
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
101
        $this->asyncLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_READ);
102
103
        $this->assertLockWorked();
104
    }
105
106
    public function testLock3()
107
    {
108
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_READ);
109
        $this->asyncLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
110
111
        $this->assertLockWorked();
112
    }
113
114
    public function testLock4()
115
    {
116
        $this->asyncFindWithLock(CmsArticle::class, $this->articleId, LockMode::NONE);
117
        $this->asyncLock(CmsArticle::class, $this->articleId, LockMode::PESSIMISTIC_WRITE);
118
119
        $this->assertLockDoesNotBlock();
120
    }
121
122
    protected function assertLockDoesNotBlock()
123
    {
124
        $this->assertLockWorked($onlyForSeconds = 1);
125
    }
126
127
    protected function assertLockWorked($forTime = 2, $notLongerThan = null)
128
    {
129
        if ($notLongerThan === null) {
130
            $notLongerThan = $forTime + 1;
131
        }
132
133
        $this->gearman->runTasks();
134
135
        $this->assertTrue($this->maxRunTime > $forTime,
136
            "Because of locking this tests should have run at least " . $forTime . " seconds, ".
137
            "but only did for " . $this->maxRunTime . " seconds.");
138
        $this->assertTrue($this->maxRunTime < $notLongerThan,
139
            "The longest task should not run longer than " . $notLongerThan . " seconds, ".
140
            "but did for " . $this->maxRunTime . " seconds."
141
        );
142
    }
143
144
    protected function asyncFindWithLock($entityName, $entityId, $lockMode)
145
    {
146
        $this->startJob('findWithLock', [
147
            'entityName' => $entityName,
148
            'entityId' => $entityId,
149
            'lockMode' => $lockMode,
150
        ]
151
        );
152
    }
153
154
    protected function asyncDqlWithLock($dql, $params, $lockMode)
155
    {
156
        $this->startJob('dqlWithLock', [
157
            'dql' => $dql,
158
            'dqlParams' => $params,
159
            'lockMode' => $lockMode,
160
        ]
161
        );
162
    }
163
164
    protected function asyncLock($entityName, $entityId, $lockMode)
165
    {
166
        $this->startJob('lock', [
167
            'entityName' => $entityName,
168
            'entityId' => $entityId,
169
            'lockMode' => $lockMode,
170
        ]
171
        );
172
    }
173
174
    protected function startJob($fn, $fixture)
175
    {
176
        $this->gearman->addTask($fn, serialize(
177
            [
178
            'conn' => $this->_em->getConnection()->getParams(),
179
            'fixture' => $fixture
180
            ]
181
        ));
182
183
        $this->assertEquals(GEARMAN_SUCCESS, $this->gearman->returnCode());
184
    }
185
}
186