1515
1616use  Cog \DbLocker \Locker \PostgresAdvisoryLocker ;
1717use  Cog \DbLocker \Locker \PostgresAdvisoryLockScopeEnum ;
18+ use  Cog \DbLocker \Locker \PostgresLockModeEnum ;
1819use  Cog \DbLocker \LockId \PostgresLockId ;
1920use  Cog \Test \DbLocker \Integration \AbstractIntegrationTestCase ;
2021use  LogicException ;
@@ -25,21 +26,69 @@ final class PostgresAdvisoryLockerTest extends AbstractIntegrationTestCase
2526    private  const  DB_INT32_VALUE_MIN  = -2_147_483_648 ;
2627    private  const  DB_INT32_VALUE_MAX  = 2_147_483_647 ;
2728
28-     public  function  testItCanTryAcquireLockWithinSession (): void 
29+     #[DataProvider('provideItCanTryAcquireLockWithinSessionData ' )]
30+     public  function  testItCanTryAcquireLockWithinSession (
31+         PostgresLockModeEnum   $ mode ,
32+     ): void  {
33+         $ locker  = $ this  ->initLocker ();
34+         $ dbConnection  = $ this  ->initPostgresPdoConnection ();
35+         $ postgresLockId  = PostgresLockId::fromKeyValue ('test ' );
36+ 
37+         $ isLockAcquired  = $ locker ->acquireLock (
38+             $ dbConnection ,
39+             $ postgresLockId ,
40+             scope: PostgresAdvisoryLockScopeEnum::Session,
41+             mode: $ mode ,
42+         );
43+ 
44+         $ this  ->assertTrue ($ isLockAcquired );
45+         $ this  ->assertPgAdvisoryLocksCount (1 );
46+         $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection , $ postgresLockId , $ mode );
47+     }
48+ 
49+     public  static  function  provideItCanTryAcquireLockWithinSessionData (): array 
2950    {
51+         return  [
52+             'exclusive lock '  => [
53+                 PostgresLockModeEnum::Exclusive,
54+             ],
55+             'share lock '  => [
56+                 PostgresLockModeEnum::Share,
57+             ],
58+         ];
59+     }
60+ 
61+     #[DataProvider('provideItCanTryAcquireLockWithinTransactionData ' )]
62+     public  function  testItCanTryAcquireLockWithinTransaction (
63+         PostgresLockModeEnum   $ mode ,
64+     ): void  {
3065        $ locker  = $ this  ->initLocker ();
3166        $ dbConnection  = $ this  ->initPostgresPdoConnection ();
3267        $ postgresLockId  = PostgresLockId::fromKeyValue ('test ' );
68+         $ dbConnection ->beginTransaction ();
3369
3470        $ isLockAcquired  = $ locker ->acquireLock (
3571            $ dbConnection ,
3672            $ postgresLockId ,
37-             PostgresAdvisoryLockScopeEnum::Session,
73+             scope: PostgresAdvisoryLockScopeEnum::Transaction,
74+             mode: $ mode ,
3875        );
3976
4077        $ this  ->assertTrue ($ isLockAcquired );
4178        $ this  ->assertPgAdvisoryLocksCount (1 );
42-         $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection , $ postgresLockId );
79+         $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection , $ postgresLockId , $ mode );
80+     }
81+ 
82+     public  static  function  provideItCanTryAcquireLockWithinTransactionData (): array 
83+     {
84+         return  [
85+             'exclusive lock '  => [
86+                 PostgresLockModeEnum::Exclusive,
87+             ],
88+             'share lock '  => [
89+                 PostgresLockModeEnum::Share,
90+             ],
91+         ];
4392    }
4493
4594    #[DataProvider('provideItCanTryAcquireLockFromIntKeysCornerCasesData ' )]
@@ -52,7 +101,7 @@ public function testItCanTryAcquireLockFromIntKeysCornerCases(): void
52101        $ isLockAcquired  = $ locker ->acquireLock (
53102            $ dbConnection ,
54103            $ postgresLockId ,
55-             PostgresAdvisoryLockScopeEnum::Session,
104+             scope:  PostgresAdvisoryLockScopeEnum::Session,
56105        );
57106
58107        $ this  ->assertTrue ($ isLockAcquired );
@@ -153,23 +202,82 @@ public function testItCannotAcquireSameLockInTwoConnections(): void
153202        $ this  ->assertPgAdvisoryLockMissingInConnection ($ dbConnection2 , $ postgresLockId );
154203    }
155204
156-     public  function  testItCanReleaseLock (): void 
157-     {
205+     #[DataProvider('provideItCanReleaseLockData ' )]
206+     public  function  testItCanReleaseLock (
207+         PostgresLockModeEnum   $ mode ,
208+     ): void  {
158209        $ locker  = $ this  ->initLocker ();
159210        $ dbConnection  = $ this  ->initPostgresPdoConnection ();
160211        $ postgresLockId  = PostgresLockId::fromKeyValue ('test ' );
161212        $ locker ->acquireLock (
162213            $ dbConnection ,
163214            $ postgresLockId ,
164-             PostgresAdvisoryLockScopeEnum::Session,
215+             scope: PostgresAdvisoryLockScopeEnum::Session,
216+             mode: $ mode ,
165217        );
166218
167-         $ isLockReleased  = $ locker ->releaseLock ($ dbConnection , $ postgresLockId );
219+         $ isLockReleased  = $ locker ->releaseLock (
220+             $ dbConnection ,
221+             $ postgresLockId ,
222+             mode: $ mode ,
223+         );
168224
169225        $ this  ->assertTrue ($ isLockReleased );
170226        $ this  ->assertPgAdvisoryLocksCount (0 );
171227    }
172228
229+     public  static  function  provideItCanReleaseLockData (): array 
230+     {
231+         return  [
232+             'exclusive lock '  => [
233+                 PostgresLockModeEnum::Exclusive,
234+             ],
235+             'share lock '  => [
236+                 PostgresLockModeEnum::Share,
237+             ],
238+         ];
239+     }
240+ 
241+     #[DataProvider('provideItCanNotReleaseLockOfDifferentModesData ' )]
242+     public  function  testItCanNotReleaseLockOfDifferentModes (
243+         PostgresLockModeEnum   $ acquireMode ,
244+         PostgresLockModeEnum   $ releaseMode ,
245+     ): void  {
246+         $ locker  = $ this  ->initLocker ();
247+         $ dbConnection  = $ this  ->initPostgresPdoConnection ();
248+         $ postgresLockId  = PostgresLockId::fromKeyValue ('test ' );
249+         $ locker ->acquireLock (
250+             $ dbConnection ,
251+             $ postgresLockId ,
252+             scope: PostgresAdvisoryLockScopeEnum::Session,
253+             mode: $ acquireMode ,
254+         );
255+ 
256+         $ isLockReleased  = $ locker ->releaseLock (
257+             $ dbConnection ,
258+             $ postgresLockId ,
259+             mode: $ releaseMode ,
260+         );
261+ 
262+         $ this  ->assertFalse ($ isLockReleased );
263+         $ this  ->assertPgAdvisoryLocksCount (1 );
264+         $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection , $ postgresLockId , $ acquireMode );
265+     }
266+ 
267+     public  static  function  provideItCanNotReleaseLockOfDifferentModesData (): array 
268+     {
269+         return  [
270+             'release exclusive lock as share '  => [
271+                 'acquireMode '  => PostgresLockModeEnum::Exclusive,
272+                 'releaseMode '  => PostgresLockModeEnum::Share,
273+             ],
274+             'release share lock as exclusive '  => [
275+                 'acquireMode '  => PostgresLockModeEnum::Share,
276+                 'releaseMode '  => PostgresLockModeEnum::Exclusive,
277+             ],
278+         ];
279+     }
280+ 
173281    public  function  testItCanReleaseLockTwiceIfAcquiredTwice (): void 
174282    {
175283        $ locker  = $ this  ->initLocker ();
@@ -350,24 +458,6 @@ public function testItCanReleaseAllLocksInConnectionButKeepsOtherLocks(): void
350458        $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection2 , $ postgresLockId4 );
351459    }
352460
353-     public  function  testItCanTryAcquireLockWithinTransaction (): void 
354-     {
355-         $ locker  = $ this  ->initLocker ();
356-         $ dbConnection  = $ this  ->initPostgresPdoConnection ();
357-         $ postgresLockId  = PostgresLockId::fromKeyValue ('test ' );
358-         $ dbConnection ->beginTransaction ();
359- 
360-         $ isLockAcquired  = $ locker ->acquireLock (
361-             $ dbConnection ,
362-             $ postgresLockId ,
363-             PostgresAdvisoryLockScopeEnum::Session,
364-         );
365- 
366-         $ this  ->assertTrue ($ isLockAcquired );
367-         $ this  ->assertPgAdvisoryLocksCount (1 );
368-         $ this  ->assertPgAdvisoryLockExistsInConnection ($ dbConnection , $ postgresLockId );
369-     }
370- 
371461    public  function  testItCannotAcquireLockWithinTransactionNotInTransaction (): void 
372462    {
373463        $ this  ->expectException (LogicException::class);
0 commit comments