From 7e8cdd7b4fba31d605cc1ad01158fec797a9344e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 19 Mar 2010 15:32:39 +0100 Subject: [PATCH] switched to PHPUnit for testing --- CHANGELOG | 1 + phpunit.xml | 24 +++++ test/Twig/Tests/AutoloaderTest.php | 24 +++++ test/Twig/Tests/Extension/SandboxTest.php | 138 +++++++++++++++++++++++++++++ test/Twig/Tests/TokenStreamTest.php | 90 +++++++++++++++++++ test/Twig/Tests/bootstrap.php | 13 +++ test/Twig/Tests/integrationTest.php | 110 +++++++++++++++++++++++ test/bin/coverage.php | 44 --------- test/bin/prove.php | 28 ------ test/unit/Twig/AutoloaderTest.php | 27 ------ test/unit/Twig/Extension/SandboxTest.php | 138 ----------------------------- test/unit/Twig/TokenStreamTest.php | 85 ------------------ test/unit/integrationTest.php | 104 ---------------------- 13 files changed, 400 insertions(+), 426 deletions(-) create mode 100644 phpunit.xml create mode 100644 test/Twig/Tests/AutoloaderTest.php create mode 100644 test/Twig/Tests/Extension/SandboxTest.php create mode 100644 test/Twig/Tests/TokenStreamTest.php create mode 100644 test/Twig/Tests/bootstrap.php create mode 100644 test/Twig/Tests/integrationTest.php delete mode 100644 test/bin/coverage.php delete mode 100644 test/bin/prove.php delete mode 100644 test/unit/Twig/AutoloaderTest.php delete mode 100644 test/unit/Twig/Extension/SandboxTest.php delete mode 100644 test/unit/Twig/TokenStreamTest.php delete mode 100644 test/unit/integrationTest.php diff --git a/CHANGELOG b/CHANGELOG index 0a7d862..c253df3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 0.9.6-DEV + * unit tests are now powered by PHPUnit * added support for gettext via the `i18n` extension * fixed twig_capitalize_string_filter() and fixed twig_length_filter() when used with UTF-8 values * added a more useful exception if an if tag is not closed properly diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..a726fab --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,24 @@ + + + + + + ./test/Twig/ + + + + + + ./lib/Twig/ + + + diff --git a/test/Twig/Tests/AutoloaderTest.php b/test/Twig/Tests/AutoloaderTest.php new file mode 100644 index 0000000..c268669 --- /dev/null +++ b/test/Twig/Tests/AutoloaderTest.php @@ -0,0 +1,24 @@ +assertFalse(class_exists('FooBarFoo'), '->autoload() does not try to load classes that does not begin with Twig'); + + $autoloader = new Twig_Autoloader(); + $this->assertTrue($autoloader->autoload('Twig_Parser'), '->autoload() returns true if it is able to load a class'); + $this->assertFalse($autoloader->autoload('Foo'), '->autoload() returns false if it is not able to load a class'); + } +} diff --git a/test/Twig/Tests/Extension/SandboxTest.php b/test/Twig/Tests/Extension/SandboxTest.php new file mode 100644 index 0000000..0060080 --- /dev/null +++ b/test/Twig/Tests/Extension/SandboxTest.php @@ -0,0 +1,138 @@ + 'Fabien', + 'obj' => new Object(), + ); + + self::$templates = array( + '1_basic1' => '{{ obj.foo }}', + '1_basic2' => '{{ name|upper }}', + '1_basic3' => '{% if name %}foo{% endif %}', + '1_basic4' => '{{ obj.bar }}', + '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); + } + + public function testSandboxGloballySet() + { + $twig = $this->getEnvironment(false, self::$templates); + $this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally'); + + $twig = $this->getEnvironment(true, self::$templates); + try + { + $twig->loadTemplate('1_basic1')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); + } + catch (Twig_Sandbox_SecurityError $e) + { + } + + $twig = $this->getEnvironment(true, self::$templates); + try + { + $twig->loadTemplate('1_basic2')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); + } + catch (Twig_Sandbox_SecurityError $e) + { + } + + $twig = $this->getEnvironment(true, self::$templates); + try + { + $twig->loadTemplate('1_basic3')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); + } + catch (Twig_Sandbox_SecurityError $e) + { + } + + $twig = $this->getEnvironment(true, self::$templates); + try + { + $twig->loadTemplate('1_basic4')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); + } + catch (Twig_Sandbox_SecurityError $e) + { + } + + $twig = $this->getEnvironment(true, self::$templates, array(), array(), array('Object' => 'foo')); + $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods'); + + $twig = $this->getEnvironment(true, self::$templates, array(), array('upper')); + $this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters'); + + $twig = $this->getEnvironment(true, self::$templates, array('if')); + $this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags'); + + $twig = $this->getEnvironment(true, self::$templates, array(), array(), array(), array('Object' => 'bar')); + $this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties'); + } + + public function testSandboxLocallySetForAnInclude() + { + self::$templates = array( + '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', + '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); + + $twig = $this->getEnvironment(false, self::$templates); + $this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); + + self::$templates = array( + '3_basic' => '{{ obj.foo }}{% include "3_included" sandboxed %}{{ obj.foo }}', + '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); + + $twig = $this->getEnvironment(false, self::$templates); + $twig = $this->getEnvironment(true, self::$templates); + try + { + $twig->loadTemplate('3_basic')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); + } + catch (Twig_Sandbox_SecurityError $e) + { + } + } + + protected function getEnvironment($sandboxed, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array()) + { + $loader = new Twig_Loader_Array($templates); + $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'debug' => true)); + $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties); + $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed)); + + return $twig; + } +} + +class Object +{ + public $bar = 'bar'; + + public function foo() + { + return 'foo'; + } +} diff --git a/test/Twig/Tests/TokenStreamTest.php b/test/Twig/Tests/TokenStreamTest.php new file mode 100644 index 0000000..981714a --- /dev/null +++ b/test/Twig/Tests/TokenStreamTest.php @@ -0,0 +1,90 @@ +isEOF()) + { + $token = $stream->next(); + + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() returns the next token in the stream'); + } + + public function testLook() + { + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $repr = array(); + while (!$stream->isEOF()) + { + $token = $stream->next(); + + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); + + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $repr = array(); + while (!$stream->isEOF()) + { + $token = $stream->next(); + + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); + } + + public function testRewind() + { + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $stream->rewind(); + $repr = array(); + while (!$stream->isEOF()) + { + $token = $stream->next(false); + + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->rewind() pushes all pushed tokens to the token array'); + } +} diff --git a/test/Twig/Tests/bootstrap.php b/test/Twig/Tests/bootstrap.php new file mode 100644 index 0000000..0b2d0a0 --- /dev/null +++ b/test/Twig/Tests/bootstrap.php @@ -0,0 +1,13 @@ +getRealpath()); + + if (!preg_match('/--TEST--\s*(.*?)\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) + { + throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace(self::$fixturesDir.'/', '', $file))); + } + + $message = $match[1]; + $templates = array(); + preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $match[2], $matches, PREG_SET_ORDER); + foreach ($matches as $match) + { + $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; + } + + $loader = new Twig_Loader_Array($templates); + $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'cache' => false)); + $twig->addExtension(new Twig_Extension_Escaper()); + $twig->addExtension(new TestExtension()); + + $template = $twig->loadTemplate('index.twig'); + + preg_match_all('/--DATA--(.*?)--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $matches, PREG_SET_ORDER); + foreach ($matches as $match) + { + $output = trim($template->render(eval($match[1].';')), "\n "); + $expected = trim($match[2], "\n "); + + $this->assertEquals($expected, $output, $message); + if ($output != $expected) + { + echo 'Compiled template that failed:'; + + foreach (array_keys($templates) as $name) + { + $source = $loader->getSource($name); + echo $twig->compile($twig->parse($twig->tokenize($source, $name))); + } + } + } + } + } +} + +class Foo +{ + public function bar($param1 = null, $param2 = null) + { + return 'bar'.($param1 ? '_'.$param1 : '').($param2 ? '-'.$param2 : ''); + } + + public function getFoo() + { + return 'foo'; + } + + public function getSelf() + { + return $this; + } +} + +class TestExtension extends Twig_Extension +{ + public function getFilters() + { + return array('nl2br' => new Twig_Filter_Method($this, 'nl2br')); + } + + public function nl2br($value, $sep = '
') + { + return str_replace("\n", $sep."\n", $value); + } + + public function getName() + { + return 'test'; + } +} diff --git a/test/bin/coverage.php b/test/bin/coverage.php deleted file mode 100644 index 015801a..0000000 --- a/test/bin/coverage.php +++ /dev/null @@ -1,44 +0,0 @@ - isset($argv) && in_array('--color', $argv), - 'base_dir' => realpath(dirname(__FILE__).'/..'), -)); - -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__).'/../unit'), RecursiveIteratorIterator::LEAVES_ONLY) as $file) -{ - if (preg_match('/Test\.php$/', $file)) - { - $suite->register($file->getRealPath()); - } -} - -$coverage = new LimeCoverage($suite, array( - 'base_dir' => realpath(dirname(__FILE__).'/../../lib'), - 'extension' => '.php', - 'verbose' => true, -)); - -$files = array(); -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__).'/../../lib'), RecursiveIteratorIterator::LEAVES_ONLY) as $file) -{ - if (preg_match('/\.php$/', $file)) - { - $files[] = $file->getRealPath(); - } -} -$coverage->setFiles($files); - -$coverage->run(); diff --git a/test/bin/prove.php b/test/bin/prove.php deleted file mode 100644 index be7bb1b..0000000 --- a/test/bin/prove.php +++ /dev/null @@ -1,28 +0,0 @@ - isset($argv) && in_array('--color', $argv), - 'base_dir' => realpath(dirname(__FILE__).'/..'), -)); - -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__FILE__).'/../unit'), RecursiveIteratorIterator::LEAVES_ONLY) as $file) -{ - if (preg_match('/Test\.php$/', $file)) - { - $suite->register($file->getRealPath()); - } -} - -exit($suite->run() ? 0 : 1); diff --git a/test/unit/Twig/AutoloaderTest.php b/test/unit/Twig/AutoloaderTest.php deleted file mode 100644 index d79c7c8..0000000 --- a/test/unit/Twig/AutoloaderTest.php +++ /dev/null @@ -1,27 +0,0 @@ -autoload() -$t->diag('->autoload()'); - -$t->ok(!class_exists('Foo'), '->autoload() does not try to load classes that does not begin with Twig'); - -$autoloader = new Twig_Autoloader(); -$t->is($autoloader->autoload('Twig_Parser'), true, '->autoload() returns true if it is able to load a class'); -$t->is($autoloader->autoload('Foo'), false, '->autoload() returns false if it is not able to load a class'); diff --git a/test/unit/Twig/Extension/SandboxTest.php b/test/unit/Twig/Extension/SandboxTest.php deleted file mode 100644 index 0cc6dd3..0000000 --- a/test/unit/Twig/Extension/SandboxTest.php +++ /dev/null @@ -1,138 +0,0 @@ - 'Fabien', - 'obj' => new Object(), -); -$templates = array( - '1_basic1' => '{{ obj.foo }}', - '1_basic2' => '{{ name|upper }}', - '1_basic3' => '{% if name %}foo{% endif %}', - '1_basic4' => '{{ obj.bar }}', - '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', -); - -$t = new LimeTest(11); - -$t->diag('Sandbox globally set'); -$twig = get_environment(false, $templates); -$t->is($twig->loadTemplate('1_basic')->render($params), 'FOO', 'Sandbox does nothing if it is disabled globally'); - -$twig = get_environment(true, $templates); -try -{ - $twig->loadTemplate('1_basic1')->render($params); - $t->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); -} -catch (Twig_Sandbox_SecurityError $e) -{ - $t->pass('Sandbox throws a SecurityError exception if an unallowed method is called'); -} - -$twig = get_environment(true, $templates); -try -{ - $twig->loadTemplate('1_basic2')->render($params); - $t->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); -} -catch (Twig_Sandbox_SecurityError $e) -{ - $t->pass('Sandbox throws a SecurityError exception if an unallowed filter is called'); -} - -$twig = get_environment(true, $templates); -try -{ - $twig->loadTemplate('1_basic3')->render($params); - $t->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); -} -catch (Twig_Sandbox_SecurityError $e) -{ - $t->pass('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); -} - -$twig = get_environment(true, $templates); -try -{ - $twig->loadTemplate('1_basic4')->render($params); - $t->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); -} -catch (Twig_Sandbox_SecurityError $e) -{ - $t->pass('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); -} - -$twig = get_environment(true, $templates, array(), array(), array('Object' => 'foo')); -$t->is($twig->loadTemplate('1_basic1')->render($params), 'foo', 'Sandbox allow some methods'); - -$twig = get_environment(true, $templates, array(), array('upper')); -$t->is($twig->loadTemplate('1_basic2')->render($params), 'FABIEN', 'Sandbox allow some filters'); - -$twig = get_environment(true, $templates, array('if')); -$t->is($twig->loadTemplate('1_basic3')->render($params), 'foo', 'Sandbox allow some tags'); - -$twig = get_environment(true, $templates, array(), array(), array(), array('Object' => 'bar')); -$t->is($twig->loadTemplate('1_basic4')->render($params), 'bar', 'Sandbox allow some properties'); - -$t->diag('Sandbox locally set for an include'); - -$templates = array( - '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', - '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', -); - -$twig = get_environment(false, $templates); -$t->is($twig->loadTemplate('2_basic')->render($params), 'fooFOOfoo', 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); - -$templates = array( - '3_basic' => '{{ obj.foo }}{% include "3_included" sandboxed %}{{ obj.foo }}', - '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', -); - -$twig = get_environment(false, $templates); -$twig = get_environment(true, $templates); -try -{ - $twig->loadTemplate('3_basic')->render($params); - $t->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); -} -catch (Twig_Sandbox_SecurityError $e) -{ - $t->pass('Sandbox throws a SecurityError exception when the included file is sandboxed'); -} - - -function get_environment($sandboxed, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array()) -{ - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'debug' => true)); - $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties); - $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed)); - - return $twig; -} diff --git a/test/unit/Twig/TokenStreamTest.php b/test/unit/Twig/TokenStreamTest.php deleted file mode 100644 index 7a39180..0000000 --- a/test/unit/Twig/TokenStreamTest.php +++ /dev/null @@ -1,85 +0,0 @@ -next() -$t->diag('->next()'); -$stream = new Twig_TokenStream($tokens, '', false); -$repr = array(); -while (!$stream->isEOF()) -{ - $token = $stream->next(); - - $repr[] = $token->getValue(); -} -$t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->next() returns the next token in the stream'); - -// ->look() -$t->diag('->look()'); -$stream = new Twig_TokenStream($tokens, '', false); -$t->is($stream->look()->getValue(), 2, '->look() returns the next token'); -$repr = array(); -while (!$stream->isEOF()) -{ - $token = $stream->next(); - - $repr[] = $token->getValue(); -} -$t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->look() pushes the token to the stack'); - -$stream = new Twig_TokenStream($tokens, '', false); -$t->is($stream->look()->getValue(), 2, '->look() returns the next token'); -$t->is($stream->look()->getValue(), 3, '->look() can be called several times to look more than one upcoming token'); -$t->is($stream->look()->getValue(), 4, '->look() can be called several times to look more than one upcoming token'); -$t->is($stream->look()->getValue(), 5, '->look() can be called several times to look more than one upcoming token'); -$repr = array(); -while (!$stream->isEOF()) -{ - $token = $stream->next(); - - $repr[] = $token->getValue(); -} -$t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->look() pushes the token to the stack'); - -// ->rewind() -$t->diag('->rewind()'); -$stream = new Twig_TokenStream($tokens, '', false); -$t->is($stream->look()->getValue(), 2, '->look() returns the next token'); -$t->is($stream->look()->getValue(), 3, '->look() can be called several times to look more than one upcoming token'); -$t->is($stream->look()->getValue(), 4, '->look() can be called several times to look more than one upcoming token'); -$t->is($stream->look()->getValue(), 5, '->look() can be called several times to look more than one upcoming token'); -$stream->rewind(); -$repr = array(); -while (!$stream->isEOF()) -{ - $token = $stream->next(false); - - $repr[] = $token->getValue(); -} -$t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->rewind() pushes all pushed tokens to the token array'); diff --git a/test/unit/integrationTest.php b/test/unit/integrationTest.php deleted file mode 100644 index f8baf68..0000000 --- a/test/unit/integrationTest.php +++ /dev/null @@ -1,104 +0,0 @@ - new Twig_Filter_Method($this, 'nl2br')); - } - - public function nl2br($value, $sep = '
') - { - return str_replace("\n", $sep."\n", $value); - } - - public function getName() - { - return 'test'; - } -} - -$t = new LimeTest(62); -$fixturesDir = realpath(dirname(__FILE__).'/../fixtures/'); - -foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) -{ - if (!preg_match('/\.test$/', $file)) - { - continue; - } - - $test = file_get_contents($file->getRealpath()); - - if (!preg_match('/--TEST--\s*(.*?)\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) - { - throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); - } - - $message = $match[1]; - $templates = array(); - preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $match[2], $matches, PREG_SET_ORDER); - foreach ($matches as $match) - { - $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; - } - - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'cache' => false)); - $twig->addExtension(new Twig_Extension_Escaper()); - $twig->addExtension(new TestExtension()); - - $template = $twig->loadTemplate('index.twig'); - - preg_match_all('/--DATA--(.*?)--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $matches, PREG_SET_ORDER); - foreach ($matches as $match) - { - $output = trim($template->render(eval($match[1].';')), "\n "); - $expected = trim($match[2], "\n "); - - $t->is($output, $expected, $message); - if ($output != $expected) - { - $t->comment('Compiled template that failed:'); - - foreach (array_keys($templates) as $name) - { - $source = $loader->getSource($name); - $t->comment($twig->compile($twig->parse($twig->tokenize($source, $name)))); - } - } - } -} -- 1.7.2.5