Skip to content

Commit

Permalink
Add test for exception location cache
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls committed Jan 22, 2020
1 parent 894c207 commit dfaf02a
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 35 deletions.
3 changes: 1 addition & 2 deletions src/PugBladeCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Blade;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Compilers\CompilerInterface;

class PugBladeCompiler extends BladeCompiler implements CompilerInterface
class PugBladeCompiler extends BladeCompiler implements PugHandlerInterface
{
use PugHandlerTrait;

Expand Down
3 changes: 1 addition & 2 deletions src/PugCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Compilers\Compiler;
use Illuminate\View\Compilers\CompilerInterface;

class PugCompiler extends Compiler implements CompilerInterface
class PugCompiler extends Compiler implements PugHandlerInterface
{
use PugHandlerTrait;

Expand Down
48 changes: 24 additions & 24 deletions src/PugException.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Facade\Ignition\Exceptions\ViewException;
use Illuminate\View\Engines\CompilerEngine;
use Phug\Util\Exception\LocatedException;
use Phug\Util\SourceLocation;
use Phug\Util\SourceLocationInterface;
use Throwable;

class PugException extends ViewException
Expand All @@ -26,31 +26,10 @@ public function __construct(CompilerEngine $context, Throwable $previous)
$file = $previous->getFile();
$line = $previous->getLine();

if ($compiler instanceof PugCompiler || $compiler instanceof PugBladeCompiler) {
if ($compiler instanceof PugHandlerInterface) {
$print = 'error-'.md5_file($file).'-'.$line.'-'.md5($previous->getTraceAsString());
$cachePath = storage_path('framework/views/'.$print.'.txt');
$location = null;

if (file_exists($cachePath)) {
[$path, $line, $offset, $offsetLength] = unserialize(file_get_contents($cachePath));
$location = new SourceLocation($path, $line, $offset, $offsetLength);
} else {
$pug = $compiler->getPug();
$error = $pug->getDebugFormatter()->getDebugError(
$previous,
file_get_contents($file),
$file
);

if ($error instanceof LocatedException && ($location = $error->getLocation())) {
file_put_contents($cachePath, serialize([
$location->getPath(),
$location->getLine(),
$location->getOffset(),
$location->getOffsetLength(),
]));
}
}
$location = $this->getLocation($compiler, $cachePath, $file, $previous);

if ($location) {
$file = $location->getPath();
Expand All @@ -60,4 +39,25 @@ public function __construct(CompilerEngine $context, Throwable $previous)

parent::__construct($message, $code, 1, $file, $line, $previous);
}

protected function getLocation(PugHandlerInterface $compiler, string $cachePath, string $file, Throwable $previous): ?SourceLocationInterface
{
if (file_exists($cachePath)) {
return unserialize(file_get_contents($cachePath));
}

$location = null;
$pug = $compiler->getPug();
$error = $pug->getDebugFormatter()->getDebugError(
$previous,
file_get_contents($file),
$file
);

if ($error instanceof LocatedException && ($location = $error->getLocation())) {
file_put_contents($cachePath, serialize($location));
}

return $location;
}
}
87 changes: 87 additions & 0 deletions src/PugHandlerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Bkwld\LaravelPug;

use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Compilers\CompilerInterface;
use InvalidArgumentException;
use Phug\CompilerInterface as PhugCompiler;
use Pug\Pug;

interface PugHandlerInterface extends CompilerInterface
{
/**
* Common pug compiler constructor.
*
* @param array $pugTarget
* @param Filesystem $files
* @param array $config
*/
public function construct(array $pugTarget, Filesystem $files, array $config, $defaultCachePath = null);

/**
* Lazy load Pug and return the instance.
*
* @return Pug
*/
public function getPug();

/**
* Returns cache path.
*
* @return string $cachePath
*/
public function getCachePath();

/**
* Get an option from pug engine or default value.
*
* @param string $name
* @param null $default
*
* @return mixed|null
*/
public function getOption($name, $default = null);

/**
* @param string $cachePath
*/
public function setCachePath($cachePath);

/**
* Determine if the view at the given path is expired.
*
* @param string $path
*
* @return bool
*/
public function isExpired($path): bool;

/**
* Return path and set it or get it from the instance.
*
* @param string $path
*
* @throws InvalidArgumentException
*
* @return string
*/
public function extractPath($path): ?string;

/**
* Returns the object the more appropriate to compile.
*/
public function getCompiler(): PhugCompiler;

/**
* Compile the view at the given path.
*
* @param string $path
* @param callable|null $callback
*
* @throws InvalidArgumentException
*
* @return void
*/
public function compileWith($path, callable $callback = null): void;
}
71 changes: 64 additions & 7 deletions tests/PugExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Illuminate\View\Engines\CompilerEngine;
use Illuminate\View\Engines\EngineResolver;
use PHPUnit\Framework\TestCase;
use Phug\Util\SourceLocation;
use Throwable;

include_once __DIR__.'/helpers.php';
Expand All @@ -26,14 +27,20 @@ class PugExceptionTest extends TestCase
{
/**
* @covers ::__construct
* @covers ::getLocation
*/
public function testPugException()
{
$cwd = getcwd();
$template = __DIR__.'/lines.pug';
$cacheDir = sys_get_temp_dir().'/pug'.mt_rand(0, 99999);
$fs = new Filesystem();
$fs->makeDirectory("$cacheDir/framework/views", 0777, true);
$viewCache = "$cacheDir/framework/views";

if (!$fs->isDirectory($viewCache)) {
$fs->makeDirectory($viewCache, 0777, true);
}

chdir($cacheDir);
$app = new LaravelTestApp();
$app['config'] = new Config();
Expand All @@ -52,6 +59,7 @@ public function testPugException()
$compiler->setCachePath($cacheDir);
$compiler->compile($template);
$phpPath = $compiler->getCompiledPath($template);
$originalContent = file_get_contents($phpPath);

$closure = function () use ($phpPath) {
$exception = null;
Expand All @@ -68,15 +76,64 @@ public function testPugException()
return $exception;
};

/** @var PugException $exception */
$exception = $closure->call($compilerEngine);
/** @var PugException $exception1 */
$exception1 = $closure->call($compilerEngine);

file_put_contents($phpPath, strtr(file_get_contents($phpPath), [
'12 / 0' => 'call_user_func(function () {throw new \\Exception("Other error");})',
]));

/** @var PugException $exception2 */
$exception2 = $closure->call($compilerEngine);

file_put_contents($phpPath, $originalContent);

/** @var PugException $exception3 */
$exception3 = null;

/** @var PugException $exception4 */
$exception4 = null;

for ($i = 0; $i < 2; $i++) {
if ($i === 1) {
$print = 'error-'.md5_file($exception3->getPrevious()->getFile()).'-'.
$exception3->getPrevious()->getLine().'-'.
md5($exception3->getPrevious()->getTraceAsString());
$cachePath = storage_path('framework/views/'.$print.'.txt');
/** @var SourceLocation $location */
$location = unserialize(file_get_contents($cachePath));
file_put_contents($cachePath, serialize(new SourceLocation(
$location->getPath(),
72,
$location->getOffset(),
$location->getOffsetLength()
)));
}

${'exception'.(3 + $i)} = $closure->call($compilerEngine);
}

$fs->deleteDirectory($cacheDir);
chdir($cwd);

self::assertInstanceOf(PugException::class, $exception);
self::assertInstanceOf(ViewException::class, $exception);
self::assertSame('Division by zero', $exception->getMessage());
self::assertSame(6, $exception->getLine());
self::assertInstanceOf(PugException::class, $exception1);
self::assertInstanceOf(ViewException::class, $exception1);
self::assertSame('Division by zero', $exception1->getMessage());
self::assertSame(6, $exception1->getLine());

self::assertInstanceOf(PugException::class, $exception2);
self::assertInstanceOf(ViewException::class, $exception2);
self::assertSame('Other error', $exception2->getMessage());
self::assertSame(6, $exception2->getLine());

self::assertInstanceOf(PugException::class, $exception3);
self::assertInstanceOf(ViewException::class, $exception3);
self::assertSame('Division by zero', $exception3->getMessage());
self::assertSame(6, $exception3->getLine());

self::assertInstanceOf(PugException::class, $exception4);
self::assertInstanceOf(ViewException::class, $exception4);
self::assertSame('Division by zero', $exception4->getMessage());
self::assertSame(72, $exception4->getLine());
}
}

0 comments on commit dfaf02a

Please sign in to comment.