2727class MutexConcurrencyTest extends TestCase
2828{
2929 /**
30- * @var \PDO The pdo instance.
30+ * @var array
3131 */
32- private $ pdo ;
33-
32+ private static $ temporaryFiles = [];
3433 /**
35- * @var string
34+ * @var \PDO The pdo instance.
3635 */
37- private $ path ;
36+ private $ pdo ;
3837
39- protected function tearDown (): void
38+ public static function tearDownAfterClass (): void
4039 {
41- if ( $ this -> path ) {
42- unlink ($ this -> path );
40+ foreach ( self :: $ temporaryFiles as $ temporaryFile ) {
41+ unlink ($ temporaryFile );
4342 }
4443
45- parent ::tearDown ();
44+ parent ::tearDownAfterClass ();
4645 }
4746
4847 /**
@@ -114,22 +113,19 @@ public function testHighContention(callable $code, callable $mutexFactory)
114113 */
115114 public function provideTestHighContention (): array
116115 {
117- $ cases = array_map (function (array $ mutexFactory ) {
118- $ filename = tempnam (sys_get_temp_dir (), 'php-lock ' );
116+ $ cases = array_map (function (array $ mutexFactory ): array {
117+ $ filename = tempnam (sys_get_temp_dir (), 'php-lock-high-contention ' );
119118
120- file_put_contents ($ filename , pack ('i ' , 0 ));
119+ static ::$ temporaryFiles [] = $ filename ;
120+
121+ file_put_contents ($ filename , '0 ' );
121122
122123 return [
123124 function (int $ increment ) use ($ filename ): int {
124- $ data = file_get_contents ($ filename );
125-
126- $ this ->assertEquals (4 , strlen ($ data ), 'Expected four bytes to be present in temporary file. ' );
127-
128- $ counter = unpack ('i ' , $ data )[1 ];
129-
125+ $ counter = file_get_contents ($ filename );
130126 $ counter += $ increment ;
131127
132- file_put_contents ($ filename , pack ( ' i ' , $ counter) );
128+ file_put_contents ($ filename , $ counter );
133129
134130 return $ counter ;
135131 },
@@ -195,26 +191,26 @@ function ($timeout = 3) use ($dsn, $user) {
195191 }
196192
197193 /**
198- * Tests that two processes run sequentially.
194+ * Tests that five processes run sequentially.
199195 *
200196 * @param callable $mutexFactory The Mutex factory.
201197 * @dataProvider provideMutexFactories
202- * @slowThreshold 1000
198+ * @slowThreshold 2000
203199 */
204200 public function testExecutionIsSerializedWhenLocked (callable $ mutexFactory )
205201 {
206- $ timestamp = microtime (true );
202+ $ timestamp = hrtime (true );
207203
208- $ this ->fork (2 , function () use ($ mutexFactory ): void {
204+ $ this ->fork (5 , function () use ($ mutexFactory ): void {
209205 /** @var Mutex $mutex */
210206 $ mutex = $ mutexFactory ();
211207 $ mutex ->synchronized (function (): void {
212- usleep (500000 );
208+ \ usleep (200000 );
213209 });
214210 });
215211
216- $ delta = microtime (true ) - $ timestamp ;
217- $ this ->assertGreaterThan (1 , $ delta );
212+ $ delta = \hrtime (true ) - $ timestamp ;
213+ $ this ->assertGreaterThan (1e9 , $ delta );
218214 }
219215
220216 /**
@@ -224,33 +220,35 @@ public function testExecutionIsSerializedWhenLocked(callable $mutexFactory)
224220 */
225221 public function provideMutexFactories ()
226222 {
227- $ this ->path = tempnam (sys_get_temp_dir (), 'mutex-concurrency-test ' );
223+ $ filename = tempnam (sys_get_temp_dir (), 'mutex-concurrency-test ' );
224+
225+ self ::$ temporaryFiles [] = $ filename ;
228226
229227 $ cases = [
230- 'flock ' => [function ($ timeout = 3 ): Mutex {
231- $ file = fopen ($ this -> path , 'w ' );
228+ 'flock ' => [function ($ timeout = 3 ) use ( $ filename ) : Mutex {
229+ $ file = fopen ($ filename , 'w ' );
232230
233231 return new FlockMutex ($ file );
234232 }],
235233
236- 'flockWithTimoutPcntl ' => [function ($ timeout = 3 ): Mutex {
237- $ file = fopen ($ this -> path , 'w ' );
234+ 'flockWithTimoutPcntl ' => [function ($ timeout = 3 ) use ( $ filename ) : Mutex {
235+ $ file = fopen ($ filename , 'w ' );
238236 $ lock = Liberator::liberate (new FlockMutex ($ file , $ timeout ));
239237 $ lock ->stategy = FlockMutex::STRATEGY_PCNTL ;
240238
241239 return $ lock ->popsValue ();
242240 }],
243241
244- 'flockWithTimoutBusy ' => [function ($ timeout = 3 ): Mutex {
245- $ file = fopen ($ this -> path , 'w ' );
242+ 'flockWithTimoutBusy ' => [function ($ timeout = 3 ) use ( $ filename ) : Mutex {
243+ $ file = fopen ($ filename , 'w ' );
246244 $ lock = Liberator::liberate (new FlockMutex ($ file , $ timeout ));
247245 $ lock ->stategy = FlockMutex::STRATEGY_BUSY ;
248246
249247 return $ lock ->popsValue ();
250248 }],
251249
252- 'semaphore ' => [function ($ timeout = 3 ): Mutex {
253- $ semaphore = sem_get (ftok ($ this -> path , 'b ' ));
250+ 'semaphore ' => [function ($ timeout = 3 ) use ( $ filename ) : Mutex {
251+ $ semaphore = sem_get (ftok ($ filename , 'b ' ));
254252 $ this ->assertTrue (is_resource ($ semaphore ));
255253
256254 return new SemaphoreMutex ($ semaphore );
@@ -266,42 +264,44 @@ public function provideMutexFactories()
266264 }];
267265 }
268266
269- $ uris = getenv ('REDIS_URIS ' ) !== false ? explode (', ' , getenv ('REDIS_URIS ' )) : [ ' redis://localhost:6379 ' ] ;
267+ $ uris = getenv ('REDIS_URIS ' ) !== false ? explode (', ' , getenv ('REDIS_URIS ' )) : false ;
270268
271- $ cases ['PredisMutex ' ] = [function ($ timeout = 3 ) use ($ uris ): Mutex {
272- $ clients = array_map (
273- function ($ uri ) {
274- return new Client ($ uri );
275- },
276- $ uris
277- );
278-
279- return new PredisMutex ($ clients , 'test ' , $ timeout );
280- }];
281-
282- if (class_exists (Redis::class)) {
283- $ cases ['PHPRedisMutex ' ] = [
284- function ($ timeout = 3 ) use ($ uris ): Mutex {
285- /** @var Redis[] $apis */
286- $ apis = array_map (
287- function (string $ uri ): Redis {
288- $ redis = new Redis ();
289-
290- $ uri = parse_url ($ uri );
291- if (!empty ($ uri ['port ' ])) {
292- $ redis ->connect ($ uri ['host ' ], $ uri ['port ' ]);
293- } else {
294- $ redis ->connect ($ uri ['host ' ]);
295- }
296-
297- return $ redis ;
298- },
299- $ uris
300- );
301-
302- return new PHPRedisMutex ($ apis , 'test ' , $ timeout );
303- }
304- ];
269+ if ($ uris ) {
270+ $ cases ['PredisMutex ' ] = [function ($ timeout = 3 ) use ($ uris ): Mutex {
271+ $ clients = array_map (
272+ function ($ uri ) {
273+ return new Client ($ uri );
274+ },
275+ $ uris
276+ );
277+
278+ return new PredisMutex ($ clients , 'test ' , $ timeout );
279+ }];
280+
281+ if (class_exists (Redis::class)) {
282+ $ cases ['PHPRedisMutex ' ] = [
283+ function ($ timeout = 3 ) use ($ uris ): Mutex {
284+ /** @var Redis[] $apis */
285+ $ apis = array_map (
286+ function (string $ uri ): Redis {
287+ $ redis = new Redis ();
288+
289+ $ uri = parse_url ($ uri );
290+ if (!empty ($ uri ['port ' ])) {
291+ $ redis ->connect ($ uri ['host ' ], $ uri ['port ' ]);
292+ } else {
293+ $ redis ->connect ($ uri ['host ' ]);
294+ }
295+
296+ return $ redis ;
297+ },
298+ $ uris
299+ );
300+
301+ return new PHPRedisMutex ($ apis , 'test ' , $ timeout );
302+ }
303+ ];
304+ }
305305 }
306306
307307 if (getenv ('MYSQL_DSN ' )) {
0 commit comments