root/livinglogic.java.ul4/src/test/java/tests/UL4Test.java @ 920:6090c7799c51

Revision 920:6090c7799c51, 144.3 KB (checked in by Walter Doerwald <walter@…>, 5 years ago)

Implement if expressions.

Line 
1package tests;
2
3import static com.livinglogic.ul4on.Utils.dumps;
4import static com.livinglogic.utils.MapUtils.makeMap;
5import static com.livinglogic.utils.SetUtils.makeSet;
6import static java.util.Arrays.asList;
7import static org.junit.Assert.assertEquals;
8import static org.junit.Assert.assertTrue;
9import static org.junit.Assert.fail;
10
11import java.io.IOException;
12import java.io.Reader;
13import java.math.BigDecimal;
14import java.math.BigInteger;
15import java.util.Date;
16import java.util.Set;
17
18import org.antlr.runtime.RecognitionException;
19import org.junit.Test;
20import org.junit.runner.RunWith;
21
22import com.livinglogic.ul4.ArgumentCountMismatchException;
23import com.livinglogic.ul4.ArgumentTypeMismatchException;
24import com.livinglogic.ul4.BlockException;
25import com.livinglogic.ul4.Color;
26import com.livinglogic.ul4.FunctionDate;
27import com.livinglogic.ul4.InterpretedTemplate;
28import com.livinglogic.ul4.MissingArgumentException;
29import com.livinglogic.ul4.MonthDelta;
30import com.livinglogic.ul4.SyntaxException;
31import com.livinglogic.ul4.TimeDelta;
32import com.livinglogic.ul4.TooManyArgumentsException;
33import com.livinglogic.ul4.UL4GetAttributes;
34import com.livinglogic.ul4.UndefinedKey;
35
36
37@RunWith(CauseTestRunner.class)
38public class UL4Test
39{
40    private static class Point implements UL4GetAttributes
41    {
42        int x;
43        int y;
44
45        Point(int x, int y)
46        {
47            this.x = x;
48            this.y = y;
49        }
50
51        public Set<String> getAttributeNamesUL4()
52        {
53            return makeSet("x", "y");
54        }
55
56        public Object getItemStringUL4(String key)
57        {
58            if ("x".equals(key))
59                return x;
60            else if ("y".equals(key))
61                return y;
62            return new UndefinedKey(key);
63        }
64    }
65
66    private static InterpretedTemplate getTemplate(String source, String name, boolean keepWhitespace)
67    {
68        try
69        {
70            InterpretedTemplate template = new InterpretedTemplate(source, name, keepWhitespace);
71            // System.out.println(template);
72            return template;
73        }
74        catch (RecognitionException ex)
75        {
76            throw new RuntimeException(ex);
77        }
78    }
79
80    private static InterpretedTemplate getTemplate(String source, boolean keepWhitespace)
81    {
82        return getTemplate(source, null, keepWhitespace);
83    }
84
85    private static InterpretedTemplate getTemplate(String source, String name)
86    {
87        return getTemplate(source, name, false);
88    }
89
90    private static InterpretedTemplate getTemplate(String source)
91    {
92        return getTemplate(source, null, false);
93    }
94
95    private static String getTemplateOutput(String source, Object... args)
96    {
97        InterpretedTemplate template = getTemplate(source);
98        return template.renders(makeMap(args));
99    }
100
101    private static void checkTemplateOutput(String expected, String source, Object... args)
102    {
103        // Render the template once by directly compiling and rendering it
104        InterpretedTemplate template1 = getTemplate(source);
105        String output1 = template1.renders(makeMap(args));
106        assertEquals(expected, output1);
107
108        // Recreate the template from the dump of the compiled template
109        InterpretedTemplate template2 = InterpretedTemplate.loads(template1.dumps());
110
111        // Check that the templates format the same
112        assertEquals(template1.toString(), template2.toString());
113
114        // Check that they have the same output
115        String output2 = template2.renders(makeMap(args));
116        assertEquals(expected, output2);
117    }
118
119    private static void checkTemplateOutput2(String expected1, String expected2, String source, Object... args)
120    {
121        // Render the template once by directly compiling and rendering it
122        InterpretedTemplate template1 = getTemplate(source);
123        String output1 = template1.renders(makeMap(args));
124        if (!output1.equals(expected1) && !output1.equals(expected2))
125            fail("expected <" + expected1 + "> or <" + expected2 + ">, got <" + output1 + ">");
126
127        // Recreate the template from the dump of the compiled template
128        InterpretedTemplate template2 = InterpretedTemplate.loads(template1.dumps());
129
130        // Check that the templates format the same
131        assertEquals(template1.toString(), template2.toString());
132
133        // Check that theyhave the same output
134        String output2 = template2.renders(makeMap(args));
135        if (!output1.equals(expected1) && !output1.equals(expected2))
136            fail("expected <" + expected1 + "> or <" + expected2 + ">, got <" + output2 + ">");
137    }
138
139    private static Object getTemplateResult(String source, Object... args)
140    {
141        InterpretedTemplate template = getTemplate(source);
142        return template.call(makeMap(args));
143    }
144
145    private static void checkTemplateResult(Object expected, String source, Object... args)
146    {
147        // Execute the template once by directly compiling and calling it
148        InterpretedTemplate template1 = getTemplate(source);
149        Object output1 = template1.call(makeMap(args));
150        assertEquals(expected, output1);
151
152        // Recreate the template from the dump of the compiled template
153        InterpretedTemplate template2 = InterpretedTemplate.loads(template1.dumps());
154
155        // Check that the templates format the same
156        assertEquals(template1.toString(), template2.toString());
157
158        // Check that they have the same output
159        Object output2 = template2.call(makeMap(args));
160        assertEquals(expected, output2);
161    }
162
163    @Test
164    public void tag_text()
165    {
166        checkTemplateOutput("gurk", "gurk");
167        checkTemplateOutput("g\tu rk", "g\t\n\t u \n  r\n\t\tk");
168    }
169
170    @Test
171    public void whitespace()
172    {
173        checkTemplateOutput("40", "<?print\na\n+\nb\n?>", "a", 17, "b", 23);
174    }
175
176    @Test
177    public void type_none()
178    {
179        checkTemplateOutput("no", "<?if None?>yes<?else?>no<?end if?>");
180        checkTemplateOutput("", "<?print None?>");
181    }
182
183    @Test
184    public void type_bool()
185    {
186        checkTemplateOutput("False", "<?print False?>");
187        checkTemplateOutput("no", "<?if False?>yes<?else?>no<?end if?>");
188        checkTemplateOutput("True", "<?print True?>");
189        checkTemplateOutput("yes", "<?if True?>yes<?else?>no<?end if?>");
190    }
191
192    @Test
193    public void type_int()
194    {
195        checkTemplateOutput("0", "<?print 0?>");
196        checkTemplateOutput("42", "<?print 42?>");
197        checkTemplateOutput("-42", "<?print -42?>");
198        checkTemplateOutput("134217727", "<?print 134217727?>");
199        checkTemplateOutput("134217728", "<?print 134217728?>");
200        checkTemplateOutput("-134217728", "<?print -134217728?>");
201        checkTemplateOutput("-134217729", "<?print -134217729?>");
202        checkTemplateOutput("576460752303423487", "<?print 576460752303423487?>");
203        checkTemplateOutput("576460752303423488", "<?print 576460752303423488?>");
204        checkTemplateOutput("-576460752303423488", "<?print -576460752303423488?>");
205        checkTemplateOutput("-576460752303423489", "<?print -576460752303423489?>");
206        checkTemplateOutput("9999999999", "<?print 9999999999?>");
207        checkTemplateOutput("-9999999999", "<?print -9999999999?>");
208        checkTemplateOutput("99999999999999999999", "<?print 99999999999999999999?>");
209        checkTemplateOutput("-99999999999999999999", "<?print -99999999999999999999?>");
210        checkTemplateOutput("255", "<?print 0xff?>");
211        checkTemplateOutput("255", "<?print 0Xff?>");
212        checkTemplateOutput("-255", "<?print -0xff?>");
213        checkTemplateOutput("-255", "<?print -0Xff?>");
214        checkTemplateOutput("63", "<?print 0o77?>");
215        checkTemplateOutput("63", "<?print 0O77?>");
216        checkTemplateOutput("-63", "<?print -0o77?>");
217        checkTemplateOutput("-63", "<?print -0O77?>");
218        checkTemplateOutput("7", "<?print 0b111?>");
219        checkTemplateOutput("7", "<?print 0B111?>");
220        checkTemplateOutput("-7", "<?print -0b111?>");
221        checkTemplateOutput("-7", "<?print -0B111?>");
222        checkTemplateOutput("no", "<?if 0?>yes<?else?>no<?end if?>");
223        checkTemplateOutput("yes", "<?if 1?>yes<?else?>no<?end if?>");
224        checkTemplateOutput("yes", "<?if -1?>yes<?else?>no<?end if?>");
225    }
226
227    @Test
228    public void type_float()
229    {
230        checkTemplateOutput("0.0", "<?print 0.?>");
231        checkTemplateOutput("42.0", "<?print 42.?>");
232        checkTemplateOutput("-42.0", "<?print -42.?>");
233        checkTemplateOutput("-42.5", "<?print -42.5?>");
234        checkTemplateOutput("1e42", "<?print 1E42?>");
235        checkTemplateOutput("1e42", "<?print 1e42?>");
236        checkTemplateOutput("-1e42", "<?print -1E42?>");
237        checkTemplateOutput("-1e42", "<?print -1e42?>");
238        checkTemplateOutput("no", "<?if 0.?>yes<?else?>no<?end if?>");
239        checkTemplateOutput("yes", "<?if 1.?>yes<?else?>no<?end if?>");
240        checkTemplateOutput("yes", "<?if -1.?>yes<?else?>no<?end if?>");
241    }
242
243    @Test
244    public void type_string()
245    {
246        checkTemplateOutput("foo", "<?print \"foo\"?>");
247        checkTemplateOutput("\n", "<?print \"\\n\"?>");
248        checkTemplateOutput("\r", "<?print \"\\r\"?>");
249        checkTemplateOutput("\t", "<?print \"\\t\"?>");
250        checkTemplateOutput("\f", "<?print \"\\f\"?>");
251        checkTemplateOutput("\u0008", "<?print \"\\b\"?>");
252        checkTemplateOutput("\u0007", "<?print \"\\a\"?>");
253        checkTemplateOutput("\u0000", "<?print \"\\x00\"?>");
254        checkTemplateOutput("\"", "<?print \"\\\"\"?>");
255        checkTemplateOutput("'", "<?print \"\\'\"?>");
256        checkTemplateOutput("\u20ac", "<?print \"\u20ac\"?>");
257        checkTemplateOutput("\u00ff", "<?print \"\\xff\"?>");
258        checkTemplateOutput("\u20ac", "<?print \"\\u20ac\"?>");
259        checkTemplateOutput("gu\trk", "<?print 'gu\trk'?>");
260        checkTemplateOutput("gu\n\r\t\\rk", "<?print 'gu\\n\\r\\t\\\\rk'?>");
261        checkTemplateOutput("gu\r\nrk", "<?print '''gu\r\nrk'''?>");
262        checkTemplateOutput("gu\r\nrk", "<?print \"\"\"gu\r\nrk\"\"\"?>");
263        checkTemplateOutput("gu\r\nrk", "<?print str('''gu\r\nrk''')?>");
264        checkTemplateOutput("gu\r\nrk", "<?print str('''gu\\r\\nrk''')?>");
265        checkTemplateOutput("no", "<?if ''?>yes<?else?>no<?end if?>");
266        checkTemplateOutput("yes", "<?if 'foo'?>yes<?else?>no<?end if?>");
267    }
268
269    @Test
270    public void type_date()
271    {
272        checkTemplateOutput("2000-02-29", "<?print @(2000-02-29).isoformat()?>");
273        checkTemplateOutput("2000-02-29", "<?print @(2000-02-29T).isoformat()?>");
274        checkTemplateOutput("2000-02-29T12:34:00", "<?print @(2000-02-29T12:34).isoformat()?>");
275        checkTemplateOutput("2000-02-29T12:34:56", "<?print @(2000-02-29T12:34:56).isoformat()?>");
276        checkTemplateOutput("2000-02-29T12:34:56.987000", "<?print @(2000-02-29T12:34:56.987000).isoformat()?>");
277        checkTemplateOutput("yes", "<?if @(2000-02-29T12:34:56.987654)?>yes<?else?>no<?end if?>");
278    }
279
280    @Test
281    public void type_color()
282    {
283        checkTemplateOutput("255,255,255,255", "<?code c = #fff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>");
284        checkTemplateOutput("255,255,255,255", "<?code c = #ffffff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>");
285        checkTemplateOutput("18,52,86,255", "<?code c = #123456?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>");
286        checkTemplateOutput("17,34,51,68", "<?code c = #1234?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>");
287        checkTemplateOutput("18,52,86,120", "<?code c = #12345678?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>");
288        checkTemplateOutput("yes", "<?if #fff?>yes<?else?>no<?end if?>");
289    }
290
291    @Test
292    public void type_list()
293    {
294        checkTemplateOutput("", "<?for item in []?><?print item?>;<?end for?>");
295        checkTemplateOutput("1;", "<?for item in [1]?><?print item?>;<?end for?>");
296        checkTemplateOutput("1;", "<?for item in [1,]?><?print item?>;<?end for?>");
297        checkTemplateOutput("1;2;", "<?for item in [1, 2]?><?print item?>;<?end for?>");
298        checkTemplateOutput("1;2;", "<?for item in [1, 2,]?><?print item?>;<?end for?>");
299        checkTemplateOutput("no", "<?if []?>yes<?else?>no<?end if?>");
300        checkTemplateOutput("yes", "<?if [1]?>yes<?else?>no<?end if?>");
301    }
302
303    @Test
304    public void type_listcomprehension()
305    {
306        checkTemplateOutput("[2, 6]", "<?code d = [2*i for i in range(4) if i%2]?><?print d?>");
307        checkTemplateOutput("[0, 2, 4, 6]", "<?code d = [2*i for i in range(4)]?><?print d?>");
308    }
309
310    @Test
311    public void type_dict()
312    {
313        checkTemplateOutput("", "<?for (key, value) in {}.items()?><?print key?>:<?print value?>!<?end for?>");
314        checkTemplateOutput("1:2!", "<?for (key, value) in {1:2}.items()?><?print key?>:<?print value?>!<?end for?>");
315        checkTemplateOutput("1:2!", "<?for (key, value) in {1:2,}.items()?><?print key?>:<?print value?>!<?end for?>");
316        // With duplicate keys, later ones simply overwrite earlier ones
317        checkTemplateOutput("1:3!", "<?for (key, value) in {1:2, 1: 3}.items()?><?print key?>:<?print value?>!<?end for?>");
318        // Test **
319        checkTemplateOutput("1:2!", "<?for (key, value) in {**{1:2}}.items()?><?print key?>:<?print value?>!<?end for?>");
320        checkTemplateOutput("1:4!", "<?for (key, value) in {1:1, **{1:2}, 1:3, **{1:4}}.items()?><?print key?>:<?print value?>!<?end for?>");
321        checkTemplateOutput("no", "<?if {}?>yes<?else?>no<?end if?>");
322        checkTemplateOutput("yes", "<?if {1:2}?>yes<?else?>no<?end if?>");
323    }
324
325    @Test
326    public void type_dictcomprehension()
327    {
328        checkTemplateOutput("", "<?code d = {i:2*i for i in range(10) if i%2}?><?if 2 in d?><?print d[2]?><?end if?>");
329        checkTemplateOutput("6", "<?code d = {i:2*i for i in range(10) if i%2}?><?if 3 in d?><?print d[3]?><?end if?>");
330        checkTemplateOutput("6", "<?code d = {i:2*i for i in range(10)}?><?print d[3]?>");
331    }
332
333    @Test
334    public void generatorexpression()
335    {
336        checkTemplateOutput("2, 6", "<?code ge = (str(2*i) for i in range(4) if i%2)?><?print ', '.join(ge)?>");
337        checkTemplateOutput("2, 6", "<?print ', '.join(str(2*i) for i in range(4) if i%2)?>");
338        checkTemplateOutput("0, 2, 4, 6", "<?print ', '.join(str(2*i) for i in range(4))?>");
339        checkTemplateOutput("0, 2, 4, 6", "<?print ', '.join((str(2*i) for i in range(4)))?>");
340    }
341
342    @Test
343    public void tag_storevar()
344    {
345        // checkTemplateOutput("42", "<?code x = 42?><?print x?>");
346        // checkTemplateOutput("xyzzy", "<?code x = 'xyzzy'?><?print x?>");
347        checkTemplateOutput("42", "<?code (x,) = [42]?><?print x?>");
348        // checkTemplateOutput("17,23", "<?code (x,y) = [17, 23]?><?print x?>,<?print y?>");
349        // checkTemplateOutput("17,23,37,42,105", "<?code ((v, w), (x,), (y,), z) = [[17, 23], [37], [42], 105]?><?print v?>,<?print w?>,<?print x?>,<?print y?>,<?print z?>");
350    }
351
352    @Test
353    public void tag_addvar()
354    {
355        String source = "<?code x += y?><?print x?>";
356        checkTemplateOutput("40", source, "x", 17, "y", 23);
357        checkTemplateOutput("40.0", source, "x", 17, "y", 23.0);
358        checkTemplateOutput("40.0", source, "x", 17.0, "y", 23);
359        checkTemplateOutput("40.0", source, "x", 17.0, "y", 23.0);
360        checkTemplateOutput("17", source, "x", 17, "y", false);
361        checkTemplateOutput("18", source, "x", 17, "y", true);
362        checkTemplateOutput("23", source, "x", false, "y", 23);
363        checkTemplateOutput("24", source, "x", true, "y", 23);
364        checkTemplateOutput("[1, 2, 3, 4]", source, "x", asList(1, 2), "y", asList(3, 4));
365    }
366
367    @Test
368    public void tag_subvar()
369    {
370        String source = "<?code x -= y?><?print x?>";
371        checkTemplateOutput("-6", source, "x", 17, "y", 23);
372        checkTemplateOutput("-6.0", source, "x", 17, "y", 23.0);
373        checkTemplateOutput("-6.0", source, "x", 17.0, "y", 23);
374        checkTemplateOutput("-6.0", source, "x", 17.0, "y", 23.0);
375        checkTemplateOutput("17", source, "x", 17, "y", false);
376        checkTemplateOutput("16", source, "x", 17, "y", true);
377        checkTemplateOutput("-23", source, "x", false, "y", 23);
378        checkTemplateOutput("-22", source, "x", true, "y", 23);
379    }
380
381    @Test
382    public void tag_mulvar()
383    {
384        String source = "<?code x *= y?><?print x?>";
385        checkTemplateOutput("391", source, "x", 17, "y", 23);
386        checkTemplateOutput("391.0", source, "x", 17, "y", 23.0);
387        checkTemplateOutput("391.0", source, "x", 17.0, "y", 23);
388        checkTemplateOutput("391.0", source, "x", 17.0, "y", 23.0);
389        checkTemplateOutput("0", source, "x", 17, "y", false);
390        checkTemplateOutput("17", source, "x", 17, "y", true);
391        checkTemplateOutput("0", source, "x", false, "y", 23);
392        checkTemplateOutput("23", source, "x", true, "y", 23);
393        checkTemplateOutput("xyzzyxyzzyxyzzy", source, "x", 3, "y", "xyzzy");
394        checkTemplateOutput("", source, "x", false, "y", "xyzzy");
395        checkTemplateOutput("xyzzy", source, "x", true, "y", "xyzzy");
396        checkTemplateOutput("xyzzyxyzzyxyzzy", source, "x", "xyzzy", "y", 3);
397        checkTemplateOutput("", source, "x", "xyzzy", "y", false);
398        checkTemplateOutput("xyzzy", source, "x", "xyzzy", "y", true);
399    }
400
401    @Test
402    public void tag_floordivvar()
403    {
404        String source = "<?code x //= y?><?print x?>";
405        checkTemplateOutput("2", source, "x", 5, "y", 2);
406        checkTemplateOutput("-3", source, "x", 5, "y", -2);
407        checkTemplateOutput("-3", source, "x", -5, "y", 2);
408        checkTemplateOutput("2", source, "x", -5, "y", -2);
409        checkTemplateOutput("2.0", source, "x", 5., "y", 2.);
410        checkTemplateOutput("-3.0", source, "x", 5., "y", -2.);
411        checkTemplateOutput("-3.0", source, "x", -5., "y", 2.);
412        checkTemplateOutput("2.0", source, "x", -5., "y", -2.);
413        checkTemplateOutput("1", source, "x", true, "y", 1);
414        checkTemplateOutput("0", source, "x", false, "y", 1);
415    }
416
417    @Test
418    public void tag_truedivvar()
419    {
420        String source = "<?code x /= y?><?print x?>";
421        checkTemplateOutput("2.5", source, "x", 5, "y", 2);
422        checkTemplateOutput("-2.5", source, "x", 5, "y", -2);
423        checkTemplateOutput("-2.5", source, "x", -5, "y", 2);
424        checkTemplateOutput("2.5", source, "x", -5, "y", -2);
425        checkTemplateOutput("2.5", source, "x", 5., "y", 2.);
426        checkTemplateOutput("-2.5", source, "x", 5., "y", -2.);
427        checkTemplateOutput("-2.5", source, "x", -5., "y", 2.);
428        checkTemplateOutput("2.5", source, "x", -5., "y", -2.);
429        checkTemplateOutput("1.0", source, "x", true, "y", 1);
430        checkTemplateOutput("0.0", source, "x", false, "y", 1);
431    }
432
433
434    @Test
435    public void tag_modvar()
436    {
437        String source = "<?code x %= y?><?print x?>";
438        checkTemplateOutput("4", source, "x", 1729, "y", 23);
439        checkTemplateOutput("19", source, "x", -1729, "y", 23);
440        checkTemplateOutput("19", source, "x", -1729, "y", 23);
441        checkTemplateOutput("-4", source, "x", -1729, "y", -23);
442        checkTemplateOutput("1.5", source, "x", 6.5, "y", 2.5);
443        checkTemplateOutput("1.0", source, "x", -6.5, "y", 2.5);
444        checkTemplateOutput("-1.0", source, "x", 6.5, "y", -2.5);
445        checkTemplateOutput("-1.5", source, "x", -6.5, "y", -2.5);
446        checkTemplateOutput("1", source, "x", true, "y", 23);
447        checkTemplateOutput("0", source, "x", false, "y", 23);
448    }
449
450    @Test
451    public void tag_for_string()
452    {
453        String source = "<?for c in data?>(<?print c?>)<?end for?>";
454        checkTemplateOutput("", source, "data", "");
455        checkTemplateOutput("(g)(u)(r)(k)", source, "data", "gurk");
456    }
457
458    @Test
459    public void tag_for_list()
460    {
461        String source = "<?for c in data?>(<?print c?>)<?end for?>";
462        checkTemplateOutput("", source, "data", asList());
463        checkTemplateOutput("(g)(u)(r)(k)", source, "data", asList("g", "u", "r", "k"));
464    }
465
466    @Test
467    public void tag_for_dict()
468    {
469        String source = "<?for c in sorted(data)?>(<?print c?>)<?end for?>";
470        checkTemplateOutput("", source, "data", makeMap());
471        checkTemplateOutput("(a)(b)(c)", source, "data", makeMap("a", 1, "b", 2, "c", 3));
472    }
473
474    @Test
475    public void tag_for_nested_loop()
476    {
477        String source = "<?for list in data?>[<?for n in list?>(<?print n?>)<?end for?>]<?end for?>";
478        checkTemplateOutput("[(1)(2)][(3)(4)]", source, "data", asList(asList(1, 2), asList(3, 4)));
479    }
480
481    @Test
482    public void tag_for_unpacking()
483    {
484        Object data1 = asList(
485            asList("spam"),
486            asList("gurk"),
487            asList("hinz")
488        );
489
490        Object data2 = asList(
491            asList("spam", "eggs"),
492            asList("gurk", "hurz"),
493            asList("hinz", "kunz")
494        );
495
496        Object data3 = asList(
497            asList("spam", "eggs", 17),
498            asList("gurk", "hurz", 23),
499            asList("hinz", "kunz", 42)
500        );
501
502        Object data4 = asList(
503            asList("spam", "eggs", 17, null),
504            asList("gurk", "hurz", 23, false),
505            asList("hinz", "kunz", 42, true)
506        );
507
508        checkTemplateOutput("(spam)(gurk)(hinz)", "<?for (a,) in data?>(<?print a?>)<?end for?>", "data", data1);
509        checkTemplateOutput("(spam,eggs)(gurk,hurz)(hinz,kunz)", "<?for (a, b) in data?>(<?print a?>,<?print b?>)<?end for?>", "data", data2);
510        checkTemplateOutput("(spam,eggs,17)(gurk,hurz,23)(hinz,kunz,42)", "<?for (a, b, c) in data?>(<?print a?>,<?print b?>,<?print c?>)<?end for?>", "data", data3);
511        checkTemplateOutput("(spam,eggs,17,)(gurk,hurz,23,False)(hinz,kunz,42,True)", "<?for (a, b, c, d) in data?>(<?print a?>,<?print b?>,<?print c?>,<?print d?>)<?end for?>", "data", data4);
512    }
513
514    @Test
515    public void tag_for_nested_unpacking()
516    {
517        Object data = asList(
518            asList(asList("spam", "eggs"), asList(17), null),
519            asList(asList("gurk", "hurz"), asList(23), false),
520            asList(asList("hinz", "kunz"), asList(42), true)
521        );
522
523        checkTemplateOutput("(spam,eggs,17,)(gurk,hurz,23,False)(hinz,kunz,42,True)", "<?for ((a, b), (c,), d) in data?>(<?print a?>,<?print b?>,<?print c?>,<?print d?>)<?end for?>", "data", data);
524    }
525
526    @Test
527    public void tag_break()
528    {
529        checkTemplateOutput("1, 2, ", "<?for i in [1,2,3]?><?print i?>, <?if i==2?><?break?><?end if?><?end for?>");
530    }
531
532    @Test
533    public void tag_break_nested()
534    {
535        checkTemplateOutput("1, 1, 2, 1, 2, 3, ", "<?for i in [1,2,3,4]?><?for j in [1,2,3,4]?><?print j?>, <?if j>=i?><?break?><?end if?><?end for?><?if i>=3?><?break?><?end if?><?end for?>");
536    }
537
538    @CauseTest(expectedCause=BlockException.class)
539    public void tag_break_outside_loop()
540    {
541        checkTemplateOutput("", "<?break?>");
542    }
543
544    @CauseTest(expectedCause=BlockException.class)
545    public void tag_break_outside_loop_in_template()
546    {
547        checkTemplateOutput("", "<?def gurk?><?break?><?end def?>");
548    }
549
550    @Test
551    public void tag_continue()
552    {
553        checkTemplateOutput("1, 3, ", "<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?print i?>, <?end for?>");
554    }
555
556    @Test
557    public void tag_continue_nested()
558    {
559        checkTemplateOutput("1, 3, !1, 3, !", "<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?for j in [1,2,3]?><?if j==2?><?continue?><?end if?><?print j?>, <?end for?>!<?end for?>");
560    }
561
562    @CauseTest(expectedCause=BlockException.class)
563    public void tag_continue_outside_loop()
564    {
565        checkTemplateOutput("", "<?continue?>");
566    }
567
568    @CauseTest(expectedCause=BlockException.class)
569    public void tag_continue_outside_loop_in_template()
570    {
571        checkTemplateOutput("", "<?def gurk?><?continue?><?end def?>");
572    }
573
574    @Test
575    public void tag_if()
576    {
577        checkTemplateOutput("42", "<?if data?><?print data?><?end if?>", "data", 42);
578    }
579
580    @Test
581    public void tag_else()
582    {
583        String source = "<?if data?><?print data?><?else?>no<?end if?>";
584        checkTemplateOutput("42", source, "data", 42);
585        checkTemplateOutput("no", source, "data", 0);
586    }
587
588    // // FIXME: Doesn't work, because of chained exceptions, needs to be split into n tests
589    // // @Test(expected=BlockException)
590    // // public void block_errors()
591    // // {
592    // //   checkTemplateOutput("", "<?for x in data?>"); // "BlockError: block unclosed"
593    // //   checkTemplateOutput("", "<?for x in data?><?end if?>"); // "BlockError: endif doesn't match any if"
594    // //   checkTemplateOutput("", "<?end?>"); // "BlockError: not in any block"
595    // //   checkTemplateOutput("", "<?end for?>"); // "BlockError: not in any block"
596    // //   checkTemplateOutput("", "<?end if?>"); // "BlockError: not in any block"
597    // //   checkTemplateOutput("", "<?else?>"); // "BlockError: else doesn't match any if"
598    // //   checkTemplateOutput("", "<?if data?>"); // "BlockError: block unclosed"
599    // //   checkTemplateOutput("", "<?if data?><?else?>"); // "BlockError: block unclosed"
600    // //   checkTemplateOutput("", "<?if data?><?else?><?else?>"); // "BlockError: duplicate else"
601    // //   checkTemplateOutput("", "<?if data?><?else?><?elif data?>"); // "BlockError: else already seen in elif"
602    // //   checkTemplateOutput("", "<?if data?><?elif data?><?elif data?><?else?><?elif data?>"); // "BlockError: else already seen in elif"
603    // // }
604
605
606    // // FIXME: Doesn't work, because of chained exceptions, needs to be split into n tests
607    // // @Test(expected=BlockException)
608    // // public void empty()
609    // // {
610    // //   checkTemplateOutput("", "<?print?>"); // "expression required"
611    // //   checkTemplateOutput("", "<?if?>"); // "expression required"
612    // //   checkTemplateOutput("", "<?if x?><?elif?><?end if?>"); // "expression required"
613    // //   checkTemplateOutput("", "<?for?>"); // "loop expression required"
614    // //   checkTemplateOutput("", "<?code?>"); // "statement required"
615    // // }
616
617    @Test
618    public void operator_add()
619    {
620        String source = "<?print x + y?>";
621
622        checkTemplateOutput("0", source, "x", false, "y", false);
623        checkTemplateOutput("1", source, "x", false, "y", true);
624        checkTemplateOutput("1", source, "x", true, "y", false);
625        checkTemplateOutput("2", source, "x", true, "y", true);
626        checkTemplateOutput("18", source, "x", 17, "y", true);
627        checkTemplateOutput("40", source, "x", 17, "y", 23);
628        checkTemplateOutput("18.0", source, "x", 17, "y", 1.0);
629        checkTemplateOutput("24", source, "x", true, "y", 23);
630        checkTemplateOutput("22.0", source, "x", -1.0, "y", 23);
631        checkTemplateOutput("foobar", source, "x", "foo", "y", "bar");
632        checkTemplateOutput("[1, 2, 3, 4][1, 2][3, 4]", "<?code z = x + y?><?print z?><?print x?><?print y?>", "x", asList(1, 2), "y", asList(3, 4));
633        checkTemplateOutput("2012-10-18 00:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(1));
634        checkTemplateOutput("2013-10-17 00:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(365));
635        checkTemplateOutput("2012-10-17 12:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 12*60*60));
636        checkTemplateOutput("2012-10-17 00:00:01", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 1));
637        checkTemplateOutput("2012-10-17 00:00:00.500000", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 0, 500000));
638        checkTemplateOutput("2012-10-17 00:00:00.001000", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 0, 1000));
639        checkTemplateOutput("2 days, 0:00:00", source, "x", new TimeDelta(1), "y", new TimeDelta(1));
640        checkTemplateOutput("1 day, 0:00:01", source, "x", new TimeDelta(1), "y", new TimeDelta(0, 1));
641        checkTemplateOutput("1 day, 0:00:00.000001", source, "x", new TimeDelta(1), "y", new TimeDelta(0, 0, 1));
642        checkTemplateOutput("2 months", source, "x", new MonthDelta(1), "y", new MonthDelta(1));
643        // List addition is not implemented: checkTemplateOutput("(foo)(bar)(gurk)(hurz)", "<?for i in a+b?>(<?print i?>)<?end for?>", "a", asList("foo", "bar"), "b", asList("gurk", "hurz"));
644        // This checks constant folding
645        checkTemplateOutput("3", "<?print 1+2?>");
646        checkTemplateOutput("2", "<?print 1+True?>");
647        checkTemplateOutput("3.0", "<?print 1+2.0?>");
648    }
649
650    @Test
651    public void operator_sub()
652    {
653        String source = "<?print x - y?>";
654
655        checkTemplateOutput("0", source, "x", false, "y", false);
656        checkTemplateOutput("-1", source, "x", false, "y", true);
657        checkTemplateOutput("1", source, "x", true, "y", false);
658        checkTemplateOutput("0", source, "x", true, "y", true);
659        checkTemplateOutput("16", source, "x", 17, "y", true);
660        checkTemplateOutput("-6", source, "x", 17, "y", 23);
661        checkTemplateOutput("16.0", source, "x", 17, "y", 1.0);
662        checkTemplateOutput("-22", source, "x", true, "y", 23);
663        checkTemplateOutput("-24.0", source, "x", -1.0, "y", 23);
664        checkTemplateOutput("2012-10-16 00:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(1));
665        checkTemplateOutput("2011-10-17 00:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(366));
666        checkTemplateOutput("2012-10-16 12:00:00", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 12*60*60));
667        checkTemplateOutput("2012-10-16 23:59:59", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 1));
668        checkTemplateOutput("2012-10-16 23:59:59.500000", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 0, 500000));
669        checkTemplateOutput("2012-10-16 23:59:59.999000", source, "x", FunctionDate.call(2012, 10, 17), "y", new TimeDelta(0, 0, 1000));
670        checkTemplateOutput("0:00:00", source, "x", new TimeDelta(1), "y", new TimeDelta(1));
671        checkTemplateOutput("1 day, 0:00:00", source, "x", new TimeDelta(2), "y", new TimeDelta(1));
672        checkTemplateOutput("23:59:59", source, "x", new TimeDelta(1), "y", new TimeDelta(0, 1));
673        checkTemplateOutput("23:59:59.999999", source, "x", new TimeDelta(1), "y", new TimeDelta(0, 0, 1));
674        checkTemplateOutput("-1 day, 23:59:59", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 1));
675        checkTemplateOutput("-1 day, 23:59:59.999999", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 0, 1));
676        // This checks constant folding
677        checkTemplateOutput("-1", "<?print 1-2?>");
678        checkTemplateOutput("1", "<?print 2-True?>");
679        checkTemplateOutput("-1.0", "<?print 1-2.0?>");
680    }
681
682    @Test
683    public void operator_neg()
684    {
685        String source = "<?print -x?>";
686
687        checkTemplateOutput("0", source, "x", false);
688        checkTemplateOutput("-1", source, "x", true);
689        checkTemplateOutput("-17", source, "x", 17);
690        checkTemplateOutput("-17.0", source, "x", 17.0);
691        checkTemplateOutput("0:00:00", source, "x", new TimeDelta());
692        checkTemplateOutput("-1 day, 0:00:00", source, "x", new TimeDelta(1));
693        checkTemplateOutput("-1 day, 23:59:59", source, "x", new TimeDelta(0, 1));
694        checkTemplateOutput("-1 day, 23:59:59.999999", source, "x", new TimeDelta(0, 0, 1));
695        // This checks constant folding
696        checkTemplateOutput("0", "<?print -False?>");
697        checkTemplateOutput("-1", "<?print -True?>");
698        checkTemplateOutput("-2", "<?print -2?>");
699        checkTemplateOutput("-2.0", "<?print -2.0?>");
700    }
701
702    @Test
703    public void operator_mul()
704    {
705        String source = "<?print x * y?>";
706
707        checkTemplateOutput("0", source, "x", false, "y", false);
708        checkTemplateOutput("0", source, "x", false, "y", true);
709        checkTemplateOutput("0", source, "x", true, "y", false);
710        checkTemplateOutput("1", source, "x", true, "y", true);
711        checkTemplateOutput("17", source, "x", 17, "y", true);
712        checkTemplateOutput("391", source, "x", 17, "y", 23);
713        checkTemplateOutput("17.0", source, "x", 17, "y", 1.0);
714        checkTemplateOutput("23", source, "x", true, "y", 23);
715        checkTemplateOutput("-23.0", source, "x", -1.0, "y", 23);
716        checkTemplateOutput("foofoofoo", source, "x", 3, "y", "foo");
717        checkTemplateOutput("foofoofoo", source, "x", "foo", "y", 3);
718        checkTemplateOutput("0:00:00", source, "x", 4, "y", new TimeDelta());
719        checkTemplateOutput("4 days, 0:00:00", source, "x", 4, "y", new TimeDelta(1));
720        checkTemplateOutput("2 days, 0:00:00", source, "x", 4, "y", new TimeDelta(0, 12*60*60));
721        checkTemplateOutput("0:00:02", source, "x", 4, "y", new TimeDelta(0, 0, 500000));
722        checkTemplateOutput("12:00:00", source, "x", 0.5, "y", new TimeDelta(1));
723        checkTemplateOutput("0:00:00", source, "x", new TimeDelta(), "y", 4);
724        checkTemplateOutput("4 days, 0:00:00", source, "x", new TimeDelta(1), "y", 4);
725        checkTemplateOutput("2 days, 0:00:00", source, "x", new TimeDelta(0, 12*60*60), "y", 4);
726        checkTemplateOutput("0:00:02", source, "x", new TimeDelta(0, 0, 500000), "y", 4);
727        checkTemplateOutput("12:00:00", source, "x", new TimeDelta(1), "y", 0.5);
728        checkTemplateOutput("(foo)(bar)(foo)(bar)(foo)(bar)", "<?for i in 3*data?>(<?print i?>)<?end for?>", "data", asList("foo", "bar"));
729        // This checks constant folding
730        checkTemplateOutput("391", "<?print 17*23?>");
731        checkTemplateOutput("17", "<?print 17*True?>");
732        checkTemplateOutput("391.0", "<?print 17.0*23.0?>");
733    }
734
735    @Test
736    public void operator_truediv()
737    {
738        String source = "<?print x / y?>";
739
740        checkTemplateOutput("0.0", source, "x", false, "y", true);
741        checkTemplateOutput("1.0", source, "x", true, "y", true);
742        checkTemplateOutput("17.0", source, "x", 17, "y", true);
743        checkTemplateOutput("17.0", source, "x", 391, "y", 23);
744        checkTemplateOutput("17.0", source, "x", 17, "y", 1.0);
745        checkTemplateOutput("0.5", source, "x", 1, "y", 2);
746        checkTemplateOutput("0:00:00", source, "x", new TimeDelta(), "y", 4);
747        checkTemplateOutput("2 days, 0:00:00", source, "x", new TimeDelta(8), "y", 4);
748        checkTemplateOutput("12:00:00", source, "x", new TimeDelta(4), "y", 8);
749        checkTemplateOutput("0:00:00.500000", source, "x", new TimeDelta(0, 4), "y", 8);
750        checkTemplateOutput("2 days, 0:00:00", source, "x", new TimeDelta(1), "y", 0.5);
751        checkTemplateOutput("9:36:00", source, "x", new TimeDelta(1), "y", 2.5);
752        // This checks constant folding
753        checkTemplateOutput("0.5", "<?print 1/2?>");
754        checkTemplateOutput("2.0", "<?print 2.0/True?>");
755    }
756
757    @Test
758    public void operator_floordiv()
759    {
760        String source = "<?print x // y?>";
761
762        checkTemplateOutput("0", source, "x", false, "y", true);
763        checkTemplateOutput("1", source, "x", true, "y", true);
764        checkTemplateOutput("17", source, "x", 17, "y", true);
765        checkTemplateOutput("17", source, "x", 392, "y", 23);
766        checkTemplateOutput("17.0", source, "x", 17, "y", 1.0);
767        checkTemplateOutput("0", source, "x", 1, "y", 2);
768        checkTemplateOutput("0:00:00", source, "x", new TimeDelta(), "y", 4);
769        checkTemplateOutput("2 days, 0:00:00", source, "x", new TimeDelta(8), "y", 4);
770        checkTemplateOutput("12:00:00", source, "x", new TimeDelta(4), "y", 8);
771        checkTemplateOutput("0:00:00.500000", source, "x", new TimeDelta(0, 4), "y", 8);
772        // This checks constant folding
773        checkTemplateOutput("0.5", "<?print 1/2?>");
774        checkTemplateOutput("2.0", "<?print 2.0/True?>");
775    }
776
777    @Test
778    public void operator_mod()
779    {
780        String source = "<?print x % y?>";
781
782        checkTemplateOutput("0", source, "x", false, "y", true);
783        checkTemplateOutput("0", source, "x", true, "y", true);
784        checkTemplateOutput("0", source, "x", 17, "y", true);
785        checkTemplateOutput("6", source, "x", 23, "y", 17);
786        checkTemplateOutput("0.5", source, "x", 5.5, "y", 2.5);
787        // This checks constant folding
788        checkTemplateOutput("6", "<?print 23 % 17?>");
789    }
790
791    @Test
792    public void operator_eq()
793    {
794        String source = "<?print x == y?>";
795
796        checkTemplateOutput("False", source, "x", false, "y", true);
797        checkTemplateOutput("True", source, "x", true, "y", true);
798        checkTemplateOutput("True", source, "x", 1, "y", true);
799        checkTemplateOutput("False", source, "x", 1, "y", false);
800        checkTemplateOutput("False", source, "x", 17, "y", 23);
801        checkTemplateOutput("True", source, "x", 17, "y", 17);
802        checkTemplateOutput("True", source, "x", 17, "y", 17.0);
803        // This checks constant folding
804        checkTemplateOutput("False", "<?print 17 == 23?>");
805        checkTemplateOutput("True", "<?print 17 == 17.?>");
806    }
807
808    @Test
809    public void operator_ne()
810    {
811        String source = "<?print x != y?>";
812
813        checkTemplateOutput("True", source, "x", false, "y", true);
814        checkTemplateOutput("False", source, "x", true, "y", true);
815        checkTemplateOutput("False", source, "x", 1, "y", true);
816        checkTemplateOutput("True", source, "x", 1, "y", false);
817        checkTemplateOutput("True", source, "x", 17, "y", 23);
818        checkTemplateOutput("False", source, "x", 17, "y", 17);
819        checkTemplateOutput("False", source, "x", 17, "y", 17.0);
820        // This checks constant folding
821        checkTemplateOutput("True", "<?print 17 != 23?>");
822        checkTemplateOutput("False", "<?print 17 != 17.?>");
823    }
824
825    @Test
826    public void operator_lt()
827    {
828        String source = "<?print x < y?>";
829
830        checkTemplateOutput("True", source, "x", false, "y", true);
831        checkTemplateOutput("False", source, "x", true, "y", true);
832        checkTemplateOutput("False", source, "x", 1, "y", true);
833        checkTemplateOutput("True", source, "x", true, "y", 2);
834        checkTemplateOutput("True", source, "x", 17, "y", 23);
835        checkTemplateOutput("False", source, "x", 23, "y", 17);
836        checkTemplateOutput("False", source, "x", 17, "y", 17.0);
837        checkTemplateOutput("True", source, "x", 17, "y", 23.0);
838        checkTemplateOutput("False", source, "x", new TimeDelta(0), "y", new TimeDelta(0));
839        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(1));
840        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 1));
841        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 0, 1));
842        checkTemplateOutput("False", source, "x", new MonthDelta(0), "y", new MonthDelta(0));
843        checkTemplateOutput("True", source, "x", new MonthDelta(0), "y", new MonthDelta(1));
844        // This checks constant folding
845        checkTemplateOutput("True", "<?print 17 < 23?>");
846        checkTemplateOutput("False", "<?print 17 < 17.?>");
847    }
848
849    @Test
850    public void operator_le()
851    {
852        String source = "<?print x <= y?>";
853
854        checkTemplateOutput("True", source, "x", false, "y", true);
855        checkTemplateOutput("True", source, "x", true, "y", true);
856        checkTemplateOutput("True", source, "x", 1, "y", true);
857        checkTemplateOutput("True", source, "x", true, "y", 2);
858        checkTemplateOutput("True", source, "x", 17, "y", 23);
859        checkTemplateOutput("False", source, "x", 23, "y", 17);
860        checkTemplateOutput("True", source, "x", 17, "y", 17);
861        checkTemplateOutput("True", source, "x", 17, "y", 17.0);
862        checkTemplateOutput("False", source, "x", new TimeDelta(1), "y", new TimeDelta(0));
863        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(1));
864        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 1));
865        checkTemplateOutput("True", source, "x", new TimeDelta(0), "y", new TimeDelta(0, 0, 1));
866        checkTemplateOutput("False", source, "x", new MonthDelta(1), "y", new MonthDelta(0));
867        checkTemplateOutput("True", source, "x", new MonthDelta(0), "y", new MonthDelta(1));
868        // This checks constant folding
869        checkTemplateOutput("True", "<?print 17 <= 23?>");
870        checkTemplateOutput("True", "<?print 17 <= 17.?>");
871        checkTemplateOutput("True", "<?print 17 <= 23.?>");
872        checkTemplateOutput("False", "<?print 18 <= 17.?>");
873    }
874
875    @Test
876    public void operator_gt()
877    {
878        String source = "<?print x > y?>";
879
880        checkTemplateOutput("False", source, "x", false, "y", true);
881        checkTemplateOutput("False", source, "x", true, "y", true);
882        checkTemplateOutput("False", source, "x", 1, "y", true);
883        checkTemplateOutput("True", source, "x", 2, "y", true);
884        checkTemplateOutput("False", source, "x", 17, "y", 23);
885        checkTemplateOutput("True", source, "x", 23, "y", 17);
886        checkTemplateOutput("False", source, "x", 17, "y", 17.0);
887        checkTemplateOutput("True", source, "x", 23.0, "y", 17);
888        checkTemplateOutput("False", source, "x", new TimeDelta(0), "y", new TimeDelta(0));
889        checkTemplateOutput("True", source, "x", new TimeDelta(1), "y", new TimeDelta(0));
890        checkTemplateOutput("True", source, "x", new TimeDelta(0, 1), "y", new TimeDelta(0));
891        checkTemplateOutput("True", source, "x", new TimeDelta(0, 0, 1), "y", new TimeDelta(0));
892        checkTemplateOutput("False", source, "x", new MonthDelta(0), "y", new MonthDelta(0));
893        checkTemplateOutput("True", source, "x", new MonthDelta(1), "y", new MonthDelta(0));
894        // This checks constant folding
895        checkTemplateOutput("False", "<?print 17 > 23?>");
896        checkTemplateOutput("False", "<?print 17 > 17.?>");
897        checkTemplateOutput("False", "<?print 17 > 23.?>");
898        checkTemplateOutput("True", "<?print 18 > 17.?>");
899    }
900
901    @Test
902    public void operator_ge()
903    {
904        String source = "<?print x >= y?>";
905
906        checkTemplateOutput("False", source, "x", false, "y", true);
907        checkTemplateOutput("True", source, "x", true, "y", true);
908        checkTemplateOutput("True", source, "x", 1, "y", true);
909        checkTemplateOutput("False", source, "x", true, "y", 2);
910        checkTemplateOutput("False", source, "x", 17, "y", 23);
911        checkTemplateOutput("True", source, "x", 23, "y", 17);
912        checkTemplateOutput("True", source, "x", 17, "y", 17);
913        checkTemplateOutput("True", source, "x", 17, "y", 17.0);
914        checkTemplateOutput("False", source, "x", new TimeDelta(0), "y", new TimeDelta(1));
915        checkTemplateOutput("True", source, "x", new TimeDelta(1), "y", new TimeDelta(0));
916        checkTemplateOutput("True", source, "x", new TimeDelta(0, 1), "y", new TimeDelta(0));
917        checkTemplateOutput("True", source, "x", new TimeDelta(0, 0, 1), "y", new TimeDelta(0));
918        checkTemplateOutput("False", source, "x", new MonthDelta(0), "y", new MonthDelta(1));
919        checkTemplateOutput("True", source, "x", new MonthDelta(1), "y", new MonthDelta(0));
920        // This checks constant folding
921        checkTemplateOutput("False", "<?print 17 >= 23?>");
922        checkTemplateOutput("True", "<?print 17 >= 17.?>");
923        checkTemplateOutput("False", "<?print 17 >= 23.?>");
924        checkTemplateOutput("True", "<?print 18 >= 17.?>");
925    }
926
927    @Test
928    public void operator_contains()
929    {
930        String source = "<?print x in y?>";
931
932        checkTemplateOutput("True", source, "x", 2, "y", asList(1, 2, 3));
933        checkTemplateOutput("False", source, "x", 4, "y", asList(1, 2, 3));
934        checkTemplateOutput("True", source, "x", 2, "y", new Integer[]{1, 2, 3});
935        checkTemplateOutput("False", source, "x", 4, "y", new Integer[]{1, 2, 3});
936        checkTemplateOutput("True", source, "x", "ur", "y", "gurk");
937        checkTemplateOutput("False", source, "x", "un", "y", "gurk");
938        checkTemplateOutput("True", source, "x", "a", "y", makeMap("a", 1, "b", 2));
939        checkTemplateOutput("False", source, "x", "c", "y", makeMap("a", 1, "b", 2));
940        checkTemplateOutput("True", source, "x", 0xff, "y", new Color(0x00, 0x80, 0xff, 0x42));
941        checkTemplateOutput("False", source, "x", 0x23, "y", new Color(0x00, 0x80, 0xff, 0x42));
942        checkTemplateOutput("True", "<?print 'x' in p?>", "p", new Point(17, 23));
943        checkTemplateOutput("False", "<?print 'z' in p?>", "p", new Point(17, 23));
944    }
945
946    @Test
947    public void operator_notcontains()
948    {
949        String source = "<?print x not in y?>";
950
951        checkTemplateOutput("False", source, "x", 2, "y", asList(1, 2, 3));
952        checkTemplateOutput("True", source, "x", 4, "y", asList(1, 2, 3));
953        checkTemplateOutput("False", source, "x", 2, "y", new Integer[]{1, 2, 3});
954        checkTemplateOutput("True", source, "x", 4, "y", new Integer[]{1, 2, 3});
955        checkTemplateOutput("False", source, "x", "ur", "y", "gurk");
956        checkTemplateOutput("True", source, "x", "un", "y", "gurk");
957        checkTemplateOutput("False", source, "x", "a", "y", makeMap("a", 1, "b", 2));
958        checkTemplateOutput("True", source, "x", "c", "y", makeMap("a", 1, "b", 2));
959        checkTemplateOutput("False", source, "x", 0xff, "y", new Color(0x00, 0x80, 0xff, 0x42));
960        checkTemplateOutput("True", source, "x", 0x23, "y", new Color(0x00, 0x80, 0xff, 0x42));
961        checkTemplateOutput("False", "<?print 'x' not in p?>", "p", new Point(17, 23));
962        checkTemplateOutput("True", "<?print 'z' not in p?>", "p", new Point(17, 23));
963    }
964
965    @Test
966    public void operator_and()
967    {
968        String source = "<?print x and y?>";
969
970        checkTemplateOutput("False", source, "x", false, "y", false);
971        checkTemplateOutput("False", source, "x", false, "y", true);
972        checkTemplateOutput("0", source, "x", 0, "y", true);
973    }
974
975    @Test
976    public void operator_or()
977    {
978        String source = "<?print x or y?>";
979
980        checkTemplateOutput("False", source, "x", false, "y", false);
981        checkTemplateOutput("True", source, "x", false, "y", true);
982        checkTemplateOutput("42", source, "x", 42, "y", true);
983    }
984
985    @Test
986    public void operator_not()
987    {
988        String source = "<?print not x?>";
989
990        checkTemplateOutput("True", source, "x", false);
991        checkTemplateOutput("False", source, "x", 42);
992    }
993
994    @Test
995    public void expression_if()
996    {
997        String source = "<?print x if y else z?>";
998
999        checkTemplateOutput("23", source, "x", 17, "y", false, "z", 23);
1000        checkTemplateOutput("17", source, "x", 17, "y", true, "z", 23);
1001    }
1002
1003    @Test
1004    public void operator_getitem()
1005    {
1006        checkTemplateOutput("u", "<?print 'gurk'[1]?>");
1007        checkTemplateOutput("u", "<?print x[1]?>", "x", "gurk");
1008        checkTemplateOutput("u", "<?print 'gurk'[-3]?>");
1009        checkTemplateOutput("u", "<?print x[-3]?>", "x", "gurk");
1010        checkTemplateOutput("", "<?print 'gurk'[4]?>");
1011        checkTemplateOutput("", "<?print x[4]?>", "x", "gurk");
1012        checkTemplateOutput("", "<?print 'gurk'[-5]?>");
1013        checkTemplateOutput("", "<?print x[-5]?>", "x", "gurk");
1014    }
1015
1016    @Test
1017    public void operator_getslice()
1018    {
1019        checkTemplateOutput("ur", "<?print 'gurk'[1:3]?>");
1020        checkTemplateOutput("ur", "<?print x[1:3]?>", "x", "gurk");
1021        checkTemplateOutput("ur", "<?print 'gurk'[-3:-1]?>");
1022        checkTemplateOutput("ur", "<?print x[-3:-1]?>", "x", "gurk");
1023        checkTemplateOutput("", "<?print 'gurk'[4:10]?>");
1024        checkTemplateOutput("", "<?print x[4:10]?>", "x", "gurk");
1025        checkTemplateOutput("", "<?print 'gurk'[-10:-5]?>");
1026        checkTemplateOutput("", "<?print x[-10:-5]?>", "x", "gurk");
1027        checkTemplateOutput("urk", "<?print 'gurk'[1:]?>");
1028        checkTemplateOutput("urk", "<?print x[1:]?>", "x", "gurk");
1029        checkTemplateOutput("urk", "<?print 'gurk'[-3:]?>");
1030        checkTemplateOutput("urk", "<?print x[-3:]?>", "x", "gurk");
1031        checkTemplateOutput("", "<?print 'gurk'[4:]?>");
1032        checkTemplateOutput("", "<?print x[4:]?>", "x", "gurk");
1033        checkTemplateOutput("gurk", "<?print 'gurk'[-10:]?>");
1034        checkTemplateOutput("gurk", "<?print x[-10:]?>", "x", "gurk");
1035        checkTemplateOutput("gur", "<?print 'gurk'[:3]?>");
1036        checkTemplateOutput("gur", "<?print x[:3]?>", "x", "gurk");
1037        checkTemplateOutput("gur", "<?print 'gurk'[:-1]?>");
1038        checkTemplateOutput("gur", "<?print x[:-1]?>", "x", "gurk");
1039        checkTemplateOutput("gurk", "<?print 'gurk'[:10]?>");
1040        checkTemplateOutput("gurk", "<?print x[:10]?>", "x", "gurk");
1041        checkTemplateOutput("", "<?print 'gurk'[:-5]?>");
1042        checkTemplateOutput("", "<?print x[:-5]?>", "x", "gurk");
1043    }
1044
1045    @Test
1046    public void operator_setslice()
1047    {
1048        checkTemplateOutput("[1, -2, -3, 4]", "<?code x = [1, 2, 3, 4]?><?code x[1:3] = [-2, -3]?><?print x?>");
1049        checkTemplateOutput("[1, -1, -4, -9, 4]", "<?code x = [1, 2, 3, 4]?><?code x[1:-1] = (-i*i for i in range(1, 4))?><?print x?>");
1050        checkTemplateOutput("[-1, -4, -9]", "<?code x = [1, 2, 3, 4]?><?code x[:] = (-i*i for i in range(1, 4))?><?print x?>");
1051    }
1052
1053    @Test
1054    public void nested()
1055    {
1056        String sc = "4";
1057        String sv = "x";
1058        int n = 4;
1059        int depth = 10;
1060        for (int i = 0; i < depth; ++i)
1061        {
1062            sc = "(" + sc + ")+(" + sc + ")";
1063            sv = "(" + sv + ")+(" + sv + ")";
1064            n = n + n;
1065        }
1066        String expected = Integer.toString(n);
1067        checkTemplateOutput(expected, "<?print " + sc + "?>");
1068        checkTemplateOutput(expected, "<?print " + sv + "?>", "x", 4);
1069    }
1070
1071    @Test
1072    public void precedence()
1073    {
1074        checkTemplateOutput("10", "<?print 2*3+4?>");
1075        checkTemplateOutput("14", "<?print 2+3*4?>");
1076        checkTemplateOutput("20", "<?print (2+3)*4?>");
1077        checkTemplateOutput("10", "<?print -2+-3*-4?>");
1078        checkTemplateOutput("14", "<?print --2+--3*--4?>");
1079        checkTemplateOutput("14", "<?print (-(-2))+(-((-3)*-(-4)))?>");
1080        checkTemplateOutput("42", "<?print 2*data.value?>", "data", makeMap("value", 21));
1081        checkTemplateOutput("42", "<?print data.value[0]?>", "data", makeMap("value", asList(42)));
1082        checkTemplateOutput("42", "<?print data[0].value?>", "data", asList(makeMap("value", 42)));
1083        checkTemplateOutput("42", "<?print data[0][0][0]?>", "data", asList(asList(asList(42))));
1084        checkTemplateOutput("42", "<?print data.value.value[0]?>", "data", makeMap("value", makeMap("value", asList(42))));
1085        checkTemplateOutput("42", "<?print data.value.value[0].value.value[0]?>", "data", makeMap("value", makeMap("value", asList(makeMap("value", makeMap("value", asList(42)))))));
1086    }
1087
1088    @Test
1089    public void associativity()
1090    {
1091        checkTemplateOutput("9", "<?print 2+3+4?>");
1092        checkTemplateOutput("-5", "<?print 2-3-4?>");
1093        checkTemplateOutput("24", "<?print 2*3*4?>");
1094        checkTemplateOutput("2.0", "<?print 24/6/2?>");
1095        checkTemplateOutput("2", "<?print 24//6//2?>");
1096    }
1097
1098    @Test
1099    public void bracket()
1100    {
1101        String sc = "42";
1102        String sv = "x";
1103        for (int i = 0; i < 10; ++i)
1104        {
1105            sc = "(" + sc + ")";
1106            sv = "(" + sv + ")";
1107        }
1108
1109        checkTemplateOutput("42", "<?print " + sc + "?>");
1110        checkTemplateOutput("42", "<?print " + sv + "?>", "x", 42);
1111    }
1112
1113    @Test
1114    public void function_now()
1115    {
1116        String output = getTemplateOutput("<?print now()?>");
1117        assertTrue(output.compareTo("2012-03-28") > 0);
1118    }
1119
1120    @CauseTest(expectedCause=TooManyArgumentsException.class)
1121    public void function_now_1_args()
1122    {
1123        checkTemplateOutput("", "<?print now(1)?>");
1124    }
1125
1126    @CauseTest(expectedCause=TooManyArgumentsException.class)
1127    public void function_now_2_args()
1128    {
1129        checkTemplateOutput("", "<?print now(1, 2)?>");
1130    }
1131
1132    @Test
1133    public void function_utcnow()
1134    {
1135        String output = getTemplateOutput("<?print utcnow()?>");
1136        assertTrue(output.compareTo("2012-03-28") > 0);
1137    }
1138
1139    @CauseTest(expectedCause=TooManyArgumentsException.class)
1140    public void function_utcnow_1_args()
1141    {
1142        checkTemplateOutput("", "<?print utcnow(1)?>");
1143    }
1144
1145    @CauseTest(expectedCause=TooManyArgumentsException.class)
1146    public void function_utcnow_2_args()
1147    {
1148        checkTemplateOutput("", "<?print utcnow(1, 2)?>");
1149    }
1150
1151    @Test
1152    public void function_date()
1153    {
1154        checkTemplateOutput("@(2012-10-06)", "<?print repr(date(2012, 10, 6))?>");
1155        checkTemplateOutput("@(2012-10-06T12:00:00)", "<?print repr(date(2012, 10, 6, 12))?>");
1156        checkTemplateOutput("@(2012-10-06T12:34:00)", "<?print repr(date(2012, 10, 6, 12, 34))?>");
1157        checkTemplateOutput("@(2012-10-06T12:34:56)", "<?print repr(date(2012, 10, 6, 12, 34, 56))?>");
1158        checkTemplateOutput("@(2012-10-06T12:34:56.987000)", "<?print repr(date(2012, 10, 6, 12, 34, 56, 987000))?>");
1159        checkTemplateOutput("@(2012-10-06T12:34:56.987000)", "<?print repr(date(year=2012, month=10, day=6, hour=12, minute=34, second=56, microsecond=987000))?>");
1160    }
1161
1162    @Test
1163    public void function_timedelta()
1164    {
1165        checkTemplateOutput("0:00:00", "<?print timedelta()?>");
1166        checkTemplateOutput("1 day, 0:00:00", "<?print timedelta(1)?>");
1167        checkTemplateOutput("2 days, 0:00:00", "<?print timedelta(2)?>");
1168        checkTemplateOutput("0:00:01", "<?print timedelta(0, 1)?>");
1169        checkTemplateOutput("0:01:00", "<?print timedelta(0, 60)?>");
1170        checkTemplateOutput("1:00:00", "<?print timedelta(0, 60*60)?>");
1171        checkTemplateOutput("1 day, 1:01:01.000001", "<?print timedelta(1, 60*60+60+1, 1)?>");
1172        checkTemplateOutput("0:00:00.000001", "<?print timedelta(0, 0, 1)?>");
1173        checkTemplateOutput("0:00:01", "<?print timedelta(0, 0, 1000000)?>");
1174        checkTemplateOutput("1 day, 0:00:00", "<?print timedelta(0, 0, 24*60*60*1000000)?>");
1175        checkTemplateOutput("1 day, 0:00:00", "<?print timedelta(0, 24*60*60)?>");
1176        checkTemplateOutput("-1 day, 0:00:00", "<?print timedelta(-1)?>");
1177        checkTemplateOutput("-1 day, 23:59:59", "<?print timedelta(0, -1)?>");
1178        checkTemplateOutput("-1 day, 23:59:59.999999", "<?print timedelta(0, 0, -1)?>");
1179        checkTemplateOutput("12:00:00", "<?print timedelta(0.5)?>");
1180        checkTemplateOutput("0:00:00.500000", "<?print timedelta(0, 0.5)?>");
1181        checkTemplateOutput("0:00:00.500000", "<?print timedelta(0.5/(24*60*60))?>");
1182        checkTemplateOutput("-1 day, 12:00:00", "<?print timedelta(-0.5)?>");
1183        checkTemplateOutput("-1 day, 23:59:59.500000", "<?print timedelta(0, -0.5)?>");
1184        checkTemplateOutput("1 day, 0:00:01.000001", "<?print timedelta(days=1, seconds=1, microseconds=1)?>");
1185    }
1186    @Test
1187    public void function_monthdelta()
1188    {
1189        checkTemplateOutput("0 months", "<?print monthdelta()?>");
1190        checkTemplateOutput("1 month", "<?print monthdelta(1)?>");
1191        checkTemplateOutput("2 months", "<?print monthdelta(2)?>");
1192        checkTemplateOutput("-1 month", "<?print monthdelta(-1)?>");
1193        checkTemplateOutput("1 month", "<?print monthdelta(months=1)?>");
1194    }
1195
1196    @CauseTest(expectedCause=TooManyArgumentsException.class)
1197    public void function_random_1_args()
1198    {
1199        checkTemplateOutput("", "<?print random(1)?>");
1200    }
1201
1202    @Test
1203    public void function_randrange()
1204    {
1205        checkTemplateOutput("ok", "<?code r = randrange(4)?><?if r>=0 and r<4?>ok<?else?>fail<?end if?>");
1206        checkTemplateOutput("ok", "<?code r = randrange(17, 23)?><?if r>=17 and r<23?>ok<?else?>fail<?end if?>");
1207        checkTemplateOutput("ok", "<?code r = randrange(17, 23, 2)?><?if r>=17 and r<23 and r%2?>ok<?else?>fail<?end if?>");
1208    }
1209
1210    @CauseTest(expectedCause=ArgumentCountMismatchException.class)
1211    public void function_randrange_0_args()
1212    {
1213        checkTemplateOutput("", "<?print randrange()?>");
1214    }
1215
1216    @CauseTest(expectedCause=ArgumentCountMismatchException.class)
1217    public void function_randrange_4_args()
1218    {
1219        checkTemplateOutput("", "<?print randrange(1, 2, 3, 4)?>");
1220    }
1221
1222    @Test
1223    public void function_randchoice()
1224    {
1225        checkTemplateOutput("ok", "<?code r = randchoice('abc')?><?if r in 'abc'?>ok<?else?>fail<?end if?>");
1226        checkTemplateOutput("ok", "<?code s = [17, 23, 42]?><?code r = randchoice(s)?><?if r in s?>ok<?else?>fail<?end if?>");
1227        checkTemplateOutput("ok", "<?code s = #12345678?><?code sl = [0x12, 0x34, 0x56, 0x78]?><?code r = randchoice(s)?><?if r in sl?>ok<?else?>fail<?end if?>");
1228        checkTemplateOutput("ok", "<?code r = randchoice(sequence='abc')?><?if r in 'abc'?>ok<?else?>fail<?end if?>");
1229    }
1230
1231    @CauseTest(expectedCause=MissingArgumentException.class)
1232    @Test
1233    public void function_randchoice_0_args()
1234    {
1235        checkTemplateOutput("", "<?print randchoice()?>");
1236    }
1237
1238    @CauseTest(expectedCause=TooManyArgumentsException.class)
1239    @Test
1240    public void function_randchoice_2_args()
1241    {
1242        checkTemplateOutput("", "<?print randchoice(1, 2)?>");
1243    }
1244
1245    @Test
1246    public void function_xmlescape()
1247    {
1248        checkTemplateOutput("&lt;&lt;&gt;&gt;&amp;&#39;&quot;gurk", "<?print xmlescape(data)?>", "data", "<<>>&'\"gurk");
1249        checkTemplateOutput("42", "<?print xmlescape(obj=data)?>", "data", 42);
1250    }
1251
1252    @CauseTest(expectedCause=MissingArgumentException.class)
1253    @Test
1254    public void function_xmlescape_0_args()
1255    {
1256        checkTemplateOutput("", "<?print xmlescape()?>");
1257    }
1258
1259    @CauseTest(expectedCause=TooManyArgumentsException.class)
1260    @Test
1261    public void function_xmlescape_2_args()
1262    {
1263        checkTemplateOutput("", "<?print xmlescape(1, 2)?>");
1264    }
1265
1266    @Test
1267    public void function_csv()
1268    {
1269        checkTemplateOutput("", "<?print csv(data)?>", "data", null);
1270        checkTemplateOutput("False", "<?print csv(data)?>", "data", false);
1271        checkTemplateOutput("True", "<?print csv(data)?>", "data", true);
1272        checkTemplateOutput("42", "<?print csv(data)?>", "data", 42);
1273        // no check for float
1274        checkTemplateOutput("abc", "<?print csv(data)?>", "data", "abc");
1275        checkTemplateOutput("\"a,b,c\"", "<?print csv(data)?>", "data", "a,b,c");
1276        checkTemplateOutput("\"a\"\"b\"\"c\"", "<?print csv(data)?>", "data", "a\"b\"c");
1277        checkTemplateOutput("\"a\nb\nc\"", "<?print csv(data)?>", "data", "a\nb\nc");
1278        checkTemplateOutput("42", "<?print csv(obj=data)?>", "data", 42);
1279    }
1280
1281    @CauseTest(expectedCause=MissingArgumentException.class)
1282    @Test
1283    public void function_csv_0_args()
1284    {
1285        checkTemplateOutput("", "<?print csv()?>");
1286    }
1287
1288    @CauseTest(expectedCause=TooManyArgumentsException.class)
1289    @Test
1290    public void function_csv_2_args()
1291    {
1292        checkTemplateOutput("", "<?print csv(1, 2)?>");
1293    }
1294
1295    @Test
1296    public void function_asjson()
1297    {
1298        checkTemplateOutput("null", "<?print asjson(data)?>", "data", null);
1299        checkTemplateOutput("false", "<?print asjson(data)?>", "data", false);
1300        checkTemplateOutput("true", "<?print asjson(data)?>", "data", true);
1301        checkTemplateOutput("42", "<?print asjson(data)?>", "data", 42);
1302        // no check for float
1303        checkTemplateOutput("\"abc\"", "<?print asjson(data)?>", "data", "abc");
1304        checkTemplateOutput("[1, 2, 3]", "<?print asjson(data)?>", "data", asList(1, 2, 3));
1305        checkTemplateOutput("[1, 2, 3]", "<?print asjson(data)?>", "data", new Integer[]{1, 2, 3});
1306        checkTemplateOutput("{\"one\": 1}", "<?print asjson(data)?>", "data", makeMap("one", 1));
1307        checkTemplateOutput("null", "<?print asjson(obj=data)?>", "data", null);
1308    }
1309
1310    @CauseTest(expectedCause=MissingArgumentException.class)
1311    @Test
1312    public void function_asjson_0_args()
1313    {
1314        checkTemplateOutput("", "<?print asjson()?>");
1315    }
1316
1317    @CauseTest(expectedCause=TooManyArgumentsException.class)
1318    @Test
1319    public void function_asjson_2_args()
1320    {
1321        checkTemplateOutput("", "<?print asjson(1, 2)?>");
1322    }
1323
1324    @Test
1325    public void function_fromjson()
1326    {
1327        checkTemplateOutput("None", "<?print repr(fromjson(data))?>", "data", "null");
1328        checkTemplateOutput("False", "<?print repr(fromjson(data))?>", "data", "false");
1329        checkTemplateOutput("True", "<?print repr(fromjson(data))?>", "data", "true");
1330        checkTemplateOutput("42", "<?print repr(fromjson(data))?>", "data", "42");
1331        checkTemplateOutput("\"abc\"", "<?print repr(fromjson(data))?>", "data", "\"abc\"");
1332        checkTemplateOutput("[1, 2, 3]", "<?print repr(fromjson(data))?>", "data", "[1,2,3]");
1333        checkTemplateOutput("{\"eins\": 42}", "<?print repr(fromjson(data))?>", "data", "{\"eins\": 42}");
1334        checkTemplateOutput("None", "<?print repr(fromjson(string=data))?>", "data", "null");
1335    }
1336
1337    @CauseTest(expectedCause=MissingArgumentException.class)
1338    @Test
1339    public void function_fromjson_0_args()
1340    {
1341        checkTemplateOutput("", "<?print fromjson()?>");
1342    }
1343
1344    @CauseTest(expectedCause=TooManyArgumentsException.class)
1345    @Test
1346    public void function_fromjson_2_args()
1347    {
1348        checkTemplateOutput("", "<?print fromjson(1, 2)?>");
1349    }
1350
1351    @Test
1352    public void function_asul4on()
1353    {
1354        checkTemplateOutput(dumps(null), "<?print asul4on(data)?>", "data", null);
1355        checkTemplateOutput(dumps(false), "<?print asul4on(data)?>", "data", false);
1356        checkTemplateOutput(dumps(true), "<?print asul4on(data)?>", "data", true);
1357        checkTemplateOutput(dumps(42), "<?print asul4on(data)?>", "data", 42);
1358        checkTemplateOutput(dumps(42.5), "<?print asul4on(data)?>", "data", 42.5);
1359        checkTemplateOutput(dumps("abc"), "<?print asul4on(data)?>", "data", "abc");
1360        checkTemplateOutput(dumps(asList(1, 2, 3)), "<?print asul4on(data)?>", "data", asList(1, 2, 3));
1361        checkTemplateOutput(dumps(makeMap("one", 1)), "<?print asul4on(data)?>", "data", makeMap("one", 1));
1362        checkTemplateOutput(dumps(null), "<?print asul4on(obj=data)?>", "data", null);
1363    }
1364
1365    @CauseTest(expectedCause=MissingArgumentException.class)
1366    @Test
1367    public void function_asul4on_0_args()
1368    {
1369        checkTemplateOutput("", "<?print asul4on()?>");
1370    }
1371
1372    @CauseTest(expectedCause=TooManyArgumentsException.class)
1373    @Test
1374    public void function_asul4on_2_args()
1375    {
1376        checkTemplateOutput("", "<?print asul4on(1, 2)?>");
1377    }
1378
1379    @Test
1380    public void function_str()
1381    {
1382        String source = "<?print str(data)?>";
1383
1384        checkTemplateOutput("", "<?print str()?>");
1385        checkTemplateOutput("", source, "data", null);
1386        checkTemplateOutput("True", source, "data", true);
1387        checkTemplateOutput("False", source, "data", false);
1388        checkTemplateOutput("42", source, "data", 42);
1389        checkTemplateOutput("4.2", source, "data", 4.2);
1390        checkTemplateOutput("foo", source, "data", "foo");
1391        checkTemplateOutput("2011-02-09 00:00:00", source, "data", FunctionDate.call(2011, 2, 9));
1392        checkTemplateOutput("2011-02-09 12:34:56", source, "data", FunctionDate.call(2011, 2, 9, 12, 34, 56));
1393        checkTemplateOutput("2011-02-09 12:34:56.987000", source, "data", FunctionDate.call(2011, 2, 9, 12, 34, 56, 987000));
1394        checkTemplateOutput("foo", "<?print str(obj=data)?>", "data", "foo");
1395    }
1396
1397    @CauseTest(expectedCause=TooManyArgumentsException.class)
1398    @Test
1399    public void function_str_2_args()
1400    {
1401        checkTemplateOutput("", "<?print str(1, 2)?>");
1402    }
1403
1404    @Test
1405    public void function_bool()
1406    {
1407        checkTemplateOutput("False", "<?print bool()?>");
1408        checkTemplateOutput("True", "<?print bool(data)?>", "data", true);
1409        checkTemplateOutput("False", "<?print bool(data)?>", "data", false);
1410        checkTemplateOutput("False", "<?print bool(data)?>", "data", 0);
1411        checkTemplateOutput("True", "<?print bool(data)?>", "data", 42);
1412        checkTemplateOutput("False", "<?print bool(data)?>", "data", new BigInteger("0"));
1413        checkTemplateOutput("True", "<?print bool(data)?>", "data", new BigInteger("42"));
1414        checkTemplateOutput("False", "<?print bool(data)?>", "data", 0.0);
1415        checkTemplateOutput("True", "<?print bool(data)?>", "data", 4.2);
1416        checkTemplateOutput("False", "<?print bool(data)?>", "data", new BigDecimal("0.000"));
1417        checkTemplateOutput("True", "<?print bool(data)?>", "data", new BigDecimal("42.5"));
1418        checkTemplateOutput("False", "<?print bool(data)?>", "data", "");
1419        checkTemplateOutput("True", "<?print bool(data)?>", "data", "foo");
1420        checkTemplateOutput("False", "<?print bool(data)?>", "data", asList());
1421        checkTemplateOutput("True", "<?print bool(data)?>", "data", asList("foo", "bar"));
1422        checkTemplateOutput("False", "<?print bool(data)?>", "data", new Integer[]{});
1423        checkTemplateOutput("True", "<?print bool(data)?>", "data", new Integer[]{1, 2, 3});
1424        checkTemplateOutput("False", "<?print bool(data)?>", "data", makeMap());
1425        checkTemplateOutput("True", "<?print bool(data)?>", "data", makeMap("foo", "bar"));
1426        checkTemplateOutput("True", "<?print bool(obj=data)?>", "data", true);
1427    }
1428
1429    @CauseTest(expectedCause=TooManyArgumentsException.class)
1430    @Test
1431    public void function_bool_2_args()
1432    {
1433        checkTemplateOutput("", "<?print bool(1, 2)?>");
1434    }
1435
1436    @Test
1437    public void function_int()
1438    {
1439        checkTemplateOutput("0", "<?print int()?>");
1440        checkTemplateOutput("1", "<?print int(data)?>", "data", true);
1441        checkTemplateOutput("0", "<?print int(data)?>", "data", false);
1442        checkTemplateOutput("42", "<?print int(data)?>", "data", 42);
1443        checkTemplateOutput("4", "<?print int(data)?>", "data", 4.2);
1444        checkTemplateOutput("42", "<?print int(data)?>", "data", "42");
1445        checkTemplateOutput("66", "<?print int(data, 16)?>", "data", "42");
1446        checkTemplateOutput("42", "<?print int(obj=data, base=None)?>", "data", "42");
1447        checkTemplateOutput("66", "<?print int(obj=data, base=16)?>", "data", "42");
1448        checkTemplateOutput("9999999999", "<?print int(data)?>", "data", "9999999999");
1449        checkTemplateOutput("999999999999999999999999", "<?print int(data)?>", "data", "999999999999999999999999");
1450        checkTemplateOutput("999999999999999999999999", "<?print int(data)?>", "data", new BigInteger("999999999999999999999999"));
1451    }
1452
1453    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1454    public void function_int_null()
1455    {
1456        checkTemplateOutput("", "<?print int(data)?>", "data", null);
1457    }
1458
1459    @CauseTest(expectedCause=NumberFormatException.class)
1460    public void function_int_badstring()
1461    {
1462        checkTemplateOutput("", "<?print int(data)?>", "data", "foo");
1463    }
1464
1465    @CauseTest(expectedCause=TooManyArgumentsException.class)
1466    @Test
1467    public void function_int_3_args()
1468    {
1469        checkTemplateOutput("", "<?print int(1, 2, 3)?>");
1470    }
1471
1472    @Test
1473    public void function_float()
1474    {
1475        String source = "<?print float(data)?>";
1476
1477        checkTemplateOutput("0.0", "<?print float()?>");
1478        checkTemplateOutput("1.0", source, "data", true);
1479        checkTemplateOutput("0.0", source, "data", false);
1480        checkTemplateOutput("42.0", source, "data", 42);
1481        checkTemplateOutput("42.0", source, "data", "42");
1482        checkTemplateOutput("1.0", "<?print float(obj=data)?>", "data", true);
1483    }
1484
1485    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1486    public void function_float_null()
1487    {
1488        checkTemplateOutput("", "<?print float(data)?>", "data", null);
1489    }
1490
1491    @CauseTest(expectedCause=NumberFormatException.class)
1492    public void function_float_badstring()
1493    {
1494        checkTemplateOutput("", "<?print float(data)?>", "data", "foo");
1495    }
1496
1497    @CauseTest(expectedCause=TooManyArgumentsException.class)
1498    public void function_float_2_args()
1499    {
1500        checkTemplateOutput("", "<?print float(1, 2)?>");
1501    }
1502
1503    @Test
1504    public void function_list()
1505    {
1506        checkTemplateOutput("[]", "<?print list()?>");
1507        checkTemplateOutput("[1, 2]", "<?print list(data)?>", "data", asList(1, 2));
1508        checkTemplateOutput("[\"g\", \"u\", \"r\", \"k\"]", "<?print list(data)?>", "data", "gurk");
1509        checkTemplateOutput("[[\"foo\", 42]]", "<?print repr(list(data.items()))?>", "data", makeMap("foo", 42));
1510        checkTemplateOutput("[0, 1, 2]", "<?print repr(list(range(3)))?>");
1511        checkTemplateOutput("[1, 2, 3]", "<?print list(data)?>", "data", new Integer[]{1, 2, 3});
1512        checkTemplateOutput("[\"x\", \"y\"]", "<?print repr(list(data))?>", "data", new Point(17, 23));
1513        checkTemplateOutput("[\"g\", \"u\", \"r\", \"k\"]", "<?print list(iterable=data)?>", "data", "gurk");
1514    }
1515
1516    @CauseTest(expectedCause=TooManyArgumentsException.class)
1517    public void function_list_2_args()
1518    {
1519        checkTemplateOutput("", "<?print list(1, 2)?>");
1520    }
1521
1522    @Test
1523    public void function_len()
1524    {
1525        String source = "<?print len(data)?>";
1526
1527        checkTemplateOutput("3", source, "data", "foo");
1528        checkTemplateOutput("3", source, "data", asList(1, 2, 3));
1529        checkTemplateOutput("3", source, "data", new Integer[]{1, 2, 3});
1530        checkTemplateOutput("3", source, "data", makeMap("a", 1, "b", 2, "c", 3));
1531        checkTemplateOutput("2", source, "data", new Point(17, 23));
1532        checkTemplateOutput("3", "<?print len(sequence=data)?>", "data", "foo");
1533    }
1534
1535    @CauseTest(expectedCause=MissingArgumentException.class)
1536    public void function_len_0_args()
1537    {
1538        checkTemplateOutput("", "<?print len()?>");
1539    }
1540
1541    @CauseTest(expectedCause=TooManyArgumentsException.class)
1542    public void function_len_2_args()
1543    {
1544        checkTemplateOutput("", "<?print len(1, 2)?>");
1545    }
1546
1547    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1548    public void function_len_null()
1549    {
1550        checkTemplateOutput("", "<?print len(data)?>", "data", null);
1551    }
1552
1553    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1554    public void function_len_true()
1555    {
1556        checkTemplateOutput("", "<?print len(data)?>", "data", true);
1557    }
1558
1559    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1560    public void function_len_false()
1561    {
1562        checkTemplateOutput("", "<?print len(data)?>", "data", false);
1563    }
1564
1565    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1566    public void function_len_int()
1567    {
1568        checkTemplateOutput("", "<?print len(data)?>", "data", 42);
1569    }
1570
1571    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1572    public void function_len_float()
1573    {
1574        checkTemplateOutput("", "<?print len(data)?>", "data", 42.4);
1575    }
1576
1577    @Test
1578    public void function_any()
1579    {
1580        checkTemplateOutput("False", "<?print any('')?>");
1581        checkTemplateOutput("True", "<?print any('foo')?>");
1582        checkTemplateOutput("True", "<?print any(i > 7 for i in range(10))?>");
1583        checkTemplateOutput("False", "<?print any(i > 17 for i in range(10))?>");
1584        checkTemplateOutput("True", "<?print any(iterable='foo')?>");
1585    }
1586
1587    @CauseTest(expectedCause=MissingArgumentException.class)
1588    public void function_any_0_args()
1589    {
1590        checkTemplateOutput("", "<?print any()?>");
1591    }
1592
1593    @CauseTest(expectedCause=TooManyArgumentsException.class)
1594    public void function_any_2_args()
1595    {
1596        checkTemplateOutput("", "<?print any(1, 2)?>");
1597    }
1598
1599    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1600    public void function_any_none()
1601    {
1602        checkTemplateOutput("", "<?print any(None)?>");
1603    }
1604
1605    @Test
1606    public void function_all()
1607    {
1608        checkTemplateOutput("True", "<?print all('')?>");
1609        checkTemplateOutput("True", "<?print all('foo')?>");
1610        checkTemplateOutput("False", "<?print all(i < 7 for i in range(10))?>");
1611        checkTemplateOutput("True", "<?print all(i < 17 for i in range(10))?>");
1612        checkTemplateOutput("True", "<?print all(iterable='foo')?>");
1613    }
1614
1615    @CauseTest(expectedCause=MissingArgumentException.class)
1616    public void function_all_0_args()
1617    {
1618        checkTemplateOutput("", "<?print all()?>");
1619    }
1620
1621    @CauseTest(expectedCause=TooManyArgumentsException.class)
1622    public void function_all_2_args()
1623    {
1624        checkTemplateOutput("", "<?print all(1, 2)?>");
1625    }
1626
1627    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1628    public void function_all_none()
1629    {
1630        checkTemplateOutput("", "<?print all(None)?>");
1631    }
1632
1633    @Test
1634    public void function_enumerate()
1635    {
1636        String source1 = "<?for (i, value) in enumerate(data)?>(<?print value?>=<?print i?>)<?end for?>";
1637        checkTemplateOutput("(f=0)(o=1)(o=2)", source1, "data", "foo");
1638        checkTemplateOutput("(foo=0)(bar=1)", source1, "data", asList("foo", "bar"));
1639        checkTemplateOutput("(foo=0)", source1, "data", makeMap("foo", true));
1640
1641        String source2 = "<?for (i, value) in enumerate(data, 42)?>(<?print value?>=<?print i?>)<?end for?>";
1642        checkTemplateOutput("(f=42)(o=43)(o=44)", source2, "data", "foo");
1643
1644        String source2kw = "<?for (i, value) in enumerate(iterable=data, start=42)?>(<?print value?>=<?print i?>)<?end for?>";
1645        checkTemplateOutput("(f=42)(o=43)(o=44)", source2kw, "data", "foo");
1646    }
1647
1648    @CauseTest(expectedCause=MissingArgumentException.class)
1649    public void function_enumerate_0_args()
1650    {
1651        checkTemplateOutput("", "<?print enumerate()?>");
1652    }
1653
1654    @CauseTest(expectedCause=TooManyArgumentsException.class)
1655    public void function_enumerate_3_args()
1656    {
1657        checkTemplateOutput("", "<?print enumerate(1, 2, 3)?>");
1658    }
1659
1660    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1661    public void function_enumerate_null()
1662    {
1663        checkTemplateOutput("", "<?print enumerate(data)?>", "data", null);
1664    }
1665
1666    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1667    public void function_enumerate_true()
1668    {
1669        checkTemplateOutput("", "<?print enumerate(data)?>", "data", true);
1670    }
1671
1672    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1673    public void function_enumerate_false()
1674    {
1675        checkTemplateOutput("", "<?print enumerate(data)?>", "data", false);
1676    }
1677
1678    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1679    public void function_enumerate_int()
1680    {
1681        checkTemplateOutput("", "<?print enumerate(data)?>", "data", 42);
1682    }
1683
1684    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1685    public void function_enumerate_float()
1686    {
1687        checkTemplateOutput("", "<?print enumerate(data)?>", "data", 42.4);
1688    }
1689
1690    @Test
1691    public void function_enumfl()
1692    {
1693        String source1 = "<?for (i, f, l, value) in enumfl(data)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>";
1694        checkTemplateOutput("", source1, "data", "");
1695        checkTemplateOutput("[(?=0)]", source1, "data", "?");
1696        checkTemplateOutput("[(f=0)(o=1)(o=2)]", source1, "data", "foo");
1697        checkTemplateOutput("[(foo=0)(bar=1)]", source1, "data", asList("foo", "bar"));
1698        checkTemplateOutput("[(foo=0)]", source1, "data", makeMap("foo", true));
1699
1700        String source2 = "<?for (i, f, l, value) in enumfl(data, 42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>";
1701        checkTemplateOutput("[(f=42)(o=43)(o=44)]", source2, "data", "foo");
1702
1703        String source2kw = "<?for (i, f, l, value) in enumfl(iterable=data, start=42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>";
1704        checkTemplateOutput("[(f=42)(o=43)(o=44)]", source2kw, "data", "foo");
1705    }
1706
1707    @CauseTest(expectedCause=MissingArgumentException.class)
1708    public void function_enumfl_0_args()
1709    {
1710        checkTemplateOutput("", "<?print enumfl()?>");
1711    }
1712
1713    @CauseTest(expectedCause=TooManyArgumentsException.class)
1714    public void function_enumfl_3_args()
1715    {
1716        checkTemplateOutput("", "<?print enumfl(1, 2, 3)?>");
1717    }
1718
1719    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1720    public void function_enumfl_null()
1721    {
1722        checkTemplateOutput("", "<?print enumfl(data)?>", "data", null);
1723    }
1724
1725    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1726    public void function_enumfl_true()
1727    {
1728        checkTemplateOutput("", "<?print enumfl(data)?>", "data", true);
1729    }
1730
1731    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1732    public void function_enumfl_false()
1733    {
1734        checkTemplateOutput("", "<?print enumfl(data)?>", "data", false);
1735    }
1736
1737    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1738    public void function_enumfl_int()
1739    {
1740        checkTemplateOutput("", "<?print enumfl(data)?>", "data", 42);
1741    }
1742
1743    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1744    public void function_enumfl_float()
1745    {
1746        checkTemplateOutput("", "<?print enumfl(data)?>", "data", 42.4);
1747    }
1748
1749    @Test
1750    public void function_isfirstlast()
1751    {
1752        String source = "<?for (f, l, value) in isfirstlast(data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>";
1753
1754        checkTemplateOutput("", source, "data", "");
1755        checkTemplateOutput("[(?)]", source, "data", "?");
1756        checkTemplateOutput("[(f)(o)(o)]", source, "data", "foo");
1757        checkTemplateOutput("[(foo)(bar)]", source, "data", asList("foo", "bar"));
1758        checkTemplateOutput("[(foo)]", source, "data", makeMap("foo", true));
1759
1760        String sourcekw = "<?for (f, l, value) in isfirstlast(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>";
1761        checkTemplateOutput("[(f)(o)(o)]", sourcekw, "data", "foo");
1762    }
1763
1764    @CauseTest(expectedCause=MissingArgumentException.class)
1765    public void function_isfirstlast_0_args()
1766    {
1767        checkTemplateOutput("", "<?print isfirstlast()?>");
1768    }
1769
1770    @CauseTest(expectedCause=TooManyArgumentsException.class)
1771    public void function_isfirstlast_2_args()
1772    {
1773        checkTemplateOutput("", "<?print isfirstlast(1, 2)?>");
1774    }
1775
1776    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1777    public void function_isfirstlast_null()
1778    {
1779        checkTemplateOutput("", "<?print isfirstlast(data)?>", "data", null);
1780    }
1781
1782    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1783    public void function_isfirstlast_true()
1784    {
1785        checkTemplateOutput("", "<?print isfirstlast(data)?>", "data", true);
1786    }
1787
1788    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1789    public void function_isfirstlast_false()
1790    {
1791        checkTemplateOutput("", "<?print isfirstlast(data)?>", "data", false);
1792    }
1793
1794    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1795    public void function_isfirstlast_int()
1796    {
1797        checkTemplateOutput("", "<?print isfirstlast(data)?>", "data", 42);
1798    }
1799
1800    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1801    public void function_isfirstlast_float()
1802    {
1803        checkTemplateOutput("", "<?print isfirstlast(data)?>", "data", 42.4);
1804    }
1805
1806    @Test
1807    public void function_isfirst()
1808    {
1809        String source = "<?for (f, value) in isfirst(data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>";
1810
1811        checkTemplateOutput("", source, "data", "");
1812        checkTemplateOutput("[(?)", source, "data", "?");
1813        checkTemplateOutput("[(f)(o)(o)", source, "data", "foo");
1814        checkTemplateOutput("[(foo)(bar)", source, "data", asList("foo", "bar"));
1815        checkTemplateOutput("[(foo)", source, "data", makeMap("foo", true));
1816
1817        String sourcekw = "<?for (f, value) in isfirst(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>";
1818        checkTemplateOutput("[(f)(o)(o)", sourcekw, "data", "foo");
1819    }
1820
1821    @CauseTest(expectedCause=MissingArgumentException.class)
1822    public void function_isfirst_0_args()
1823    {
1824        checkTemplateOutput("", "<?print isfirst()?>");
1825    }
1826
1827    @CauseTest(expectedCause=TooManyArgumentsException.class)
1828    public void function_isfirst_2_args()
1829    {
1830        checkTemplateOutput("", "<?print isfirst(1, 2)?>");
1831    }
1832
1833    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1834    public void function_isfirst_null()
1835    {
1836        checkTemplateOutput("", "<?print isfirst(data)?>", "data", null);
1837    }
1838
1839    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1840    public void function_isfirst_true()
1841    {
1842        checkTemplateOutput("", "<?print isfirst(data)?>", "data", true);
1843    }
1844
1845    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1846    public void function_isfirst_false()
1847    {
1848        checkTemplateOutput("", "<?print isfirst(data)?>", "data", false);
1849    }
1850
1851    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1852    public void function_isfirst_int()
1853    {
1854        checkTemplateOutput("", "<?print isfirst(data)?>", "data", 42);
1855    }
1856
1857    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1858    public void function_isfirst_float()
1859    {
1860        checkTemplateOutput("", "<?print isfirst(data)?>", "data", 42.4);
1861    }
1862
1863    @Test
1864    public void function_islast()
1865    {
1866        String source = "<?for (l, value) in islast(data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>";
1867
1868        checkTemplateOutput("", source, "data", "");
1869        checkTemplateOutput("(?)]", source, "data", "?");
1870        checkTemplateOutput("(f)(o)(o)]", source, "data", "foo");
1871        checkTemplateOutput("(foo)(bar)]", source, "data", asList("foo", "bar"));
1872        checkTemplateOutput("(foo)]", source, "data", makeMap("foo", true));
1873
1874        String sourcekw = "<?for (l, value) in islast(iterable=data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>";
1875        checkTemplateOutput("(f)(o)(o)]", sourcekw, "data", "foo");
1876    }
1877
1878    @CauseTest(expectedCause=MissingArgumentException.class)
1879    public void function_islast_0_args()
1880    {
1881        checkTemplateOutput("", "<?print islast()?>");
1882    }
1883
1884    @CauseTest(expectedCause=TooManyArgumentsException.class)
1885    public void function_islast_2_args()
1886    {
1887        checkTemplateOutput("", "<?print islast(1, 2)?>");
1888    }
1889
1890    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1891    public void function_islast_null()
1892    {
1893        checkTemplateOutput("", "<?print islast(data)?>", "data", null);
1894    }
1895
1896    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1897    public void function_islast_true()
1898    {
1899        checkTemplateOutput("", "<?print islast(data)?>", "data", true);
1900    }
1901
1902    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1903    public void function_islast_false()
1904    {
1905        checkTemplateOutput("", "<?print islast(data)?>", "data", false);
1906    }
1907
1908    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1909    public void function_islast_int()
1910    {
1911        checkTemplateOutput("", "<?print islast(data)?>", "data", 42);
1912    }
1913
1914    @CauseTest(expectedCause=ArgumentTypeMismatchException.class)
1915    public void function_islast_float()
1916    {
1917        checkTemplateOutput("", "<?print islast(data)?>", "data", 42.4);
1918    }
1919
1920    @Test
1921    public void function_isundefined()
1922    {
1923        String source = "<?print isundefined(data)?>";
1924
1925        checkTemplateOutput("True", source, "data", new UndefinedKey("foo"));
1926        checkTemplateOutput("False", source, "data", null);
1927        checkTemplateOutput("False", source, "data", true);
1928        checkTemplateOutput("False", source, "data", false);
1929        checkTemplateOutput("False", source, "data", 42);
1930        checkTemplateOutput("False", source, "data", 4.2);
1931        checkTemplateOutput("False", source, "data", "foo");
1932        checkTemplateOutput("False", source, "data", new Date());
1933        checkTemplateOutput("False", source, "data", new TimeDelta(1));
1934        checkTemplateOutput("False", source, "data", new MonthDelta(1));
1935        checkTemplateOutput("False", source, "data", asList());
1936        checkTemplateOutput("False", source, "data", makeMap());
1937        checkTemplateOutput("False", source, "data", getTemplate(""));
1938        checkTemplateOutput("False", source, "data", getTemplate(""));
1939        checkTemplateOutput("False", "<?print isundefined(repr)?>");
1940        checkTemplateOutput("False", "<?print isundefined(obj=data)?>", "data", null);
1941    }
1942
1943    @CauseTest(expectedCause=MissingArgumentException.class)
1944    public void function_isundefined_0_args()
1945    {
1946        checkTemplateOutput("", "<?print isundefined()?>");
1947    }
1948
1949    @CauseTest(expectedCause=TooManyArgumentsException.class)
1950    public void function_isundefined_2_args()
1951    {
1952        checkTemplateOutput("", "<?print isundefined(1, 2)?>");
1953    }
1954
1955    @Test
1956    public void function_isdefined()
1957    {
1958        String source = "<?print isdefined(data)?>";
1959
1960        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
1961        checkTemplateOutput("True", source, "data", null);
1962        checkTemplateOutput("True", source, "data", true);
1963        checkTemplateOutput("True", source, "data", false);
1964        checkTemplateOutput("True", source, "data", 42);
1965        checkTemplateOutput("True", source, "data", 4.2);
1966        checkTemplateOutput("True", source, "data", "foo");
1967        checkTemplateOutput("True", source, "data", new Date());
1968        checkTemplateOutput("True", source, "data", new TimeDelta(1));
1969        checkTemplateOutput("True", source, "data", new MonthDelta(1));
1970        checkTemplateOutput("True", source, "data", asList());
1971        checkTemplateOutput("True", source, "data", makeMap());
1972        checkTemplateOutput("True", source, "data", getTemplate(""));
1973        checkTemplateOutput("True", "<?print isdefined(repr)?>");
1974        checkTemplateOutput("True", source, "data", new Color(0, 0, 0));
1975        checkTemplateOutput("True", "<?print isdefined(obj=data)?>", "data", null);
1976    }
1977
1978    @CauseTest(expectedCause=MissingArgumentException.class)
1979    public void function_isdefined_0_args()
1980    {
1981        checkTemplateOutput("", "<?print isdefined()?>");
1982    }
1983
1984    @CauseTest(expectedCause=TooManyArgumentsException.class)
1985    public void function_isdefined_2_args()
1986    {
1987        checkTemplateOutput("", "<?print isdefined(1, 2)?>");
1988    }
1989
1990    @Test
1991    public void function_isnone()
1992    {
1993        String source = "<?print isnone(data)?>";
1994
1995        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
1996        checkTemplateOutput("True", source, "data", null);
1997        checkTemplateOutput("False", source, "data", true);
1998        checkTemplateOutput("False", source, "data", false);
1999        checkTemplateOutput("False", source, "data", 42);
2000        checkTemplateOutput("False", source, "data", 4.2);
2001        checkTemplateOutput("False", source, "data", "foo");
2002        checkTemplateOutput("False", source, "data", new Date());
2003        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2004        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2005        checkTemplateOutput("False", source, "data", asList());
2006        checkTemplateOutput("False", source, "data", makeMap());
2007        checkTemplateOutput("False", source, "data", getTemplate(""));
2008        checkTemplateOutput("False", "<?print isnone(repr)?>");
2009        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2010        checkTemplateOutput("True", "<?print isnone(obj=data)?>", "data", null);
2011    }
2012
2013    @CauseTest(expectedCause=MissingArgumentException.class)
2014    public void function_isnone_0_args()
2015    {
2016        checkTemplateOutput("", "<?print isnone()?>");
2017    }
2018
2019    @CauseTest(expectedCause=TooManyArgumentsException.class)
2020    public void function_isnone_2_args()
2021    {
2022        checkTemplateOutput("", "<?print isnone(1, 2)?>");
2023    }
2024
2025    @Test
2026    public void function_isbool()
2027    {
2028        String source = "<?print isbool(data)?>";
2029
2030        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2031        checkTemplateOutput("False", source, "data", null);
2032        checkTemplateOutput("True", source, "data", true);
2033        checkTemplateOutput("True", source, "data", false);
2034        checkTemplateOutput("False", source, "data", 42);
2035        checkTemplateOutput("False", source, "data", 4.2);
2036        checkTemplateOutput("False", source, "data", "foo");
2037        checkTemplateOutput("False", source, "data", new Date());
2038        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2039        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2040        checkTemplateOutput("False", source, "data", asList());
2041        checkTemplateOutput("False", source, "data", makeMap());
2042        checkTemplateOutput("False", source, "data", getTemplate(""));
2043        checkTemplateOutput("False", "<?print isbool(repr)?>");
2044        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2045        checkTemplateOutput("False", "<?print isbool(obj=data)?>", "data", null);
2046    }
2047
2048    @CauseTest(expectedCause=MissingArgumentException.class)
2049    public void function_isbool_0_args()
2050    {
2051        checkTemplateOutput("", "<?print isbool()?>");
2052    }
2053
2054    @CauseTest(expectedCause=TooManyArgumentsException.class)
2055    public void function_isbool_2_args()
2056    {
2057        checkTemplateOutput("", "<?print isbool(1, 2)?>");
2058    }
2059
2060    @Test
2061    public void function_isint()
2062    {
2063        String source = "<?print isint(data)?>";
2064
2065        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2066        checkTemplateOutput("False", source, "data", null);
2067        checkTemplateOutput("False", source, "data", true);
2068        checkTemplateOutput("False", source, "data", false);
2069        checkTemplateOutput("True", source, "data", 42);
2070        checkTemplateOutput("False", source, "data", 4.2);
2071        checkTemplateOutput("False", source, "data", "foo");
2072        checkTemplateOutput("False", source, "data", new Date());
2073        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2074        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2075        checkTemplateOutput("False", source, "data", asList());
2076        checkTemplateOutput("False", source, "data", makeMap());
2077        checkTemplateOutput("False", source, "data", getTemplate(""));
2078        checkTemplateOutput("False", "<?print isint(repr)?>");
2079        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2080        checkTemplateOutput("False", "<?print isint(obj=data)?>", "data", null);
2081    }
2082
2083    @CauseTest(expectedCause=MissingArgumentException.class)
2084    public void function_isint_0_args()
2085    {
2086        checkTemplateOutput("", "<?print isint()?>");
2087    }
2088
2089    @CauseTest(expectedCause=TooManyArgumentsException.class)
2090    public void function_isint_2_args()
2091    {
2092        checkTemplateOutput("", "<?print isint(1, 2)?>");
2093    }
2094
2095    @Test
2096    public void function_isfloat()
2097    {
2098        String source = "<?print isfloat(data)?>";
2099
2100        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2101        checkTemplateOutput("False", source, "data", null);
2102        checkTemplateOutput("False", source, "data", true);
2103        checkTemplateOutput("False", source, "data", false);
2104        checkTemplateOutput("False", source, "data", 42);
2105        checkTemplateOutput("True", source, "data", 4.2);
2106        checkTemplateOutput("False", source, "data", "foo");
2107        checkTemplateOutput("False", source, "data", new Date());
2108        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2109        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2110        checkTemplateOutput("False", source, "data", asList());
2111        checkTemplateOutput("False", source, "data", makeMap());
2112        checkTemplateOutput("False", source, "data", getTemplate(""));
2113        checkTemplateOutput("False", "<?print isfloat(repr)?>");
2114        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2115        checkTemplateOutput("False", "<?print isfloat(obj=data)?>", "data", null);
2116    }
2117
2118    @CauseTest(expectedCause=MissingArgumentException.class)
2119    public void function_isfloat_0_args()
2120    {
2121        checkTemplateOutput("", "<?print isfloat()?>");
2122    }
2123
2124    @CauseTest(expectedCause=TooManyArgumentsException.class)
2125    public void function_isfloat_2_args()
2126    {
2127        checkTemplateOutput("", "<?print isfloat(1, 2)?>");
2128    }
2129
2130    @Test
2131    public void function_isstr()
2132    {
2133        String source = "<?print isstr(data)?>";
2134
2135        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2136        checkTemplateOutput("False", source, "data", null);
2137        checkTemplateOutput("False", source, "data", true);
2138        checkTemplateOutput("False", source, "data", false);
2139        checkTemplateOutput("False", source, "data", 42);
2140        checkTemplateOutput("False", source, "data", 4.2);
2141        checkTemplateOutput("True", source, "data", "foo");
2142        checkTemplateOutput("False", source, "data", new Date());
2143        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2144        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2145        checkTemplateOutput("False", source, "data", asList());
2146        checkTemplateOutput("False", source, "data", makeMap());
2147        checkTemplateOutput("False", source, "data", getTemplate(""));
2148        checkTemplateOutput("False", "<?print isstr(repr)?>");
2149        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2150        checkTemplateOutput("False", "<?print isstr(obj=data)?>", "data", null);
2151    }
2152
2153    @CauseTest(expectedCause=MissingArgumentException.class)
2154    public void function_isstr_0_args()
2155    {
2156        checkTemplateOutput("", "<?print isstr()?>");
2157    }
2158
2159    @CauseTest(expectedCause=TooManyArgumentsException.class)
2160    public void function_isstr_2_args()
2161    {
2162        checkTemplateOutput("", "<?print isstr(1, 2)?>");
2163    }
2164
2165    @Test
2166    public void function_isdate()
2167    {
2168        String source = "<?print isdate(data)?>";
2169
2170        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2171        checkTemplateOutput("False", source, "data", null);
2172        checkTemplateOutput("False", source, "data", true);
2173        checkTemplateOutput("False", source, "data", false);
2174        checkTemplateOutput("False", source, "data", 42);
2175        checkTemplateOutput("False", source, "data", 4.2);
2176        checkTemplateOutput("False", source, "data", "foo");
2177        checkTemplateOutput("True", source, "data", new Date());
2178        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2179        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2180        checkTemplateOutput("False", source, "data", asList());
2181        checkTemplateOutput("False", source, "data", makeMap());
2182        checkTemplateOutput("False", source, "data", getTemplate(""));
2183        checkTemplateOutput("False", "<?print isdate(repr)?>");
2184        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2185        checkTemplateOutput("False", "<?print isdate(obj=data)?>", "data", null);
2186    }
2187
2188    @CauseTest(expectedCause=MissingArgumentException.class)
2189    public void function_isdate_0_args()
2190    {
2191        checkTemplateOutput("", "<?print isdate()?>");
2192    }
2193
2194    @CauseTest(expectedCause=TooManyArgumentsException.class)
2195    public void function_isdate_2_args()
2196    {
2197        checkTemplateOutput("", "<?print isdate(1, 2)?>");
2198    }
2199
2200    @Test
2201    public void function_islist()
2202    {
2203        String source = "<?print islist(data)?>";
2204
2205        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2206        checkTemplateOutput("False", source, "data", null);
2207        checkTemplateOutput("False", source, "data", true);
2208        checkTemplateOutput("False", source, "data", false);
2209        checkTemplateOutput("False", source, "data", 42);
2210        checkTemplateOutput("False", source, "data", 4.2);
2211        checkTemplateOutput("False", source, "data", "foo");
2212        checkTemplateOutput("False", source, "data", new Date());
2213        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2214        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2215        checkTemplateOutput("True", source, "data", asList());
2216        checkTemplateOutput("True", source, "data", new Integer[]{1, 2, 3});
2217        checkTemplateOutput("False", source, "data", makeMap());
2218        checkTemplateOutput("False", source, "data", getTemplate(""));
2219        checkTemplateOutput("False", "<?print islist(repr)?>");
2220        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2221        checkTemplateOutput("False", "<?print islist(obj=data)?>", "data", null);
2222    }
2223
2224    @CauseTest(expectedCause=MissingArgumentException.class)
2225    public void function_islist_0_args()
2226    {
2227        checkTemplateOutput("", "<?print islist()?>");
2228    }
2229
2230    @CauseTest(expectedCause=TooManyArgumentsException.class)
2231    public void function_islist_2_args()
2232    {
2233        checkTemplateOutput("", "<?print islist(1, 2)?>");
2234    }
2235
2236    @Test
2237    public void function_isdict()
2238    {
2239        String source = "<?print isdict(data)?>";
2240
2241        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2242        checkTemplateOutput("False", source, "data", null);
2243        checkTemplateOutput("False", source, "data", true);
2244        checkTemplateOutput("False", source, "data", false);
2245        checkTemplateOutput("False", source, "data", 42);
2246        checkTemplateOutput("False", source, "data", 4.2);
2247        checkTemplateOutput("False", source, "data", "foo");
2248        checkTemplateOutput("False", source, "data", new Date());
2249        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2250        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2251        checkTemplateOutput("False", source, "data", asList());
2252        checkTemplateOutput("True", source, "data", makeMap());
2253        checkTemplateOutput("False", source, "data", getTemplate(""));
2254        checkTemplateOutput("False", "<?print isdict(repr)?>");
2255        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2256        checkTemplateOutput("False", "<?print isdict(obj=data)?>", "data", null);
2257    }
2258
2259    @CauseTest(expectedCause=MissingArgumentException.class)
2260    public void function_isdict_0_args()
2261    {
2262        checkTemplateOutput("", "<?print isdict()?>");
2263    }
2264
2265    @CauseTest(expectedCause=TooManyArgumentsException.class)
2266    public void function_isdict_2_args()
2267    {
2268        checkTemplateOutput("", "<?print isdict(1, 2)?>");
2269    }
2270
2271    @Test
2272    public void function_istemplate()
2273    {
2274        String source = "<?print istemplate(data)?>";
2275
2276        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2277        checkTemplateOutput("False", source, "data", null);
2278        checkTemplateOutput("False", source, "data", true);
2279        checkTemplateOutput("False", source, "data", false);
2280        checkTemplateOutput("False", source, "data", 42);
2281        checkTemplateOutput("False", source, "data", 4.2);
2282        checkTemplateOutput("False", source, "data", "foo");
2283        checkTemplateOutput("False", source, "data", new Date());
2284        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2285        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2286        checkTemplateOutput("False", source, "data", asList());
2287        checkTemplateOutput("False", source, "data", makeMap());
2288        checkTemplateOutput("True", source, "data", getTemplate(""));
2289        checkTemplateOutput("False", "<?print istemplate(repr)?>");
2290        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2291        checkTemplateOutput("False", "<?print istemplate(obj=data)?>", "data", null);
2292    }
2293
2294    @CauseTest(expectedCause=MissingArgumentException.class)
2295    public void function_istemplate_0_args()
2296    {
2297        checkTemplateOutput("", "<?print istemplate()?>");
2298    }
2299
2300    @CauseTest(expectedCause=TooManyArgumentsException.class)
2301    public void function_istemplate_2_args()
2302    {
2303        checkTemplateOutput("", "<?print istemplate(1, 2)?>");
2304    }
2305
2306    @Test
2307    public void function_isfunction()
2308    {
2309        String source = "<?print isfunction(data)?>";
2310
2311        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2312        checkTemplateOutput("False", source, "data", null);
2313        checkTemplateOutput("False", source, "data", true);
2314        checkTemplateOutput("False", source, "data", false);
2315        checkTemplateOutput("False", source, "data", 42);
2316        checkTemplateOutput("False", source, "data", 4.2);
2317        checkTemplateOutput("False", source, "data", "foo");
2318        checkTemplateOutput("False", source, "data", new Date());
2319        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2320        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2321        checkTemplateOutput("False", source, "data", asList());
2322        checkTemplateOutput("False", source, "data", makeMap());
2323        checkTemplateOutput("True", source, "data", getTemplate(""));
2324        checkTemplateOutput("True", "<?print isfunction(repr)?>");
2325        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2326        checkTemplateOutput("False", "<?print isfunction(obj=data)?>", "data", null);
2327    }
2328
2329    @CauseTest(expectedCause=MissingArgumentException.class)
2330    public void function_isfunction_0_args()
2331    {
2332        checkTemplateOutput("", "<?print isfunction()?>");
2333    }
2334
2335    @CauseTest(expectedCause=TooManyArgumentsException.class)
2336    public void function_isfunction_2_args()
2337    {
2338        checkTemplateOutput("", "<?print isfunction(1, 2)?>");
2339    }
2340
2341    @Test
2342    public void function_iscolor()
2343    {
2344        String source = "<?print iscolor(data)?>";
2345
2346        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2347        checkTemplateOutput("False", source, "data", null);
2348        checkTemplateOutput("False", source, "data", true);
2349        checkTemplateOutput("False", source, "data", false);
2350        checkTemplateOutput("False", source, "data", 42);
2351        checkTemplateOutput("False", source, "data", 4.2);
2352        checkTemplateOutput("False", source, "data", "foo");
2353        checkTemplateOutput("False", source, "data", new Date());
2354        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2355        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2356        checkTemplateOutput("False", source, "data", asList());
2357        checkTemplateOutput("False", source, "data", makeMap());
2358        checkTemplateOutput("False", source, "data", getTemplate(""));
2359        checkTemplateOutput("False", "<?print iscolor(repr)?>");
2360        checkTemplateOutput("True", source, "data", new Color(0, 0, 0));
2361        checkTemplateOutput("False", "<?print iscolor(obj=data)?>", "data", null);
2362    }
2363
2364    @CauseTest(expectedCause=MissingArgumentException.class)
2365    public void function_iscolor_0_args()
2366    {
2367        checkTemplateOutput("", "<?print iscolor()?>");
2368    }
2369
2370    @CauseTest(expectedCause=TooManyArgumentsException.class)
2371    public void function_iscolor_2_args()
2372    {
2373        checkTemplateOutput("", "<?print iscolor(1, 2)?>");
2374    }
2375
2376    @Test
2377    public void function_istimedelta()
2378    {
2379        String source = "<?print istimedelta(data)?>";
2380
2381        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2382        checkTemplateOutput("False", source, "data", null);
2383        checkTemplateOutput("False", source, "data", true);
2384        checkTemplateOutput("False", source, "data", false);
2385        checkTemplateOutput("False", source, "data", 42);
2386        checkTemplateOutput("False", source, "data", 4.2);
2387        checkTemplateOutput("False", source, "data", "foo");
2388        checkTemplateOutput("False", source, "data", new Date());
2389        checkTemplateOutput("True", source, "data", new TimeDelta(1));
2390        checkTemplateOutput("False", source, "data", new MonthDelta(1));
2391        checkTemplateOutput("False", source, "data", asList());
2392        checkTemplateOutput("False", source, "data", makeMap());
2393        checkTemplateOutput("False", source, "data", getTemplate(""));
2394        checkTemplateOutput("False", "<?print istimedelta(repr)?>");
2395        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2396        checkTemplateOutput("False", "<?print istimedelta(obj=data)?>", "data", null);
2397    }
2398
2399    @CauseTest(expectedCause=MissingArgumentException.class)
2400    public void function_istimedelta_0_args()
2401    {
2402        checkTemplateOutput("", "<?print istimedelta()?>");
2403    }
2404
2405    @CauseTest(expectedCause=TooManyArgumentsException.class)
2406    public void function_istimedelta_2_args()
2407    {
2408        checkTemplateOutput("", "<?print istimedelta(1, 2)?>");
2409    }
2410
2411    @Test
2412    public void function_ismonthdelta()
2413    {
2414        String source = "<?print ismonthdelta(data)?>";
2415
2416        checkTemplateOutput("False", source, "data", new UndefinedKey("foo"));
2417        checkTemplateOutput("False", source, "data", null);
2418        checkTemplateOutput("False", source, "data", true);
2419        checkTemplateOutput("False", source, "data", false);
2420        checkTemplateOutput("False", source, "data", 42);
2421        checkTemplateOutput("False", source, "data", 4.2);
2422        checkTemplateOutput("False", source, "data", "foo");
2423        checkTemplateOutput("False", source, "data", new Date());
2424        checkTemplateOutput("False", source, "data", new TimeDelta(1));
2425        checkTemplateOutput("True", source, "data", new MonthDelta(1));
2426        checkTemplateOutput("False", source, "data", asList());
2427        checkTemplateOutput("False", source, "data", makeMap());
2428        checkTemplateOutput("False", source, "data", getTemplate(""));
2429        checkTemplateOutput("False", "<?print ismonthdelta(repr)?>");
2430        checkTemplateOutput("False", source, "data", new Color(0, 0, 0));
2431        checkTemplateOutput("False", "<?print ismonthdelta(obj=data)?>", "data", null);
2432    }
2433
2434    @CauseTest(expectedCause=MissingArgumentException.class)
2435    public void function_ismonthdelta_0_args()
2436    {
2437        checkTemplateOutput("", "<?print ismonthdelta()?>");
2438    }
2439
2440    @CauseTest(expectedCause=TooManyArgumentsException.class)
2441    public void function_ismonthdelta_2_args()
2442    {
2443        checkTemplateOutput("", "<?print ismonthdelta(1, 2)?>");
2444    }
2445
2446    @Test
2447    public void function_repr()
2448    {
2449        String source = "<?print repr(data)?>";
2450
2451        checkTemplateOutput("None", source, "data", null);
2452        checkTemplateOutput("True", source, "data", true);
2453        checkTemplateOutput("False", source, "data", false);
2454        checkTemplateOutput("42", source, "data", 42);
2455        checkTemplateOutput("42.5", source, "data", 42.5);
2456        checkTemplateOutput("\"foo\"", source, "data", "foo");
2457        checkTemplateOutput("[1, 2, 3]", source, "data", asList(1, 2, 3));
2458        checkTemplateOutput("[1, 2, 3]", source, "data", new Integer[]{1, 2, 3});
2459        checkTemplateOutput("{\"a\": 1}", source, "data", makeMap("a", 1));
2460        checkTemplateOutput2("{\"a\": 1, \"b\": 2}", "{\"b\": 2, \"a\": 1}", source, "data", makeMap("a", 1, "b", 2));
2461        checkTemplateOutput("@(2011-02-07T12:34:56.123000)", source, "data", FunctionDate.call(2011, 2, 7, 12, 34, 56, 123000));
2462        checkTemplateOutput("@(2011-02-07T12:34:56)", source, "data", FunctionDate.call(2011, 2, 7, 12, 34, 56));
2463        checkTemplateOutput("@(2011-02-07)", source, "data", FunctionDate.call(2011, 2, 7));
2464        checkTemplateOutput("@(2011-02-07)", source, "data", FunctionDate.call(2011, 2, 7));
2465        checkTemplateOutput("None", "<?print repr(obj=data)?>", "data", null);
2466    }
2467
2468    @CauseTest(expectedCause=MissingArgumentException.class)
2469    public void function_repr_0_args()
2470    {
2471        checkTemplateOutput("", "<?print repr()?>");
2472    }
2473
2474    @CauseTest(expectedCause=TooManyArgumentsException.class)
2475    public void function_repr_2_args()
2476    {
2477        checkTemplateOutput("", "<?print repr(1, 2)?>");
2478    }
2479
2480    @Test
2481    public void function_format_date()
2482    {
2483        Date t = FunctionDate.call(2011, 1, 25, 13, 34, 56, 987000);
2484
2485        String source2 = "<?print format(data, fmt)?>";
2486        String source3 = "<?print format(data, fmt, lang)?>";
2487        String source3kw = "<?print format(obj=data, fmt=fmt, lang=lang)?>";
2488
2489        checkTemplateOutput("2011", source2, "data", t, "fmt", "%Y");
2490        checkTemplateOutput("01", source2, "data", t, "fmt", "%m");
2491        checkTemplateOutput("25", source2, "data", t, "fmt", "%d");
2492        checkTemplateOutput("13", source2, "data", t, "fmt", "%H");
2493        checkTemplateOutput("34", source2, "data", t, "fmt", "%M");
2494        checkTemplateOutput("56", source2, "data", t, "fmt", "%S");
2495        checkTemplateOutput("987000", source2, "data", t, "fmt", "%f");
2496        checkTemplateOutput("Tue", source2, "data", t, "fmt", "%a");
2497        checkTemplateOutput("Tue", source3, "data", t, "fmt", "%a", "lang", null);
2498        checkTemplateOutput("Tue", source3, "data", t, "fmt", "%a", "lang", "en");
2499        checkTemplateOutput("Di", source3, "data", t, "fmt", "%a", "lang", "de");
2500        checkTemplateOutput("Di", source3, "data", t, "fmt", "%a", "lang", "de_DE");
2501        checkTemplateOutput("Tuesday", source2, "data", t, "fmt", "%A");
2502        checkTemplateOutput("Tuesday", source3, "data", t, "fmt", "%A", "lang", null);
2503        checkTemplateOutput("Tuesday", source3, "data", t, "fmt", "%A", "lang", "en");
2504        checkTemplateOutput("Dienstag", source3, "data", t, "fmt", "%A", "lang", "de");
2505        checkTemplateOutput("Dienstag", source3, "data", t, "fmt", "%A", "lang", "de_DE");
2506        checkTemplateOutput("Jan", source2, "data", t, "fmt", "%b");
2507        checkTemplateOutput("Jan", source3, "data", t, "fmt", "%b", "lang", null);
2508        checkTemplateOutput("Jan", source3, "data", t, "fmt", "%b", "lang", "en");
2509        checkTemplateOutput("Jan", source3, "data", t, "fmt", "%b", "lang", "de");
2510        checkTemplateOutput("Jan", source3, "data", t, "fmt", "%b", "lang", "de_DE");
2511        checkTemplateOutput("January", source2, "data", t, "fmt", "%B");
2512        checkTemplateOutput("January", source3, "data", t, "fmt", "%B", "lang", null);
2513        checkTemplateOutput("January", source3, "data", t, "fmt", "%B", "lang", "en");
2514        checkTemplateOutput("Januar", source3, "data", t, "fmt", "%B", "lang", "de");
2515        checkTemplateOutput("Januar", source3, "data", t, "fmt", "%B", "lang", "de_DE");
2516        checkTemplateOutput("01", source2, "data", t, "fmt", "%I");
2517        checkTemplateOutput("025", source2, "data", t, "fmt", "%j");
2518        checkTemplateOutput("PM", source2, "data", t, "fmt", "%p");
2519        checkTemplateOutput("04", source2, "data", t, "fmt", "%U");
2520        checkTemplateOutput("2", source2, "data", t, "fmt", "%w");
2521        checkTemplateOutput("04", source2, "data", t, "fmt", "%W");
2522        checkTemplateOutput("11", source2, "data", t, "fmt", "%y");
2523        checkTemplateOutput("Tue 25 Jan 2011 01:34:56 PM", source2, "data", t, "fmt", "%c");
2524        checkTemplateOutput("01/25/2011", source2, "data", t, "fmt", "%x");
2525        checkTemplateOutput("01/25/2011", source3, "data", t, "fmt", "%x", "lang", null);
2526        checkTemplateOutput("01/25/2011", source3, "data", t, "fmt", "%x", "lang", "en");
2527        checkTemplateOutput("25.01.2011", source3, "data", t, "fmt", "%x", "lang", "de");
2528        checkTemplateOutput("25.01.2011", source3, "data", t, "fmt", "%x", "lang", "de_DE");
2529        checkTemplateOutput("13:34:56", source2, "data", t, "fmt", "%X");
2530        checkTemplateOutput("13:34:56", source3, "data", t, "fmt", "%X", "lang", null);
2531        checkTemplateOutput("13:34:56", source3, "data", t, "fmt", "%X", "lang", "en");
2532        checkTemplateOutput("13:34:56", source3, "data", t, "fmt", "%X", "lang", "de");
2533        checkTemplateOutput("13:34:56", source3, "data", t, "fmt", "%X", "lang", "de_DE");
2534        checkTemplateOutput("%", source2, "fmt", "%%", "data", t);
2535        checkTemplateOutput("2011", source3kw, "data", t, "fmt", "%Y", "lang", "de_DE");
2536    }
2537
2538    @Test
2539    public void function_format_int()
2540    {
2541        String source2 = "<?print format(data, fmt)?>";
2542        String source3 = "<?print format(data, fmt, lang)?>";
2543
2544        checkTemplateOutput("42", source2, "data", 42, "fmt", "");
2545        checkTemplateOutput("-42", source2, "data", -42, "fmt", "");
2546        checkTemplateOutput("   42", source2, "data", 42, "fmt", "5");
2547        checkTemplateOutput("00042", source2, "data", 42, "fmt", "05");
2548        checkTemplateOutput("-0042", source2, "data", -42, "fmt", "05");
2549        checkTemplateOutput("+0042", source2, "data", 42, "fmt", "+05");
2550        checkTemplateOutput(" +101010", source2, "data", 42, "fmt", "+8b");
2551        checkTemplateOutput(" +0b101010", source2, "data", 42, "fmt", "+#10b");
2552        checkTemplateOutput("52", source2, "data", 42, "fmt", "o");
2553        checkTemplateOutput("+0x2a", source2, "data", 42, "fmt", "+#x");
2554        checkTemplateOutput("+0X2A", source2, "data", 42, "fmt", "+#X");
2555        checkTemplateOutput("42   ", source2, "data", 42, "fmt", "<5");
2556        checkTemplateOutput("   42", source2, "data", 42, "fmt", ">5");
2557        checkTemplateOutput("???42", source2, "data", 42, "fmt", "?>5");
2558        checkTemplateOutput(" 42  ", source2, "data", 42, "fmt", "^5");
2559        checkTemplateOutput(" ??42", source2, "data", 42, "fmt", "?= 5");
2560        checkTemplateOutput(" 0b??101010", source2, "data", 42, "fmt", "?= #11b");
2561        checkTemplateOutput("00001", source2, "data", true, "fmt", "05");
2562        checkTemplateOutput("00042", source2, "data", new BigInteger("42"), "fmt", "05");
2563    }
2564
2565    @Test
2566    public void function_chr()
2567    {
2568        String source = "<?print chr(data)?>";
2569        checkTemplateOutput("\u0000", source, "data", 0);
2570        checkTemplateOutput("a", source, "data", (int)'a');
2571        checkTemplateOutput("\u20ac", source, "data", 0x20ac);
2572
2573        String sourcekw = "<?print chr(i=data)?>";
2574        checkTemplateOutput("\u0000", sourcekw, "data", 0);
2575    }
2576
2577    @Test
2578    public void function_ord()
2579    {
2580        String source = "<?print ord(data)?>";
2581        checkTemplateOutput("0", source, "data", "\u0000");
2582        checkTemplateOutput("97", source, "data", "a");
2583        checkTemplateOutput("8364", source, "data", "\u20ac");
2584
2585        String sourcekw = "<?print ord(c=data)?>";
2586        checkTemplateOutput("0", sourcekw, "data", "\u0000");
2587    }
2588
2589    @Test
2590    public void function_hex()
2591    {
2592        String source = "<?print hex(data)?>";
2593        checkTemplateOutput("0x0", source, "data", 0);
2594        checkTemplateOutput("0xff", source, "data", 0xff);
2595        checkTemplateOutput("0xffff", source, "data", 0xffff);
2596        checkTemplateOutput("-0xffff", source, "data", -0xffff);
2597
2598        String sourcekw = "<?print hex(number=data)?>";
2599        checkTemplateOutput("0x0", sourcekw, "data", 0);
2600    }
2601
2602    @Test
2603    public void function_oct()
2604    {
2605        String source = "<?print oct(data)?>";
2606        checkTemplateOutput("0o0", source, "data", 0);
2607        checkTemplateOutput("0o77", source, "data", 077);
2608        checkTemplateOutput("0o7777", source, "data", 07777);
2609        checkTemplateOutput("-0o7777", source, "data", -07777);
2610
2611
2612        String sourcekw = "<?print oct(number=data)?>";
2613        checkTemplateOutput("0o0", sourcekw, "data", 0);
2614    }
2615
2616    @Test
2617    public void function_bin()
2618    {
2619        String source = "<?print bin(data)?>";
2620
2621        checkTemplateOutput("0b0", source, "data", 0);
2622        checkTemplateOutput("0b11", source, "data", 3);
2623        checkTemplateOutput("-0b1111", source, "data", -15);
2624
2625
2626        String sourcekw = "<?print bin(number=data)?>";
2627        checkTemplateOutput("0b0", sourcekw, "data", 0);
2628    }
2629
2630    @Test
2631    public void function_abs()
2632    {
2633        String source = "<?print abs(data)?>";
2634        checkTemplateOutput("0", source, "data", 0);
2635        checkTemplateOutput("42", source, "data", 42);
2636        checkTemplateOutput("42", source, "data", -42);
2637        checkTemplateOutput("1 month", source, "data", new MonthDelta(-1));
2638        checkTemplateOutput("1 day, 0:00:01.000001", source, "data", new TimeDelta(-1, -1, -1));
2639
2640        String sourcekw = "<?print abs(number=data)?>";
2641        checkTemplateOutput("0", sourcekw, "data", 0);
2642    }
2643
2644    @Test
2645    public void function_min()
2646    {
2647        checkTemplateOutput("1", "<?print min('123')?>");
2648        checkTemplateOutput("1", "<?print min(1, 2, 3)?>");
2649        checkTemplateOutput("0", "<?print min(0, False, 1, True)?>");
2650        checkTemplateOutput("False", "<?print min(False, 0, True, 1)?>");
2651        checkTemplateOutput("False", "<?print min([False, 0, True, 1])?>");
2652    }
2653
2654    @CauseTest(expectedCause=MissingArgumentException.class)
2655    public void function_min_0_args()
2656    {
2657        checkTemplateOutput("", "<?print min()?>");
2658    }
2659
2660    @Test
2661    public void function_max()
2662    {
2663        checkTemplateOutput("3", "<?print max('123')?>");
2664        checkTemplateOutput("3", "<?print max(1, 2, 3)?>");
2665        checkTemplateOutput("1", "<?print max(0, False, 1, True)?>");
2666        checkTemplateOutput("True", "<?print max(False, 0, True, 1)?>");
2667        checkTemplateOutput("True", "<?print max([False, 0, True, 1])?>");
2668    }
2669
2670    @CauseTest(expectedCause=MissingArgumentException.class)
2671    public void function_max_0_args()
2672    {
2673        checkTemplateOutput("", "<?print max()?>");
2674    }
2675
2676    @Test
2677    public void function_sum()
2678    {
2679        checkTemplateOutput("0", "<?print sum([])?>");
2680        checkTemplateOutput("6", "<?print sum([1, 2, 3])?>");
2681        checkTemplateOutput("12", "<?print sum([1, 2, 3], 6)?>");
2682        checkTemplateOutput("5050", "<?print sum(range(101))?>");
2683
2684        checkTemplateOutput("12", "<?print sum(iterable=[1, 2, 3], start=6)?>");
2685    }
2686
2687    @CauseTest(expectedCause=MissingArgumentException.class)
2688    public void function_sum_0_args()
2689    {
2690        checkTemplateOutput("", "<?print sum()?>");
2691    }
2692
2693    @Test
2694    public void function_first()
2695    {
2696        checkTemplateOutput("g", "<?print first('gurk')?>");
2697        checkTemplateOutput("None", "<?print repr(first(''))?>");
2698        checkTemplateOutput("x", "<?print first('', 'x')?>");
2699
2700        checkTemplateOutput("x", "<?print first(iterable='', default='x')?>");
2701    }
2702
2703    @Test
2704    public void function_last()
2705    {
2706        checkTemplateOutput("k", "<?print last('gurk')?>");
2707        checkTemplateOutput("None", "<?print repr(last(''))?>");
2708        checkTemplateOutput("x", "<?print last('', 'x')?>");
2709
2710        checkTemplateOutput("x", "<?print last(iterable='', default='x')?>");
2711    }
2712
2713    @Test
2714    public void function_sorted()
2715    {
2716        String source = "<?for i in sorted(data)?><?print i?><?end for?>";
2717        checkTemplateOutput("gkru", source, "data", "gurk");
2718        checkTemplateOutput("24679", source, "data", "92746");
2719        checkTemplateOutput("172342", source, "data", asList(42, 17, 23));
2720        checkTemplateOutput("012", source, "data", makeMap(0, "zero", 1, "one", 2, "two"));
2721
2722        String sourcekw = "<?for i in sorted(iterable=data)?><?print i?><?end for?>";
2723        checkTemplateOutput("gkru", sourcekw, "data", "gurk");
2724    }
2725
2726    @Test
2727    public void function_range()
2728    {
2729        String source1 = "<?for i in range(data)?><?print i?>;<?end for?>";
2730        String source2 = "<?for i in range(data[0], data[1])?><?print i?>;<?end for?>";
2731        String source3 = "<?for i in range(data[0], data[1], data[2])?><?print i?>;<?end for?>";
2732
2733        checkTemplateOutput("", source1, "data", -10);
2734        checkTemplateOutput("", source1, "data", 0);
2735        checkTemplateOutput("0;", source1, "data", 1);
2736        checkTemplateOutput("0;1;2;3;4;", source1, "data", 5);
2737        checkTemplateOutput("", source2, "data", asList(0, -10));
2738        checkTemplateOutput("", source2, "data", asList(0, 0));
2739        checkTemplateOutput("0;1;2;3;4;", source2, "data", asList(0, 5));
2740        checkTemplateOutput("-5;-4;-3;-2;-1;0;1;2;3;4;", source2, "data", asList(-5, 5));
2741        checkTemplateOutput("", source3, "data", asList(0, -10, 1));
2742        checkTemplateOutput("", source3, "data", asList(0, 0, 1));
2743        checkTemplateOutput("0;2;4;6;8;", source3, "data", asList(0, 10, 2));
2744        checkTemplateOutput("", source3, "data", asList(0, 10, -2));
2745        checkTemplateOutput("10;8;6;4;2;", source3, "data", asList(10, 0, -2));
2746        checkTemplateOutput("", source3, "data", asList(10, 0, 2));
2747        checkTemplateOutput("0;1;", "<?for i in range(0, *[2, 1])?><?print i?>;<?end for?>");
2748    }
2749
2750    @Test
2751    public void function_slice()
2752    {
2753        String source2 = "<?for i in slice(data[0], data[1])?><?print i?>;<?end for?>";
2754        String source3 = "<?for i in slice(data[0], data[1], data[2])?><?print i?>;<?end for?>";
2755        String source4 = "<?for i in slice(data[0], data[1], data[2], data[3])?><?print i?>;<?end for?>";
2756
2757        checkTemplateOutput("g;u;r;k;", source2, "data", asList("gurk", null));
2758        checkTemplateOutput("g;u;", source2, "data", asList("gurk", 2));
2759        checkTemplateOutput("u;r;", source3, "data", asList("gurk", 1, 3));
2760        checkTemplateOutput("u;r;k;", source3, "data", asList("gurk", 1, null));
2761        checkTemplateOutput("g;u;", source3, "data", asList("gurk", null, 2));
2762        checkTemplateOutput("u;u;", source4, "data", asList("gurkgurk", 1, 6, 4));
2763    }
2764
2765    @Test
2766    public void function_zip()
2767    {
2768        String source2 = "<?for (ix, iy) in zip(x, y)?><?print ix?>-<?print iy?>;<?end for?>";
2769        String source3 = "<?for (ix, iy, iz) in zip(x, y, z)?><?print ix?>-<?print iy?>+<?print iz?>;<?end for?>";
2770
2771        checkTemplateOutput("", source2, "x", asList(), "y", asList());
2772        checkTemplateOutput("1-3;2-4;", source2, "x", asList(1, 2), "y", asList(3, 4));
2773        checkTemplateOutput("1-4;2-5;", source2, "x", asList(1, 2, 3), "y", asList(4, 5));
2774        checkTemplateOutput("", source3, "x", asList(), "y", asList(), "z", asList());
2775        checkTemplateOutput("1-3+5;2-4+6;", source3, "x", asList(1, 2), "y", asList(3, 4), "z", asList(5, 6));
2776        checkTemplateOutput("1-4+6;", source3, "x", asList(1, 2, 3), "y", asList(4, 5), "z", asList(6));
2777    }
2778
2779    @Test
2780    public void function_type()
2781    {
2782        String source = "<?print type(data)?>";
2783        checkTemplateOutput("undefined", source);
2784        checkTemplateOutput("none", source, "data", null);
2785        checkTemplateOutput("bool", source, "data", false);
2786        checkTemplateOutput("bool", source, "data", true);
2787        checkTemplateOutput("int", source, "data", 42);
2788        checkTemplateOutput("float", source, "data", 4.2);
2789        checkTemplateOutput("str", source, "data", "foo");
2790        checkTemplateOutput("date", source, "data", new Date());
2791        checkTemplateOutput("list", source, "data", asList(1, 2));
2792        checkTemplateOutput("dict", source, "data", makeMap(1, 2));
2793        checkTemplateOutput("template", source, "data", getTemplate(""));
2794        checkTemplateOutput("color", source, "data", new Color(0, 0, 0));
2795
2796        String sourcekw = "<?print type(obj=data)?>";
2797        checkTemplateOutput("none", sourcekw, "data", null);
2798    }
2799
2800    @Test
2801    public void function_reversed()
2802    {
2803        String source = "<?for i in reversed(x)?>(<?print i?>)<?end for?>";
2804        checkTemplateOutput("(3)(2)(1)", source, "x", "123");
2805        checkTemplateOutput("(3)(2)(1)", source, "x", asList(1, 2, 3));
2806
2807        String sourcekw = "<?for i in reversed(sequence=x)?>(<?print i?>)<?end for?>";
2808        checkTemplateOutput("(3)(2)(1)", sourcekw, "x", "123");
2809    }
2810
2811    @Test
2812    public void function_urlquote()
2813    {
2814        checkTemplateOutput("gurk", "<?print urlquote('gurk')?>");
2815        checkTemplateOutput("%3C%3D%3E%2B%3F", "<?print urlquote('<=>+?')?>");
2816        checkTemplateOutput("%7F%C3%BF%EF%BF%BF", "<?print urlquote('\u007f\u00ff\uffff')?>");
2817
2818        checkTemplateOutput("gurk", "<?print urlquote(string='gurk')?>");
2819    }
2820
2821    @Test
2822    public void function_urlunquote()
2823    {
2824        checkTemplateOutput("gurk", "<?print urlunquote('gurk')?>");
2825        checkTemplateOutput("<=>+?", "<?print urlunquote('%3C%3D%3E%2B%3F')?>");
2826        checkTemplateOutput("\u007f\u00ff\uffff", "<?print urlunquote('%7F%C3%BF%EF%BF%BF')?>");
2827
2828        checkTemplateOutput("gurk", "<?print urlunquote(string='gurk')?>");
2829    }
2830
2831    @Test
2832    public void function_rgb()
2833    {
2834        checkTemplateOutput("#369", "<?print repr(rgb(0.2, 0.4, 0.6))?>");
2835        checkTemplateOutput("#369c", "<?print repr(rgb(0.2, 0.4, 0.6, 0.8))?>");
2836
2837        checkTemplateOutput("#369c", "<?print repr(rgb(r=0.2, g=0.4, b=0.6, a=0.8))?>");
2838    }
2839
2840    @Test
2841    public void function_hls()
2842    {
2843        checkTemplateOutput("#fff", "<?print repr(hls(0, 1, 0))?>");
2844        checkTemplateOutput("#fff0", "<?print repr(hls(0, 1, 0, 0))?>");
2845
2846        checkTemplateOutput("#fff0", "<?print repr(hls(h=0, l=1, s=0, a=0))?>");
2847    }
2848
2849    @Test
2850    public void function_hsv()
2851    {
2852        checkTemplateOutput("#fff", "<?print repr(hsv(0, 0, 1))?>");
2853        checkTemplateOutput("#fff0", "<?print repr(hsv(0, 0, 1, 0))?>");
2854
2855        checkTemplateOutput("#fff0", "<?print repr(hsv(h=0, s=0, v=1, a=0))?>");
2856    }
2857
2858    @Test
2859    public void method_upper()
2860    {
2861        checkTemplateOutput("GURK", "<?print 'gurk'.upper()?>");
2862        checkTemplateOutput("GURK", "<?code m = 'gurk'.upper?><?print m()?>");
2863    }
2864
2865    @Test
2866    public void method_lower()
2867    {
2868        checkTemplateOutput("gurk", "<?print 'GURK'.lower()?>");
2869        checkTemplateOutput("gurk", "<?code m = 'GURK'.lower?><?print m()?>");
2870    }
2871
2872    @Test
2873    public void method_capitalize()
2874    {
2875        checkTemplateOutput("Gurk", "<?print 'gURK'.capitalize()?>");
2876        checkTemplateOutput("Gurk", "<?code m = 'gURK'.capitalize?><?print m()?>");
2877    }
2878
2879    @Test
2880    public void method_startswith()
2881    {
2882        checkTemplateOutput("True", "<?print 'gurkhurz'.startswith('gurk')?>");
2883        checkTemplateOutput("False", "<?print 'gurkhurz'.startswith('hurz')?>");
2884        checkTemplateOutput("False", "<?code m = 'gurkhurz'.startswith?><?print m('hurz')?>");
2885
2886        checkTemplateOutput("False", "<?print 'gurkhurz'.startswith(prefix='hurz')?>");
2887    }
2888
2889    @Test
2890    public void method_endswith()
2891    {
2892        checkTemplateOutput("True", "<?print 'gurkhurz'.endswith('hurz')?>");
2893        checkTemplateOutput("False", "<?print 'gurkhurz'.endswith('gurk')?>");
2894        checkTemplateOutput("False", "<?code m = 'gurkhurz'.endswith?><?print m('gurk')?>");
2895
2896        checkTemplateOutput("False", "<?print 'gurkhurz'.endswith(suffix='gurk')?>");
2897    }
2898
2899    @Test
2900    public void method_strip()
2901    {
2902        checkTemplateOutput("gurk", "<?print obj.strip()?>", "obj", " \t\r\ngurk \t\r\n");
2903        checkTemplateOutput("gurk", "<?print obj.strip('xyz')?>", "obj", "xyzzygurkxyzzy");
2904        checkTemplateOutput("gurk", "<?code m = obj.strip?><?print m('xyz')?>", "obj", "xyzzygurkxyzzy");
2905
2906        checkTemplateOutput("gurk", "<?print obj.strip(chars='xyz')?>", "obj", "xyzzygurkxyzzy");
2907    }
2908
2909    @Test
2910    public void method_lstrip()
2911    {
2912        checkTemplateOutput("gurk \t\r\n", "<?print obj.lstrip()?>", "obj", " \t\r\ngurk \t\r\n");
2913        checkTemplateOutput("gurkxyzzy", "<?print obj.lstrip(arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2914        checkTemplateOutput("gurkxyzzy", "<?code m = obj.lstrip?><?print m(arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2915
2916        checkTemplateOutput("gurkxyzzy", "<?print obj.lstrip(chars=arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2917    }
2918
2919    @Test
2920    public void method_rstrip()
2921    {
2922        checkTemplateOutput(" \t\r\ngurk", "<?print obj.rstrip()?>", "obj", " \t\r\ngurk \t\r\n");
2923        checkTemplateOutput("xyzzygurk", "<?print obj.rstrip(arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2924        checkTemplateOutput("xyzzygurk", "<?code m = obj.rstrip?><?print m(arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2925
2926        checkTemplateOutput("xyzzygurk", "<?print obj.rstrip(chars=arg)?>", "obj", "xyzzygurkxyzzy", "arg", "xyz");
2927    }
2928
2929    @Test
2930    public void method_split()
2931    {
2932        checkTemplateOutput("(f)(o)(o)", "<?for item in obj.split()?>(<?print item?>)<?end for?>", "obj", " \t\r\nf \t\r\no \t\r\no \t\r\n");
2933        checkTemplateOutput("(f)(o \t\r\no \t\r\n)", "<?for item in obj.split(None, 1)?>(<?print item?>)<?end for?>", "obj", " \t\r\nf \t\r\no \t\r\no \t\r\n");
2934        checkTemplateOutput("()(f)(o)(o)()", "<?for item in obj.split(arg)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2935        checkTemplateOutput("()(f)(o)(o)()", "<?for item in obj.split(arg, None)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2936        checkTemplateOutput("()(f)(oxxoxx)", "<?for item in obj.split(arg, 2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2937        checkTemplateOutput("()(f)(oxxoxx)", "<?code m = obj.split?><?for item in m(arg, 2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2938
2939        checkTemplateOutput("()(f)(oxxoxx)", "<?for item in obj.split(sep=arg, count=2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2940    }
2941
2942    @Test
2943    public void method_rsplit()
2944    {
2945        checkTemplateOutput("(f)(o)(o)", "<?for item in obj.rsplit()?>(<?print item?>)<?end for?>", "obj", " \t\r\nf \t\r\no \t\r\no \t\r\n");
2946        checkTemplateOutput("( \t\r\nf \t\r\no)(o)", "<?for item in obj.rsplit(None, 1)?>(<?print item?>)<?end for?>", "obj", " \t\r\nf \t\r\no \t\r\no \t\r\n");
2947        checkTemplateOutput("()(f)(o)(o)()", "<?for item in obj.rsplit(arg)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2948        checkTemplateOutput("()(f)(o)(o)()", "<?for item in obj.rsplit(arg, None)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2949        checkTemplateOutput("(xxfxxo)(o)()", "<?for item in obj.rsplit(arg, 2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2950        checkTemplateOutput("(xxfxxo)(o)()", "<?code m = obj.rsplit?><?for item in m(arg, 2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2951
2952        checkTemplateOutput("(xxfxxo)(o)()", "<?for item in obj.rsplit(sep=arg, count=2)?>(<?print item?>)<?end for?>", "obj", "xxfxxoxxoxx", "arg", "xx");
2953    }
2954
2955    @Test
2956    public void method_replace()
2957    {
2958        checkTemplateOutput("goork", "<?print 'gurk'.replace('u', 'oo')?>");
2959        checkTemplateOutput("fuuuu", "<?print 'foo'.replace('o', 'uu', None)?>");
2960        checkTemplateOutput("fuuo", "<?print 'foo'.replace('o', 'uu', 1)?>");
2961        checkTemplateOutput("fuuo", "<?code m = 'foo'.replace?><?print m('o', 'uu', 1)?>");
2962        checkTemplateOutput("fuuo", "<?print 'foo'.replace(old='o', new='uu', count=1)?>");
2963    }
2964
2965    @Test
2966    public void method_renders()
2967    {
2968        InterpretedTemplate t1 = getTemplate("(<?print data?>)", "t1");
2969
2970        checkTemplateOutput("(GURK)", "<?print t.renders(data='gurk').upper()?>", "t", t1);
2971        checkTemplateOutput("(GURK)", "<?code m = t.renders?><?print m(data='gurk').upper()?>", "t", t1);
2972
2973        InterpretedTemplate t2 = getTemplate("(gurk)", "t2");
2974        checkTemplateOutput("(GURK)", "<?print t.renders().upper()?>", "t", t2);
2975    }
2976
2977    @Test
2978    public void method_render()
2979    {
2980        InterpretedTemplate t1 = getTemplate("<?print prefix?><?print data?><?print suffix?>");
2981        InterpretedTemplate t2 = getTemplate("<?print 'foo'?>");
2982
2983        checkTemplateOutput("(f)(o)(o)", "<?for c in data?><?code t.render(data=c, prefix='(', suffix=')')?><?end for?>", "t", t1, "data", "foo");
2984        checkTemplateOutput("foo", "<?print t.render()?>", "t", t2);
2985        checkTemplateOutput("foo", "<?code m = t.render?><?code m()?>", "t", t2);
2986        checkTemplateOutput("foo", "<?print t.render \n\t(\n \t)\n\t ?>", "t", t2);
2987
2988        checkTemplateOutput("42", "<?code globals.template.render(value=42)?>", "globals", makeMap("template", getTemplate("<?print value?>")));
2989        checkTemplateOutput("", "<?code globals.template.render(value=42)?>", "globals", makeMap("template", getTemplate("")));
2990    }
2991
2992    @Test
2993    public void method_render_local_vars()
2994    {
2995        InterpretedTemplate t = getTemplate("<?code x += 1?><?print x?>");
2996
2997        checkTemplateOutput("42,43,42", "<?print x?>,<?code t.render(x=x)?>,<?print x?>", "t", t, "x", 42);
2998    }
2999
3000    @Test
3001    public void method_render_localtemplate()
3002    {
3003        checkTemplateOutput("foo", "<?def lower?><?print x.lower()?><?end def?><?print lower.renders(x='FOO')?>");
3004    }
3005
3006    @Test
3007    public void method_render_nested()
3008    {
3009        String source = (
3010            "<?def outer?>" +
3011                "<?def inner?>" +
3012                    "<?code x += 1?>" +
3013                    "<?code y += 1?>" +
3014                    "<?print x?>!" +
3015                    "<?print y?>!" +
3016                "<?end def?>" +
3017                "<?code x += 1?>" +
3018                "<?code y += 1?>" +
3019                "<?code inner.render(x=x)?>" +
3020                "<?print x?>!" +
3021                "<?print y?>!" +
3022            "<?end def?>" +
3023            "<?code x += 1?>" +
3024            "<?code y += 1?>" +
3025            "<?code outer.render(x=x)?>" +
3026            "<?print x?>!" +
3027            "<?print y?>!"
3028        );
3029        checkTemplateOutput("45!43!44!43!43!43!", source, "x", 42, "y", 42);
3030    }
3031
3032    @Test
3033    public void method_mimeformat()
3034    {
3035        Date t = FunctionDate.call(2010, 2, 22, 12, 34, 56);
3036        checkTemplateOutput("Mon, 22 Feb 2010 12:34:56 GMT", "<?print data.mimeformat()?>", "data", t);
3037        checkTemplateOutput("Mon, 22 Feb 2010 12:34:56 GMT", "<?code m = data.mimeformat?><?print m()?>", "data", t);
3038    }
3039
3040    @Test
3041    public void method_items()
3042    {
3043        checkTemplateOutput("a:42;b:17;c:23;", "<?for (key, value) in sorted(data.items())?><?print key?>:<?print value?>;<?end for?>", "data", makeMap("a", 42, "b", 17, "c", 23));
3044        checkTemplateOutput("x:17;y:23;", "<?for (key, value) in data.items()?><?print key?>:<?print value?>;<?end for?>", "data", new Point(17, 23));
3045        checkTemplateOutput("x:17;y:23;", "<?code m = data.items?><?for (key, value) in m()?><?print key?>:<?print value?>;<?end for?>", "data", new Point(17, 23));
3046    }
3047
3048    @Test
3049    public void method_values()
3050    {
3051        checkTemplateOutput("17;23;42;", "<?for value in sorted(data.values())?><?print value?>;<?end for?>", "data", makeMap("a", 42, "b", 17, "c", 23));
3052        checkTemplateOutput("17;23;", "<?for value in data.values()?><?print value?>;<?end for?>", "data", new Point(17, 23));
3053        checkTemplateOutput("17;23;", "<?code m = data.values?><?for value in m()?><?print value?>;<?end for?>", "data", new Point(17, 23));
3054    }
3055
3056    @Test
3057    public void method_get()
3058    {
3059        checkTemplateOutput("42", "<?print {}.get('foo', 42)?>");
3060        checkTemplateOutput("17", "<?print {'foo': 17}.get('foo', 42)?>");
3061        checkTemplateOutput("", "<?print {}.get('foo')?>");
3062        checkTemplateOutput("17", "<?print {'foo': 17}.get('foo')?>");
3063        checkTemplateOutput("17", "<?code m = {'foo': 17}.get?><?print m('foo')?>");
3064
3065        checkTemplateOutput("17", "<?print {'foo': 17}.get(key='foo', default=42)?>");
3066    }
3067
3068    @Test
3069    public void method_r_g_b_a()
3070    {
3071        checkTemplateOutput("0x11", "<?code c = #123?><?print hex(c.r())?>");
3072        checkTemplateOutput("0x22", "<?code c = #123?><?print hex(c.g())?>");
3073        checkTemplateOutput("0x33", "<?code c = #123?><?print hex(c.b())?>");
3074        checkTemplateOutput("0xff", "<?code c = #123?><?print hex(c.a())?>");
3075        checkTemplateOutput("0x11", "<?code c = #123?><?code m = c.r?><?print hex(m())?>");
3076        checkTemplateOutput("0x22", "<?code c = #123?><?code m = c.g?><?print hex(m())?>");
3077        checkTemplateOutput("0x33", "<?code c = #123?><?code m = c.b?><?print hex(m())?>");
3078        checkTemplateOutput("0xff", "<?code c = #123?><?code m = c.a?><?print hex(m())?>");
3079    }
3080
3081    @Test
3082    public void method_hls()
3083    {
3084        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hls()[0])?>");
3085        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hls()[1])?>");
3086        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hls()[2])?>");
3087        checkTemplateOutput("0", "<?code c = #fff?><?code m = c.hls?><?print int(m()[0])?>");
3088    }
3089
3090    @Test
3091    public void method_hlsa()
3092    {
3093        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hlsa()[0])?>");
3094        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hlsa()[1])?>");
3095        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hlsa()[2])?>");
3096        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hlsa()[3])?>");
3097        checkTemplateOutput("0", "<?code c = #fff?><?code m = c.hlsa?><?print int(m()[0])?>");
3098    }
3099
3100    @Test
3101    public void method_hsv()
3102    {
3103        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hsv()[0])?>");
3104        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hsv()[1])?>");
3105        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hsv()[2])?>");
3106        checkTemplateOutput("0", "<?code c = #fff?><?code m = c.hsv?><?print int(m()[0])?>");
3107    }
3108
3109    @Test
3110    public void method_hsva()
3111    {
3112        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hsva()[0])?>");
3113        checkTemplateOutput("0", "<?code c = #fff?><?print int(c.hsva()[1])?>");
3114        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hsva()[2])?>");
3115        checkTemplateOutput("1", "<?code c = #fff?><?print int(c.hsva()[3])?>");
3116        checkTemplateOutput("0", "<?code c = #fff?><?code m = c.hsva?><?print int(m()[0])?>");
3117    }
3118
3119    @Test
3120    public void method_lum()
3121    {
3122        checkTemplateOutput("True", "<?print #fff.lum() == 1?>");
3123        checkTemplateOutput("True", "<?code m = #fff.lum?><?print m() == 1?>");
3124    }
3125
3126    @Test
3127    public void method_withlum()
3128    {
3129        checkTemplateOutput("#fff", "<?print #000.withlum(1)?>");
3130        checkTemplateOutput("#fff", "<?code m = #000.withlum?><?print m(1)?>");
3131
3132        checkTemplateOutput("#fff", "<?print #000.withlum(lum=1)?>");
3133    }
3134
3135    @Test
3136    public void method_witha()
3137    {
3138        checkTemplateOutput("#0063a82a", "<?print repr(#0063a8.witha(42))?>");
3139        checkTemplateOutput("#0063a82a", "<?code m =#0063a8.witha?><?print repr(m(42))?>");
3140
3141        checkTemplateOutput("#0063a82a", "<?print repr(#0063a8.witha(a=42))?>");
3142    }
3143
3144    @Test
3145    public void method_abslum()
3146    {
3147        checkTemplateOutput("#fff", "<?print #000.abslum(1)?>");
3148        checkTemplateOutput("#fff", "<?code m = #000.abslum?><?print m(1)?>");
3149        checkTemplateOutput("#000", "<?print #fff.abslum(-1)?>");
3150    }
3151
3152    @Test
3153    public void method_rellum()
3154    {
3155        checkTemplateOutput("#000", "<?print #888.rellum(-1)?>");
3156        checkTemplateOutput("#888", "<?print #888.rellum(0)?>");
3157        checkTemplateOutput("#fff", "<?print #888.rellum(1)?>");
3158        checkTemplateOutput("#000", "<?code m = #888.rellum?><?print m(-1)?>");
3159    }
3160
3161    @Test
3162    public void method_join()
3163    {
3164        checkTemplateOutput("1,2,3,4", "<?print ','.join('1234')?>");
3165        checkTemplateOutput("1,2,3,4", "<?print ','.join(['1', '2', '3', '4'])?>");
3166        checkTemplateOutput("1,2,3,4", "<?code m = ','.join?><?print m('1234')?>");
3167
3168        checkTemplateOutput("1,2,3,4", "<?print ','.join(iterable='1234')?>");
3169    }
3170
3171    @Test
3172    public void method_find()
3173    {
3174        checkTemplateOutput("-1", "<?print s.find('ks')?>", "s", "gurkgurk");
3175        checkTemplateOutput("2", "<?print s.find('rk')?>", "s", "gurkgurk");
3176        checkTemplateOutput("2", "<?print s.find('rk', 2)?>", "s", "gurkgurk");
3177        checkTemplateOutput("2", "<?print s.find('rk', 2, 4)?>", "s", "gurkgurk");
3178        checkTemplateOutput("6", "<?print s.find('rk', 4, 8)?>", "s", "gurkgurk");
3179        checkTemplateOutput("5", "<?print s.find('ur', -4, -1)?>", "s", "gurkgurk");
3180        checkTemplateOutput("-1", "<?print s.find('rk', 2, 3)?>", "s", "gurkgurk");
3181        checkTemplateOutput("-1", "<?print s.find('rk', 7)?>", "s", "gurkgurk");
3182        checkTemplateOutput("-1", "<?code m = s.find?><?print m('ks')?>", "s", "gurkgurk");
3183
3184        checkTemplateOutput("-1", "<?print l.find('x')?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3185        checkTemplateOutput("2", "<?print l.find('r')?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3186        checkTemplateOutput("2", "<?print l.find('r', 2)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3187        checkTemplateOutput("2", "<?print l.find('r', 2, 4)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3188        checkTemplateOutput("6", "<?print l.find('r', 4, 8)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3189        checkTemplateOutput("6", "<?print l.find('r', -3, -1)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3190        checkTemplateOutput("-1", "<?print l.find('r', 2, 2)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3191        checkTemplateOutput("-1", "<?print l.find('r', 7)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3192        checkTemplateOutput("2", "<?print l.find(None)?>", "l", asList("g", "u", null, "k", "g", "u", "r", "k"));
3193
3194        checkTemplateOutput("2", "<?print s.find(sub='rk', start=2, end=4)?>", "s", "gurkgurk");
3195    }
3196
3197    @Test
3198    public void method_rfind()
3199    {
3200        checkTemplateOutput("-1", "<?print s.rfind('ks')?>", "s", "gurkgurk");
3201        checkTemplateOutput("6", "<?print s.rfind('rk')?>", "s", "gurkgurk");
3202        checkTemplateOutput("6", "<?print s.rfind('rk', 2)?>", "s", "gurkgurk");
3203        checkTemplateOutput("2", "<?print s.rfind('rk', 2, 4)?>", "s", "gurkgurk");
3204        checkTemplateOutput("6", "<?print s.rfind('rk', 4, 8)?>", "s", "gurkgurk");
3205        checkTemplateOutput("5", "<?print s.rfind('ur', -4, -1)?>", "s", "gurkgurk");
3206        checkTemplateOutput("-1", "<?print s.rfind('rk', 2, 3)?>", "s", "gurkgurk");
3207        checkTemplateOutput("-1", "<?print s.rfind('rk', 7)?>", "s", "gurkgurk");
3208        checkTemplateOutput("-1", "<?code m = s.rfind?><?print m('ks')?>", "s", "gurkgurk");
3209
3210        checkTemplateOutput("-1", "<?print l.rfind('x')?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3211        checkTemplateOutput("6", "<?print l.rfind('r')?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3212        checkTemplateOutput("6", "<?print l.rfind('r', 2)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3213        checkTemplateOutput("2", "<?print l.rfind('r', 2, 4)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3214        checkTemplateOutput("6", "<?print l.rfind('r', 4, 8)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3215        checkTemplateOutput("6", "<?print l.rfind('r', -3, -1)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3216        checkTemplateOutput("-1", "<?print l.rfind('r', 2, 2)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3217        checkTemplateOutput("-1", "<?print l.rfind('r', 7)?>", "l", asList("g", "u", "r", "k", "g", "u", "r", "k"));
3218        checkTemplateOutput("2", "<?print l.rfind(None)?>", "l", asList("g", "u", null, "k", "g", "u", "r", "k"));
3219
3220        checkTemplateOutput("2", "<?print s.rfind(sub='rk', start=2, end=4)?>", "s", "gurkgurk");
3221    }
3222
3223    @Test
3224    public void method_day()
3225    {
3226        checkTemplateOutput("12", "<?print @(2010-05-12).day()?>");
3227        checkTemplateOutput("12", "<?code m = @(2010-05-12).day?><?print m()?>");
3228        checkTemplateOutput("12", "<?print d.day()?>", "d", FunctionDate.call(2010, 5, 12));
3229    }
3230
3231    @Test
3232    public void method_month()
3233    {
3234        checkTemplateOutput("5", "<?print @(2010-05-12).month()?>");
3235        checkTemplateOutput("5", "<?code m = @(2010-05-12).month?><?print m()?>");
3236        checkTemplateOutput("5", "<?print d.month()?>", "d", FunctionDate.call(2010, 5, 12));
3237    }
3238
3239    @Test
3240    public void method_year()
3241    {
3242        checkTemplateOutput("2010", "<?print @(2010-05-12).year()?>");
3243        checkTemplateOutput("2010", "<?code m = @(2010-05-12).year?><?print m()?>");
3244        checkTemplateOutput("2010", "<?print d.year()?>", "d", FunctionDate.call(2010, 5, 12));
3245    }
3246
3247    @Test
3248    public void method_hour()
3249    {
3250        checkTemplateOutput("16", "<?print @(2010-05-12T16:47:56).hour()?>");
3251        checkTemplateOutput("16", "<?code m = @(2010-05-12T16:47:56).hour?><?print m()?>");
3252        checkTemplateOutput("16", "<?print d.hour()?>", "d", FunctionDate.call(2010, 5, 12, 16, 47, 56));
3253    }
3254
3255    @Test
3256    public void method_minute()
3257    {
3258        checkTemplateOutput("47", "<?print @(2010-05-12T16:47:56).minute()?>");
3259        checkTemplateOutput("47", "<?code m = @(2010-05-12T16:47:56).minute?><?print m()?>");
3260        checkTemplateOutput("47", "<?print d.minute()?>", "d", FunctionDate.call(2010, 5, 12, 16, 47, 56));
3261    }
3262
3263    @Test
3264    public void method_second()
3265    {
3266        checkTemplateOutput("56", "<?print @(2010-05-12T16:47:56).second()?>");
3267        checkTemplateOutput("56", "<?code m = @(2010-05-12T16:47:56).second?><?print m()?>");
3268        checkTemplateOutput("56", "<?print d.second()?>", "d", FunctionDate.call(2010, 5, 12, 16, 47, 56));
3269    }
3270
3271    @Test
3272    public void method_microsecond()
3273    {
3274        checkTemplateOutput("123000", "<?print @(2010-05-12T16:47:56.123000).microsecond()?>");
3275        checkTemplateOutput("123000", "<?code m = @(2010-05-12T16:47:56.123000).microsecond?><?print m()?>");
3276        checkTemplateOutput("123000", "<?print d.microsecond()?>", "d", FunctionDate.call(2010, 5, 12, 16, 47, 56, 123000));
3277    }
3278
3279    @Test
3280    public void method_weekday()
3281    {
3282        checkTemplateOutput("2", "<?print @(2010-05-12).weekday()?>");
3283        checkTemplateOutput("2", "<?code m = @(2010-05-12).weekday?><?print m()?>");
3284        checkTemplateOutput("2", "<?print d.weekday()?>", "d", FunctionDate.call(2010, 5, 12));
3285    }
3286
3287    @Test
3288    public void method_yearday()
3289    {
3290        checkTemplateOutput("1", "<?print @(2010-01-01).yearday()?>");
3291        checkTemplateOutput("1", "<?code m = @(2010-01-01).yearday?><?print m()?>");
3292        checkTemplateOutput("366", "<?print @(2008-12-31).yearday()?>");
3293        checkTemplateOutput("365", "<?print @(2010-12-31).yearday()?>");
3294        checkTemplateOutput("132", "<?print @(2010-05-12).yearday()?>");
3295        checkTemplateOutput("132", "<?print @(2010-05-12T16:47:56).yearday()?>");
3296        checkTemplateOutput("132", "<?print d.yearday()?>", "d", FunctionDate.call(2010, 5, 12));
3297        checkTemplateOutput("132", "<?print d.yearday()?>", "d", FunctionDate.call(2010, 5, 12, 16, 47, 56));
3298    }
3299
3300    @Test
3301    public void method_append()
3302    {
3303        checkTemplateOutput("[17, 23, 42]", "<?code l = [17]?><?code l.append(23, 42)?><?print l?>");
3304        checkTemplateOutput("[17, 23, 42]", "<?code l = [17]?><?code m = l.append?><?code m(23, 42)?><?print l?>");
3305    }
3306
3307    @Test
3308    public void method_insert()
3309    {
3310        checkTemplateOutput("[1, 2, 3, 4]", "<?code l = [1,4]?><?code l.insert(1, 2, 3)?><?print l?>");
3311        checkTemplateOutput("[1, 2, 3, 4]", "<?code l = [1,4]?><?code m = l.insert?><?code m(1, 2, 3)?><?print l?>");
3312    }
3313
3314    @Test
3315    public void method_pop()
3316    {
3317        checkTemplateOutput("42;17;23;", "<?code l = [17, 23, 42]?><?print l.pop()?>;<?print l.pop(-2)?>;<?print l.pop(0)?>;");
3318        checkTemplateOutput("42;17;23;", "<?code l = [17, 23, 42]?><?code m = l.pop?><?print m()?>;<?print m(-2)?>;<?print m(0)?>;");
3319    }
3320
3321    @Test
3322    public void method_update()
3323    {
3324        checkTemplateOutput("0", "<?code d = {}?><?code d.update()?><?print len(d)?>");
3325        checkTemplateOutput("1", "<?code d = {}?><?code d.update([['one', 1]])?><?print d.one?>");
3326        checkTemplateOutput("1", "<?code d = {}?><?code d.update({'one': 1})?><?print d.one?>");
3327        checkTemplateOutput("1", "<?code d = {}?><?code d.update(one=1)?><?print d.one?>");
3328        checkTemplateOutput("1", "<?code d = {}?><?code m = d.update?><?code m(one=1)?><?print d.one?>");
3329        checkTemplateOutput("1", "<?code d = {}?><?code d.update([['one', 0]], {'one': 0}, one=1)?><?print d.one?>");
3330    }
3331
3332    @Test
3333    public void set_lvalue()
3334    {
3335        checkTemplateOutput("bar", "<?code d = {}?><?code d.foo = 'bar'?><?print d.foo?>");
3336        checkTemplateOutput("bar", "<?code d = {}?><?code d['foo'] = 'bar'?><?print d['foo']?>");
3337        checkTemplateOutput("bar", "<?code d = ['bar']?><?code d[0] = 'bar'?><?print d[0]?>");
3338        checkTemplateOutput("baz", "<?code d = {'foo': {}}?><?code d.foo.bar = 'baz'?><?print d.foo.bar?>");
3339        checkTemplateOutput("baz", "<?code d = {'foo': {}}?><?code d.foo['bar'] = 'baz'?><?print d.foo['bar']?>");
3340        checkTemplateOutput("baz", "<?code d = {'foo': ['bar']}?><?code d.foo[0] = 'baz'?><?print d.foo[0]?>");
3341        checkTemplateOutput("baz", "<?code d = ['bar']?><?def f?><?return d?><?end def?><?code f()[0] = 'baz'?><?print d[0]?>");
3342    }
3343
3344    @Test
3345    public void add_lvalue()
3346    {
3347        checkTemplateOutput("barbaz", "<?code d = {'foo': 'bar'}?><?code d.foo += 'baz'?><?print d.foo?>");
3348        checkTemplateOutput("barbaz", "<?code d = {'foo': 'bar'}?><?code d['foo'] += 'baz'?><?print d['foo']?>");
3349        checkTemplateOutput("barbaz", "<?code d = ['bar']?><?code d[0] += 'baz'?><?print d[0]?>");
3350        checkTemplateOutput("barbaz", "<?code d = {'foo': {'bar' : 'bar'}}?><?code d.foo.bar += 'baz'?><?print d.foo.bar?>");
3351        checkTemplateOutput("barbaz", "<?code d = {'foo': {'bar' : 'bar'}}?><?code d.foo['bar'] += 'baz'?><?print d.foo['bar']?>");
3352        checkTemplateOutput("barbaz", "<?code d = {'foo': ['bar']}?><?code d.foo[0] += 'baz'?><?print d.foo[0]?>");
3353        checkTemplateOutput("barbaz", "<?code d = ['bar']?><?def f?><?return d?><?end def?><?code f()[0] += 'baz'?><?print d[0]?>");
3354        checkTemplateOutput("[1, 2, 3, 4][1, 2, 3, 4]", "<?code d = {'foo': [1, 2]}?><?code l = d.foo?><?code d.foo += [3, 4]?><?print d.foo?><?print l?>");
3355    }
3356
3357    @Test
3358    public void sub_lvalue()
3359    {
3360        checkTemplateOutput("6", "<?code d = {'foo': 23}?><?code d.foo -= 17?><?print d.foo?>");
3361        checkTemplateOutput("6", "<?code d = {'foo': 23}?><?code d['foo'] -= 17?><?print d['foo']?>");
3362        checkTemplateOutput("6", "<?code d = [23]?><?code d[0] -= 17?><?print d[0]?>");
3363        checkTemplateOutput("6", "<?code d = {'foo': {'bar' : 23}}?><?code d.foo.bar -= 17?><?print d.foo.bar?>");
3364        checkTemplateOutput("6", "<?code d = {'foo': {'bar' : 23}}?><?code d.foo['bar'] -= 17?><?print d.foo['bar']?>");
3365        checkTemplateOutput("6", "<?code d = {'foo': [23]}?><?code d.foo[0] -= 17?><?print d.foo[0]?>");
3366        checkTemplateOutput("6", "<?code d = [23]?><?def f?><?return d?><?end def?><?code f()[0] -= 17?><?print d[0]?>");
3367    }
3368
3369    @Test
3370    public void mul_lvalue()
3371    {
3372        checkTemplateOutput("42", "<?code d = {'foo': 6}?><?code d.foo *= 7?><?print d.foo?>");
3373        checkTemplateOutput("42", "<?code d = {'foo': 6}?><?code d['foo'] *= 7?><?print d['foo']?>");
3374        checkTemplateOutput("42", "<?code d = [6]?><?code d[0] *= 7?><?print d[0]?>");
3375        checkTemplateOutput("42", "<?code d = {'foo': {'bar' : 6}}?><?code d.foo.bar *= 7?><?print d.foo.bar?>");
3376        checkTemplateOutput("42", "<?code d = {'foo': {'bar' : 6}}?><?code d.foo['bar'] *= 7?><?print d.foo['bar']?>");
3377        checkTemplateOutput("42", "<?code d = {'foo': [6]}?><?code d.foo[0] *= 7?><?print d.foo[0]?>");
3378        checkTemplateOutput("42", "<?code d = [6]?><?def f?><?return d?><?end def?><?code f()[0] *= 7?><?print d[0]?>");
3379    }
3380
3381    @Test
3382    public void floordiv_lvalue()
3383    {
3384        checkTemplateOutput("2", "<?code d = {'foo': 5}?><?code d.foo //= 2?><?print d.foo?>");
3385        checkTemplateOutput("2", "<?code d = {'foo': 5}?><?code d['foo'] //= 2?><?print d['foo']?>");
3386        checkTemplateOutput("2", "<?code d = [5]?><?code d[0] //= 2?><?print d[0]?>");
3387        checkTemplateOutput("2", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar //= 2?><?print d.foo.bar?>");
3388        checkTemplateOutput("2", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] //= 2?><?print d.foo['bar']?>");
3389        checkTemplateOutput("2", "<?code d = {'foo': [5]}?><?code d.foo[0] //= 2?><?print d.foo[0]?>");
3390        checkTemplateOutput("2", "<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] //= 2?><?print d[0]?>");
3391    }
3392
3393    @Test
3394    public void truediv_lvalue()
3395    {
3396        checkTemplateOutput("2.5", "<?code d = {'foo': 5}?><?code d.foo /= 2?><?print d.foo?>");
3397        checkTemplateOutput("2.5", "<?code d = {'foo': 5}?><?code d['foo'] /= 2?><?print d['foo']?>");
3398        checkTemplateOutput("2.5", "<?code d = [5]?><?code d[0] /= 2?><?print d[0]?>");
3399        checkTemplateOutput("2.5", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar /= 2?><?print d.foo.bar?>");
3400        checkTemplateOutput("2.5", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] /= 2?><?print d.foo['bar']?>");
3401        checkTemplateOutput("2.5", "<?code d = {'foo': [5]}?><?code d.foo[0] /= 2?><?print d.foo[0]?>");
3402        checkTemplateOutput("2.5", "<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] /= 2?><?print d[0]?>");
3403    }
3404
3405    @Test
3406    public void mod_lvalue()
3407    {
3408        checkTemplateOutput("1", "<?code d = {'foo': 5}?><?code d.foo %= 2?><?print d.foo?>");
3409        checkTemplateOutput("1", "<?code d = {'foo': 5}?><?code d['foo'] %= 2?><?print d['foo']?>");
3410        checkTemplateOutput("1", "<?code d = [5]?><?code d[0] %= 2?><?print d[0]?>");
3411        checkTemplateOutput("1", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar %= 2?><?print d.foo.bar?>");
3412        checkTemplateOutput("1", "<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] %= 2?><?print d.foo['bar']?>");
3413        checkTemplateOutput("1", "<?code d = {'foo': [5]}?><?code d.foo[0] %= 2?><?print d.foo[0]?>");
3414        checkTemplateOutput("1", "<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] %= 2?><?print d[0]?>");
3415    }
3416
3417
3418    @Test
3419    public void parse()
3420    {
3421        checkTemplateOutput("42", "<?print data.Noner?>", "data", makeMap("Noner", 42));
3422    }
3423
3424    @CauseTest(expectedCause=SyntaxException.class)
3425    public void lexer_error()
3426    {
3427        checkTemplateOutput("", "<?print ??>");
3428    }
3429
3430    @CauseTest(expectedCause=SyntaxException.class)
3431    public void parser_error()
3432    {
3433        checkTemplateOutput("", "<?print 1++2?>");
3434    }
3435
3436    @Test
3437    public void tag_note()
3438    {
3439        checkTemplateOutput("foo", "f<?note This is?>o<?note a comment?>o");
3440    }
3441
3442    @Test
3443    public void templateattributes_1()
3444    {
3445        String source = "<?print x?>";
3446        InterpretedTemplate t = getTemplate(source);
3447
3448        checkTemplateOutput("<?", "<?print template.startdelim?>", "template", t);
3449        checkTemplateOutput("?>", "<?print template.enddelim?>", "template", t);
3450        checkTemplateOutput(source, "<?print template.source?>", "template", t);
3451        checkTemplateOutput("1", "<?print len(template.content)?>", "template", t);
3452        checkTemplateOutput("print", "<?print template.content[0].type?>", "template", t);
3453        checkTemplateOutput(source, "<?print template.content[0].location.tag?>", "template", t);
3454        checkTemplateOutput("x", "<?print template.content[0].location.code?>", "template", t);
3455        checkTemplateOutput("var", "<?print template.content[0].obj.type?>", "template", t);
3456        checkTemplateOutput("x", "<?print template.content[0].obj.name?>", "template", t);
3457    }
3458
3459    @Test
3460    public void templateattributes_2()
3461    {
3462        String source = "<?printx 42?>";
3463        InterpretedTemplate t = getTemplate(source);
3464
3465        checkTemplateOutput("printx", "<?print template.content[0].type?>", "template", t);
3466        checkTemplateOutput("const", "<?print template.content[0].obj.type?>", "template", t);
3467        checkTemplateOutput("42", "<?print template.content[0].obj.value?>", "template", t);
3468    }
3469
3470    @Test
3471    public void templateattributes_3()
3472    {
3473        String source = "foo";
3474        InterpretedTemplate t = getTemplate(source);
3475
3476        checkTemplateOutput("text", "<?print template.content[0].type?>", "template", t);
3477        checkTemplateOutput("foo", "<?print template.content[0].text?>", "template", t);
3478    }
3479
3480    @Test
3481    public void templateattributes_localtemplate()
3482    {
3483        String source = "<?def lower?><?print t.lower()?><?end def?>";
3484
3485        checkTemplateOutput(source + "<?print lower.source?>", source + "<?print lower.source?>");
3486        checkTemplateOutput(source, source + "<?print lower.source[lower.location.starttag:lower.endlocation.endtag]?>");
3487        checkTemplateOutput("<?print t.lower()?>", source + "<?print lower.source[lower.location.endtag:lower.endlocation.starttag]?>");
3488        checkTemplateOutput("lower", source + "<?print lower.name?>");
3489    }
3490
3491    @Test
3492    public void nestedscopes()
3493    {
3494        checkTemplateOutput("0;1;2;", "<?for i in range(3)?><?def x?><?print i?>;<?end def?><?code x.render()?><?end for?>");
3495        checkTemplateOutput("1;", "<?for i in range(3)?><?if i == 1?><?def x?><?print i?>;<?end def?><?end if?><?end for?><?code x.render()?>");
3496        checkTemplateOutput("1", "<?code i = 1?><?def x?><?print i?><?end def?><?code i = 2?><?code x.render()?>");
3497        checkTemplateOutput("1", "<?code i = 1?><?def x?><?def y?><?print i?><?end def?><?code i = 2?><?code y.render()?><?end def?><?code i = 3?><?code x.render()?>");
3498    }
3499
3500    @Test
3501    public void pass_functions()
3502    {
3503        checkTemplateOutput("&lt;", "<?def x?><?print x('<')?><?end def?><?code x.render(x=xmlescape)?>");
3504    }
3505
3506    @Test
3507    public void function()
3508    {
3509        checkTemplateResult(42, "<?return 42?>");
3510    }
3511
3512    @Test
3513    public void function_value()
3514    {
3515        checkTemplateResult(84, "<?return 2*x?>", "x", 42);
3516    }
3517
3518    @Test
3519    public void function_multiple_returnvalues()
3520    {
3521        checkTemplateResult(84, "<?return 2*x?><?return 3*x?>", "x", 42);
3522    }
3523
3524    @Test
3525    public void function_name()
3526    {
3527        checkTemplateResult("f", "<?def f?><?return f.name?><?end def?><?return f(f=f)?>");
3528    }
3529
3530    @Test
3531    public void function_closure()
3532    {
3533        checkTemplateResult(24, "<?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner(x=4)?>");
3534        checkTemplateResult(24, "<?def outer?><?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner?><?end def?><?return outer()(x=4)?>");
3535    }
3536
3537    @Test
3538    public void return_in_template()
3539    {
3540        checkTemplateOutput("gurk", "gurk<?return 42?>hurz");
3541    }
3542
3543    @Test
3544    public void keepWhitespace()
3545    {
3546        InterpretedTemplate template1 = getTemplate("<?if True?> foo<?end if?>");
3547        assertEquals(template1.renders(), " foo");
3548
3549        InterpretedTemplate template2 = getTemplate("<?if True?> foo\n bar<?end if?>");
3550        assertEquals(template2.renders(), " foobar");
3551
3552        InterpretedTemplate template3 = getTemplate("<?if True?>\n foo\n bar<?end if?>");
3553        assertEquals(template3.renders(), "foobar");
3554    }
3555
3556    private InterpretedTemplate universaltemplate()
3557    {
3558        return getTemplate(
3559            "text" +
3560            "<?xml version='1.0' encoding='utf-8'?>" + // will not be recognized as a tag
3561            "<?code x = 'gurk'?>" +
3562            "<?code x = 42?>" +
3563            "<?code x = 4.2?>" +
3564            "<?code x = None?>" +
3565            "<?code x = False?>" +
3566            "<?code x = True?>" +
3567            "<?code x = @(2009-01-04)?>" +
3568            "<?code x = @(2009-01-04T)?>" +
3569            "<?code x = @(2009-01-04T12:34)?>" +
3570            "<?code x = @(2009-01-04T12:34:56)?>" +
3571            "<?code x = @(2009-01-04T12:34:56.987654)?>" +
3572            "<?code x = #0063a8?>" +
3573            "<?code x = [42]?>" +
3574            "<?code x = {'fortytwo': 42}?>" +
3575            "<?code x = {**{'fortytwo': 42}}?>" +
3576            "<?code x = y?>" +
3577            "<?code x += 42?>" +
3578            "<?code x -= 42?>" +
3579            "<?code x *= 42?>" +
3580            "<?code x /= 42?>" +
3581            "<?code x //= 42?>" +
3582            "<?code x %= 42?>" +
3583            "<?print x.gurk?>" +
3584            "<?print x['gurk']?>" +
3585            "<?print x[1:2]?>" +
3586            "<?print x[1:]?>" +
3587            "<?print x[:2]?>" +
3588            "<?print x[:]?>" +
3589            "<?printx x?>" +
3590            "<?for x in '12'?><?print x?><?break?><?continue?><?end for?>" +
3591            "<?print not x?>" +
3592            "<?print -x?>" +
3593            "<?print x in y?>" +
3594            "<?print x not in y?>" +
3595            "<?print x==y?>" +
3596            "<?print x!=y?>" +
3597            "<?print x<y?>" +
3598            "<?print x<=y?>" +
3599            "<?print x>y?>" +
3600            "<?print x>=y?>" +
3601            "<?print x+y?>" +
3602            "<?print x*y?>" +
3603            "<?print x/y?>" +
3604            "<?print x//y?>" +
3605            "<?print x and y?>" +
3606            "<?print x or y?>" +
3607            "<?print x % y?>" +
3608            "<?print now()?>" +
3609            "<?print repr(1)?>" +
3610            "<?print range(1, 2)?>" +
3611            "<?print range(1, 2, 3)?>" +
3612            "<?print rgb(1, 2, 3, 4)?>" +
3613            "<?print x.r()?>" +
3614            "<?print x.find(1)?>" +
3615            "<?print x.find(1, 2)?>" +
3616            "<?print x.find(1, 2, 3)?>" +
3617            "<?if x?>gurk<?elif y?>hurz<?else?>hinz<?end if?>" +
3618            "<?def x?>foo<?end def?>"
3619        );
3620    }
3621
3622    @Test
3623    public void template_str()
3624    {
3625        universaltemplate().toString();
3626    }
3627
3628    @Test
3629    public void reader() throws IOException
3630    {
3631        String li = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";
3632        InterpretedTemplate template = getTemplate("<?for i in range(100)?>" + li + "<?end for?>", "reader");
3633
3634        Reader reader = template.reader(null);
3635
3636        int c;
3637        StringBuilder buffer = new StringBuilder();
3638        while ((c = reader.read()) != -1)
3639        {
3640            buffer.append((char)c);
3641        }
3642
3643        StringBuilder expected = new StringBuilder();
3644        for (int i = 0; i < 100; i++)
3645            expected.append(li);
3646
3647        assertEquals(buffer.toString(), expected.toString());
3648    }
3649}
Note: See TracBrowser for help on using the browser.