Page MenuHomeSealhub

No OneTemporary

diff --git a/src/filesystem/__tests__/PhutilDeferredLogTestCase.php b/src/filesystem/__tests__/PhutilDeferredLogTestCase.php
index 3e6c6432..1d129871 100644
--- a/src/filesystem/__tests__/PhutilDeferredLogTestCase.php
+++ b/src/filesystem/__tests__/PhutilDeferredLogTestCase.php
@@ -1,169 +1,147 @@
<?php
final class PhutilDeferredLogTestCase extends PhutilTestCase {
public function testLogging() {
$this->checkLog(
"derp\n",
'derp',
array());
$this->checkLog(
"[20 Aug 1984] alincoln\n",
'[%T] %u',
array(
'T' => '20 Aug 1984',
'u' => 'alincoln',
));
$this->checkLog(
"%%%%%\n",
'%%%%%%%%%%',
array(
'%' => '%',
));
$this->checkLog(
"\\000\\001\\002\n",
'%a%b%c',
array(
'a' => chr(0),
'b' => chr(1),
'c' => chr(2),
));
$this->checkLog(
"Download: 100%\n",
'Download: %C',
array(
'C' => '100%',
));
$this->checkLog(
"- bee -\n",
'%a %b %c',
array(
'b' => 'bee',
));
$this->checkLog(
"\\\\\n",
'%b',
array(
'b' => '\\',
));
$this->checkLog(
"a\t\\t\n",
"%a\t%b",
array(
'a' => 'a',
'b' => "\t",
));
$this->checkLog(
"\1ab\n",
"\1a%a",
array(
'a' => 'b',
));
$this->checkLog(
"a % xb\n",
'%a %% x%b',
array(
'a' => 'a',
'b' => 'b',
));
}
public function testLogWriteFailure() {
$caught = null;
try {
if (phutil_is_hiphop_runtime()) {
// In HipHop exceptions thrown in destructors are not normally
// catchable, so call __destruct() explicitly.
$log = new PhutilDeferredLog('/derp/derp/derp/derp/derp', 'derp');
$log->__destruct();
} else {
new PhutilDeferredLog('/derp/derp/derp/derp/derp', 'derp');
}
} catch (Exception $ex) {
$caught = $ex;
}
$this->assertTrue($caught instanceof Exception);
}
- public function testManyWriters() {
- $root = phutil_get_library_root('arcanist').'/../';
- $bin = $root.'scripts/test/deferred_log.php';
-
- $n_writers = 3;
- $n_lines = 8;
-
- $tmp = new TempFile();
-
- $futures = array();
- for ($ii = 0; $ii < $n_writers; $ii++) {
- $futures[] = new ExecFuture('%s %d %s', $bin, $n_lines, (string)$tmp);
- }
-
- id(new FutureIterator($futures))
- ->resolveAll();
-
- $this->assertEqual(
- str_repeat("abcdefghijklmnopqrstuvwxyz\n", $n_writers * $n_lines),
- Filesystem::readFile($tmp));
- }
-
public function testNoWrite() {
$tmp = new TempFile();
$log = new PhutilDeferredLog($tmp, 'xyz');
$log->setFile(null);
unset($log);
$this->assertEqual('', Filesystem::readFile($tmp), pht('No Write'));
}
public function testDoubleWrite() {
$tmp = new TempFile();
$log = new PhutilDeferredLog($tmp, 'xyz');
$log->write();
$log->write();
unset($log);
$this->assertEqual(
"xyz\n",
Filesystem::readFile($tmp), pht('Double Write'));
}
public function testSetAfterWrite() {
$tmp1 = new TempFile();
$tmp2 = new TempFile();
$log = new PhutilDeferredLog($tmp1, 'xyz');
$log->write();
$caught = null;
try {
$log->setFile($tmp2);
} catch (Exception $ex) {
$caught = $ex;
}
$this->assertTrue($caught instanceof Exception, pht('Set After Write'));
}
private function checkLog($expect, $format, $data) {
$tmp = new TempFile();
$log = new PhutilDeferredLog($tmp, $format);
$log->setData($data);
unset($log);
$this->assertEqual($expect, Filesystem::readFile($tmp), $format);
}
}
diff --git a/src/filesystem/__tests__/PhutilFileLockTestCase.php b/src/filesystem/__tests__/PhutilFileLockTestCase.php
index 17f9632b..9dcc2c30 100644
--- a/src/filesystem/__tests__/PhutilFileLockTestCase.php
+++ b/src/filesystem/__tests__/PhutilFileLockTestCase.php
@@ -1,184 +1,186 @@
<?php
final class PhutilFileLockTestCase extends PhutilTestCase {
public function testLockTesting() {
// We should be able to acquire locks.
$file = new TempFile();
$this->assertTrue($this->lockTest($file));
$this->assertTrue($this->lockTest($file));
}
public function testLockHolding() {
// When a process is holding a lock, other processes should be unable
// to acquire it.
$file = new TempFile();
$hold = $this->holdLock($file);
$this->assertFalse($this->lockTest($file));
$hold->resolveKill();
$this->assertTrue($this->lockTest($file));
}
public function testInProcessLocking() {
// Other processes should be unable to lock a file if we hold the lock.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$lock->lock();
$this->assertFalse($this->lockTest($file));
$lock->unlock();
$this->assertTrue($this->lockTest($file));
}
public function testInProcessHolding() {
// We should be unable to lock a file if another process is holding the
// lock.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$hold = $this->holdLock($file);
$caught = null;
try {
$lock->lock();
} catch (PhutilLockException $ex) {
$caught = $ex;
}
$this->assertTrue($caught instanceof PhutilLockException);
$hold->resolveKill();
$this->assertTrue($this->lockTest($file));
$lock->lock();
$lock->unlock();
}
public function testRelock() {
// Trying to lock a file twice should throw an exception.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$lock->lock();
$caught = null;
try {
$lock->lock();
} catch (Exception $ex) {
$caught = $ex;
}
$this->assertTrue($caught instanceof Exception);
}
public function testExcessiveUnlock() {
// Trying to unlock a file twice should throw an exception.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$lock->lock();
$lock->unlock();
$caught = null;
try {
$lock->unlock();
} catch (Exception $ex) {
$caught = $ex;
}
$this->assertTrue($caught instanceof Exception);
}
public function testUnlockAll() {
// unlockAll() should release all locks.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$lock->lock();
$this->assertFalse($this->lockTest($file));
PhutilFileLock::unlockAll();
$this->assertTrue($this->lockTest($file));
// Calling this again shouldn't do anything bad.
PhutilFileLock::unlockAll();
$this->assertTrue($this->lockTest($file));
$lock->lock();
$lock->unlock();
}
public function testIsLocked() {
// isLocked() should report lock status accurately.
$file = new TempFile();
$lock = PhutilFileLock::newForPath($file);
$this->assertFalse($lock->isLocked());
$lock->lock();
$this->assertTrue($lock->isLocked());
$lock->unlock();
$this->assertFalse($lock->isLocked());
}
private function lockTest($file) {
list($err) = $this->buildLockFuture('--test', $file)->resolve();
return ($err == 0);
}
private function holdLock($file) {
$future = $this->buildLockFuture('--hold', $file);
// We can't return until we're sure the subprocess has had time to acquire
// the lock. Since actually testing for the lock would be kind of silly
// and guarantee that we loop forever if the locking primitive broke,
// watch stdout for a *claim* that it has acquired the lock instead.
// Make sure we don't loop forever, no matter how bad things get.
$future->setTimeout(30);
$buf = '';
while (!$future->isReady()) {
list($stdout) = $future->read();
$buf .= $stdout;
if (strpos($buf, 'LOCK ACQUIRED') !== false) {
return $future;
}
}
throw new Exception(pht('Unable to hold lock in external process!'));
}
private function buildLockFuture($flags, $file) {
$root = dirname(phutil_get_library_root('arcanist'));
- $bin = $root.'/scripts/utils/lock.php';
+ $bin = $root.'/support/test/lock-file.php';
+
+ $flags = (array)$flags;
// NOTE: Use `exec` so this passes on Ubuntu, where the default `dash` shell
// will eat any kills we send during the tests.
- $future = new ExecFuture('exec php %s %C %s', $bin, $flags, $file);
+ $future = new ExecFuture('exec php -f %R -- %Ls %R', $bin, $flags, $file);
$future->start();
return $future;
}
}
diff --git a/support/test/lock-file.php b/support/test/lock-file.php
new file mode 100644
index 00000000..b7ec9df3
--- /dev/null
+++ b/support/test/lock-file.php
@@ -0,0 +1,82 @@
+#!/usr/bin/env php
+<?php
+
+require_once dirname(__FILE__).'/../../scripts/init/init-script.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline(pht('acquire and hold a lockfile'));
+$args->setSynopsis(<<<EOHELP
+**lock.php** __file__ [__options__]
+ Acquire a lockfile and hold it until told to unlock it.
+
+EOHELP
+);
+
+$args->parseStandardArguments();
+$args->parse(array(
+ array(
+ 'name' => 'test',
+ 'help' => pht('Instead of holding the lock, release it and exit.'),
+ ),
+ array(
+ 'name' => 'hold',
+ 'help' => pht('Hold indefinitely without prompting.'),
+ ),
+ array(
+ 'name' => 'wait',
+ 'param' => 'n',
+ 'help' => pht('Block for up to __n__ seconds waiting for the lock.'),
+ 'default' => 0,
+ ),
+ array(
+ 'name' => 'file',
+ 'wildcard' => true,
+ ),
+));
+
+
+$file = $args->getArg('file');
+if (count($file) !== 1) {
+ $args->printHelpAndExit();
+}
+$file = head($file);
+
+$console = PhutilConsole::getConsole();
+$console->writeOut(
+ "%s\n",
+ pht('This process has PID %d. Acquiring lock...', getmypid()));
+
+$lock = PhutilFileLock::newForPath($file);
+
+try {
+ $lock->lock($args->getArg('wait'));
+} catch (PhutilFileLockException $ex) {
+ $console->writeOut(
+ "**%s** %s\n",
+ pht('UNABLE TO ACQUIRE LOCK:'),
+ pht('Lock is already held.'));
+ exit(1);
+}
+
+// NOTE: This string is magic, the unit tests look for it.
+$console->writeOut("%s\n", pht('LOCK ACQUIRED'));
+if ($args->getArg('test')) {
+ $lock->unlock();
+ exit(0);
+}
+
+if ($args->getArg('hold')) {
+ while (true) {
+ sleep(1);
+ }
+}
+
+while (!$console->confirm(pht('Release lock?'))) {
+ // Keep asking until they say yes.
+}
+
+$console->writeOut("%s\n", pht('Unlocking...'));
+$lock->unlock();
+
+$console->writeOut("%s\n", pht('Done.'));
+exit(0);

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 11, 09:16 (6 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
984096
Default Alt Text
(10 KB)

Event Timeline