package com.opensymphony.module.sitemesh.parser; import com.opensymphony.module.sitemesh.DefaultSitemeshBuffer; import com.opensymphony.module.sitemesh.HTMLPage; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.PageParser; import java.io.*; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import junit.framework.TestCase; import junit.framework.TestSuite; import junit.framework.Test; /** * Test case for HTMLPageParser implementations. See parser-tests/readme.txt. * * @author Joe Walnes */ public class HTMLPageParserTest extends TestCase { private static final Pattern PARSER_PATTERN = Pattern.compile("parser\\.(.+)\\.class"); /** * This test case builds a custom suite, containing a collection of smaller suites (one for each file in src/parser-tests). */ public static Test suite() throws Exception { TestSuite result = new TestSuite(HTMLPageParserTest.class.getName()); Properties props = new Properties(); props.load(new FileInputStream("src/parser-tests/parsers.properties")); Collection<String> parsers = new ArrayList<String>(); for (String key : props.stringPropertyNames()) { Matcher matcher = PARSER_PATTERN.matcher(key); if (matcher.matches()) { parsers.add(matcher.group(1)); } } for (String p : parsers) { String name = props.getProperty("parser." + p + ".class"); Class<? extends PageParser> parserClass = Class.forName(name).asSubclass(PageParser.class); PageParser parser = parserClass.newInstance(); String filesPath = props.getProperty("parser." + p + ".tests", "src/parser-tests"); List<File> files = new ArrayList<File>(Arrays.asList(listParserTests(new File(filesPath)))); Collections.sort(files); TestSuite suiteForParser = new TestSuite(name); for (File file : files) { TestSuite suiteForFile = new TestSuite(file.getName().replace('.', '_')); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testTitle")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testBody")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testHead")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testFullPage")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testProperties")); suiteForFile.addTest(new HTMLPageParserTest(parser, file, "testContentSanity")); suiteForParser.addTest(suiteForFile); } result.addTest(suiteForParser); } return result; } private Page page; private Map blocks; private String encoding; private final PageParser parser; private File file; public HTMLPageParserTest(PageParser parser, File inputFile, String test) { super(test); this.parser = parser; file = inputFile; encoding = "UTF8"; } protected void setUp() throws Exception { super.setUp(); // read blocks from input file. this.blocks = readBlocks(new FileReader(file)); // create PageParser and parse input block into HTMLPage object. String input = (String) blocks.get("INPUT"); this.page = parser.parse(new DefaultSitemeshBuffer(input.toCharArray())); } public void testTitle() throws Exception { assertBlock("TITLE", page.getTitle()); } public void testBody() throws Exception { StringWriter body = new StringWriter(); page.writeBody(body); body.flush(); assertBlock("BODY", body.toString()); } public void testHead() throws Exception { String head; if (page instanceof HTMLPage) { StringWriter headWriter = new StringWriter(); ((HTMLPage)page).writeHead(headWriter); headWriter.flush(); head = headWriter.toString(); } else { head = ""; } assertBlock("HEAD", head.toString()); } public void testFullPage() throws Exception { StringWriter fullPage = new StringWriter(); page.writePage(fullPage); fullPage.flush(); assertBlock("INPUT", fullPage.toString()); } public void testProperties() throws Exception { Properties props = new Properties(); String propsString = (String) blocks.get("PROPERTIES"); ByteArrayInputStream input = new ByteArrayInputStream(propsString.trim().getBytes(encoding)); props.load(input); String[] pageKeys = page.getPropertyKeys(); assertEquals(file.getName() + " : Unexpected number of page properties [" + join(pageKeys) + "]", props.size(), pageKeys.length); for (int i = 0; i < pageKeys.length; i++) { String pageKey = pageKeys[i]; String blockValue = props.getProperty(pageKey); String pageValue = page.getProperty(pageKey); assertEquals(file.getName() + ": " + pageKey, blockValue == null ? null : blockValue.trim(), pageValue == null ? null : pageValue.trim()); } } /** * compare difference between using parse(char[]) and parse(char[], length) */ public void testContentSanity() throws Exception { String input = (String) blocks.get("INPUT"); final char[] chars = input.toCharArray(); final char[] bigChars = new char[chars.length * 2 + 10]; // make it bigger System.arraycopy(chars, 0, bigChars, 0, chars.length); Page bigPage = parser.parse(new DefaultSitemeshBuffer(bigChars, chars.length)); assertEquals(bigPage.getPage(), page.getPage()); } private String join(String[] values) { StringBuffer result = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) { result.append(','); } result.append(values[i]); } return result.toString(); } //------------------------------------------------- private static File[] listParserTests(File dir) throws IOException { // get list of files to ignore LineNumberReader ignoreReader = new LineNumberReader(new FileReader(new File(dir, "ignore.txt"))); final List ignoreFileNames = new ArrayList(); String line; while ((line = ignoreReader.readLine()) != null) { ignoreFileNames.add(line); } return dir.listFiles(new FilenameFilter() { public boolean accept(File currentDir, String name) { return name.startsWith("test") && !ignoreFileNames.contains(name); } }); } private void assertBlock(String blockName, String result) throws Exception { String expected = (String) blocks.get(blockName); assertEquals(file.getName() + " : Block did not match", expected.trim(), result.trim()); } /** * Read input to test and break down into blocks. See parser-tests/readme.txt */ private Map readBlocks(Reader input) throws IOException { Map blocks = new HashMap(); LineNumberReader reader = new LineNumberReader(input); String line; String blockName = null; StringBuffer blockContents = null; while ((line = reader.readLine()) != null) { if (line.startsWith("~~~ ") && line.endsWith(" ~~~")) { if (blockName != null) { blocks.put(blockName, blockContents.toString()); } blockName = line.substring(4, line.length() - 4); blockContents = new StringBuffer(); } else { if (blockName != null) { blockContents.append(line); blockContents.append('\n'); } } } if (blockName != null) { blocks.put(blockName, blockContents.toString()); } return blocks; } }