GearmanLockTest.php 5.9 KB

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