]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of Twig. | |
5 | * | |
6 | * (c) Fabien Potencier | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase | |
12 | { | |
13 | /** | |
14 | * @expectedException Twig_Error_Syntax | |
15 | */ | |
16 | public function testSetMacroThrowsExceptionOnReservedMethods() | |
17 | { | |
18 | $parser = $this->getParser(); | |
19 | $parser->setMacro('display', $this->getMock('Twig_Node_Macro', array(), array(), '', null)); | |
20 | } | |
21 | ||
22 | /** | |
23 | * @expectedException Twig_Error_Syntax | |
24 | * @expectedExceptionMessage Unknown tag name "foo". Did you mean "for" at line 1 | |
25 | */ | |
26 | public function testUnknownTag() | |
27 | { | |
28 | $stream = new Twig_TokenStream(array( | |
29 | new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), | |
30 | new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1), | |
31 | new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), | |
32 | new Twig_Token(Twig_Token::EOF_TYPE, '', 1), | |
33 | )); | |
34 | $parser = new Twig_Parser(new Twig_Environment()); | |
35 | $parser->parse($stream); | |
36 | } | |
37 | ||
38 | /** | |
39 | * @dataProvider getFilterBodyNodesData | |
40 | */ | |
41 | public function testFilterBodyNodes($input, $expected) | |
42 | { | |
43 | $parser = $this->getParser(); | |
44 | ||
45 | $this->assertEquals($expected, $parser->filterBodyNodes($input)); | |
46 | } | |
47 | ||
48 | public function getFilterBodyNodesData() | |
49 | { | |
50 | return array( | |
51 | array( | |
52 | new Twig_Node(array(new Twig_Node_Text(' ', 1))), | |
53 | new Twig_Node(array()), | |
54 | ), | |
55 | array( | |
56 | $input = new Twig_Node(array(new Twig_Node_Set(false, new Twig_Node(), new Twig_Node(), 1))), | |
57 | $input, | |
58 | ), | |
59 | array( | |
60 | $input = new Twig_Node(array(new Twig_Node_Set(true, new Twig_Node(), new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1))))), 1))), | |
61 | $input, | |
62 | ), | |
63 | ); | |
64 | } | |
65 | ||
66 | /** | |
67 | * @dataProvider getFilterBodyNodesDataThrowsException | |
68 | * @expectedException Twig_Error_Syntax | |
69 | */ | |
70 | public function testFilterBodyNodesThrowsException($input) | |
71 | { | |
72 | $parser = $this->getParser(); | |
73 | ||
74 | $parser->filterBodyNodes($input); | |
75 | } | |
76 | ||
77 | public function getFilterBodyNodesDataThrowsException() | |
78 | { | |
79 | return array( | |
80 | array(new Twig_Node_Text('foo', 1)), | |
81 | array(new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1)))))), | |
82 | ); | |
83 | } | |
84 | ||
85 | /** | |
86 | * @expectedException Twig_Error_Syntax | |
87 | * @expectedExceptionMessage A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed at line 1. | |
88 | */ | |
89 | public function testFilterBodyNodesWithBOM() | |
90 | { | |
91 | $parser = $this->getParser(); | |
92 | $parser->filterBodyNodes(new Twig_Node_Text(chr(0xEF).chr(0xBB).chr(0xBF), 1)); | |
93 | } | |
94 | ||
95 | public function testParseIsReentrant() | |
96 | { | |
97 | $twig = new Twig_Environment(null, array( | |
98 | 'autoescape' => false, | |
99 | 'optimizations' => 0, | |
100 | )); | |
101 | $twig->addTokenParser(new TestTokenParser()); | |
102 | ||
103 | $parser = new Twig_Parser($twig); | |
104 | ||
105 | $parser->parse(new Twig_TokenStream(array( | |
106 | new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), | |
107 | new Twig_Token(Twig_Token::NAME_TYPE, 'test', 1), | |
108 | new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), | |
109 | new Twig_Token(Twig_Token::VAR_START_TYPE, '', 1), | |
110 | new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1), | |
111 | new Twig_Token(Twig_Token::VAR_END_TYPE, '', 1), | |
112 | new Twig_Token(Twig_Token::EOF_TYPE, '', 1), | |
113 | ))); | |
114 | ||
115 | $this->assertEquals(null, $parser->getParent()); | |
116 | } | |
117 | ||
118 | // The getVarName() must not depend on the template loaders, | |
119 | // If this test does not throw any exception, that's good. | |
120 | // see https://github.com/symfony/symfony/issues/4218 | |
121 | public function testGetVarName() | |
122 | { | |
123 | $twig = new Twig_Environment(null, array( | |
124 | 'autoescape' => false, | |
125 | 'optimizations' => 0, | |
126 | )); | |
127 | ||
128 | $twig->parse($twig->tokenize(<<<EOF | |
129 | {% from _self import foo %} | |
130 | ||
131 | {% macro foo() %} | |
132 | {{ foo }} | |
133 | {% endmacro %} | |
134 | EOF | |
135 | )); | |
136 | } | |
137 | ||
138 | protected function getParser() | |
139 | { | |
140 | $parser = new TestParser(new Twig_Environment()); | |
141 | $parser->setParent(new Twig_Node()); | |
142 | $parser->stream = $this->getMockBuilder('Twig_TokenStream')->disableOriginalConstructor()->getMock(); | |
143 | ||
144 | return $parser; | |
145 | } | |
146 | } | |
147 | ||
148 | class TestParser extends Twig_Parser | |
149 | { | |
150 | public $stream; | |
151 | ||
152 | public function filterBodyNodes(Twig_NodeInterface $node) | |
153 | { | |
154 | return parent::filterBodyNodes($node); | |
155 | } | |
156 | } | |
157 | ||
158 | class TestTokenParser extends Twig_TokenParser | |
159 | { | |
160 | public function parse(Twig_Token $token) | |
161 | { | |
162 | // simulate the parsing of another template right in the middle of the parsing of the current template | |
163 | $this->parser->parse(new Twig_TokenStream(array( | |
164 | new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), | |
165 | new Twig_Token(Twig_Token::NAME_TYPE, 'extends', 1), | |
166 | new Twig_Token(Twig_Token::STRING_TYPE, 'base', 1), | |
167 | new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), | |
168 | new Twig_Token(Twig_Token::EOF_TYPE, '', 1), | |
169 | ))); | |
170 | ||
171 | $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); | |
172 | ||
173 | return new Twig_Node(array()); | |
174 | } | |
175 | ||
176 | public function getTag() | |
177 | { | |
178 | return 'test'; | |
179 | } | |
180 | } |