d2df756d |
<?php
|
2119e60c |
namespace Twig\Tests;
|
d2df756d |
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
|
90d579e4 |
|
34bdab4d |
use PHPUnit\Framework\TestCase;
|
90d579e4 |
use Twig\Environment;
|
5ebcecf2 |
use Twig\Error\SyntaxError;
|
90d579e4 |
use Twig\Lexer;
use Twig\Loader\LoaderInterface;
use Twig\Source;
use Twig\Token;
|
34bdab4d |
class LexerTest extends TestCase
|
d2df756d |
{
|
112a16bf |
public function testNameLabelForTag()
{
|
c8fe2538 |
$template = '{% § %}';
|
112a16bf |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
112a16bf |
|
90d579e4 |
$stream->expect(Token::BLOCK_START_TYPE);
$this->assertSame('§', $stream->expect(Token::NAME_TYPE)->getValue());
|
112a16bf |
}
public function testNameLabelForFunction()
{
|
c8fe2538 |
$template = '{{ §() }}';
|
112a16bf |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
112a16bf |
|
90d579e4 |
$stream->expect(Token::VAR_START_TYPE);
$this->assertSame('§', $stream->expect(Token::NAME_TYPE)->getValue());
|
112a16bf |
}
|
d2df756d |
public function testBracketsNesting()
{
$template = '{{ {"a":{"b":"c"}} }}';
|
90d579e4 |
$this->assertEquals(2, $this->countToken($template, Token::PUNCTUATION_TYPE, '{'));
$this->assertEquals(2, $this->countToken($template, Token::PUNCTUATION_TYPE, '}'));
|
d2df756d |
}
protected function countToken($template, $type, $value = null)
{
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
d2df756d |
$count = 0;
while (!$stream->isEOF()) {
$token = $stream->next();
if ($type === $token->getType()) {
if (null === $value || $value === $token->getValue()) {
++$count;
}
}
}
return $count;
}
|
5ec19550 |
public function testLineDirective()
{
$template = "foo\n"
|
00ecabf1 |
."bar\n"
."{% line 10 %}\n"
."{{\n"
."baz\n"
."}}\n";
|
5ec19550 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
5ec19550 |
// foo\nbar\n
|
90d579e4 |
$this->assertSame(1, $stream->expect(Token::TEXT_TYPE)->getLine());
|
5ec19550 |
// \n (after {% line %})
|
90d579e4 |
$this->assertSame(10, $stream->expect(Token::TEXT_TYPE)->getLine());
|
5ec19550 |
// {{
|
90d579e4 |
$this->assertSame(11, $stream->expect(Token::VAR_START_TYPE)->getLine());
|
5ec19550 |
// baz
|
90d579e4 |
$this->assertSame(12, $stream->expect(Token::NAME_TYPE)->getLine());
|
5ec19550 |
}
public function testLineDirectiveInline()
{
$template = "foo\n"
|
00ecabf1 |
."bar{% line 10 %}{{\n"
."baz\n"
."}}\n";
|
5ec19550 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
5ec19550 |
// foo\nbar
|
90d579e4 |
$this->assertSame(1, $stream->expect(Token::TEXT_TYPE)->getLine());
|
5ec19550 |
// {{
|
90d579e4 |
$this->assertSame(10, $stream->expect(Token::VAR_START_TYPE)->getLine());
|
5ec19550 |
// baz
|
90d579e4 |
$this->assertSame(11, $stream->expect(Token::NAME_TYPE)->getLine());
|
5ec19550 |
}
|
6783d581 |
public function testLongComments()
{
$template = '{# '.str_repeat('*', 100000).' #}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
6783d581 |
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
6783d581 |
}
|
8c4291ac |
public function testLongVerbatim()
|
6783d581 |
{
|
39885c91 |
$template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}';
|
6783d581 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
6783d581 |
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
6783d581 |
}
|
7da9f2f9 |
public function testLongVar()
|
6783d581 |
{
|
7da9f2f9 |
$template = '{{ '.str_repeat('x', 100000).' }}';
|
6783d581 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
6783d581 |
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
6783d581 |
}
|
7da9f2f9 |
public function testLongBlock()
|
6783d581 |
{
|
7da9f2f9 |
$template = '{% '.str_repeat('x', 100000).' %}';
|
6783d581 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
6783d581 |
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
6783d581 |
}
|
a6f9f9b5 |
public function testBigNumbers()
{
$template = '{{ 922337203685477580700 }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
|
2030482e |
$stream->next();
|
a6f9f9b5 |
$node = $stream->next();
|
b0c41d42 |
$this->assertEquals('922337203685477580700', $node->getValue());
|
a6f9f9b5 |
}
|
1036f90e |
|
8b569e49 |
public function testStringWithEscapedDelimiter()
{
|
5c55243d |
$tests = [
|
8b569e49 |
"{{ 'foo \' bar' }}" => 'foo \' bar',
|
b0c41d42 |
'{{ "foo \" bar" }}' => 'foo " bar',
|
5c55243d |
];
|
a089f1e8 |
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
8b569e49 |
foreach ($tests as $template => $expected) {
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, $expected);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
8b569e49 |
}
}
public function testStringWithInterpolation()
|
c8bba24d |
{
$template = 'foo {{ "bar #{ baz + 1 }" }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::TEXT_TYPE, 'foo ');
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'bar ');
$stream->expect(Token::INTERPOLATION_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'baz');
$stream->expect(Token::OPERATOR_TYPE, '+');
$stream->expect(Token::NUMBER_TYPE, '1');
$stream->expect(Token::INTERPOLATION_END_TYPE);
$stream->expect(Token::VAR_END_TYPE);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
c8bba24d |
}
public function testStringWithEscapedInterpolation()
{
$template = '{{ "bar \#{baz+1}" }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'bar #{baz+1}');
$stream->expect(Token::VAR_END_TYPE);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
c8bba24d |
}
public function testStringWithHash()
{
$template = '{{ "bar # baz" }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'bar # baz');
$stream->expect(Token::VAR_END_TYPE);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
c8bba24d |
}
public function testStringWithUnterminatedInterpolation()
{
|
5ebcecf2 |
$this->expectException(SyntaxError::class);
|
b776e41f |
$this->expectExceptionMessage('Unclosed """');
|
c8bba24d |
$template = '{{ "bar #{x" }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
c8bba24d |
}
public function testStringWithNestedInterpolations()
{
$template = '{{ "bar #{ "foo#{bar}" }" }}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'bar ');
$stream->expect(Token::INTERPOLATION_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'foo');
$stream->expect(Token::INTERPOLATION_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'bar');
$stream->expect(Token::INTERPOLATION_END_TYPE);
$stream->expect(Token::INTERPOLATION_END_TYPE);
$stream->expect(Token::VAR_END_TYPE);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
c8bba24d |
}
public function testStringWithNestedInterpolationsInBlock()
{
$template = '{% foo "bar #{ "foo#{bar}" }" %}';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::BLOCK_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'foo');
$stream->expect(Token::STRING_TYPE, 'bar ');
$stream->expect(Token::INTERPOLATION_START_TYPE);
$stream->expect(Token::STRING_TYPE, 'foo');
$stream->expect(Token::INTERPOLATION_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'bar');
$stream->expect(Token::INTERPOLATION_END_TYPE);
$stream->expect(Token::INTERPOLATION_END_TYPE);
$stream->expect(Token::BLOCK_END_TYPE);
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
c8bba24d |
}
|
ae250f6b |
public function testOperatorEndingWithALetterAtTheEndOfALine()
{
$template = "{{ 1 and\n0}}";
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::NUMBER_TYPE, 1);
$stream->expect(Token::OPERATOR_TYPE, 'and');
|
7259e52f |
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
|
ae250f6b |
}
|
ac86c636 |
public function testUnterminatedVariable()
{
|
5ebcecf2 |
$this->expectException(SyntaxError::class);
|
b776e41f |
$this->expectExceptionMessage('Unclosed "variable" in "index" at line 3');
|
ac86c636 |
$template = '
{{
bar
';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
ac86c636 |
}
public function testUnterminatedBlock()
{
|
5ebcecf2 |
$this->expectException(SyntaxError::class);
|
b776e41f |
$this->expectExceptionMessage('Unclosed "block" in "index" at line 3');
|
ac86c636 |
$template = '
{%
bar
';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)));
|
90d579e4 |
$lexer->tokenize(new Source($template, 'index'));
|
ac86c636 |
}
|
7b5851fe |
public function testOverridingSyntax()
{
$template = '[# comment #]{# variable #}/# if true #/true/# endif #/';
|
656c295e |
$lexer = new Lexer(new Environment($this->createMock(LoaderInterface::class)), [
|
7b5851fe |
'tag_comment' => ['[#', '#]'],
'tag_block' => ['/#', '#/'],
'tag_variable' => ['{#', '#}'],
]);
$stream = $lexer->tokenize(new Source($template, 'index'));
$stream->expect(Token::VAR_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'variable');
$stream->expect(Token::VAR_END_TYPE);
$stream->expect(Token::BLOCK_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'if');
$stream->expect(Token::NAME_TYPE, 'true');
$stream->expect(Token::BLOCK_END_TYPE);
$stream->expect(Token::TEXT_TYPE, 'true');
$stream->expect(Token::BLOCK_START_TYPE);
$stream->expect(Token::NAME_TYPE, 'endif');
$stream->expect(Token::BLOCK_END_TYPE);
// add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
// can be executed without throwing any exceptions
$this->addToAssertionCount(1);
}
|
d2df756d |
}
|