/* * #! * Ontopia Navigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * 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 net.ontopia.topicmaps.nav2.impl.framework; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import javax.servlet.jsp.PageContext; import net.ontopia.utils.FileUtils; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.StreamUtils; import net.ontopia.utils.TestFileUtils; import net.ontopia.utils.ontojsp.FakeHttpSession; import net.ontopia.utils.ontojsp.FakePageContext; import net.ontopia.utils.ontojsp.FakeServletConfig; import net.ontopia.utils.ontojsp.FakeServletContext; import net.ontopia.utils.ontojsp.FakeServletRequest; import net.ontopia.utils.ontojsp.JSPPageExecuter; import net.ontopia.utils.ontojsp.JSPPageReader; import net.ontopia.utils.ontojsp.JSPTreeNodeIF; import net.ontopia.xml.DefaultXMLReaderFactory; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; /** * INTERNAL: A class which represents a single testcase of the nav2 * testing framework. */ @RunWith(Parameterized.class) public class TaglibTestCase extends AbstractTaglibTestCase { private final static String testdataDirectory = "nav2"; // initialization of logging facility private static final Logger log = LoggerFactory .getLogger(TaglibTestCase.class.getName()); // navigator environment (app-scope) shared by all test cases private static Map<String, Object> appAttrs; // filename of output result file without path private String filename; // boolean value which is true if the test should fail. private final boolean shouldFail; // string value that holds the expected exception if it is given. private String expectedException = ""; // boolean value that indicates whether tag pooling should be used private final boolean useTagPooling; private final String PARAM_TAGPOOLING = "tagpooling"; @Parameters public static List<Object[]> generateTests() throws IOException, SAXException { InputStream in = StreamUtils.getInputStream( TestFileUtils.getTestInputFile(testdataDirectory, "config", "tests.xml")); XMLReader parser = DefaultXMLReaderFactory.createXMLReader(); TestCaseContentHandler handler = new TestCaseContentHandler(); handler.register(parser); parser.parse(new InputSource(in)); Map<String, Set<Map<String, String>>> result = handler.getTests(); List<Object[]> tests = new ArrayList<Object[]>(); for (String key : result.keySet()) { Set<Map<String, String>> value = result.get(key); StringTokenizer strtok = new StringTokenizer(key, "$$$"); String tm = strtok.nextToken(); String jsp = strtok.nextToken(); for (Map<String, String> test_params : value) { tests.add(new Object[] {jsp, /* base, */ tm, test_params}); } } return tests; } /** * Default constructor. */ public TaglibTestCase(String jspfile, String topicmapId, Map params) { super(jspfile, topicmapId); if (params.containsKey("output")) { filename = (String) params.get("output"); params.remove("output"); } if (params.containsKey("fail")) { String test = (String) params.get("fail"); if (test.equals("true")) shouldFail = true; else shouldFail = false; params.remove("fail"); } else shouldFail = false; if (params.containsKey(PARAM_TAGPOOLING)) { useTagPooling = ("true".equals(params.get(PARAM_TAGPOOLING))); params.remove(PARAM_TAGPOOLING); } else { useTagPooling = false; } if (params.containsKey("exception")) { expectedException = (String) params.get("exception"); params.remove("exception"); } setRequestParameters(params); } @Test public void testJSP() throws OntopiaRuntimeException { try { // setup environment and execute single test case PageContext page = makePageContext(); String jspSource = TestFileUtils.getTestInputFile(testdataDirectory, "jsp", jspfile); JSPPageReader reader = new JSPPageReader(jspSource); JSPTreeNodeIF root = reader.read(useTagPooling); JSPPageExecuter exec = new JSPPageExecuter(); log.info("Run testcase for " + generateTestCaseDescriptor()); exec.run(page, null, root); page.getOut().flush(); log.debug("Compare results."); evaluate(); } catch (Exception e) { if (e instanceof OntopiaRuntimeException) { e = (Exception) e.getCause(); } log.info("Got an exception: " + e); if (shouldFail) { if (e.getClass().getName().equals(expectedException)) Assert.assertTrue(true); else throw new OntopiaRuntimeException("Expected exception " + expectedException+ ", got " + e.getClass(), e); } else { if (e instanceof java.io.FileNotFoundException) // handle this special to get rid of the baseline not found problem Assert.assertTrue("Could not find file: " + e.getMessage(), false); else if (e.getClass().getName().equals(expectedException)) { try { javax.servlet.jsp.JspWriter out = makePageContext().getOut(); out.print(e.getMessage()); out.flush(); log.info("Compare results."); evaluate(); } catch (Exception e1) { throw new OntopiaRuntimeException(e1); } } else throw new OntopiaRuntimeException(e); } } } /** * Compares if output result and baseline are identical. */ private void evaluate() throws IOException { String _filename = (filename == null) ? generateTestCaseFilename() : filename; String infile = TestFileUtils.getTestInputFile(testdataDirectory, "baseline", _filename); File outfile = TestFileUtils.getTestOutputFile(testdataDirectory, "out", _filename); boolean fileExists = true; try { StreamUtils.getInputStream(infile); } catch (IOException e) { fileExists = false; } if (!fileExists) { if (!shouldFail) Assert.fail("Cannot compare result, because baseline " + "file does not exist: " + infile); else { Assert.assertTrue("This test case should fail, and the file does not exist", true); return; } } if (shouldFail) { Assert.assertTrue("This testcase should have failed, but the result from the JSP file" + " is the same as the baseline. [" + infile + "]", !FileUtils.compareFileToResource(outfile, infile)); } else { Assert.assertTrue("Result from the JSP file is not the same as baseline. [" + infile + "]", FileUtils.compareFileToResource(outfile, infile)); } } /** * Creates the fake page context for the fake environment. */ private PageContext makePageContext() throws IOException { // reuse same NavigatorApplication object for all test cases // so the topicmaps have not to be loaded several times. // setup attributes for application and session context if (appAttrs == null) appAttrs = new HashMap<String, Object>(); // Set up a complete page context, reusing the application scope attributes FakePageContext pageContext = new FakePageContext(getWriter()); FakeServletRequest servletRequest = new FakeServletRequest(getRequestParameters()); servletRequest.setContextPath("jsp/" + getJspFileName()); String path = "classpath:net/ontopia/testdata/nav2/"; // so that it can find the WEB-INF directory. Map<String, String> initParams = new HashMap<String, String>(2); initParams.put("source_config", "classpath:net/ontopia/testdata/nav2/WEB-INF/config/tm-sources.xml"); initParams.put("app_config", "classpath:net/ontopia/testdata/nav2/WEB-INF/config/application.xml"); FakeServletContext servletContext = new FakeServletContext(path, appAttrs, initParams); FakeServletConfig servletConfig = new FakeServletConfig(servletContext); FakeHttpSession session = new FakeHttpSession(servletContext); pageContext.setRequest(servletRequest); pageContext.setServletConfig(servletConfig); pageContext.setSession(session); return pageContext; } /** * Creates the outputfile in the "out" directory. */ private Writer getWriter() throws IOException { String _filename = (filename == null) ? generateTestCaseFilename() : filename; File file = TestFileUtils.getTestOutputFile(testdataDirectory, "out", _filename); if (!file.createNewFile()) { file.delete(); file.createNewFile(); log.info("Deleting old resultfile, and creating a new one."); } return new OutputStreamWriter(new FileOutputStream(file), "iso-8859-1"); } /** * Constructs filename with the help of the topicmap id, the jsp * filename and the request parameters. */ private String generateTestCaseFilename() { StringBuilder filename = new StringBuilder(32); // (1) Append the topicmap ID first. filename.append( getTopicMapId() ); filename.append("-"); // (2) Append the jsp file name next (without file extension). String jspname = getJspFileName(); filename.append( jspname.substring(0, jspname.lastIndexOf(".jsp")) ); // (3) Append the request parameters Map<String, String[]> params = getRequestParameters(); for (String key : params.keySet()) { String vals[] = params.get(key); if (vals.length != 0) { filename.append("-").append(key).append("=").append(vals[0]); for (int i = 1; i < vals.length; i++) filename.append("_").append(vals[i]); } } // (4) filename suffix filename.append(".res"); return filename.toString(); } /** * Constructs description of this testcase which consists of the * topicmap id, the jsp filename and the request parameters. */ private String generateTestCaseDescriptor() { StringBuilder descriptor = new StringBuilder(32); // (1) Append the topicmap ID first. descriptor.append("TopicMapId: "); descriptor.append( getTopicMapId() ); // (2) Append the jsp file name next (without file extension). descriptor.append(", InputFile: "); descriptor.append( getJspFileName() ); // (3) Append the request parameters descriptor.append(", Params: "); Map<String, String[]> params = getRequestParameters(); for (String key : params.keySet()) { descriptor.append(" ").append(key).append("="); Object val = params.get(key); if (val instanceof String) descriptor.append(val); else { String[] vals = (String[]) val; for (int i=0; i < vals.length; i++) { descriptor.append(vals[i]); if (i < vals.length-1) descriptor.append(","); } } } // while return descriptor.toString(); } }