/*
* Copyright 2011-2013 HTTL Team.
*
* 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 httl.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import httl.Context;
import httl.Engine;
import httl.Template;
import httl.spi.Codec;
import httl.spi.Loader;
import httl.spi.loaders.ClasspathLoader;
import httl.spi.loaders.MultiLoader;
import httl.test.model.Book;
import httl.test.model.Model;
import httl.test.model.User;
import httl.util.ClassUtils;
import httl.util.IOUtils;
import httl.util.StringUtils;
import httl.util.UnsafeByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* TemplateTest
*
* @author Liang Fei (liangfei0201 AT gmail DOT com)
* @author Jerry Lee (oldratlee AT gmail DOT com)
*/
@RunWith(Parameterized.class)
public class TemplateTest {
private static final Set<String> includes = loadSystemPropertySet("includes");
private static final Set<String> excludes = loadSystemPropertySet("excludes");
private static Set<String> loadSystemPropertySet(String key) {
String value = System.getProperty(key);
Set<String> values = new HashSet<String>();
if (StringUtils.isNotEmpty(value) && ! value.startsWith("$")) {
values.addAll(Arrays.asList(value.split("\\,")));
}
return Collections.unmodifiableSet(values);
}
@Parameters
public static Collection<Object[]> prepareData() throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setTimeZone(TimeZone.getTimeZone("+0"));
User user = new User("liangfei", "admin", "Y", 1, 3);
Book[] books = new Book[10];
books[0] = new Book("Practical API Design", "Jaroslav Tulach", "Apress", format.parse("2008-07-29"), 75, 85);
books[1] = new Book("Effective Java", "Joshua Bloch", "Addison-Wesley Professional", format.parse("2008-05-28"), 55, 70);
books[2] = new Book("Java Concurrency in Practice", "Doug Lea", "Addison-Wesley Professional", format.parse("2006-05-19"), 60, 60);
books[3] = new Book("Java Programming Language", "James Gosling", "Prentice Hall", format.parse("2005-08-27"), 65, 75);
books[4] = new Book("Domain-Driven Design", "Eric Evans", "Addison-Wesley Professional", format.parse("2003-08-30"), 70, 80);
books[5] = new Book("Agile Project Management with Scrum", "Ken Schwaber", "Microsoft Press", format.parse("2004-03-10"), 40, 80);
books[6] = new Book("J2EE Development without EJB", "Rod Johnson", "Wrox", format.parse("2011-09-17"), 40, 70);
books[7] = new Book("Design Patterns", "Erich Gamma", "Addison-Wesley Professional", format.parse("1994-11-10"), 60, 80);
books[8] = new Book("Agile Software Development, Principles, Patterns, and Practices", " Robert C. Martin", "Prentice Hall", format.parse("2002-10-25"), 80, 75);
books[9] = new Book("Design by Contract, by Example", "Richard Mitchell", "Addison-Wesley Publishing Company", format.parse("2001-10-22"), 50, 85);
user.setBook(books[0]);
Book[] books2 = new Book[2];
books2[0] = new Book("Practical API Design2", "Jaroslav Tulach", "Apress", format.parse("2010-07-29"), 75, 85);
books2[1] = new Book("Effective Java2", "Joshua Bloch", "Addison-Wesley Professional", format.parse("2010-05-28"), 55, 70);
Map<String, Book> bookmap = new TreeMap<String, Book>();
Map<String, Map<String, Object>> mapbookmap = new TreeMap<String, Map<String, Object>>();
List<Map<String, Object>> mapbooklist = new ArrayList<Map<String, Object>>();
for (Book book : books) {
bookmap.put(book.getTitle().replaceAll("\\s+", ""), book);
Map<String, Object> genericBook = ClassUtils.getProperties(book);
mapbookmap.put(book.getTitle().replaceAll("\\s+", ""), genericBook);
mapbooklist.add(genericBook);
}
Map<String, Book> bookmap2 = new TreeMap<String, Book>();
for (Book book : books2) {
bookmap2.put(book.getTitle().replaceAll("\\s+", ""), book);
}
Map<Integer, Integer> intmap = new HashMap<Integer, Integer>();
for (int i = 0; i < 5; i ++) {
intmap.put(i, i + 10);
}
Map<String, Object> context = new HashMap<String, Object>();
context.put("chinese", "中文");
context.put("impvar", "abcxyz");
context.put("defvar", "mnnm");
context.put("html", "<a href=\"foo.html\">foo</a>");
context.put("user", user);
context.put("books", books);
context.put("booklist", Arrays.asList(books));
context.put("bookmap", bookmap);
context.put("mapbookmap", mapbookmap);
context.put("mapbooklist", mapbooklist);
context.put("emptybooks", new Book[0]);
context.put("books2", books2);
context.put("booklist2", Arrays.asList(books2));
context.put("bookmap2", bookmap2);
context.put("intmap", intmap);
context.put("begin", 3);
context.put("end", 7);
context.put("logined", true);
Model model = new Model();
model.setChinese("中文");
model.setImpvar("abcxyz");
model.setDefvar("mnnm");
model.setHtml("<a href=\"foo.html\">foo</a>");
model.user = user; // public field test
model.setBooks(books);
model.setBooklist(Arrays.asList(books));
model.setBookmap(bookmap);
model.setMapbookmap(mapbookmap);
model.setMapbooklist(mapbooklist);
model.setEmptybooks(new Book[0]);
model.setBooks2(books2);
model.setBooklist2(Arrays.asList(books2));
model.setBookmap2(bookmap2);
model.setIntmap(intmap);
model.setBegin(3);
model.setEnd(7);
model.setLogined(true);
final List<Object[]> retTestData = new ArrayList<Object[]>();
String[] configs = new String[] { "httl.properties", "httl-comment.properties", "httl-comment-text.properties", "httl-comment-javassist.properties", "httl-comment-compile.properties", "httl-comment-interpret.properties", "httl-attribute.properties", "httl-velocity.properties" };
for (String config : configs) {
if (! "httl-comment.properties".equals(config)) continue; // 指定配置测试
Engine engine = Engine.getEngine(config);
Codec[] codecs = engine.getProperty("codecs", Codec[].class);
String json = codecs[0].toString("context", model);
Object[] maps = new Object[] {context, model, json, null};
for (Object map : maps) {
if (! (map instanceof Map)) continue; // 指定模型测试
if ("httl-velocity.properties".equals(config)
&& (map == null || map instanceof String)) continue;
String dir = engine.getProperty("template.directory", "");
if (dir.length() > 0 && dir.startsWith("/")) {
dir = dir.substring(1);
}
if (dir.length() > 0 && ! dir.endsWith("/")) {
dir += "/";
}
File directory = new File(TemplateTest.class.getClassLoader().getResource(dir + "templates/").getFile());
assertTrue(directory.isDirectory());
File[] files = directory.listFiles();
for (int i = 0, n = files.length; i < n; i ++) {
File file = files[i];
String templateName = file.getName();
//if (! "literal_collection.httl".equals(templateName)) continue; // 指定模板测试
//if ("extends_default.httl".equals(templateName)) continue; // 跳过模板测试
if ("httl-comment-interpret.properties".equals(config) // FIXME
&& ("include_hide.httl".equals(templateName)
|| "overload_method.httl".equals(templateName)
|| "extends_default.httl".equals(templateName))) continue;
if (excludes.contains(templateName) ||
(includes.size() > 0 && ! includes.contains(templateName))) {
continue;
}
retTestData.add(new Object[]{config, map, templateName});
}
}
}
return retTestData;
}
private String config;
private Object data;
private String templateName;
public TemplateTest(String config, Object data, String templateName) {
this.config = config;
this.data = data;
this.templateName = templateName;
}
@SuppressWarnings("unchecked")
@Test
public void testTemplate() throws Exception {
Engine engine = Engine.getEngine(config);
Loader loader = engine.getProperty("loader", Loader.class);
assertEquals(MultiLoader.class, loader.getClass());
Loader[] loaders = engine.getProperty("loaders", Loader[].class);
assertEquals(ClasspathLoader.class, loaders[0].getClass());
loader = engine.getProperty("loaders", ClasspathLoader.class);
assertEquals(ClasspathLoader.class, loader.getClass());
String[] suffixes = engine.getProperty("template.suffix", new String[] { ".httl" });
List<String> list = loader.list(suffixes[0]);
assertTrue(list.size() > 0);
String dir = engine.getProperty("template.directory", "");
if (dir.length() > 0 && dir.startsWith("/")) {
dir = dir.substring(1);
}
if (dir.length() > 0 && ! dir.endsWith("/")) {
dir += "/";
}
System.out.println(config + ": " + (data == null ? "null" : data.getClass().getSimpleName()) + " => " + templateName);
String encoding = "UTF-8";
if ("gbk.httl".equals(templateName)) {
encoding = "GBK";
}
Engine _engine = engine;
if ("extends_default.httl".equals(templateName)) {
_engine = Engine.getEngine("httl-comment-extends.properties");
}
Template template = _engine.getTemplate("/templates/" + templateName, Locale.CHINA, encoding, data);
UnsafeByteArrayOutputStream actualStream = new UnsafeByteArrayOutputStream();
StringWriter actualWriter = new StringWriter();
if ("extends_var.httl".equals(templateName)) {
if (data instanceof Map) {
((Map<String, Object>) data).put("extends", "default.httl");
} else if (data instanceof Model) {
((Model) data).setExtends("default.httl");
}
}
try {
template.render(data, actualWriter);
template.render(data, actualStream);
} catch (Throwable e) {
System.out.println("\n================================\n" + config + ": " + template.getName() + "\n================================\n");
e.printStackTrace();
throw new IllegalStateException(e.getMessage() + "\n================================\n" + config + ": " + template.getName() + "\n================================\n", e);
}
if ("extends_var.httl".equals(templateName)) {
if (data instanceof Map) {
((Map<String, Object>) data).remove("extends");
} else if (data instanceof Model) {
((Model) data).setExtends(null);
}
}
if (data != null && ! (data instanceof String)) { // FIXME JSON数据的Map没有排序,导致断言失败,暂先跳过
URL url = this.getClass().getClassLoader().getResource(dir + "results/" + templateName + ".txt");
if (url == null) {
throw new FileNotFoundException("Not found file: " + dir + "results/" + templateName + ".txt");
}
File result = new File(url.getFile());
if (! result.exists()) {
throw new FileNotFoundException("Not found file: " + result.getAbsolutePath());
}
String expected = IOUtils.readToString(new InputStreamReader(new FileInputStream(result), encoding));
expected = expected.replace("\r", "");
if ("httl-comment-text.properties".equals(config)
&& ! template.getSource().contains("read(")) {
expected = expected.replace("<!--", "").replace("-->", "");
}
assertEquals(templateName, expected, actualWriter.getBuffer().toString().replace("\r", ""));
assertEquals(templateName, expected, new String(actualStream.toByteArray()).replace("\r", ""));
if ("set_parameters.httl".equals(templateName)) {
assertEquals(templateName, "abc", Context.getContext().get("title"));
}
}
}
}