Last active
December 25, 2015 15:29
-
-
Save jubianchi/6998632 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace | |
| { | |
| use mageekguy\atoum; | |
| require_once __DIR__ . '/../vendor/autoload.php'; | |
| class locker | |
| { | |
| protected $adapter; | |
| public function __construct(atoum\adapter $adapter = null) | |
| { | |
| $this->adapter = $adapter ?: new atoum\adapter(); | |
| } | |
| public function lock($handle) | |
| { | |
| if(false === $this->adapter->flock($handle, LOCK_EX)) { | |
| throw new \RuntimeException('Could not lock file'); | |
| } | |
| return $this; | |
| } | |
| public function unlock($handle) | |
| { | |
| if(false === $this->adapter->flock($handle, LOCK_UN)) { | |
| throw new \RuntimeException('Could not unlock file'); | |
| } | |
| return $this; | |
| } | |
| } | |
| class writer | |
| { | |
| protected $path; | |
| protected $locker; | |
| protected $adapter; | |
| protected $handle; | |
| public function __construct($path, locker $locker = null, atoum\adapter $adapter = null) | |
| { | |
| $this->path = $path; | |
| $this->adapter = $adapter ?: new atoum\adapter(); | |
| $this->locker = $locker ?: new locker($this->adapter); | |
| } | |
| public function getPath() | |
| { | |
| return $this->path; | |
| } | |
| public function open() | |
| { | |
| if (false === file_exists($this->path)) | |
| { | |
| throw new \RuntimeException(sprintf('File %s does not exist', $this->path)); | |
| } | |
| $this->handle = $this->adapter->fopen($this->path, 'w'); | |
| if (false === $this->handle) | |
| { | |
| $this->handle = null; | |
| throw new \RuntimeException(sprintf('Could not open %s for writing', $this->path)); | |
| } | |
| try | |
| { | |
| $this->locker->lock($this->handle); | |
| } | |
| catch (\RuntimeException $exception) | |
| { | |
| $this->close(); | |
| throw new \RuntimeException(sprintf('Could not lock %s', $this->path), null, $exception); | |
| } | |
| return $this; | |
| } | |
| public function write($str) | |
| { | |
| if (false === is_writable($this->isOpen()->path)) | |
| { | |
| throw new \RuntimeException(sprintf('File %s is not writable', $this->path)); | |
| } | |
| if(false === $this->adapter->fwrite($this->handle, $str)) | |
| { | |
| throw new \RuntimeException(sprintf('Could not write to %s', $this->path)); | |
| } | |
| return $this; | |
| } | |
| public function close() | |
| { | |
| try | |
| { | |
| $this->locker->unlock($this->isOpen()->handle); | |
| } | |
| catch (\RuntimeException $exception) {} | |
| $this->adapter->fclose($this->handle); | |
| $this->handle = null; | |
| return $this; | |
| } | |
| protected function isOpen() | |
| { | |
| if (null === $this->handle) | |
| { | |
| throw new \LogicException(sprintf('File %s was not opened', $this->path)); | |
| } | |
| return $this; | |
| } | |
| } | |
| } | |
| namespace tests\units | |
| { | |
| use | |
| mageekguy\atoum, | |
| mageekguy\atoum\mock\streams\fs, | |
| locker as testedLocker, | |
| writer as testedWriter | |
| ; | |
| class locker extends atoum | |
| { | |
| public function testLock() | |
| { | |
| $this | |
| ->if($handle = fopen((string) fs\file::get(), 'r')) | |
| ->and($adapter = new atoum\test\adapter()) | |
| ->and($locker = new testedLocker($adapter)) | |
| ->then | |
| ->object($locker->lock($handle))->isIdenticalTo($locker) | |
| ->adapter($adapter) | |
| ->call('flock')->withArguments($handle, LOCK_EX)->once() | |
| ->if($adapter->flock = false) | |
| ->then | |
| ->exception(function() use ($locker, $handle) { | |
| $locker->lock($handle); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage('Could not lock file') | |
| ; | |
| } | |
| public function testUnlock() | |
| { | |
| $this | |
| ->if($handle = fopen((string) fs\file::get(), 'r')) | |
| ->and($adapter = new atoum\test\adapter()) | |
| ->and($locker = new testedLocker($adapter)) | |
| ->then | |
| ->object($locker->unlock($handle))->isIdenticalTo($locker) | |
| ->adapter($adapter) | |
| ->call('flock')->withArguments($handle, LOCK_UN)->once() | |
| ->if($adapter->flock = false) | |
| ->then | |
| ->exception(function() use ($locker, $handle) { | |
| $locker->unlock($handle); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage('Could not unlock file') | |
| ; | |
| } | |
| } | |
| class writer extends atoum | |
| { | |
| public function test__construct() | |
| { | |
| $this | |
| ->if($writer = new testedWriter($path = uniqid())) | |
| ->then | |
| ->string($writer->getPath())->isEqualTo($path) | |
| ; | |
| } | |
| public function testOpen() | |
| { | |
| $this | |
| ->given($file = fs\file::get()) | |
| ->and($adapter = new atoum\test\adapter()) | |
| ->and($locker = new \mock\locker($adapter)) | |
| ->and($writer = new testedWriter((string) $file, $locker, $adapter)) | |
| ->if($file->notExists()) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->open(); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage(sprintf('File %s does not exist', $file)) | |
| ->if($file->exists()) | |
| ->and($adapter->fopen = false) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->open(); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage(sprintf('Could not open %s for writing', $file)) | |
| ->if($this->resetAdapter($adapter)) | |
| ->and($this->resetMock($locker)) | |
| ->and($this->calling($locker)->lock->throw = $exception = new \RuntimeException()) | |
| ->and($this->calling($locker)->unlock = $locker) | |
| ->and($adapter->fopen = $handle = uniqid()) | |
| ->and($adapter->fclose = true) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->open(); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage(sprintf('Could not lock %s', $file)) | |
| ->object($this->exception->getPrevious())->isIdenticalTo($exception) | |
| ->adapter($adapter) | |
| ->call('fclose')->withArguments($handle) | |
| ->after($this->adapter($adapter)->call('fopen')->withArguments((string) $file, 'w')) | |
| ->after($this->mock($locker)->call('lock')->withArguments($handle)) | |
| ->after($this->mock($locker)->call('unlock')->withArguments($handle)) | |
| ->once() | |
| ->mock($locker) | |
| ->call('lock')->withArguments($handle) | |
| ->after($this->adapter($adapter)->call('fopen')->withArguments((string) $file, 'w')) | |
| ->once() | |
| ->call('unlock')->withArguments($handle) | |
| ->before($this->adapter($adapter)->call('fclose')->withArguments($handle)) | |
| ->once() | |
| ->if($this->resetAdapter($adapter)) | |
| ->and($this->resetMock($locker)) | |
| ->and($this->calling($locker)->lock = $locker) | |
| ->and($this->calling($locker)->unlock = $locker) | |
| ->then | |
| ->object($writer->open())->isIdenticalTo($writer) | |
| ->adapter($adapter) | |
| ->call('fopen')->withArguments((string) $file, 'w') | |
| ->before($this->mock($locker)->call('lock')->withArguments($handle)) | |
| ->once() | |
| ; | |
| } | |
| public function testWrite() | |
| { | |
| $this | |
| ->given($file = fs\file::get()) | |
| ->and($adapter = new atoum\test\adapter()) | |
| ->if($writer = new testedWriter((string) $file, null, $adapter)) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->write(uniqid()); | |
| }) | |
| ->isInstanceOf('LogicException') | |
| ->hasMessage(sprintf('File %s was not opened', $file)) | |
| ->if($writer->open()) | |
| ->and($file->isNotWritable()) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->write(uniqid()); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage(sprintf('File %s is not writable', $file)) | |
| ->if($file->isWritable()) | |
| ->then | |
| ->object($writer->write($str = uniqid()))->isIdenticalTo($writer) | |
| ->adapter($file) | |
| ->call('stream_write')->withArguments($str)->once() | |
| ->if($adapter->fwrite = false) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->write(uniqid()); | |
| }) | |
| ->isInstanceOf('RuntimeException') | |
| ->hasMessage(sprintf('Could not write to %s', $file)) | |
| ; | |
| } | |
| public function testClose() | |
| { | |
| $this | |
| ->given($file = fs\file::get()) | |
| ->and($adapter = new atoum\test\adapter()) | |
| ->and($locker = new \mock\locker($adapter)) | |
| ->if($writer = new testedWriter((string) $file, $locker, $adapter)) | |
| ->then | |
| ->exception(function() use ($writer) { | |
| $writer->close(); | |
| }) | |
| ->isInstanceOf('LogicException') | |
| ->hasMessage(sprintf('File %s was not opened', $file)) | |
| ->if($adapter->fopen = $handle = uniqid()) | |
| ->and($adapter->fclose = true) | |
| ->and($this->calling($locker)->lock = $locker) | |
| ->and($this->calling($locker)->unlock = $locker) | |
| ->and($writer->open()) | |
| ->then | |
| ->object($writer->close())->isIdenticalTo($writer) | |
| ->adapter($adapter) | |
| ->call('fclose')->withArguments($handle) | |
| ->after($this->mock($locker)->call('unlock')->withArguments($handle)) | |
| ->once() | |
| ; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment