LockingProvider.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. * @author Robin Appelman <icewind@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2015, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Test\Lock;
  22. use OCP\Lock\ILockingProvider;
  23. use OCP\Lock\LockedException;
  24. use Test\TestCase;
  25. abstract class LockingProvider extends TestCase {
  26. /**
  27. * @var \OCP\Lock\ILockingProvider
  28. */
  29. protected $instance;
  30. /**
  31. * @return \OCP\Lock\ILockingProvider
  32. */
  33. abstract protected function getInstance();
  34. protected function setUp() {
  35. parent::setUp();
  36. $this->instance = $this->getInstance();
  37. }
  38. public function testExclusiveLock() {
  39. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  40. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  41. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  42. }
  43. public function testSharedLock() {
  44. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  45. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  46. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  47. }
  48. public function testDoubleSharedLock() {
  49. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  50. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  51. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  52. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  53. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  54. }
  55. public function testReleaseSharedLock() {
  56. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  57. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  58. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  59. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  60. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  61. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  62. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  63. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  64. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  65. }
  66. /**
  67. * @expectedException \OCP\Lock\LockedException
  68. */
  69. public function testDoubleExclusiveLock() {
  70. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  71. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  72. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  73. }
  74. public function testReleaseExclusiveLock() {
  75. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  76. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  77. $this->instance->releaseLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  78. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  79. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  80. }
  81. /**
  82. * @expectedException \OCP\Lock\LockedException
  83. */
  84. public function testExclusiveLockAfterShared() {
  85. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  86. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  87. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  88. }
  89. public function testExclusiveLockAfterSharedReleased() {
  90. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  91. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  92. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  93. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  94. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  95. }
  96. public function testReleaseAll() {
  97. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  98. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  99. $this->instance->acquireLock('bar', ILockingProvider::LOCK_SHARED);
  100. $this->instance->acquireLock('asd', ILockingProvider::LOCK_EXCLUSIVE);
  101. $this->instance->acquireLock('fizz#A=23', ILockingProvider::LOCK_EXCLUSIVE);
  102. $this->instance->releaseAll();
  103. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  104. $this->assertFalse($this->instance->isLocked('bar', ILockingProvider::LOCK_SHARED));
  105. $this->assertFalse($this->instance->isLocked('asd', ILockingProvider::LOCK_EXCLUSIVE));
  106. $this->assertFalse($this->instance->isLocked('fizz#A=23', ILockingProvider::LOCK_EXCLUSIVE));
  107. }
  108. public function testReleaseAllAfterChange() {
  109. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  110. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  111. $this->instance->acquireLock('bar', ILockingProvider::LOCK_SHARED);
  112. $this->instance->acquireLock('asd', ILockingProvider::LOCK_EXCLUSIVE);
  113. $this->instance->changeLock('bar', ILockingProvider::LOCK_EXCLUSIVE);
  114. $this->instance->releaseAll();
  115. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  116. $this->assertFalse($this->instance->isLocked('bar', ILockingProvider::LOCK_SHARED));
  117. $this->assertFalse($this->instance->isLocked('bar', ILockingProvider::LOCK_EXCLUSIVE));
  118. $this->assertFalse($this->instance->isLocked('asd', ILockingProvider::LOCK_EXCLUSIVE));
  119. }
  120. public function testReleaseAllAfterUnlock() {
  121. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  122. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  123. $this->instance->acquireLock('bar', ILockingProvider::LOCK_SHARED);
  124. $this->instance->acquireLock('asd', ILockingProvider::LOCK_EXCLUSIVE);
  125. $this->instance->releaseLock('bar', ILockingProvider::LOCK_SHARED);
  126. $this->instance->releaseAll();
  127. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  128. $this->assertFalse($this->instance->isLocked('asd', ILockingProvider::LOCK_EXCLUSIVE));
  129. }
  130. public function testReleaseAfterReleaseAll() {
  131. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  132. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  133. $this->instance->releaseAll();
  134. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  135. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  136. }
  137. /**
  138. * @expectedException \OCP\Lock\LockedException
  139. */
  140. public function testSharedLockAfterExclusive() {
  141. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  142. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  143. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  144. }
  145. public function testLockedExceptionHasPathForShared() {
  146. try {
  147. $this->testSharedLockAfterExclusive();
  148. $this->fail('Expected locked exception');
  149. } catch (LockedException $e) {
  150. $this->assertEquals('foo', $e->getPath());
  151. }
  152. }
  153. public function testLockedExceptionHasPathForExclusive() {
  154. try {
  155. $this->testExclusiveLockAfterShared();
  156. $this->fail('Expected locked exception');
  157. } catch (LockedException $e) {
  158. $this->assertEquals('foo', $e->getPath());
  159. }
  160. }
  161. public function testChangeLockToExclusive() {
  162. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  163. $this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  164. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  165. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  166. }
  167. public function testChangeLockToShared() {
  168. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  169. $this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
  170. $this->assertFalse($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  171. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_SHARED));
  172. }
  173. /**
  174. * @expectedException \OCP\Lock\LockedException
  175. */
  176. public function testChangeLockToExclusiveDoubleShared() {
  177. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  178. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  179. $this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  180. }
  181. /**
  182. * @expectedException \OCP\Lock\LockedException
  183. */
  184. public function testChangeLockToExclusiveNoShared() {
  185. $this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  186. }
  187. /**
  188. * @expectedException \OCP\Lock\LockedException
  189. */
  190. public function testChangeLockToExclusiveFromExclusive() {
  191. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  192. $this->instance->changeLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  193. }
  194. /**
  195. * @expectedException \OCP\Lock\LockedException
  196. */
  197. public function testChangeLockToSharedNoExclusive() {
  198. $this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
  199. }
  200. /**
  201. * @expectedException \OCP\Lock\LockedException
  202. */
  203. public function testChangeLockToSharedFromShared() {
  204. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  205. $this->instance->changeLock('foo', ILockingProvider::LOCK_SHARED);
  206. }
  207. public function testReleaseNonExistingShared() {
  208. $this->instance->acquireLock('foo', ILockingProvider::LOCK_SHARED);
  209. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  210. // releasing a lock once to many should not result in a locked state
  211. $this->instance->releaseLock('foo', ILockingProvider::LOCK_SHARED);
  212. $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  213. $this->assertTrue($this->instance->isLocked('foo', ILockingProvider::LOCK_EXCLUSIVE));
  214. $this->instance->releaseLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
  215. }
  216. }