Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Framework/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,27 @@ public static function getTestAnnotations()
}


/**
* Removes keyword final from source codes.
* @return void
*/
public static function bypassFinals()
{
FileMutator::addMutator(function ($code) {
if (strpos($code, 'final') !== false) {
$tokens = token_get_all($code);
$code = '';
foreach ($tokens as $token) {
$code .= is_array($token)
? ($token[0] === T_FINAL ? '' : $token[1])
: $token;
}
}
return $code;
});
}


/**
* Loads data according to the file annotation or specified by Tester\Runner\TestHandler::initiateDataProvider()
* @return array
Expand Down
212 changes: 212 additions & 0 deletions src/Framework/FileMutator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<?php

/**
* This file is part of the Nette Tester.
* Copyright (c) 2009 David Grudl (https://davidgrudl.com)
*/

namespace Tester;


/**
* PHP file mutator.
*/
class FileMutator
{
const PROTOCOL = 'file';

/** @var resource|null */
public $context;

/** @var resource|null */
private $handle;

/** @var callable[] */
private static $mutators = [];


public static function addMutator(callable $mutator)
{
self::$mutators[] = $mutator;
stream_wrapper_unregister(self::PROTOCOL);
stream_wrapper_register(self::PROTOCOL, __CLASS__);
}


public function dir_closedir()
{
closedir($this->handle);
}


public function dir_opendir($path, $options)
{
$this->handle = $this->native('opendir', $path, $this->context);
return (bool) $this->handle;
}


public function dir_readdir()
{
return readdir($this->handle);
}


public function dir_rewinddir()
{
return rewinddir($this->handle);
}


public function mkdir($path, $mode, $options)
{
return $this->native('mkdir', $mode, false, $this->context);
}


public function rename($pathFrom, $pathTo)
{
return $this->native('rename', $pathFrom, $pathTo, $this->context);
}


public function rmdir($path, $options)
{
return $this->native('rmdir', $this->context);
}


public function stream_cast($castAs)
{
return $this->handle;
}


public function stream_close()
{
fclose($this->handle);
}


public function stream_eof()
{
return feof($this->handle);
}


public function stream_flush()
{
return fflush($this->handle);
}


public function stream_lock($operation)
{
return flock($this->handle, $operation);
}


public function stream_metadata($path, $option, $value)
{
switch ($option) {
case STREAM_META_TOUCH:
return $this->native('touch', $path, $value[0], $value[1]);
case STREAM_META_OWNER_NAME:
case STREAM_META_OWNER:
return $this->native('chown', $path, $value);
case STREAM_META_GROUP_NAME:
case STREAM_META_GROUP:
return $this->native('chgrp', $path, $value);
case STREAM_META_ACCESS:
return $this->native('chmod', $path, $value);
}
}


public function stream_open($path, $mode, $options, &$openedPath)
{
$usePath = (bool) ($options & STREAM_USE_PATH);
if (pathinfo($path, PATHINFO_EXTENSION) === 'php') {
$content = $this->native('file_get_contents', $path, $usePath, $this->context);
if ($content === false) {
return false;
} else {
foreach (self::$mutators as $mutator) {
$content = call_user_func($mutator, $content);
}
$this->handle = tmpfile();
$this->native('fwrite', $this->handle, $content);
$this->native('fseek', $this->handle, 0);
return true;
}
} else {
$this->handle = $this->context
? $this->native('fopen', $path, $mode, $usePath, $this->context)
: $this->native('fopen', $path, $mode, $usePath);
return (bool) $this->handle;
}
}


public function stream_read($count)
{
return fread($this->handle, $count);
}


public function stream_seek($offset, $whence = SEEK_SET)
{
return fseek($this->handle, $offset, $whence);
}


public function stream_set_option($option, $arg1, $arg2)
{
}


public function stream_stat()
{
return fstat($this->handle);
}


public function stream_tell()
{
return ftell($this->handle);
}


public function stream_truncate($newSize)
{
return ftruncate($this->handle, $newSize);
}


public function stream_write($data)
{
return fwrite($this->handle, $data);
}


public function unlink($path)
{
return $this->native('unlink', $path);
}


public function url_stat($path, $flags)
{
return $this->native('fstat', $path, $flags);
}


private function native($func)
{
stream_wrapper_restore(self::PROTOCOL);
$res = call_user_func_array($func, array_slice(func_get_args(), 1));
stream_wrapper_unregister(self::PROTOCOL);
stream_wrapper_register(self::PROTOCOL, __CLASS__);
return $res;
}
}
1 change: 1 addition & 0 deletions src/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require __DIR__ . '/Framework/FileMock.php';
require __DIR__ . '/Framework/TestCase.php';
require __DIR__ . '/Framework/DomQuery.php';
require __DIR__ . '/Framework/FileMutator.php';
require __DIR__ . '/CodeCoverage/Collector.php';
require __DIR__ . '/Runner/Job.php';

Expand Down
14 changes: 14 additions & 0 deletions tests/Framework/FileMutator.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


Tester\Environment::bypassFinals();

require __DIR__ . '/fixtures/final.class.php';

$rc = new ReflectionClass('FinalClass');
Assert::false($rc->isFinal());
Assert::false($rc->getMethod('finalMethod')->isFinal());
8 changes: 8 additions & 0 deletions tests/Framework/fixtures/final.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

final class FinalClass
{
final function finalMethod()
{
}
}
1 change: 1 addition & 0 deletions tests/coding-standard.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ parameters:
skip:
PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff:
- src/Framework/FileMock.php
- src/Framework/FileMutator.php