/** * The Constructor. * * @param array $config Possible options values are: * - `'driver'` _object_: the driver instance which will log the coverage data. * - `'path'` _array_ : the path(s) which contain the code source files. * - `'base'` _string_: the base path of the repo (default: `getcwd`). * - `'prefix'` _string_: some prefix to remove to get the real file path. */ public function __construct($config = []) { $defaults = ['driver' => null, 'path' => [], 'include' => '*.php', 'exclude' => [], 'type' => 'file', 'skipDots' => true, 'leavesOnly' => false, 'followSymlinks' => true, 'recursive' => true, 'base' => getcwd()]; $config += $defaults; if (Interceptor::instance()) { $config += ['prefix' => rtrim(Interceptor::instance()->cachePath(), DS)]; } else { $config += ['prefix' => '']; } $this->_driver = $config['driver']; $this->_paths = (array) $config['path']; $this->_base = $config['base']; $this->_prefix = $config['prefix']; $files = Dir::scan($this->_paths, $config); foreach ($files as $file) { $this->_coverage[realpath($file)] = []; } }
<?php namespace Kahlan\Spec\Suite\Plugin; use Kahlan\Jit\Interceptor; use Kahlan\QuitException; use Kahlan\Plugin\Quit; use Kahlan\Jit\Patcher\Quit as QuitPatcher; use Kahlan\Spec\Fixture\Plugin\Quit\Foo; describe("Quit", function () { /** * Save current & reinitialize the Interceptor class. */ beforeAll(function () { $this->previous = Interceptor::instance(); Interceptor::unpatch(); $cachePath = rtrim(sys_get_temp_dir(), DS) . DS . 'kahlan'; $include = ['Kahlan\\Spec\\']; $interceptor = Interceptor::patch(compact('include', 'cachePath')); $interceptor->patchers()->add('quit', new QuitPatcher()); }); /** * Restore Interceptor class. */ afterAll(function () { Interceptor::load($this->previous); }); describe("::enable()", function () { it("enables quit statements", function () { Quit::disable(); expect(Quit::enabled())->toBe(false);
/** * The default `'patcher'` filter. */ protected function _patchers() { return Filter::on($this, 'patchers', [], function ($chain) { if (!($interceptor = Interceptor::instance())) { return; } $patchers = $interceptor->patchers(); $patchers->add('pointcut', new Pointcut()); $patchers->add('monkey', new Monkey()); $patchers->add('rebase', new Rebase()); $patchers->add('quit', new Quit()); }); }
expect($this->interceptor->loadFile($sourcePath))->toBe(true); expect(class_exists('loadFileNamespace\\ClassA', false))->toBe(true); }); it("loads cached files", function () { $sourcePath = $this->loadFileNamespacePath . DS . 'ClassCached.php'; $body = $this->classBuilder('ClassCached'); file_put_contents($sourcePath, $body); $sourceTimestamp = filemtime($sourcePath); $this->interceptor->cache($sourcePath, $body, $sourceTimestamp + 1); expect($this->interceptor->loadFile($sourcePath))->toBe(true); expect(class_exists('loadFileNamespace\\ClassCached', false))->toBe(true); }); it("throws an exception for unexisting files", function () { $path = $this->loadFileNamespacePath . DS . 'ClassUnexisting.php'; $closure = function () use($path) { $interceptor = Interceptor::instance(); $interceptor->loadFile($path); }; expect($closure)->toThrow("Error, the file `'{$path}'` doesn't exist."); }); it("caches a loaded files and set the cached file motification time to be the same as the source file", function () { $sourcePath = $this->loadFileNamespacePath . DS . 'ClassB.php'; file_put_contents($sourcePath, $this->classBuilder('ClassB')); $currentTimestamp = time(); $sourceTimestamp = $currentTimestamp - 5 * 60; touch($sourcePath, $sourceTimestamp); expect($this->interceptor->loadFile($sourcePath))->toBe(true); expect(class_exists('loadFileNamespace\\ClassB', false))->toBe(true); $cacheTimestamp = filemtime($this->interceptor->cachePath() . $sourcePath); expect($sourceTimestamp)->toBe($cacheTimestamp - 1); });
Interceptor::unpatch(); expect(class_exists(Parrot2::class, false))->toBe(false); $interceptor = Filters::patch([Parrot2::class => 'tell']); Filters::apply(Parrot2::class, 'tell', function ($next, $message) { return $next("HeHe! {$message}"); }); $parrot = new Parrot2(); expect($parrot->tell('Hello'))->toBe('HeHe! Hello'); $patchers = $interceptor->patchers(); expect($patchers->exists('filter'))->toBe(true); Filters::unpatch(); expect($patchers->exists('filter'))->toBe(false); Interceptor::load($previous); }); it("enables/disables the filter JIT patching by using composer compatible autoloader", function () { $previous = Interceptor::instance(); Interceptor::unpatch(); expect(class_exists(Parrot3::class, false))->toBe(false); $interceptor = Filters::patch([Parrot3::class], ['loader' => Interceptor::composer()]); Filters::apply(Parrot3::class, 'tell', function ($next, $message) { return $next("HeHe! {$message}"); }); $parrot = new Parrot3(); expect($parrot->tell('Hello'))->toBe('HeHe! Hello'); $patchers = $interceptor->patchers(); expect($patchers->exists('filter'))->toBe(true); Filters::unpatch(); expect($patchers->exists('filter'))->toBe(false); Interceptor::load($previous); }); it("throws an exception when no autoloader are available", function () {