public function testMergeFailDelayed() { /* * Test concurrent merges by forking this process, if: * - not manually called with --use-bagostuff * - pcntl_fork is supported by the system * - cache type will correctly support calls over forks */ $fork = (bool) $this->getCliArg('use-bagostuff'); $fork &= function_exists('pcntl_fork'); $fork &= !$this->cache instanceof HashBagOStuff; $fork &= !$this->cache instanceof EmptyBagOStuff; $fork &= !$this->cache instanceof MultiWriteBagOStuff; if (!$fork) { $this->markTestSkipped("Unable to fork, can't test merge"); } $this->cache->set('key', 'value'); $callback = function (\BagOStuff $cache, $key, $value) { // prepend merged to whatever is in cache return 'merged-' . (string) $value; }; $this->bufferedCache->merge('key', $callback, 0, 1); // callback should take awhile now so that we can test concurrent merge attempts $pid = pcntl_fork(); if ($pid == -1) { // can't fork, ignore this test... } elseif ($pid) { // wait a little, making sure that the child process is calling merge usleep(3000); // attempt a merge - this should fail to persist to real cache $this->bufferedCache->commit(); // make sure the child's merge is completed and verify usleep(3000); // check that the values failed to merge $this->assertEquals(false, $this->bufferedCache->get('key')); $this->assertEquals(false, $this->cache->get('key')); } else { $this->bufferedCache->commit(); // before exiting, tear down - MediaWikiTestCase will check for it // on destruct & throw an exception if it wasn't called $this->tearDown(); // Note: I'm not even going to check if the merge worked, I'll // compare values in the parent process to test if this merge worked. // I'm just going to exit this child process, since I don't want the // child to output any test results (would be rather confusing to // have test output twice) exit; } }
/** * @param string $key * @param Closure $callback * @param int $attempts * @return bool */ public function merge($key, Closure $callback, $attempts = 10) { return $this->cache->merge($key, $callback, $this->exptime, $attempts); }