/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed 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. */ package com.alibaba.citrus.util.templatelite; import static com.alibaba.citrus.test.TestEnvStatic.*; import static com.alibaba.citrus.test.TestUtil.*; import static com.alibaba.citrus.util.ArrayUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import com.alibaba.citrus.util.IllegalPathException; import com.alibaba.citrus.util.io.ByteArrayInputStream; import com.alibaba.citrus.util.io.StreamUtil; import com.alibaba.citrus.util.templatelite.Template.IncludeTemplate; import com.alibaba.citrus.util.templatelite.Template.Node; import com.alibaba.citrus.util.templatelite.Template.Placeholder; import com.alibaba.citrus.util.templatelite.Template.PlaceholderParameter; import com.alibaba.citrus.util.templatelite.Template.Text; import org.junit.Test; public class TemplateParserTests extends AbstractTemplateTests { @Test public void test01_text_simple() throws Exception { loadTemplate("test01_text_simple.txt", 1, 0, 0); assertText("hello,\n world", template.nodes[0]); } @Test public void test01_text_failure() throws Exception { String s; // text在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " hello"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid text here at test.txt: Line 4 Column 3")); // \#text在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " \\#hello"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid text here at test.txt: Line 4 Column 3")); } @Test public void test02_placeholder_simple() throws Exception { loadTemplate("test02_placeholder_simple.txt", 8, 0, 0); int i = 0; assertText("a${123}", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "a123", "Line 1 Column 8"); assertText("${abc}", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "abc", "Line 1 Column 22"); assertPlaceholder(template.nodes[i++], "a", "Line 1 Column 30", new String[] { "123" }, "123"); assertPlaceholder(template.nodes[i++], "a", "Line 1 Column 38"); assertPlaceholder(template.nodes[i++], "a", "Line 1 Column 45", new String[] { "1", "2", "3" }, "1,2,3"); assertText("b", template.nodes[i++]); } @Test public void test02_placeholder_template() throws Exception { loadTemplate("test02_placeholder_template.txt", 2, 2, 0); Placeholder placeholder = (Placeholder) template.nodes[0]; assertPlaceholder(placeholder, "for", "Line 1 Column 1", new String[] { "#aaa", "#bbb.ccc", "ccc" }, "#aaa, #bbb.ccc, ccc"); PlaceholderParameter param; int i = 0; param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("aaa", param.getTemplateName()); assertEquals("aaa", param.getTemplateReference().getName()); assertTemplateRef(template.getSubTemplate("aaa"), param.getTemplateReference()); param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("bbb.ccc", param.getTemplateName()); assertEquals("ccc", param.getTemplateReference().getName()); assertTemplateRef(template.getSubTemplate("bbb").getSubTemplate("ccc"), param.getTemplateReference()); param = placeholder.params[i++]; assertFalse(param.isTemplateReference()); assertNull(param.getTemplateName()); assertNull(param.getTemplateReference()); } @Test public void test02_placeholder_template_group() throws Exception { loadTemplate("test02_placeholder_template_group.txt", 1, 1, 1); Placeholder placeholder = (Placeholder) template.nodes[0]; // 子模板的顺序和模板文件中的一致 assertPlaceholder(placeholder, "for", "Line 3 Column 1", new String[] { "#aaa.d", "#aaa.c", "#aaa.b", "ccc" }, "#aaa.*, ccc"); PlaceholderParameter param; int i = 0; param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("aaa.d", param.getTemplateName()); assertEquals("d", param.getTemplateReference().getName()); assertTemplateRef(template.getSubTemplate("aaa").getSubTemplate("d"), param.getTemplateReference()); param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("aaa.c", param.getTemplateName()); assertEquals("c", param.getTemplateReference().getName()); assertTemplateRef(template.getSubTemplate("aaa").getSubTemplate("c"), param.getTemplateReference()); param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("aaa.b", param.getTemplateName()); assertEquals("b", param.getTemplateReference().getName()); assertTemplateRef(template.getSubTemplate("aaa").getSubTemplate("b"), param.getTemplateReference()); param = placeholder.params[i++]; assertFalse(param.isTemplateReference()); assertNull(param.getTemplateName()); assertNull(param.getTemplateReference()); } @Test public void test02_placeholder_template_group_2() throws Exception { loadTemplate("test02_placeholder_template_group_2.txt", 0, 1, 1); Placeholder placeholder = (Placeholder) template.getSubTemplate("aaa").nodes[0]; // 子模板的顺序和模板文件中的一致 assertPlaceholder(placeholder, "for", "Line 4 Column 3", new String[] { "#d", "#c", "#b", "ccc" }, "#*, ccc"); PlaceholderParameter param; int i = 0; param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("d", param.getTemplateName()); assertEquals("d", param.getTemplateReference().getName()); param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("c", param.getTemplateName()); assertEquals("c", param.getTemplateReference().getName()); param = placeholder.params[i++]; assertTrue(param.isTemplateReference()); assertEquals("b", param.getTemplateName()); assertEquals("b", param.getTemplateReference().getName()); param = placeholder.params[i++]; assertFalse(param.isTemplateReference()); assertNull(param.getTemplateName()); assertNull(param.getTemplateReference()); } @Test public void test02_placeholder_failure() throws Exception { String s; // ${}在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " ${hello}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid ${hello} here at test.txt: Line 4 Column 3")); // ${}在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " ${hello:param1, param2}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid ${hello:param1, param2} here at test.txt: Line 4 Column 3")); // keyword s = ""; s += "This\n"; s += "is a keyword: \n"; s += "${placeholder}\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Reserved name: placeholder at test.txt: Line 3 Column 1")); // ${xxx: #notexist}模板未找到 s = ""; s += " ${xxx: aaa, #notexist}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Referenced template notexist is not found in the context around test.txt: Line 1 Column 3")); // ${xxx: #a.b.c}模板未找到 s = ""; s += " ${xxx: #a.b.c}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Referenced template a.b.c is not found in the context around test.txt: Line 1 Column 3")); s = ""; s += " ${xxx: #a.b.c}\n"; s += "#a\n"; s += "#b\n"; s += "#end\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Referenced template a.b.c is not found in the context around test.txt: Line 1 Column 3")); // ${xxx: #a.b.*}模板未找到 s = ""; s += " ${xxx: #a.b.*}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Referenced template a.b is not found in the context around test.txt: Line 1 Column 3")); s = ""; s += " ${xxx: #a.b.*}\n"; s += "#a\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Referenced template a.b is not found in the context around test.txt: Line 1 Column 3")); } @Test public void test03_subtemplate_simple() throws Exception { loadTemplate("test03_subtemplate_simple.txt", 1, 2, 0); int i = 0; assertText("a\\#abc#123$#{abc}#@xxx", template.nodes[i++]); assertTemplate(template.getSubTemplate("abc"), "abc", 0, 1, 0, "Line 2 Column 3"); assertTemplate(template.getSubTemplate("abc").getSubTemplate("def"), "def", 1, 0, 0, "Line 3 Column 5"); assertText("hello", template.getSubTemplate("abc").getSubTemplate("def").nodes[0]); assertTemplate(template.getSubTemplate("def"), "def", 0, 0, 0, "Line 9 Column 1"); } @Test public void test03_subtemplate_failure() throws Exception { String s; // #abc前有内容 s = ""; s += "hhhhh #abc\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("#abc should start at new line, which is now at test.txt: Line 1 Column 8")); // #abc后跟#end s = ""; s += "hhhhh\n"; s += " #abc#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid content followed after #abc at test.txt: Line 2 Column 7")); // #abc后跟content s = ""; s += "hhhhh\n"; s += " #abc content\n"; s += "#end"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid content followed after #abc at test.txt: Line 2 Column 8")); // 缺少#end s = ""; s += "#abc\n"; s += "#def\n"; s += "#ghi\n"; s += "#end"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Unclosed tags: #def, #abc at test.txt: Line 5")); // systemId未指定时的错误信息 loadTemplateFailure(s.getBytes(), null); assertThat(parseError, exception("Unclosed tags: #def, #abc at [unknown source]: Line 5")); // #end后跟() s = ""; s += "#abc\n"; s += "#end ()"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid character '(' after #end tag at test.txt: Line 2 Column 6")); s = ""; s += "#abc\n"; s += "#end( ... )"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid character '(' after #end tag at test.txt: Line 2 Column 5")); // #end太多 s = ""; s += "#abc\n"; s += "#def\n"; s += "#ghi\n"; s += "#end\n"; s += "#end\n"; s += "#end\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Unmatched #end tag at test.txt: Line 7 Column 1")); // import name为空 s = ""; s += "#abc()\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Import file name is not specified at test.txt: Line 1 Column 6")); s = ""; s += "#abc ( )\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Import file name is not specified at test.txt: Line 1 Column 8")); s = ""; s += "#abc ( \" \" )\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Import file name is not specified at test.txt: Line 1 Column 8")); s = ""; s += "#abc(\"\")\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Import file name is not specified at test.txt: Line 1 Column 6")); // 无法import,因为input source不存在 s = ""; s += "#abc(\"any.txt\")\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Could not import template file \"any.txt\" at test.txt: Line 1 Column 6")); // template name重复 s = ""; s += " #abc\n"; s += "#end\n"; s += " #abc\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Duplicated template name #abc at test.txt: Line 3 Column 3. " + "Another template with the same name is located in test.txt: Line 1 Column 2")); // keyword s = ""; s += "This\n"; s += "is a keyword: \n"; s += "#text\n"; s += "#end"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Reserved name: text at test.txt: Line 3 Column 1")); s = ""; s += "This\n"; s += "is a keyword: \n"; s += "#text (any.txt)\n"; s += "#end"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Reserved name: text at test.txt: Line 3 Column 1")); } @Test public void test04_include_template_simple() { loadTemplate("test04_include_template_simple.txt", 5, 2, 0); int i = 0; assertText("a$#{123}", template.nodes[i++]); assertIncludeTemplate(template.nodes[i++], "a123", "Line 1 Column 9", template.getSubTemplate("a123")); assertText("$#{abc}", template.nodes[i++]); assertIncludeTemplate(template.nodes[i++], "abc", "Line 1 Column 25", template.getSubTemplate("abc")); assertText("$#{a:123}$#{a : }$#{a:1,2,3}b", template.nodes[i++]); assertTemplate(template.getSubTemplate("a123"), "a123", 0, 0, 0, "Line 2 Column 1"); assertTemplate(template.getSubTemplate("abc"), "abc", 0, 0, 0, "Line 4 Column 1"); } @Test public void test04_include_template_override() { loadTemplate("test04_include_template_override.txt", 0, 3, 0); Template b_level0 = template.getSubTemplate("bbb"); Template a_level2 = template.getSubTemplate("level1").getSubTemplate("level2").getSubTemplate("aaa"); Template level2 = template.getSubTemplate("level1").getSubTemplate("level2"); IncludeTemplate includeA = (IncludeTemplate) level2.nodes[1]; IncludeTemplate includeB = (IncludeTemplate) level2.nodes[2]; assertTemplateRef(a_level2, includeA.includedTemplate); assertTemplateRef(b_level0, includeB.includedTemplate); } @Test public void test04_include_template_sub() { loadTemplate("test04_include_template_sub.txt", 1, 1, 1); IncludeTemplate include = (IncludeTemplate) template.nodes[0]; assertEquals("level1.level2.aaa", include.templateName); assertTemplateRef(template.getSubTemplate("level1").getSubTemplate("level2").getSubTemplate("aaa"), include.includedTemplate); } @Test public void test04_include_template_failure() throws Exception { String s; // $#{xxx}在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " $#{abc}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid $#{abc} here at test.txt: Line 4 Column 3")); // $#{notexist}模板未找到 s = ""; s += " $#{notexist}"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Included template notexist is not found in the context around test.txt: Line 1 Column 3")); // $#{abc}模板未找到(嵌套) s = ""; s += "#xxx\n"; s += " #yyy\n"; s += " hello, $#{abc}\n"; s += " #end\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Included template abc is not found in the context around test.txt: Line 3 Column 12")); // $#{a.b.c}模板未找到(子模板) s = "$#{a.b.c}\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Included template a.b.c is not found in the context around test.txt: Line 1 Column 1")); s = "$#{a.b.c}\n"; s += "#a\n"; s += "#b\n"; s += "#end\n"; s += "#end\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Included template a.b.c is not found in the context around test.txt: Line 1 Column 1")); } @Test public void test05_param_charset() { loadTemplate("test05_param_utf8.txt", 1, 0, 1); assertText("\n你好!", template.nodes[0]); assertEquals("UTF-8", template.getParameter("charset")); loadTemplate("test05_param_gbk.txt", 1, 0, 1); assertText("\n你好!", template.nodes[0]); assertEquals("GBK", template.getParameter("charset")); } @Test public void test05_param_override() { loadTemplate("test05_param_override.txt", 0, 1, 2); assertEquals("111", template.getParameter("xxx")); assertEquals(null, template.getParameter("yyy")); assertEquals("", template.getParameter("zzz")); assertEquals("222", template.getSubTemplate("level1").getParameter("xxx")); assertEquals("444", template.getSubTemplate("level1").getParameter("yyy")); assertEquals("", template.getSubTemplate("level1").getParameter("zzz")); assertEquals("333", template.getSubTemplate("level1").getSubTemplate("level2").getParameter("xxx")); assertEquals("444", template.getSubTemplate("level1").getSubTemplate("level2").getParameter("yyy")); assertEquals("", template.getSubTemplate("level1").getSubTemplate("level2").getParameter("zzz")); } @Test public void test05_param_failure() throws Exception { String s; // #@param前有内容 s = ""; s += "hhhhh #@param\n"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("#@param should start at new line, which is now at test.txt: Line 1 Column 8")); // #@param在text的后面 s = ""; s += "\n"; s += "abc\n"; s += " #@hello"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid #@hello here at test.txt: Line 3 Column 3")); // #@param在${abc}的后面 s = ""; s += "\n"; s += " ${abc}\n"; s += " #@hello"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid #@hello here at test.txt: Line 3 Column 3")); // #@param在#abc后面 s = ""; s += "#abc\n"; s += "#end\n"; s += "\n"; s += " #@hello"; loadTemplateFailure(s.getBytes(), "test.txt"); assertThat(parseError, exception("Invalid #@hello here at test.txt: Line 4 Column 3")); } @Test public void test05_param_trim() throws Exception { String s; // no trimming s = ""; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " hello, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; loadTemplate(s.getBytes(), "test.txt", 3, 0, 2); int i = 0; assertText(" \n\n hello, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 5 Column 11"); assertText(" \n hi \n \n \nha\n ", template.nodes[i++]); // with trimming s = ""; s += "#@trimming on\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " hello, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " "; loadTemplate(s.getBytes(), "test.txt", 3, 0, 3); i = 0; assertText("hello, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 6 Column 11"); assertText("\nhi\n\n\nha", template.nodes[i++]); // with trimming, drop first/last s = ""; s += "#@trimming on\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "${xxx} \n"; loadTemplate(s.getBytes(), "test.txt", 3, 0, 3); i = 0; assertPlaceholder(template.nodes[i++], "name", "Line 6 Column 4"); assertText("\nhi\n\n\nha\n\n", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "xxx", "Line 12 Column 1"); } @Test public void test05_param_trim_subtemplate() throws Exception { String s; // no trimming s = ""; s += "#sub\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " hello, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "#end"; loadTemplate(s.getBytes(), "test.txt", 0, 1, 0); template = template.getSubTemplate("sub"); int i = 0; assertText(" \n\n hello, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 6 Column 11"); assertText(" \n hi \n \n \nha\n ", template.nodes[i++]); // with trimming s = ""; s = "#@trimming YES\n"; s += "#sub\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " hello, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "#end"; loadTemplate(s.getBytes(), "test.txt", 0, 1, 1); template = template.getSubTemplate("sub"); i = 0; assertText("hello, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 7 Column 11"); assertText("\nhi\n\n\nha", template.nodes[i++]); // with trimming, drop first/last s = ""; s += "#@trimming on\n"; s += "#sub\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "${xxx} \n"; s += "#end"; loadTemplate(s.getBytes(), "test.txt", 0, 1, 1); template = template.getSubTemplate("sub"); i = 0; assertPlaceholder(template.nodes[i++], "name", "Line 7 Column 4"); assertText("\nhi\n\n\nha\n\n", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "xxx", "Line 13 Column 1"); } @Test public void test05_param_collapse_ws() throws Exception { String s; // with collapsing s = ""; s += "#@whitespace collapse\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " he llo, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; loadTemplate(s.getBytes(), "test.txt", 3, 0, 3); int i = 0; assertText("\nhe llo, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 6 Column 15"); assertText("\nhi\nha\n", template.nodes[i++]); // with trimming & collapsing, drop first/last s = ""; s += "#@trimming on\n"; s += "#@whitespace COLLAPSE\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "${xxx} \n"; loadTemplate(s.getBytes(), "test.txt", 3, 0, 4); i = 0; assertPlaceholder(template.nodes[i++], "name", "Line 7 Column 4"); assertText("\nhi\nha\n", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "xxx", "Line 13 Column 1"); } @Test public void test05_param_collapse_ws_subtemplate() throws Exception { String s; // with collapsing s = ""; s += "#sub\n"; s += "#@whitespace collapse\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " hello, ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "#end"; loadTemplate(s.getBytes(), "test.txt", 0, 1, 0); template = template.getSubTemplate("sub"); int i = 0; assertText("\nhello, ", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "name", "Line 7 Column 13"); assertText("\nhi\nha\n", template.nodes[i++]); // with trimming & collapsing, drop first/last s = ""; s += "#sub\n"; s += "#@trimming on\n"; s += "#@whitespace COLLAPSE\n"; s += "#@param1\n"; s += " \n"; s += "#@param2\n"; s += "\n"; s += " ${name} \n"; s += " hi \n"; s += " \n"; s += " \n"; s += "ha\n"; s += " \n"; s += "${xxx} \n"; s += "#end\n"; loadTemplate(s.getBytes(), "test.txt", 0, 1, 0); template = template.getSubTemplate("sub"); i = 0; assertPlaceholder(template.nodes[i++], "name", "Line 8 Column 4"); assertText("\nhi\nha\n", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "xxx", "Line 14 Column 1"); } @Test public void test06_real_case() throws Exception { loadTemplate("test06_real_case.txt", 5, 1, 3); int i = 0; assertText("<html>\n" // + "<head>\n" // + "<title>", template.nodes[i++]); assertPlaceholder(template.nodes[i++], "title", "Line 7 Column 12", new String[] { "我的标题" }, "我的标题"); assertText("</title>\n" // + "</head>\n" // + "<body>\n", template.nodes[i++]); assertIncludeTemplate(template.nodes[i++], "itemlist", "Line 10 Column 5", template.getSubTemplate("itemlist")); assertText("\n</body>\n" // + "</html>", template.nodes[i++]); // ------------------------------- Template itemlist = template.getSubTemplate("itemlist"); i = 0; assertText("<ul>\n", itemlist.nodes[i++]); assertPlaceholder(itemlist.nodes[i++], "item", "Line 18 Column 5", new String[] { "#dateItem", "#datetimeItem" }, "#dateItem, #datetimeItem"); assertText("\n</ul>", itemlist.nodes[i++]); // ------------------------------- Template dateItem = itemlist.getSubTemplate("dateItem"); i = 0; assertText("<li> ", dateItem.nodes[i++]); // spaces are not collpased assertPlaceholder(dateItem.nodes[i++], "date", "Line 22 Column 11", new String[] { "yyyy-MM-dd" }, "yyyy-MM-dd"); assertText(" </li>", dateItem.nodes[i++]); // ------------------------------- Template datetimeItem = itemlist.getSubTemplate("datetimeItem"); i = 0; assertText("<li> ", datetimeItem.nodes[i++]); assertPlaceholder(datetimeItem.nodes[i++], "date", "Line 26 Column 10", new String[] { "yyyy-MM-dd", "HH:mm" }, "yyyy-MM-dd,HH:mm"); assertText(" </li>", datetimeItem.nodes[i++]); } @Test public void test07_predefined_templates() { loadTemplate("test07_predefined_templates.txt", 6, 2, 1); String expected = ""; expected += "<a href=\"test\" onclick=\"alert('hi')\">hello\n"; expected += "</a>"; assertEquals(expected, template.renderToString(new FallbackTextWriter<StringBuilder>())); } @Test public void test08_import_file() { loadTemplate("test08_import.txt", 1, 1, 1); assertPlaceholder(template.nodes[0], "abc", "Line 3 Column 1", new String[] { "#abc" }, "#abc"); Template subTemplate = template.getSubTemplate("abc"); source = "def.txt"; assertTemplate(subTemplate, "abc", 1, 0, 1, null); assertText(" hello,\n" // + "world", subTemplate.nodes[0]); // no trimming assertLocation(subTemplate.nodes[0].location, "Line 2 Column 3"); } @Test public void test08_import_url() throws IOException { URL jarurl = copyFilesToJar("dest.jar", "test08_import.txt", "import.txt", "inc/def.txt", "inc/def.txt"); template = new Template(new URL("jar:" + jarurl + "!/import.txt")); source = "import.txt"; assertPlaceholder(template.nodes[0], "abc", "Line 3 Column 1", new String[] { "#abc" }, "#abc"); Template subTemplate = template.getSubTemplate("abc"); source = "inc/def.txt"; assertTemplate(subTemplate, "abc", 1, 0, 1, null); assertText(" hello,\n" // + "world", subTemplate.nodes[0]); // no trimming assertLocation(subTemplate.nodes[0].location, "Line 2 Column 3"); } @Test public void test08_import_notfound() { try { loadTemplate("test08_import_notfound.txt", 1, 1, 1); fail(); } catch (TemplateParseException e) { // source.getRelative()计算成功,但是文件没找到 assertThat( e, exception(FileNotFoundException.class, "Could not import template file \"notfound.txt\" at ", "Line 5 Column 6")); } } @Test public void test08_import_invalid() throws Exception { String importedFile = repeat("../", countMatches(srcdir.toURI().toURL().toExternalForm(), "/")) + "../def.htm"; String s = "#@trimming on\n"; s += "${abc: #abc}\n"; s += "#abc(" + importedFile + ") ## xxxx"; File f = new File(destdir, "testinvalid.htm"); StreamUtil.writeText(s, new FileOutputStream(f), "UTF-8", true); try { new Template(f); fail(); } catch (TemplateParseException e) { // source.getRelative()报错 assertThat( e, exception(IllegalPathException.class, "Could not import template file \"" + importedFile + "\" at ", "Line 3 Column 6")); } } @Test public void test08_import_invalid2() { String s = "#@trimming on\n"; s += "${abc: #abc}\n"; s += "#abc(def.htm) ## xxxx"; try { new Template(new ByteArrayInputStream(s.getBytes()), "test.txt"); fail(); } catch (TemplateParseException e) { // source.getRelative()返回null assertThat(e, exception("Could not import template file \"def.htm\" at ", "Line 3 Column 6")); } } private void assertText(String text, Node node) { Text t = (Text) node; assertEquals(text, t.text); String str = t.toString(); assertThat(str, containsAll("Text with ", "characters: ")); } private void assertPlaceholder(Node node, String name, String location) { assertPlaceholder(node, name, location, new String[0], null); } private void assertPlaceholder(Node node, String name, String location, String[] params, String paramsString) { Placeholder placeholder = (Placeholder) node; assertEquals(name, placeholder.name); assertEquals(paramsString, placeholder.paramsString); assertLocation(placeholder.location, location); if (isEmptyArray(params)) { assertEquals(0, placeholder.params.length); } else { assertEquals(params.length, placeholder.params.length); for (int i = 0; i < params.length; i++) { assertEquals(params[i], placeholder.params[i].getValue()); } } String str = placeholder.toString(); if (paramsString == null) { assertThat(str, startsWith("${" + name + "}")); } else { assertThat(str, startsWith("${" + name + ":" + paramsString + "}")); } assertLocation(str, location); } private void assertIncludeTemplate(Node node, String templateName, String location, Template template) { IncludeTemplate includeTemplate = (IncludeTemplate) node; assertEquals(templateName, includeTemplate.templateName); assertLocation(includeTemplate.location, location); String str = includeTemplate.toString(); assertThat(str, startsWith("$#{" + templateName + "}")); assertLocation(str, location); assertNotNull(includeTemplate.includedTemplate); assertTemplateRef(template, includeTemplate.includedTemplate); } private void assertTemplateRef(Template orig, Template ref) { assertNull(orig.ref); assertSame(orig, ref.ref); assertNull(ref.source); assertNull(ref.location); assertNull(ref.nodes); assertNull(ref.params); assertNull(ref.subtemplates); assertSame(orig.getName(), ref.getName()); for (String name : orig.params.keySet()) { assertSame(orig.getParameter(name), ref.getParameter(name)); } for (String name : orig.subtemplates.keySet()) { assertSame(orig.getSubTemplate(name), ref.getSubTemplate(name)); } assertEquals("ref to " + orig.toString(), ref.toString()); } }