http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/range.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/range.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/range.ftl
new file mode 100644
index 0000000..d2f5450
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/range.ftl
@@ -0,0 +1,50 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#include 'range-common.ftl'>
+
+<@assertEquals actual=(4..)?size expected=2147483647 />
+<@assertEquals actual=limitedJoin(4.., 3) expected="4, 5, 6, ..." />
+
+<@assertEquals actual=(4..)[0] expected=4 />
+<@assertEquals actual=(4..)[1] expected=5 />
+<@assertEquals actual=(4..)[1000000] expected=1000004 />
+<@assertFails message="out of bounds">
+       <@assertEquals actual=(4..)[-1] expected=5 />
+</@>
+
+<#assign r = 2147483646..>
+<@assertEquals actual=r?size expected=2147483647 />
+<@assertEquals actual=limitedJoin(r, 3) expected="2147483646, 2147483647, 
2147483648, ..." />
+<@assertEquals actual=r[100] expected=2147483746 />
+
+<#assign r = -2..>
+<@assertEquals actual=limitedJoin(r, 5) expected="-2, -1, 0, 1, 2, ..." />
+<@assertEquals actual=r[0] expected=-2 />
+<@assertEquals actual=r[1] expected=-1 />
+
+<#function limitedJoin range limit>
+       <#assign joined="">
+       <#list range as i>
+               <#assign joined = joined + i?c>
+               <#if i_has_next><#assign joined = joined + ', '></#if>
+               <#local limit = limit - 1>
+               <#if limit == 0><#assign joined = joined + "..."><#break></#if>
+       </#list>
+       <#return joined>
+</#function>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/recover.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/recover.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/recover.ftl
new file mode 100644
index 0000000..f7dc437
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/recover.ftl
@@ -0,0 +1,47 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#attempt>
+ <#assign sequence = ["Hello, World"]>
+ ${sequence[0]}
+<#recover>
+  We should never get here.
+</#recover>
+<#attempt>
+ Let's try to output an undefined variable: ${undefinedVariable}
+<#recover>
+ Well, that did not work.<@assert test=.error?contains('undefinedVariable') />
+ Now we nest another attempt/recover here:
+ <#attempt>
+   ${sequence[1]}
+ <#recover>
+   Oops...<@assert test=.error?contains('sequence[1]') />
+   Remember, freeMarker sequences are zero-based! ${sequence[0]}
+ </#recover>
+ Now we check the current error message.<@assert 
test=.error?contains('undefinedVariable') />
+</#recover>
+<#attempt>
+  <#include "nonexistent_template">
+<#recover>
+  The template is not currently available
+</#recover>
+<#attempt>
+  <#include "undefined.ftl">
+<#recover>
+  The included template had a problem.<@assert 
test=.error?contains('undefined_variable') />
+</#attempt>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/root.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/root.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/root.ftl
new file mode 100644
index 0000000..e1bc7f3
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/root.ftl
@@ -0,0 +1,47 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html>
+<head>
+<title>FreeMarker: Root Lookup Test</title>
+</head>
+<body>
+
+<p>A simple test follows:</p>
+
+<p>${message}</p>
+
+<p>Access the same variable via the root variable (dot syntax):</p>
+
+<p>${.data_model.message}</p>
+
+<p>Access the same variable via the root variable (bracket syntax):</p>
+
+<p>${.data_model["message"]}</p>
+
+<p>Ensure that root lookups are unaffected by local variables:</p>
+
+<#macro test message>
+  ${.data_model.message}
+  ${message}
+</#macro>
+
+<@test message + " Part Deux" />
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/sequence-builtins.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/sequence-builtins.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/sequence-builtins.ftl
new file mode 100644
index 0000000..e21bc2d
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/sequence-builtins.ftl
@@ -0,0 +1,360 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<@noOutput>
+<#setting locale="en_US">
+<#setting number_format="0.#########">
+
+<#assign ls = []?sort>
+<#list ls as i>
+- ${i}
+</#list>
+<@assertEquals expected=0 actual=ls?size />
+<@assertEquals expected=3 actual=set?size />
+</@noOutput>
+Sorting scalars:
+----------------
+
+String order:
+<#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort>
+<#list ls as i>
+- ${i}
+</#list>
+
+First: ${ls?first}
+Last: ${ls?last}
+Size ${ls?size}
+
+Numerical order:
+<#assign ls = [123?byte, 543, -324, -34?float, 0.11, 0, 111?int, 0.1?double, 
1, 5]?sort>
+<#list ls as i>
+- ${i}
+</#list>
+
+First: ${ls?first}
+Last: ${ls?last}
+Size ${ls?size}
+
+Date/time order:
+<#assign x = [
+        '08:05'?time('HH:mm'),
+        '18:00'?time('HH:mm'),
+        '06:05'?time('HH:mm'),
+        '08:15'?time('HH:mm')]>
+<#list x?sort as i>
+- ${i?string('HH:mm')}
+</#list>
+
+Boolean order:
+<#assign x = [
+        true,
+        false,
+        false,
+        true]>
+<#list x?sort as i>
+- ${i?string}
+</#list>
+
+
+Sorting hashes:
+---------------
+
+<#assign ls = [
+  {"name":"whale", "weight":2000?short},
+  {"name":"Barbara", "weight":53},
+  {"name":"zeppelin", "weight":-200?float},
+  {"name":"aardvark", "weight":30?long},
+  {"name":"beetroot", "weight":0.3}
+]>
+Order by name:
+<#assign ls = ls?sort_by("name")>
+<#list ls as i>
+- ${i.name}: ${i.weight}
+</#list>
+
+Order by weight:
+<#assign ls = ls?sort_by("weight")>
+<#list ls as i>
+- ${i.name}: ${i.weight}
+</#list>
+
+Order by a.x.v:
+<#assign x = [
+        {"a": {"x": {"v": "qweqw", "w": "asd"}, "y": 
'1998-02-20'?date('yyyy-MM-dd')}},
+        {"a": {"x": {"v": "aqweqw", "w": "asd"}, "y": 
'1999-01-20'?date('yyyy-MM-dd')}},
+        {"a": {"x": {"v": "dfgdf", "w": "asd"}, "y": 
'1999-04-20'?date('yyyy-MM-dd')}},
+        {"a": {"x": {"v": "utyu", "w": "asd"}, "y": 
'1999-04-19'?date('yyyy-MM-dd')}}]>
+<#list x?sort_by(['a', 'x', 'v']) as i>
+- ${i.a.x.v}
+</#list>
+
+Order by a.y, which is a date:
+<#list x?sort_by(['a', 'y']) as i>
+- ${i.a.y?string('yyyy-MM-dd')}
+</#list>
+
+Reverse:
+--------
+
+Order by weight desc:
+<#assign ls = ls?reverse>
+<#list ls as i>
+- ${i.name}: ${i.weight}
+</#list>
+
+Order by weight desc desc:
+<#assign ls = ls?reverse>
+<#list ls as i>
+- ${i.name}: ${i.weight}
+</#list>
+
+Order by weight desc desc desc:
+<#assign ls = ls?reverse>
+<#list ls as i>
+- ${i.name}: ${i.weight}
+</#list>
+
+Contains:
+---------
+
+<#macro test></#macro>
+<#assign x = [1, "2", true, [1,2,3], {"a":1}, test, 
'1992-02-21'?date('yyyy-MM-dd')]>
+True:
+${x?seq_contains(1.0)?string}
+${x?seq_contains("2")?string}
+${x?seq_contains(true)?string}
+${x?seq_contains('1992-02-21'?date('yyyy-MM-dd'))?string}
+${abcSet?seq_contains("a")?string}
+${abcSet?seq_contains("b")?string}
+${abcSet?seq_contains("c")?string}
+
+False:
+${x?seq_contains("1")?string}
+${x?seq_contains(2)?string}
+${x?seq_contains(false)?string}
+${x?seq_contains('1992-02-22'?date('yyyy-MM-dd'))?string}
+${abcSet?seq_contains("A")?string}
+${abcSet?seq_contains(1)?string}
+${abcSet?seq_contains(true)?string}
+
+<#assign x = []>
+False: ${x?seq_contains(1)?string}
+
+Index_of:
+---------
+
+<#assign x = [1, "2", true, [1,2,3], {"a":1}, test, 
'1992-02-21'?date('yyyy-MM-dd')]>
+0 = ${x?seq_index_of(1.0)}
+1 = ${x?seq_index_of("2")}
+2 = ${x?seq_index_of(true)}
+6 = ${x?seq_index_of('1992-02-21'?date('yyyy-MM-dd'))}
+0 = ${abcSet?seq_index_of("a")}
+1 = ${abcSet?seq_index_of("b")}
+2 = ${abcSet?seq_index_of("c")}
+
+-1 = ${x?seq_index_of("1")}
+-1 = ${x?seq_index_of(2)}
+-1 = ${x?seq_index_of(false)}
+-1 = ${x?seq_index_of('1992-02-22'?date('yyyy-MM-dd'))}
+-1 = ${abcSet?seq_index_of("A")}
+-1 = ${abcSet?seq_index_of(1)}
+-1 = ${abcSet?seq_index_of(true)}
+
+<#assign x = []>
+-1 = ${x?seq_index_of(1)}
+
+Last_index_of:
+--------------
+
+<#assign x = [1, "2", true, [1,2,3], {"a":1}, test, 1, 
'1992-02-21'?date('yyyy-MM-dd')]>
+6 = ${x?seq_last_index_of(1.0)}
+1 = ${x?seq_last_index_of("2")}
+2 = ${x?seq_last_index_of(true)}
+7 = ${x?seq_last_index_of('1992-02-21'?date('yyyy-MM-dd'))}
+-1 = ${x?seq_last_index_of("1")}
+0 = ${abcSet?seq_last_index_of("a")}
+1 = ${abcSet?seq_last_index_of("b")}
+2 = ${abcSet?seq_last_index_of("c")}
+-1 = ${abcSet?seq_last_index_of("A")}
+
+Index_of and last_index_of with starting indices
+------------------------------------------------
+
+<#assign names = ["Joe", "Fred", "Joe", "Susan"]>
+seq_index_of "Joe":
+0 = ${names?seq_index_of("Joe", -2)}
+0 = ${names?seq_index_of("Joe", -1)}
+0 = ${names?seq_index_of("Joe", 0)}
+2 = ${names?seq_index_of("Joe", 1)}
+2 = ${names?seq_index_of("Joe", 2)}
+-1 = ${names?seq_index_of("Joe", 3)}
+-1 = ${names?seq_index_of("Joe", 4)}
+ 
+seq_last_index_of "Joe":
+-1 = ${names?seq_last_index_of("Joe", -2)}
+-1 = ${names?seq_last_index_of("Joe", -1)}
+0 = ${names?seq_last_index_of("Joe", 0)}
+0 = ${names?seq_last_index_of("Joe", 1)}
+2 = ${names?seq_last_index_of("Joe", 2)}
+2 = ${names?seq_last_index_of("Joe", 3)}
+2 = ${names?seq_last_index_of("Joe", 4)}
+ 
+seq_index_of "Susan":
+3 = ${names?seq_index_of("Susan", -2)}
+3 = ${names?seq_index_of("Susan", -1)}
+3 = ${names?seq_index_of("Susan", 0)}
+3 = ${names?seq_index_of("Susan", 1)}
+3 = ${names?seq_index_of("Susan", 2)}
+3 = ${names?seq_index_of("Susan", 3)}
+-1 = ${names?seq_index_of("Susan", 4)}
+ 
+seq_last_index_of "Susan":
+-1 = ${names?seq_last_index_of("Susan", -2)}
+-1 = ${names?seq_last_index_of("Susan", -1)}
+-1 = ${names?seq_last_index_of("Susan", 0)}
+-1 = ${names?seq_last_index_of("Susan", 1)}
+-1 = ${names?seq_last_index_of("Susan", 2)}
+3 = ${names?seq_last_index_of("Susan", 3)}
+3 = ${names?seq_last_index_of("Susan", 4)}
+
+seq_index_of "a":
+0 = ${abcSet?seq_index_of("a", -2)}
+0 = ${abcSet?seq_index_of("a", -1)}
+0 = ${abcSet?seq_index_of("a", 0)}
+-1 = ${abcSet?seq_index_of("a", 1)}
+-1 = ${abcSet?seq_index_of("a", 2)}
+-1 = ${abcSet?seq_index_of("a", 3)}
+-1 = ${abcSet?seq_index_of("a", 4)}
+
+seq_index_of "b":
+1 = ${abcSet?seq_index_of("b", -2)}
+1 = ${abcSet?seq_index_of("b", -1)}
+1 = ${abcSet?seq_index_of("b", 0)}
+1 = ${abcSet?seq_index_of("b", 1)}
+-1 = ${abcSet?seq_index_of("b", 2)}
+-1 = ${abcSet?seq_index_of("b", 3)}
+
+seq_index_of "c":
+2 = ${abcSet?seq_index_of("c", -2)}
+2 = ${abcSet?seq_index_of("c", -1)}
+2 = ${abcSet?seq_index_of("c", 0)}
+2 = ${abcSet?seq_index_of("c", 1)}
+2 = ${abcSet?seq_index_of("c", 2)}
+-1 = ${abcSet?seq_index_of("c", 3)}
+ 
+seq_last_index_of "a":
+-1 = ${abcSet?seq_last_index_of("a", -2)}
+-1 = ${abcSet?seq_last_index_of("a", -1)}
+0 = ${abcSet?seq_last_index_of("a", 0)}
+0 = ${abcSet?seq_last_index_of("a", 1)}
+0 = ${abcSet?seq_last_index_of("a", 2)}
+0 = ${abcSet?seq_last_index_of("a", 3)}
+0 = ${abcSet?seq_last_index_of("a", 4)}
+
+seq_last_index_of "b":
+-1 = ${abcSet?seq_last_index_of("b", -2)}
+-1 = ${abcSet?seq_last_index_of("b", -1)}
+-1 = ${abcSet?seq_last_index_of("b", 0)}
+1 = ${abcSet?seq_last_index_of("b", 1)}
+1 = ${abcSet?seq_last_index_of("b", 2)}
+1 = ${abcSet?seq_last_index_of("b", 3)}
+
+seq_last_index_of "c":
+-1 = ${abcSet?seq_last_index_of("c", -2)}
+-1 = ${abcSet?seq_last_index_of("c", -1)}
+-1 = ${abcSet?seq_last_index_of("c", 0)}
+-1 = ${abcSet?seq_last_index_of("c", 1)}
+2 = ${abcSet?seq_last_index_of("c", 2)}
+2 = ${abcSet?seq_last_index_of("c", 3)}
+
+Sequence builtins ignoring nulls
+--------------------------------
+
+true = ${listWithNull?seq_contains('c')?string}
+2 = ${listWithNull?seq_index_of('c')}
+0 = ${listWithNull?seq_last_index_of('a')}
+
+These should throw exception, but for BC they don't:
+false = ${listWithNull?seq_contains(noSuchVar)?string}
+-1 = ${listWithNull?seq_index_of(noSuchVar)}
+-1 = ${listWithNull?seq_last_index_of(noSuchVar)}
+
+Sequence built-ins failing on date-type mismatch
+------------------------------------------------
+
+<#assign x = ['1992-02-21'?date('yyyy-MM-dd'), 'foo']>
+<@assertEquals actual=x?seq_index_of('foo') expected=1 />
+<@assertEquals actual=x?seq_index_of('1992-02-21'?date('yyyy-MM-dd')) 
expected=0 />
+<@assertFails message="dates of different types">
+  0 = ${x?seq_index_of('1992-02-21 00:00:00'?datetime('yyyy-MM-dd HH:mm:ss'))}
+</@>
+
+Chunk
+-----
+
+<#assign ls = ['a', 'b', 'c', 'd', 'e', 'f', 'g']>
+<#list ['NULL', '-'] as fill>
+  <#list [1, 2, 3, 4, 5, 10] as columns>
+    <@printTable ls, columns, fill />
+  </#list>
+</#list>
+<@printTable [1, 2, 3, 4, 5, 6, 7, 8, 9], 3, 'NULL' />
+<@printTable [1, 2, 3, 4, 5, 6, 7, 8, 9], 3, '-' />
+<@printTable [1], 3, 'NULL' />
+<@printTable [1], 3, '-' />
+<@printTable [], 3, 'NULL' />
+<@printTable [], 3, '-' />
+
+<#macro printTable ls columns fill>
+  columns = ${columns}, fill = ${fill}:<#lt>
+  <#if fill='NULL'>
+    <#local rows = ls?chunk(columns)>
+  <#else>
+    <#local rows = ls?chunk(columns, fill)>
+  </#if>
+  Rows: ${rows?size}
+  <#list rows as row>
+    <#list row as i>${i} </#list>  <-- Columns: ${row?size}
+  </#list>
+  
+</#macro>
+
+
+Join
+----
+
+<#assign xs = [1, "two", "three", 4]>
+- ${xs?join(", ")}
+- ${[]?join(", ")}
+- ${xs?join(", ", "(empty)", ".")}
+- ${[]?join(", ", "(empty)", ".")}
+- ${listWithNull?join(", ")}
+- ${listWithNull?join(", ", "(empty)")}
+- ${listWithNull?join(", ", "(empty)", ".")}
+- ${listWithNullsOnly?join(", ")}
+- ${listWithNullsOnly?join(", ", "(empty)")}
+- ${listWithNullsOnly?join(", ", "(empty)", ".")}
+- ${abcSet?join(", ", "(empty)", ".")}
+- ${abcCollection?join(", ", "(empty)", ".")}
+<@assertFails message="index 1">${['a', [], 'c']?join(", ", "(empty)", 
".")}</@>
+
+Misc
+----
+
+First of set 1: ${abcSet?first}
+First of set 2: ${abcSetNonSeq?first}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/setting.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/setting.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/setting.ftl
new file mode 100644
index 0000000..89f3e23
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/setting.ftl
@@ -0,0 +1,53 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#setting locale='de_DE'>
+<@assertEquals expected='de_DE' actual=.locale />
+<@assertEquals expected='de' actual=.lang />
+<@assertEquals expected='java.util.Locale "de_DE"' 
actual=javaObjectInfo.info(.locale_object) />
+
+<#setting number_format="'f'#">
+<@assertEquals expected='f1' actual=1?string />
+
+<#setting boolean_format="t,f">
+<@assertEquals expected='t' actual=true?string />
+
+<#setting date_format="'df'">
+<@assertEquals expected='df' actual=.now?date?string />
+
+<#setting time_format="'tf'">
+<@assertEquals expected='tf' actual=.now?time?string />
+
+<#setting datetime_format="'dtf'">
+<@assertEquals expected='dtf' actual=.now?string />
+
+<#setting time_zone='GMT+00'>
+<#assign t1='2000'?datetime('yyyy')>
+<#setting time_zone='GMT+01'>
+<#assign t2='2000'?datetime('yyyy')>
+<@assertEquals expected=1000*60*60 actual=t1?long-t2?long />
+
+<#setting sql_date_and_time_time_zone='GMT+01'>
+
+<#setting url_escaping_charset='ISO-8859-1'>
+<@assertEquals expected='%E1' actual='á'?url />
+<#setting url_escaping_charset='UTF-8'>
+<@assertEquals expected='%C3%A1' actual='á'?url />
+
+<#setting output_encoding="ISO-8859-2">
+<@assertEquals expected="ISO-8859-2" actual=.output_encoding />

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/simplehash-char-key.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/simplehash-char-key.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/simplehash-char-key.ftl
new file mode 100644
index 0000000..07a3f1e
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/simplehash-char-key.ftl
@@ -0,0 +1,44 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<@assertEquals expected="string" actual=mStringC.c />
+<@assertEquals expected=1 actual=mStringC?keys?size />
+<@assertEquals expected="null" actual=mStringC.d!'null' />
+<@assertEquals expected=1 actual=mStringC?keys?size />
+
+<@assertEquals expected="null" actual=mStringCNull.c!'null' />
+<@assertEquals expected=1 actual=mStringCNull?keys?size />
+<@assertEquals expected="null" actual=mStringCNull.d!'null' />
+<@assertEquals expected=1 actual=mStringCNull?keys?size />
+
+<@assertEquals expected="char" actual=mCharC.c />
+<@assertEquals expected=1 actual=mCharC?keys?size />
+<@assertEquals expected="null" actual=mCharC.d!'null' />
+<@assertEquals expected=1 actual=mCharC?keys?size />
+
+<@assertEquals expected="null" actual=mCharCNull.c!'null' />
+<@assertEquals expected=1 actual=mCharCNull?keys?size />
+<@assertEquals expected="null" actual=mCharCNull.d!'null' />
+<@assertEquals expected=1 actual=mCharCNull?keys?size />
+
+<@assertEquals expected="char" actual=mMixed.c />
+<@assertEquals expected="string" actual=mMixed.s />
+<@assertEquals expected="string2" actual=mMixed.s2 />
+<@assertEquals expected="null" actual=mMixed.s2n!'null' />
+<@assertEquals expected="null" actual=mMixed.wrong!'null' />
+<@assertEquals expected=4 actual=mMixed?keys?size />

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/specialvars.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/specialvars.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/specialvars.ftl
new file mode 100644
index 0000000..50416c9
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/specialvars.ftl
@@ -0,0 +1,38 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#-- Mostly just checks if the expressions doesn't fail -->
+<#assign works = .data_model>
+<#attempt>
+  ${noSuchVariableExists}
+<#recover>
+  <#assign works = .error>
+</#attempt>
+<#assign works = .globals>
+${.lang} == en
+${.locale} == en_US
+<#assign works = .locals!>
+<#assign works = .main>
+<#assign works = .node!>
+${.output_encoding?lower_case} == utf-8
+${.template_name} == specialvars.ftl
+${.url_escaping_charset?lower_case} == iso-8859-1
+<#assign foo = "x">
+${.vars['foo']} == x
+<#assign works = .version>
+${.now?is_datetime?c} == true
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtin-coercion.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtin-coercion.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtin-coercion.ftl
new file mode 100644
index 0000000..5d2e094
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtin-coercion.ftl
@@ -0,0 +1,34 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+Was broken 2.3.19:
+<#setting number_format="0.#">
+<@assert test=1232?contains('2') />
+<@assert test=1232?index_of('2') == 1 />
+<@assert test=1232?last_index_of('2') == 3 />
+<@assert test=1232?left_pad(6) == '  1232' /><@assert test=1232?left_pad(6, 
'0') == '001232' />
+<@assert test=1232?right_pad(6) == '1232  ' /><@assert test=1232?right_pad(6, 
'0') == '123200' />
+<@assert test=1232?matches('[1-3]+') />
+<@assert test=1232?replace('2', 'z') == '1z3z' />
+<@assert test=1232?replace('2', 'z', 'r') == '1z3z' />
+<@assert test=1232?split('2')[1] == '3' /><@assert test=1232?split('2')[2] == 
'' />
+<@assert test=1232?split('2', 'r')[1] == '3' />
+
+Was no broken in 2.3.19:
+<@assert test=1232?starts_with('12') />
+<@assert test=1232?ends_with('32') />

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps-matches.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps-matches.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps-matches.ftl
new file mode 100644
index 0000000..201f404
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps-matches.ftl
@@ -0,0 +1,118 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#assign input>
+L16
+L27
+L38
+L49
+</#assign>
+
+List mode:
+<#assign matches = input?matches(".+") >
+Size: ${matches?size}
+<#list 0..<matches?size as i>[${matches[i]}]</#list>
+<#list matches as m>[${m}]</#list>
+
+Iterator mode:
+<#assign matches = input?matches(".+") >
+<#list matches as m>[${m}]</#list>
+<#list matches as m>[${m}(${matches?join(', ')})]</#list>
+<#list matches as m>[${m}]</#list>
+
+Iterator mode changes to list mode:
+<#assign matches = input?matches(".+") >
+<#list matches as m>[${m}]/${matches?size}</#list>
+<#list matches as m>[${m}]</#list>
+
+Iterator mode changes to list mode 2:
+<#assign matches = input?matches(".+") >
+<#list matches as m>[${m}]</#list>
+<#list matches as m>[${m}]/${matches?size}<#t></#list>
+
+List mode with embedded iteration:
+<#assign matches = input?matches(".+") >
+<#list 0..<matches?size as i>[${matches[i]}(${matches?join(', ')})]</#list>
+
+Entire input match:
+<#assign matches = input?matches(r".*(\d)(\d)") >
+<#assign firstGS = false>
+<#list matches as m>
+- M: ${m}
+    <#if firstGS?is_boolean>
+      <#assign firstGS = m?groups>
+    </#if>
+    <#list m?groups as g>
+    - G: ${g}
+    </#list>
+</#list>
+firstGS was: ${firstGS?join(', ')}
+
+Entire input match 2:
+<#assign match = "x12"?matches(r"x(\d)(\d)") >
+Matches: ${match?c}
+<#list match?groups as g>
+- G: ${g}
+</#list>
+As list:
+<#list match as m>
+- M: ${m}
+  <#list m?groups as g>
+    - G: ${g}
+  </#list>
+</#list>
+Groups again:
+<#list match?groups as g>
+- G: ${g}
+</#list>
+
+Entire input match 3:
+<#assign match = "x12"?matches(r"y(\d)(\d)") >
+Matches: ${match?c}
+<@assertEquals expected=3 actual=match?groups?size />
+<@assertEquals expected=0 actual=match?size />
+
+Entire input match 4:
+<#assign match = "x12"?matches(r"x(\d)(\d)") >
+Matches: ${match?c}
+<#assign gs = match?groups>
+<@assertEquals expected=3 actual=gs?size />
+<@assertEquals expected=1 actual=match?size />
+- G: ${gs[0]}
+- G: ${match?groups[1]}
+- G: ${gs[2]}
+
+Substring match nested into entire input match:
+<#assign match = "x12"?matches(r"x(\d)(\d)") >
+<#list match?groups as g>
+- G: ${g} (<#list match as m>[${m}{${m?groups?join(', ')}}]</#list>)
+</#list>
+
+Different entire input and substring matches:
+<#assign match = "123"?matches(r"(\d+?)") >
+${match?groups?join(", ")}
+<#list match as m>
+- M: ${m} (Gs: ${m?groups?join(", ")})
+</#list>
+
+Different entire input and substring matches 2:
+<#assign match = "123"?matches(r"\d+?") >
+${match?groups?join(", ")}
+<#list match as m>
+- M: ${m} (Gs: ${m?groups?join(", ")})
+</#list>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps.ftl
new file mode 100644
index 0000000..81c0b8f
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins-regexps.ftl
@@ -0,0 +1,136 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+${"test"?matches('test')?string} == true
+${"test"?matches('test', '')?string} == true
+
+${"TEST"?matches('test')?string} == false
+${"TEST"?matches('test', 'i')?string} == true
+
+${"test\nfoo"?matches('.*^foo')?string} == false
+${"test\nfoo"?matches(r'.*\n^foo', 'm')?string} == true
+
+${"test\nfoo"?matches('test.foo')?string} == false
+${"test\nfoo"?matches('test.foo', 's')?string} == true
+
+${"test\nFoo"?matches('.*foo', 's')?string} == false
+${"test\nFoo"?matches('.*foo', 'i')?string} == false
+${"test\nFoo"?matches('.*foo', 'im')?string} == false
+${"test\nFoo"?matches('.*foo', 'si')?string} == true
+${"test\nFoo"?matches('.*foo', 'is')?string} == true
+${"test\nFoo"?matches('.*foo', 'mis')?string} == true
+
+${"test\nFoo"?matches('.*\n^foo', 'm')?string} == false
+${"test\nFoo"?matches('.*\n^foo', 'i')?string} == false
+${"test\nFoo"?matches('.*\n^foo', 'im')?string} == true
+${"test\nFoo"?matches('.*\n^foo', 'mi')?string} == true
+${"test\nFoo"?matches('.*^foo', 'ism')?string} == true
+${"test\nFoo"?matches('.*^foo', 'smi')?string} == true
+<#setting boolean_format="True,False">
+<@assert test=false?matches('[eslaF]+') />
+<@assert test='False'?matches('[eslaF]+') />
+
+<#assign s = "Code without test coverage\nis considered to be BROKEN">
+
+Lower 'c'-words:
+<#list s?matches('c[a-z]*') as m>
+- ${m}
+</#list>
+
+Any 'c'-words:
+<#list s?matches('c[a-z]*', 'i') as m>
+- ${m}
+</#list>  
+
+Lower line-last words:
+<#list s?matches('[a-z]+$', 'm') as m>
+- ${m}
+</#list>  
+
+Any line-last words:
+<#list s?matches('[a-z]+$', 'mi') as m>
+- ${m}
+</#list>
+
+Any last words:
+<#list s?matches('[a-z]+$', 'i') as m>
+- ${m}
+</#list>
+
+c-word with follower:
+<#list s?matches('(c[a-z]*+).([a-z]++)', 'is') as m>
+- "${m?j_string}"
+  Groups: <#list m?groups as g>"${g?j_string}"<#if g_has_next>, </#if></#list>
+</#list>
+
+c-word with follower in the same line:
+<#list s?matches('c[a-z]*+.[a-z]++', 'i') as m>
+- ${m}
+</#list>
+
+Lower c-word with follower in the same line:
+<#list s?matches('c[a-z]*+.[a-z]++', '') as m>
+- ${m}
+</#list>
+
+<#attempt>
+  Ignored but logged in 2.3: ${s?matches('broken', 'I')?string} == False
+<#recover>
+  Fails in 2.4
+</#attempt>
+<#attempt>
+  Ignored but logged in 2.3: ${s?matches('broken', 'f')?string} == False
+<#recover>
+  Fails in 2.4
+</#attempt>
+
+${"foobar"?replace("foo", "FOO")} == FOObar
+${"Foobar"?replace("foo", "FOO", "")} == Foobar
+${"Foobar"?replace("foo", "FOO", "i")} == FOObar
+${"FoobarfOO"?replace("foo", "FOO", "i")} == FOObarFOO
+${"FoobarfOO"?replace("foo", "FOO", "if")} == FOObarfOO
+${"FoobarfOO"?replace("foo", "FOO", "fi")} == FOObarfOO
+${"Foobar"?replace("foo", "FOO", "r")} == Foobar
+${"Foobar"?replace("foo", "FOO", "ri")} == FOObar
+${"FoobarfOO"?replace("foo", "FOO", "ri")} == FOObarFOO
+${"FoobarfOO"?replace("foo", "FOO", "rif")} == FOObarfOO
+${"FoobarfOO"?replace("foo", "FOO", "fri")} == FOObarfOO
+${"foobar"?replace("fo+", "FOO")} == foobar
+${"foobar"?replace("fo+", "FOO", "")} == foobar
+${"foobar"?replace("fo+", "FOO", "r")} == FOObar
+${"foobarfOo"?replace("fo+", "FOO", "ri")} == FOObarFOO
+${"foobarfOo"?replace("fo+", "FOO", "rif")} == FOObarfOo
+${false?replace('a', 'A')} == FAlse
+${false?replace('[abc]', 'A', 'r')} == FAlse
+
+<#attempt>
+  Ignored but logged in 2.3: ${"foobar"?replace("foo", "FOO", "c")}
+<#recover>
+  Fails in 2.4
+</#attempt>
+
+<#macro dumpList xs>[<#list xs as x>${x}<#if x_has_next>, 
</#if></#list>]</#macro>
+<@dumpList "fooXbarxbaaz"?split("X") /> == [foo, barxbaaz]
+<@dumpList "fooXbarxbaaz"?split("X", "") /> == [foo, barxbaaz]
+<@dumpList "fooXbarxbaaz"?split("X", "i") /> == [foo, bar, baaz]
+<@dumpList "fooXbarxbaaz"?split("X", "r") /> == [foo, barxbaaz]
+<@dumpList "fooXbarxbaaz"?split("X", "ri") /> == [foo, bar, baaz]
+<@dumpList "fooXXbarxxbaaz"?split("X+", "i") /> == [fooXXbarxxbaaz]
+<@dumpList "fooXXbarxxbaaz"?split("X+", "ri") /> == [foo, bar, baaz]
+<@dumpList false?split("[ae]", "r") /> == [F, ls]
+<@dumpList false?split("e") /> == [Fals, ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins1.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins1.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins1.ftl
new file mode 100644
index 0000000..0e18520
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins1.ftl
@@ -0,0 +1,129 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+FreeMarker: Encoding string built-in tests
+
+<#assign x = r'  dieBugsDie! * vazzZE 123456 --cdc-- --<<--@ x 
${"kigyo"?upper_case}  '>
+  
+cap_first:  ${x?cap_first}
+uncap_first:${x?uncap_first}
+uncap_first:${"Blah"?uncap_first}
+capitalize: ${x?capitalize}
+html:       ${x?html}
+length:     ${x?length}
+lower_case: ${x?lower_case}
+rtf:        ${x?rtf}
+trim:       ${x?trim}
+trim2:      ${"foo bar"?trim}
+trim3:      ${" foo bar"?trim}
+trim4:      ${"foo bar "?trim}
+upper_case: ${x?upper_case}
+xml:        ${x?xml}
+xhtml:      ${"\"Blah's is > 1 & < 2\""?xhtml}
+<@assertEquals actual="'"?html expected="&#39;" />
+<@assertEquals actual="'"?xhtml expected="&#39;" />
+<@assertEquals actual="'"?xml expected="&apos;" />
+<#-- ?substring: -->
+<@assertEquals actual="ab"?substring(0) expected="ab" />
+<@assertEquals actual="ab"?substring(1) expected="b" />
+<@assertEquals actual="ab"?substring(2) expected="" />
+<@assertFails message="at least 0">${"ab"?substring(-1)}</@><#t>
+<@assertFails message="greater than the length of the 
string">${"ab"?substring(3)}</@><#t>
+<@assertEquals actual="ab"?substring(0, 0) expected="" />
+<@assertEquals actual="ab"?substring(0, 1) expected="a" />
+<@assertEquals actual="ab"?substring(0, 2) expected="ab" />
+<@assertFails message="at least 0">${"ab"?substring(0, -1)}</@><#t>
+<@assertFails message="greater than the length of the 
string">${"ab"?substring(0, 3)}</@><#t>
+<@assertEquals actual="ab"?substring(1, 1) expected="" />
+<@assertEquals actual="ab"?substring(1, 2) expected="b" />
+<@assertFails message="at least 0">${"ab"?substring(1, -1)}</@><#t>
+<@assertFails message="greater than the length of the 
string">${"ab"?substring(1, 3)}</@><#t>
+<@assertFails message="shouldn't be greater than the end 
index">${"ab"?substring(1, 0)}</@><#t>
+
+word_list:
+<#global words = x?word_list>
+<#list words as w>- ${w}
+</#list>
+
+<#global canufeelitbabe = x?interpret>
+interpret: <@canufeelitbabe></@>
+<#setting locale="es_ES">number: ${"-123.45"?number + 1.1}
+${"1.5e3"?number?c}
+${"0005"?number?c}
+${"+0"?number?c}
+${"-0"?number?c}
+${"NaN"?number?is_nan?c}
+${("INF"?number?is_infinite && "INF"?number > 0)?c}
+${("-INF"?number?is_infinite && "-INF"?number < 0)?c}
+${("Infinity"?number?is_infinite && "Infinity"?number > 0)?c}
+${("-Infinity"?number?is_infinite && "-Infinity"?number < 0)?c}
+
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new()}
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new(1)}
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new("xxx")}
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new("xxx", 
"yyy")}
+
+<#assign x = "In the beginning, God created the Heavens and The Earth.">
+
+${x?replace("the", "The Sacred, Holy", "i")} <#-- case insensitive replacement 
-->
+${x?replace("the", "the very", "f")} <#-- replace only the first one -->
+${x?replace("", "|")} <#-- replace empry string -->
+${x?replace("", "|", "f")} <#-- replace first empty string -->
+
+${x?replace("the H[a-z]+", "the sky", "r")} <#-- regexp replacement -->
+
+<#if x?matches(".*Heav..s.*")>matches<#else>Really?</#if>
+
+<#list x?matches("(the) ([a-z]+)", "i") as match>
+  ${match}
+  ${match?groups[1]} sacred ${match?groups[2]}
+</#list>  
+
+<#assign matches = x?matches("In the ([a-z]+), God created (.*)")>
+${matches?groups[0]}
+${matches?groups[1]}
+${matches?groups[2]}
+
+<#assign x="foo, bar;baz,     foobar">
+<#list x?split("[,;] ?", "r") as word>
+   ${word}
+</#list>
+
+
+<#assign a = "foo", b="bar", c="(a+b)?upper_case">
+${c?eval}
+
+[${"a"?j_string}] = [a]
+[${"a\\'x'\nb"?j_string}] = [a\\'x'\nb]
+[${"\x1\x1A\x20"?j_string}] = [\u0001\u001a ]
+
+[${"a"?js_string}] = [a]
+[${"a\\'x'\nb"?js_string}] = [a\\\'x\'\nb]
+[${"\x1\x1A\x20"?js_string}] = [\x01\x1A ]
+[${"<![CDATA["?js_string}] = [\x3C![CDATA[]
+[${"]]>"?js_string}] = []]\>]
+
+[${"a"?json_string}] = [a]
+[${"a\\'x'\nb"?json_string}] = [a\\'x'\nb]
+[${"\x1\x1A\x20"?json_string}] = [\u0001\u001A ]
+[${"\n\r\t\f\b\""?json_string}] = [\n\r\t\f\b\"]
+[${"/"?json_string}] = [\/]
+[${"a/b"?json_string}] = [a/b]
+[${"</script>"?json_string}] = [<\/script>]
+[${"<![CDATA["?json_string}] = [\u003C![CDATA[]
+[${"]]>"?json_string}] = []]\u003E]

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins2.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins2.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins2.ftl
new file mode 100644
index 0000000..c9294fa
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins2.ftl
@@ -0,0 +1,135 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+--
+<#assign s = "abbcdbb">
+${s?index_of("bb")} = 1
+${s?index_of("bb", 2)} = 5
+${s?index_of("")} = 0
+--
+${s?last_index_of("bb")} = 5
+${s?last_index_of("bb", 4)} = 1
+${s?last_index_of("")} = ${s?length}
+--
+${s?starts_with("abb")?string} = true
+${s?starts_with("bb")?string} = false
+${s?starts_with("")?string} = true
+--
+${s?ends_with("dbb")?string} = true
+${s?ends_with("cbb")?string} = false
+${s?ends_with("")?string} = true
+--
+${s?contains("abb")?string} = true
+${s?contains("bcd")?string} = true
+${s?contains("dbb")?string} = true
+${s?contains("bbx")?string} = false
+${s?contains("")?string} = true
+--
+[${s?chop_linebreak}] = [abbcdbb]
+[${"qwe\n"?chop_linebreak}] = [qwe]
+[${"qwe\r"?chop_linebreak}] = [qwe]
+[${"qwe\r\n"?chop_linebreak}] = [qwe]
+[${"qwe\r\n\r\n"?chop_linebreak}] = [qwe
+]
+[${"qwe\n\n"?chop_linebreak}] = [qwe
+]
+--
+[${s?replace("A", "-")}] = [abbcdbb]
+[${s?replace("c", "-")}] = [abb-dbb]
+[${s?replace("bb", "-=*")}] = [a-=*cd-=*]
+--
+<#assign ls = s?split("b")>
+<#list ls as i>[${i}]</#list> == [a][][cd][][]
+<#list "--die--maggots--!"?split("--") as i>[${i}]</#list> == 
[][die][maggots][!]
+<#list "Die maggots!"?split("--") as i>[${i}]</#list> == [Die maggots!]
+--
+[${""?left_pad(5)}]
+[${"a"?left_pad(5)}]
+[${"ab"?left_pad(5)}]
+[${"abc"?left_pad(5)}]
+[${"abcd"?left_pad(5)}]
+[${"abcde"?left_pad(5)}]
+[${"abcdef"?left_pad(5)}]
+[${"abcdefg"?left_pad(5)}]
+[${"abcdefgh"?left_pad(5)}]
+[${""?left_pad(5, "-")}]
+[${"a"?left_pad(5, "-")}]
+[${"ab"?left_pad(5, "-")}]
+[${"abc"?left_pad(5, "-")}]
+[${"abcd"?left_pad(5, "-")}]
+[${"abcde"?left_pad(5, "-")}]
+[${"abcdef"?left_pad(5, "-")}]
+[${"abcdefg"?left_pad(5, "-")}]
+[${"abcdefgh"?left_pad(5, "-")}]
+[${""?left_pad(8, ".oO")}]
+[${"a"?left_pad(8, ".oO")}]
+[${"ab"?left_pad(8, ".oO")}]
+[${"abc"?left_pad(8, ".oO")}]
+[${"abcd"?left_pad(8, ".oO")}]
+[${"abcde"?left_pad(8, ".oO")}]
+[${"abcdef"?left_pad(8, ".oO")}]
+[${"abcdefg"?left_pad(8, ".oO")}]
+[${"abcdefgh"?left_pad(8, ".oO")}]
+[${"abcdefghi"?left_pad(8, ".oO")}]
+[${"abcdefghij"?left_pad(8, ".oO")}]
+[${""?left_pad(0, r"/\_")}]
+[${""?left_pad(1, r"/\_")}]
+[${""?left_pad(2, r"/\_")}]
+[${""?left_pad(3, r"/\_")}]
+[${""?left_pad(4, r"/\_")}]
+[${""?left_pad(5, r"/\_")}]
+[${""?left_pad(6, r"/\_")}]
+[${""?left_pad(7, r"/\_")}]
+--
+[${""?right_pad(5)}]
+[${"a"?right_pad(5)}]
+[${"ab"?right_pad(5)}]
+[${"abc"?right_pad(5)}]
+[${"abcd"?right_pad(5)}]
+[${"abcde"?right_pad(5)}]
+[${"abcdef"?right_pad(5)}]
+[${"abcdefg"?right_pad(5)}]
+[${"abcdefgh"?right_pad(5)}]
+[${""?right_pad(5, "-")}]
+[${"a"?right_pad(5, "-")}]
+[${"ab"?right_pad(5, "-")}]
+[${"abc"?right_pad(5, "-")}]
+[${"abcd"?right_pad(5, "-")}]
+[${"abcde"?right_pad(5, "-")}]
+[${"abcdef"?right_pad(5, "-")}]
+[${"abcdefg"?right_pad(5, "-")}]
+[${"abcdefgh"?right_pad(5, "-")}]
+[${""?right_pad(8, ".oO")}]
+[${"a"?right_pad(8, ".oO")}]
+[${"ab"?right_pad(8, ".oO")}]
+[${"abc"?right_pad(8, ".oO")}]
+[${"abcd"?right_pad(8, ".oO")}]
+[${"abcde"?right_pad(8, ".oO")}]
+[${"abcdef"?right_pad(8, ".oO")}]
+[${"abcdefg"?right_pad(8, ".oO")}]
+[${"abcdefgh"?right_pad(8, ".oO")}]
+[${"abcdefghi"?right_pad(8, ".oO")}]
+[${"abcdefghij"?right_pad(8, ".oO")}]
+[${""?right_pad(0, r"/\_")}]
+[${""?right_pad(1, r"/\_")}]
+[${""?right_pad(2, r"/\_")}]
+[${""?right_pad(3, r"/\_")}]
+[${""?right_pad(4, r"/\_")}]
+[${""?right_pad(5, r"/\_")}]
+[${""?right_pad(6, r"/\_")}]
+[${""?right_pad(7, r"/\_")}]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins3.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins3.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins3.ftl
new file mode 100644
index 0000000..77389fa
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/string-builtins3.ftl
@@ -0,0 +1,225 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<@assertEquals expected='foo' actual='foo'?keep_before('x') />
+<@assertEquals expected='f' actual='foo'?keep_before('o') />
+<@assertEquals expected='' actual='foo'?keep_before('f') />
+<@assertEquals expected='fo' actual='foobar'?keep_before('ob') />
+<@assertEquals expected='foob' actual='foobar'?keep_before('ar') />
+<@assertEquals expected='' actual='foobar'?keep_before('foobar') />
+<@assertEquals expected='' actual='foobar'?keep_before('') />
+<@assertEquals expected='' actual='foobar'?keep_before('', 'r') />
+<@assertEquals expected='FOO' actual='FOO'?keep_before('o') />
+<@assertEquals expected='F' actual='FOO'?keep_before('o', 'i') />
+<@assertEquals expected='fo' actual='fo.o'?keep_before('.') />
+<@assertEquals expected='' actual='fo.o'?keep_before('.', 'r') />
+<@assertEquals expected='FOOb' actual='FOObaar'?keep_before(r'([a-z])\1', 'r') 
/>
+<@assertEquals expected='F' actual='FOObaar'?keep_before(r'([a-z])\1', 'ri') />
+<@assertEquals expected='foo' actual="foo : bar"?keep_before(r"\s*:\s*", "r") 
/>
+<@assertEquals expected='foo' actual="foo:bar"?keep_before(r"\s*:\s*", "r") />
+<@assertFails message='"m" flag'>
+    ${'x'?keep_before('x', 'm')}
+</@assertFails>
+<@assertFails message='3'>
+    ${'x'?keep_before('x', 'i', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?keep_before()}
+</@assertFails>
+
+<@assertEquals expected='' actual=''?keep_before_last('f') />
+<@assertEquals expected='ff' actual='fff'?keep_before_last('f') />
+<@assertEquals expected='' actual='foo'?keep_before_last('f') />
+<@assertEquals expected='' actual='f'?keep_before_last('f') />
+<@assertEquals expected='a.b' actual='a.b.txt'?keep_before_last('.') />
+<@assertEquals expected='ab' actual='ab'?keep_before_last('.') />
+<@assertEquals expected='a' actual='ab'?keep_before_last('.', 'r') />
+<@assertEquals expected='ab' actual='ab'?keep_before_last(r'\.', 'r') />
+<@assertEquals expected='af' actual='afFf'?keep_before_last('F') />
+<@assertEquals expected='afF' actual='afFf'?keep_before_last('F', 'i') />
+<@assertEquals expected='1a2' actual='1a2b3'?keep_before_last('[ab]', 'r') />
+<@assertEquals expected='aa' actual='aaabb'?keep_before_last('[ab]{3}', 'r') />
+<@assertEquals expected='aaabbx' 
actual='aaabbxbabe'?keep_before_last('[ab]{3}', 'r') />
+<@assertEquals expected='xxxaa' actual='xxxaaayyy'?keep_before_last('a+', 'r') 
/>
+<@assertEquals expected='foobar' actual='foobar'?keep_before_last('') />
+<@assertEquals expected='foobar' actual='foobar'?keep_before_last('', 'r') />
+<@assertFails message='"m" flag'>
+    ${'x'?keep_before_last('x', 'm')}
+</@assertFails>
+<@assertFails message='3'>
+    ${'x'?keep_before_last('x', 'i', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?keep_before_last()}
+</@assertFails>
+
+<@assertEquals expected='' actual='foo'?keep_after('x') />
+<@assertEquals expected='o' actual='foo'?keep_after('o') />
+<@assertEquals expected='oo' actual='foo'?keep_after('f') />
+<@assertEquals expected='ar' actual='foobar'?keep_after('ob') />
+<@assertEquals expected='' actual='foobar'?keep_after('ar') />
+<@assertEquals expected='' actual='foobar'?keep_after('foobar') />
+<@assertEquals expected='foobar' actual='foobar'?keep_after('') />
+<@assertEquals expected='foobar' actual='foobar'?keep_after('', 'r') />
+<@assertEquals expected='' actual='FOO'?keep_after('o') />
+<@assertEquals expected='O' actual='FOO'?keep_after('o', 'i') />
+<@assertEquals expected='o' actual='fo.o'?keep_after('.') />
+<@assertEquals expected='o.o' actual='fo.o'?keep_after('.', 'r') />
+<@assertEquals expected='r' actual='FOObaar'?keep_after(r'([a-z])\1', 'r') />
+<@assertEquals expected='baar' actual='FOObaar'?keep_after(r'([a-z])\1', 'ri') 
/>
+<@assertEquals expected='bar' actual="foo : bar"?keep_after(r"\s*:\s*", "r") />
+<@assertEquals expected='bar' actual="foo:bar"?keep_after(r"\s*:\s*", "r") />
+<@assertFails message='"m" flag'>
+    ${'x'?keep_after('x', 'm')}
+</@assertFails>
+<@assertFails message='3'>
+    ${'x'?keep_after('x', 'i', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?keep_after()}
+</@assertFails>
+
+<@assertEquals expected='' actual=''?keep_after_last('f') />
+<@assertEquals expected='' actual='fff'?keep_after_last('f') />
+<@assertEquals expected='' actual='oof'?keep_after_last('f') />
+<@assertEquals expected='' actual='f'?keep_after_last('f') />
+<@assertEquals expected='txt' actual='a.b.txt'?keep_after_last('.') />
+<@assertEquals expected='' actual='ab'?keep_after_last('.') />
+<@assertEquals expected='' actual='ab'?keep_after_last('.', 'r') />
+<@assertEquals expected='' actual='ab'?keep_after_last(r'\.', 'r') />
+<@assertEquals expected='fa' actual='fFfa'?keep_after_last('F') />
+<@assertEquals expected='a' actual='fFfa'?keep_after_last('F', 'i') />
+<@assertEquals expected='3' actual='1a2b3'?keep_after_last('[ab]', 'r') />
+<@assertEquals expected='' actual='aaabb'?keep_after_last('[ab]{3}', 'r') />
+<@assertEquals expected='x' actual='aaabbx'?keep_after_last('[ab]{3}', 'r') />
+<@assertEquals expected='e' actual='aaabbxbabe'?keep_after_last('[ab]{3}', 
'r') />
+<@assertEquals expected='12345' actual='aaabb12345'?keep_after_last('[ab]{3}', 
'r') />
+<@assertEquals expected='yyy' actual='xxxaaayyy'?keep_after_last('a+', 'r') />
+<@assertEquals expected='' actual='foobar'?keep_after_last('') />
+<@assertEquals expected='' actual='foobar'?keep_after_last('', 'r') />
+<@assertFails message='"m" flag'>
+    ${'x'?keep_after_last('x', 'm')}
+</@assertFails>
+<@assertFails message='3'>
+    ${'x'?keep_after_last('x', 'i', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?keep_after_last()}
+</@assertFails>
+
+<@assertEquals expected='foo' actual='foo'?remove_beginning('x') />
+<@assertEquals expected='foo' actual='foo'?remove_beginning('o') />
+<@assertEquals expected='foo' actual='foo'?remove_beginning('fooo') />
+<@assertEquals expected='oo' actual='foo'?remove_beginning('f') />
+<@assertEquals expected='o' actual='foo'?remove_beginning('fo') />
+<@assertEquals expected='' actual='foo'?remove_beginning('foo') />
+<@assertEquals expected='foo' actual='foo'?remove_beginning('') />
+<@assertFails message='2'>
+    ${'x'?remove_beginning('x', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?remove_beginning()}
+</@assertFails>
+
+<@assertEquals expected='bar' actual='bar'?remove_ending('x') />
+<@assertEquals expected='bar' actual='bar'?remove_ending('a') />
+<@assertEquals expected='bar' actual='bar'?remove_ending('barr') />
+<@assertEquals expected='ba' actual='bar'?remove_ending('r') />
+<@assertEquals expected='b' actual='bar'?remove_ending('ar') />
+<@assertEquals expected='' actual='bar'?remove_ending('bar') />
+<@assertEquals expected='bar' actual='bar'?remove_ending('') />
+<@assertFails message='2'>
+    ${'x'?remove_ending('x', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?remove_ending()}
+</@assertFails>
+
+<@assertEquals expected='xfoo' actual='foo'?ensure_starts_with('x') />
+<@assertEquals expected='foo' actual='foo'?ensure_starts_with('f') />
+<@assertEquals expected='foo' actual='foo'?ensure_starts_with('foo') />
+<@assertEquals expected='fooofoo' actual='foo'?ensure_starts_with('fooo') />
+<@assertEquals expected='foo' actual='foo'?ensure_starts_with('') />
+<@assertEquals expected='x' actual=''?ensure_starts_with('x') />
+<@assertEquals expected='' actual=''?ensure_starts_with('') />
+<@assertEquals expected='bacdef' actual="bacdef"?ensure_starts_with("[ab]{2}", 
"ab") />
+<@assertEquals expected='bacdef' 
actual="bacdef"?ensure_starts_with("^[ab]{2}", "ab") />
+<@assertEquals expected='abcacdef' 
actual="cacdef"?ensure_starts_with("[ab]{2}", "ab") />
+<@assertEquals expected='abcacdef' 
actual="cacdef"?ensure_starts_with("^[ab]{2}", "ab") />
+<@assertEquals expected='ab!cdef' actual="cdef"?ensure_starts_with("ab", 
"ab!") />
+<@assertEquals expected='ab!ABcdef' actual="ABcdef"?ensure_starts_with("ab", 
"ab!") />
+<@assertEquals expected='ABcdef' actual="ABcdef"?ensure_starts_with("ab", 
"ab!", 'i') />
+<@assertEquals expected='abABcdef' actual="ABcdef"?ensure_starts_with(".b", 
"ab", 'i') />
+<@assertEquals expected='ABcdef' actual="ABcdef"?ensure_starts_with(".b", 
"ab", 'ri') />
+<@assertEquals expected='http://example.com' 
actual="example.com"?ensure_starts_with("[a-z]+://", "http://";) />
+<@assertEquals expected='http://example.com' 
actual="http://example.com"?ensure_starts_with("[a-z]+://", "http://";) />
+<@assertEquals expected='https://example.com' 
actual="https://example.com"?ensure_starts_with("[a-z]+://", "http://";) />
+<@assertEquals expected='http://HTTP://example.com' 
actual="HTTP://example.com"?ensure_starts_with("[a-z]+://", "http://";) />
+<@assertEquals expected='HTTP://example.com' 
actual="HTTP://example.com"?ensure_starts_with("[a-z]+://", "http://";, "ir") />
+<@assertFails message='4'>
+    ${'x'?ensure_starts_with('x', 'x', 'x', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?ensure_starts_with()}
+</@assertFails>
+
+<@assertEquals expected='foox' actual='foo'?ensure_ends_with('x') />
+<@assertEquals expected='foo' actual='foo'?ensure_ends_with('o') />
+<@assertEquals expected='foo' actual='foo'?ensure_ends_with('foo') />
+<@assertEquals expected='foofooo' actual='foo'?ensure_ends_with('fooo') />
+<@assertEquals expected='foo' actual='foo'?ensure_ends_with('') />
+<@assertEquals expected='x' actual=''?ensure_ends_with('x') />
+<@assertEquals expected='' actual=''?ensure_ends_with('') />
+<@assertFails message='2'>
+    ${'x'?ensure_ends_with('x', 'x')}
+</@assertFails>
+<@assertFails message='none'>
+    ${'x'?ensure_ends_with()}
+</@assertFails>
+
+<@assertEquals expected='a' actual=1?lower_abc />
+<@assertEquals expected='b' actual=2?lower_abc />
+<@assertEquals expected='z' actual=26?lower_abc />
+<@assertEquals expected='aa' actual=27?lower_abc />
+<@assertEquals expected='ab' actual=28?lower_abc />
+<@assertEquals expected='cv' actual=100?lower_abc />
+<@assertFails messageRegexp='0|at least 1']>
+    ${0?lower_abc}
+</@assertFails>
+<@assertFails messageRegexp='0|at least 1'>
+    ${-1?lower_abc}
+</@assertFails>
+<@assertFails messageRegexp='1.00001|integer'>
+    ${1.00001?lower_abc}
+</@assertFails>
+
+<@assertEquals expected='A' actual=1?upper_abc />
+<@assertEquals expected='B' actual=2?upper_abc />
+<@assertEquals expected='Z' actual=26?upper_abc />
+<@assertEquals expected='AA' actual=27?upper_abc />
+<@assertEquals expected='AB' actual=28?upper_abc />
+<@assertEquals expected='CV' actual=100?upper_abc />
+<@assertFails messageRegexp='0|at least 1']>
+    ${0?upper_abc}
+</@assertFails>
+<@assertFails messageRegexp='0|at least 1'>
+    ${-1?upper_abc}
+</@assertFails>
+<@assertFails messageRegexp='1.00001|integer'>
+    ${1.00001?upper_abc}
+</@assertFails>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringbimethods.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringbimethods.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringbimethods.ftl
new file mode 100644
index 0000000..1d31c44
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringbimethods.ftl
@@ -0,0 +1,36 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#setting locale="en_US">
+<#assign x = 3>
+${x?string["0.00"]}
+${x?string("0.00")}
+${'01:02:03'?time.iso?string["iso ms nz"]}
+${'01:02:03'?time.iso?string("iso ms nz")}
+---
+${multi}
+<#assign a = true>
+<#assign b = false>
+${a?string} ${b?string}
+${a?string("yes", "no")} ${b?string("yes", "no")}
+<#setting boolean_format="igen,nem"/>
+${a?string} ${b?string}
+<#setting number_format="0.0">
+${a?string(0, 1)} ${b?string(0, 1)}
+<#setting boolean_format="true,false"/>
+${a?string(0, 1)?is_string?string} ${b?string(0, 1)?is_string?string}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringliteral.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringliteral.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringliteral.ftl
new file mode 100644
index 0000000..436c632
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/stringliteral.ftl
@@ -0,0 +1,69 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html>
+<head>
+  <title>FreeMarker: String literal test</title>
+  <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
+</head>
+<body>
+
+<p>A simple test follows:</p>
+
+<#assign x = "Hello", y = "World">
+<#assign message = "${x}, ${y}!">
+
+${message}
+
+<p>
+[${""}] = []<br>
+[${"a"}] = [a]<br>
+[${"abcdef"}] = [abcdef]<br>
+[${"\""}] = ["]<br>
+[${"\"\"\""}] = ["""]<br>
+[${"a\""}] = [a"]<br>
+[${"\"a"}] = ["a]<br>
+[${"a\"b"}] = [a"b]<br>
+[${"a\nb"}] = [a
+b]<br>
+[${"'"}] = [']<br>
+[${"a'a"}] = [a'a]<br>
+[${"\"\'\n\r\f\b\t\l\a\g"}]<br>
+[${"\xA\x0A\x00A\x000A\x0000A"}]<br>
+[${"\x15Bz\x15b"}]<br>
+[${"\x010Cz\x010c"}]<br>
+
+<p>
+[${''}] = []<br>
+[${'a'}] = [a]<br>
+[${'abcdef'}] = [abcdef]<br>
+[${'"'}] = ["]<br>
+[${'"""'}] = ["""]<br>
+[${'a"'}] = [a"]<br>
+[${'"a'}] = ["a]<br>
+[${'a"b'}] = [a"b]<br>
+[${'a\nb'}] = [a
+b]<br>
+[${'\''}] = [']<br>
+[${'a\'a'}] = [a'a]<br>
+[${'\"\'\n\r\f\b\t\l\a\g'}]<br>
+[${'\xA\x0A\x00A\x000A\x0000A'}]<br>
+[${'\x15Bz\x15b'}]<br>
+[${'\x010Cz\x010c'}]<br>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir.ftl
new file mode 100644
index 0000000..cd24873
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir.ftl
@@ -0,0 +1,27 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<p>This is include-subdir.ftl</p>
+<p>Testing including from same directory</p>
+<#include "include-subdir2.ftl">
+<p>Testing including from relative parent</p>
+<#include "../included.ftl">
+<p>Testing including from loader root</p>
+<#include "/included.ftl">
+<p>Testing including through acquisition</p>
+<#include "*/subdir/include-subdir2.ftl">
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir2.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir2.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir2.ftl
new file mode 100644
index 0000000..356fcb2
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/include-subdir2.ftl
@@ -0,0 +1,19 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<p>This is include-subdir2.ftl</p>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin-2.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin-2.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin-2.ftl
new file mode 100644
index 0000000..687661b
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin-2.ftl
@@ -0,0 +1,24 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new("works")}
+<#attempt>
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel2"?new("works")}
+<#recover>
+fails
+</#attempt>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin.ftl
new file mode 100644
index 0000000..242d221
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/new-optin.ftl
@@ -0,0 +1,26 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new("works")}
+<#attempt>
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel2"?new("works")}
+<#recover>
+fails
+</#attempt>
+
+<#include "new-optin-2.ftl">
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/subsub/new-optin.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/subsub/new-optin.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/subsub/new-optin.ftl
new file mode 100644
index 0000000..687661b
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/subdir/subsub/new-optin.ftl
@@ -0,0 +1,24 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel"?new("works")}
+<#attempt>
+${"org.apache.freemarker.test.templatesuite.models.NewTestModel2"?new("works")}
+<#recover>
+fails
+</#attempt>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch-builtin.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch-builtin.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch-builtin.ftl
new file mode 100644
index 0000000..7441733
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch-builtin.ftl
@@ -0,0 +1,54 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<@assertEquals expected="A" actual="a"?switch("a", "A") />
+<@assertFails message="didn't match">${"b"?switch("a", "A")}</@>
+<@assertEquals expected="D" actual="b"?switch("a", "A", "D") />
+<@assertEquals expected="B" actual="b"?switch("a", "A", "b", "B") />
+<@assertFails message="didn't match">${"c"?switch("a", "A", "b", "B")}</@>
+<@assertEquals expected="D" actual="c"?switch("a", "A", "b", "B", "D") />
+
+<#assign out = "">
+<#assign fInvocationCnt = 0>
+<#list 0..5 as x>
+  <#assign out += x?switch(1, f("one"), 2, f("two"), 3, f("three"), 
f("default")) + ";">
+</#list>
+<@assertEquals expected="default;one;two;three;default;default;" actual=out />
+<@assertEquals expected=6 actual=fInvocationCnt />
+
+<#assign out = "">
+<#list 0..5 as x>
+  <#assign out += true?switch(x <= 1, "low", x == 2 || x == 3, "medium", x >= 
3, "high") + ";">
+</#list>
+<@assertEquals expected="low;low;medium;medium;high;high;" actual=out />
+
+<#function f x>
+  <#assign fInvocationCnt++>
+  <#return x>
+</#function>
+
+<@assertFails message="noSuchVar1">${1?switch(noSuchVar1, noSuchVar2)}</@>
+<@assertFails message="noSuchVar2">${1?switch(1, noSuchVar2)}</@>
+<@assertFails message="noSuchVar3">${noSuchVar3?switch(1, 1)}</@>
+
+<@assertEquals expected="one" actual=1?switch(1, "one", "2", "two") />
+<@assertFails messageRegexp="Can't compare.+number.+string">${2?switch(1, 
"one", "2", "two")}</@>
+<@assertFails messageRegexp="Can't compare.+number.+string">${2?switch(1, 
"one", "2", "two", "default")}</@>
+
+<#assign out><#escape x as x?switch(2 * x, "zero", 1, "one", x, 
x?string("0.0"))>${0} ${1} ${2}</#escape></#assign>
+<@assertEquals expected="zero one 2.0" actual=out />

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch.ftl
new file mode 100644
index 0000000..6bbab3c
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/switch.ftl
@@ -0,0 +1,139 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html>
+<head>
+<title>FreeMarker: Switch-Case Test</title>
+</head>
+<body>
+
+<p>Here we iterate over a list of animals.</p>
+<#assign animalList = [ "aardvark", "kiwi", "gecko", "cat", "dog", "elephant",
+    "squirrel", "zebra" ]>
+<#assign favoriteAnimal = "kiwi">
+
+<#list animalList as animal>
+<p>Animal is: ${animal}.<br />
+<#switch animal>
+    <#case "zebra">
+        This is the HTML for a large stripey animal.
+    <#case "elephant">
+    <#case "rhinocerous">
+        This is the HTML for large animals.
+        <#break>
+    <#case "squirrel">
+    <#case "gecko">
+        This is the HTML for small animals.
+        <#break>
+    <#case favoriteAnimal>
+        This is the HTML for the user's favorite animal.
+        <#break>
+    <#default>
+        This is the HTML for other animals.
+        <#break>
+</#switch>
+</p>
+</#list>
+
+<#-- Nesting and no-match -->
+<#list [ 1, 2, 3 ] as x>
+  <#switch x>
+    <#case 1>
+      1
+      <#switch x*2>
+        <#case 1>
+          i1
+          <#break>
+        <#case 2>
+          i2
+          <#break>
+        <#case 3>
+          i3
+          <#break>
+        <#case 4>
+          i4
+          <#break>
+        <#case 6>
+          i6
+          <#break>
+      </#switch>
+      <#break>     
+    <#case 2>
+      2
+      <#switch x*2>
+        <#case 1>
+          i1
+          <#break>
+        <#case 2>
+          i2
+          <#break>
+        <#case 3>
+          i3
+          <#break>
+        <#case 4>
+          i4
+          <#-- falls through -->
+        <#case 5>
+          ft
+          <#-- falls through -->
+      </#switch>
+      ft
+      <#-- falls through -->     
+    <#case 3>
+      3
+      <#switch x*2>
+        <#case 1>
+          i1
+          <#break>
+        <#case 2>
+          i2
+          <#break>
+        <#case 3>
+          i3
+          <#break>
+        <#case 4>
+          i4
+          <#break>
+        <#case 6>
+          i6
+          <#break>
+      </#switch>
+      <#break>     
+  </#switch>
+</#list>
+
+<#-- No match -->
+[<#switch 213>
+  <#case 1>sadas
+</#switch>]
+
+<#-- Fall-through -->
+<#list [ 0, 1, 2, 3, 4 ] as x>
+  "<#switch x><#case 1>1<#case 2>2<#case 3>3<#case 4>4</#switch>"
+</#list>
+
+<#-- Legacy parser bug: #default might not be the last, but it doesn't fall 
through if called directly -->
+<#list [1, 2, 3, 4, 5] as x>
+  "<#switch x><#case 1>1<#case 2>2<#default>default<#case 4>4<#case 
5>5</#switch>"
+</#list>
+
+<#-- two #default-s are parsing error -->
+<@assertFails message="can only have one default"><@"<#switch 1><#case 
1><#default><#default></#switch>"?interpret /></@>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/then-builtin.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/then-builtin.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/then-builtin.ftl
new file mode 100644
index 0000000..de809e1
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/then-builtin.ftl
@@ -0,0 +1,53 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#assign f1InvocationCnt = 0>
+<#assign f2InvocationCnt = 0>
+
+<@assertEquals expected="f1 1" actual=true?then(f1(), f2()) />
+<@assertEquals expected="f2 1" actual=false?then(f1(), f2()) />
+<@assertEquals expected="f1 2" actual=true?then(f1(), f2()) />
+<@assertEquals expected="f2 2" actual=false?then(f1(), f2()) />
+<@assertEquals expected=2 actual=f1InvocationCnt />
+<@assertEquals expected=2 actual=f2InvocationCnt />
+
+<#function f1>
+  <#assign f1InvocationCnt++>
+  <#return "f1 " + f1InvocationCnt>
+</#function>
+
+<#function f2>
+  <#assign f2InvocationCnt++>
+  <#return "f2 " + f2InvocationCnt>
+</#function>
+
+<#assign x = 1>
+<@assertEquals expected='Y' actual=(x < 2 * x)?then(-x < x, false)?then('Y', 
'N') />
+
+<@assertEquals expected=1 actual=true?then(x, noSuchVar) />
+<@assertEquals expected=1 actual=false?then(noSuchVar, x) />
+
+<@assertFails message="noSuchVar1">${true?then(noSuchVar1, noSuchVar2)}</@>
+<@assertFails message="noSuchVar2">${false?then(noSuchVar1, noSuchVar2)}</@>
+<@assertFails message="noSuchVar3">${noSuchVar3?then(noSuchVar1, 
noSuchVar2)}</@>
+
+<#assign out><#escape x as x?then(1, 0)>${false} ${true}</#escape></#assign>
+<@assertEquals expected="0 1" actual=out />
+
+<#assign out><#escape x as (x < 0)?then(-x * 3, x * 2)>${-1} 
${1}</#escape></#assign>
+<@assertEquals expected="3 2" actual=out />
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/transforms.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/transforms.ftl
 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/transforms.ftl
new file mode 100644
index 0000000..9e5613a
--- /dev/null
+++ 
b/freemarker-core-test/src/test/resources/org/apache/freemarker/test/templatesuite/templates/transforms.ftl
@@ -0,0 +1,100 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<#assign htmlEscape = "org.apache.freemarker.core.util.HtmlEscape"?new(),
+         utility = 
"org.apache.freemarker.test.templatesuite.models.TransformHashWrapper"?new()>
+<html>
+<head>
+<title>FreeMarker: Transformation Test</title>
+</head>
+<body>
+
+<p>A simple test follows:</p>
+
+<p>${message}</p>
+
+<@htmlEscape>
+<p>${message}</p>
+</@htmlEscape>
+
+<P>Now try the Utility package:</p>
+<p>${utility}</p>
+
+<@utility.htmlEscape>
+<p>${utility}</p>
+</@>
+
+<p>Now some nested transforms:</p>
+<@utility.compress>
+<p    >This tests the compress transformation</p >
+</@>
+<@utility.compress>
+<@utility.htmlEscape>
+<p    >This tests the compress transformation</p >
+</@>
+</@utility.compress>
+<#assign html_transform = "org.apache.freemarker.core.util.HtmlEscape"?new() />
+<@html_transform><#--Using the transform via an instantiation -->
+<@utility.compress>
+<p    >This tests the compress transformation</p >
+</@>
+</@>
+
+<p>Now try method and transform interactions:</p>
+<@utility.escape("xml")>
+<p>This isn't a valid XML string.</p>
+</@>
+<@utility.escape("html")>
+<p>This isn't a valid HTML string.</p>
+</@>
+
+<p>A more advanced interaction involves getting a TemplateMethodModel
+to initialise a TemplateTransformModel, as follow:</p>
+
+<@utility.special("This is a comment")>
+Comment: *
+
+A test string containing quotes: "This isn't a test".
+A test string containing amps: Fish & Chips.
+A test string containing tags: <p>Fish &amp; Chips.</p>
+</@>
+
+<@utility.special("This is a second comment", "quote")>
+Comment: *
+
+A test string containing quotes: "This isn't a test".
+A test string containing amps: Fish & Chips.
+A test string containing tags: <p>Fish &amp; Chips.</p>
+</@>
+<@utility.special("This is a third comment", "ampersand", "quote")>
+Comment: *
+
+A test string containing quotes: "This isn't a test".
+A test string containing amps: Fish & Chips.
+A test string containing tags: <p>Fish &amp; Chips.</p>
+</@>
+<@utility.special("tag", utility)>
+Comment: *
+
+A test string containing quotes: "This isn't a test".
+A test string containing amps: Fish & Chips.
+A test string containing tags: <p>Fish &amp; Chips.</p>
+</@>
+
+</body>
+</html>

Reply via email to