3 namespace Doctrine\Tests\ORM\Functional\Locking;
5 use Doctrine\Tests\Models\CMS\CmsArticle,
6 Doctrine\Tests\Models\CMS\CmsUser,
7 Doctrine\DBAL\LockMode,
8 Doctrine\ORM\EntityManager;
10 require_once __DIR__ . '/../../../TestInit.php';
13 * @group locking_functional
15 class GearmanLockTest extends \Doctrine\Tests\OrmFunctionalTestCase
17 private $gearman = null;
18 private $maxRunTime = 0;
21 protected function setUp()
23 if (!class_exists('GearmanClient', false)) {
24 $this->markTestSkipped('pecl/gearman is required for this test to run.');
27 $this->useModelSet('cms');
29 $this->tasks = array();
31 $this->gearman = new \GearmanClient();
32 $this->gearman->addServer();
33 $this->gearman->setCompleteCallback(array($this, "gearmanTaskCompleted"));
35 $article = new CmsArticle();
36 $article->text = "my article";
37 $article->topic = "Hello";
39 $this->_em->persist($article);
42 $this->articleId = $article->id;
45 public function gearmanTaskCompleted($task)
47 $this->maxRunTime = max($this->maxRunTime, $task->data());
50 public function testFindWithLock()
52 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
53 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
55 $this->assertLockWorked();
58 public function testFindWithWriteThenReadLock()
60 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
61 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_READ);
63 $this->assertLockWorked();
66 public function testFindWithReadThenWriteLock()
68 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_READ);
69 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
71 $this->assertLockWorked();
74 public function testFindWithOneLock()
76 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
77 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::NONE);
79 $this->assertLockDoesNotBlock();
82 public function testDqlWithLock()
84 $this->asyncDqlWithLock('SELECT a FROM Doctrine\Tests\Models\CMS\CmsArticle a', array(), LockMode::PESSIMISTIC_WRITE);
85 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
87 $this->assertLockWorked();
90 public function testLock()
92 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
93 $this->asyncLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
95 $this->assertLockWorked();
98 public function testLock2()
100 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
101 $this->asyncLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_READ);
103 $this->assertLockWorked();
106 public function testLock3()
108 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_READ);
109 $this->asyncLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
111 $this->assertLockWorked();
114 public function testLock4()
116 $this->asyncFindWithLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::NONE);
117 $this->asyncLock('Doctrine\Tests\Models\CMS\CmsArticle', $this->articleId, LockMode::PESSIMISTIC_WRITE);
119 $this->assertLockDoesNotBlock();
122 protected function assertLockDoesNotBlock()
124 $this->assertLockWorked($onlyForSeconds = 1);
127 protected function assertLockWorked($forTime = 2, $notLongerThan = null)
129 if ($notLongerThan === null) {
130 $notLongerThan = $forTime + 1;
133 $this->gearman->runTasks();
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."
144 protected function asyncFindWithLock($entityName, $entityId, $lockMode)
146 $this->startJob('findWithLock', array(
147 'entityName' => $entityName,
148 'entityId' => $entityId,
149 'lockMode' => $lockMode,
153 protected function asyncDqlWithLock($dql, $params, $lockMode)
155 $this->startJob('dqlWithLock', array(
157 'dqlParams' => $params,
158 'lockMode' => $lockMode,
162 protected function asyncLock($entityName, $entityId, $lockMode)
164 $this->startJob('lock', array(
165 'entityName' => $entityName,
166 'entityId' => $entityId,
167 'lockMode' => $lockMode,
171 protected function startJob($fn, $fixture)
173 $this->gearman->addTask($fn, serialize(array(
174 'conn' => $this->_em->getConnection()->getParams(),
175 'fixture' => $fixture
178 $this->assertEquals(GEARMAN_SUCCESS, $this->gearman->returnCode());