@@ -82,12 +82,17 @@ private function fork(int $concurrency, \Closure $code): void
8282 *
8383 * @param \Closure(0|1): int $code The counter code
8484 * @param \Closure(float): Mutex $mutexFactory
85+ * @param \Closure(): void $setUp
8586 *
8687 * @dataProvider provideHighContentionCases
8788 */
8889 #[DataProvider('provideHighContentionCases ' )]
89- public function testHighContention (\Closure $ code , \Closure $ mutexFactory ): void
90+ public function testHighContention (\Closure $ code , \Closure $ mutexFactory, ? \ Closure $ setUp = null ): void
9091 {
92+ if ($ setUp !== null ) {
93+ $ setUp ();
94+ }
95+
9196 $ concurrency = 10 ;
9297 $ iterations = 1000 / $ concurrency ;
9398 $ timeout = $ concurrency * 20 ;
@@ -110,14 +115,12 @@ public function testHighContention(\Closure $code, \Closure $mutexFactory): void
110115 */
111116 public static function provideHighContentionCases (): iterable
112117 {
113- foreach (static ::provideExecutionIsSerializedWhenLockedCases () as [$ mutexFactory ]) {
118+ foreach (static ::provideExecutionIsSerializedWhenLockedCases () as $ name => [$ mutexFactory ]) {
114119 $ filename = tempnam (sys_get_temp_dir (), 'php-lock-high-contention ' );
115120
116121 static ::$ temporaryFiles [] = $ filename ;
117122
118- file_put_contents ($ filename , '0 ' );
119-
120- yield [
123+ yield $ name => [
121124 static function (int $ increment ) use ($ filename ): int {
122125 $ counter = file_get_contents ($ filename );
123126 $ counter += $ increment ;
@@ -127,21 +130,19 @@ static function (int $increment) use ($filename): int {
127130 return $ counter ;
128131 },
129132 $ mutexFactory ,
133+ static function () use ($ filename ): void {
134+ file_put_contents ($ filename , '0 ' );
135+ },
130136 ];
131137 }
132138
133- $ addPDO = static function ($ dsn , $ user , $ password , $ vendor ) {
139+ $ makePDOCase = static function (string $ dsn , string $ user , string $ password , string $ vendor ) {
134140 $ pdo = self ::getPDO ($ dsn , $ user , $ password );
135141
136142 $ options = ['mysql ' => 'engine=InnoDB ' ];
137143 $ option = $ options [$ vendor ] ?? '' ;
138144 $ pdo ->exec ('CREATE TABLE IF NOT EXISTS counter(id INT PRIMARY KEY, counter INT) ' . $ option );
139145
140- $ pdo ->beginTransaction ();
141- $ pdo ->exec ('DELETE FROM counter ' );
142- $ pdo ->exec ('INSERT INTO counter VALUES (1, 0) ' );
143- $ pdo ->commit ();
144-
145146 self ::$ pdo = null ;
146147
147148 return [
@@ -163,34 +164,40 @@ static function (int $increment) use ($dsn, $user, $password) {
163164
164165 return $ counter ;
165166 },
166- static function ($ timeout = 3 ) use ($ dsn , $ user , $ password ) {
167+ static function ($ timeout ) use ($ dsn , $ user , $ password ) {
167168 self ::$ pdo = null ;
168169 $ pdo = self ::getPDO ($ dsn , $ user , $ password );
169170
170171 return new TransactionalMutex ($ pdo , $ timeout );
171172 },
173+ static function () use ($ pdo ): void {
174+ $ pdo ->beginTransaction ();
175+ $ pdo ->exec ('DELETE FROM counter ' );
176+ $ pdo ->exec ('INSERT INTO counter VALUES (1, 0) ' );
177+ $ pdo ->commit ();
178+ },
172179 ];
173180 };
174181
175182 if (getenv ('MYSQL_DSN ' )) {
176183 $ dsn = getenv ('MYSQL_DSN ' );
177184 $ user = getenv ('MYSQL_USER ' );
178185 $ password = getenv ('MYSQL_PASSWORD ' );
179- yield 'mysql ' => $ addPDO ($ dsn , $ user , $ password , 'mysql ' );
186+ yield 'mysql ' => $ makePDOCase ($ dsn , $ user , $ password , 'mysql ' );
180187 }
181188
182189 if (getenv ('PGSQL_DSN ' )) {
183190 $ dsn = getenv ('PGSQL_DSN ' );
184191 $ user = getenv ('PGSQL_USER ' );
185192 $ password = getenv ('PGSQL_PASSWORD ' );
186- yield 'postgres ' => $ addPDO ($ dsn , $ user , $ password , 'postgres ' );
193+ yield 'postgres ' => $ makePDOCase ($ dsn , $ user , $ password , 'postgres ' );
187194 }
188195 }
189196
190197 /**
191198 * Tests that five processes run sequentially.
192199 *
193- * @param \Closure(): Mutex $mutexFactory
200+ * @param \Closure(float ): Mutex $mutexFactory
194201 *
195202 * @dataProvider provideExecutionIsSerializedWhenLockedCases
196203 */
@@ -200,7 +207,7 @@ public function testExecutionIsSerializedWhenLocked(\Closure $mutexFactory): voi
200207 $ time = \microtime (true );
201208
202209 $ this ->fork (6 , static function () use ($ mutexFactory ): void {
203- $ mutex = $ mutexFactory ();
210+ $ mutex = $ mutexFactory (3 );
204211 $ mutex ->synchronized (static function (): void {
205212 \usleep (200 * 1000 );
206213 });
@@ -221,29 +228,29 @@ public static function provideExecutionIsSerializedWhenLockedCases(): iterable
221228
222229 self ::$ temporaryFiles [] = $ filename ;
223230
224- yield 'flock ' => [static function ($ timeout = 3 ) use ($ filename ): Mutex {
231+ yield 'flock ' => [static function ($ timeout ) use ($ filename ): Mutex {
225232 $ file = fopen ($ filename , 'w ' );
226233
227- return new FlockMutex ($ file );
234+ return new FlockMutex ($ file, $ timeout );
228235 }];
229236
230- yield 'flockWithTimoutPcntl ' => [static function ($ timeout = 3 ) use ($ filename ): Mutex {
237+ yield 'flockWithTimoutPcntl ' => [static function ($ timeout ) use ($ filename ): Mutex {
231238 $ file = fopen ($ filename , 'w ' );
232239 $ lock = Liberator::liberate (new FlockMutex ($ file , $ timeout ));
233240 $ lock ->strategy = FlockMutex::STRATEGY_PCNTL ; // @phpstan-ignore property.notFound
234241
235242 return $ lock ->popsValue ();
236243 }];
237244
238- yield 'flockWithTimoutBusy ' => [static function ($ timeout = 3 ) use ($ filename ): Mutex {
245+ yield 'flockWithTimoutBusy ' => [static function ($ timeout ) use ($ filename ): Mutex {
239246 $ file = fopen ($ filename , 'w ' );
240247 $ lock = Liberator::liberate (new FlockMutex ($ file , $ timeout ));
241248 $ lock ->strategy = FlockMutex::STRATEGY_BUSY ; // @phpstan-ignore property.notFound
242249
243250 return $ lock ->popsValue ();
244251 }];
245252
246- yield 'semaphore ' => [static function ($ timeout = 3 ) use ($ filename ): Mutex {
253+ yield 'semaphore ' => [static function () use ($ filename ): Mutex {
247254 $ semaphore = sem_get (ftok ($ filename , 'b ' ));
248255 self ::assertThat (
249256 $ semaphore ,
@@ -257,7 +264,7 @@ public static function provideExecutionIsSerializedWhenLockedCases(): iterable
257264 }];
258265
259266 if (getenv ('MEMCACHE_HOST ' )) {
260- yield 'memcached ' => [static function ($ timeout = 3 ): Mutex {
267+ yield 'memcached ' => [static function ($ timeout ): Mutex {
261268 $ memcached = new \Memcached ();
262269 $ memcached ->addServer (getenv ('MEMCACHE_HOST ' ), 11211 );
263270
@@ -268,7 +275,7 @@ public static function provideExecutionIsSerializedWhenLockedCases(): iterable
268275 if (getenv ('REDIS_URIS ' )) {
269276 $ uris = explode (', ' , getenv ('REDIS_URIS ' ));
270277
271- yield 'PredisMutex ' => [static function ($ timeout = 3 ) use ($ uris ): Mutex {
278+ yield 'PredisMutex ' => [static function ($ timeout ) use ($ uris ): Mutex {
272279 $ clients = array_map (
273280 static fn ($ uri ) => new Client ($ uri ),
274281 $ uris
@@ -279,7 +286,7 @@ public static function provideExecutionIsSerializedWhenLockedCases(): iterable
279286
280287 if (class_exists (\Redis::class)) {
281288 yield 'PHPRedisMutex ' => [
282- static function ($ timeout = 3 ) use ($ uris ): Mutex {
289+ static function ($ timeout ) use ($ uris ): Mutex {
283290 $ apis = array_map (
284291 static function (string $ uri ): \Redis {
285292 $ redis = new \Redis ();
@@ -306,7 +313,7 @@ static function (string $uri): \Redis {
306313 }
307314
308315 if (getenv ('MYSQL_DSN ' )) {
309- yield 'MySQLMutex ' => [static function ($ timeout = 3 ): Mutex {
316+ yield 'MySQLMutex ' => [static function ($ timeout ): Mutex {
310317 $ pdo = new \PDO (getenv ('MYSQL_DSN ' ), getenv ('MYSQL_USER ' ), getenv ('MYSQL_PASSWORD ' ));
311318 $ pdo ->setAttribute (\PDO ::ATTR_ERRMODE , \PDO ::ERRMODE_EXCEPTION );
312319
0 commit comments