From b53f26a3750a775ca100678dbcd104a49ca61541 Mon Sep 17 00:00:00 2001 From: j2blake Date: Tue, 21 Feb 2012 17:06:55 +0000 Subject: [PATCH] NIHVIVO-3628 Create unit tests to cover the parsing and interpreting of custom list view config files. --- .../vitro/testing/AbstractTestClass.java | 18 + ...yTemplateModel_PropertyListConfigTest.java | 683 ++++++++++++++++++ .../testConfig-constructQueryMissing.xml | 20 + .../testConfig-constructQueryMultiple.xml | 24 + .../individual/testConfig-default.xml | 28 + .../individual/testConfig-notValidXml.xml | 28 + .../testConfig-postProcessorClassNotFound.xml | 30 + ...stConfig-postProcessorClassNotSuitable.xml | 30 + ...ostProcessorConstructorThrowsException.xml | 30 + .../testConfig-postProcessorNameEmpty.xml | 30 + .../individual/testConfig-postProcessorOK.xml | 30 + ...stConfig-postProcessorWrongConstructor.xml | 30 + .../testConfig-selectQueryCollatedNoOrder.xml | 11 + ...testConfig-selectQueryCollatedNoSelect.xml | 11 + .../testConfig-selectQueryCollatedValid.xml | 11 + .../testConfig-selectQueryNoSubNodes.xml | 11 + .../testConfig-selectQueryNodeBlank.xml | 20 + .../testConfig-selectQueryNodeNotFound.xml | 17 + .../testConfig-selectQuerySubNodes.xml | 12 + .../testConfig-templateDoesNotExist.xml | 28 + .../testConfig-templateNodeIsEmpty.xml | 28 + .../testConfig-templateNodeNotFound.xml | 27 + .../webapp/dao/ObjectPropertyDaoStub.java | 43 +- .../webapp/dao/WebappDaoFactoryStub.java | 16 +- .../freemarker/cache/TemplateLoaderStub.java | 58 ++ .../javax/servlet/ServletContextStub.java | 28 +- 26 files changed, 1282 insertions(+), 20 deletions(-) create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-constructQueryMissing.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-constructQueryMultiple.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-default.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-notValidXml.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorClassNotFound.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorClassNotSuitable.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorConstructorThrowsException.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorNameEmpty.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorOK.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-postProcessorWrongConstructor.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryCollatedNoOrder.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryCollatedNoSelect.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryCollatedValid.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNoSubNodes.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNodeBlank.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQueryNodeNotFound.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-selectQuerySubNodes.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-templateDoesNotExist.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-templateNodeIsEmpty.xml create mode 100644 webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/testConfig-templateNodeNotFound.xml create mode 100644 webapp/test/stubs/freemarker/cache/TemplateLoaderStub.java diff --git a/webapp/test/edu/cornell/mannlib/vitro/testing/AbstractTestClass.java b/webapp/test/edu/cornell/mannlib/vitro/testing/AbstractTestClass.java index cd54e7ee0..7539311e1 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/testing/AbstractTestClass.java +++ b/webapp/test/edu/cornell/mannlib/vitro/testing/AbstractTestClass.java @@ -97,6 +97,24 @@ public abstract class AbstractTestClass { Logger.getLogger(category).setLevel(level); } + /** + * Capture the log for this class to this Writer. Choose whether or not to + * suppress it from the console. + */ + protected void captureLogOutput(Class clazz, Writer writer, + boolean suppress) { + PatternLayout layout = new PatternLayout("%p %m%n"); + + ConsoleAppender appender = new ConsoleAppender(); + appender.setWriter(writer); + appender.setLayout(layout); + + Logger logger = Logger.getLogger(clazz); + logger.removeAllAppenders(); + logger.setAdditivity(!suppress); + logger.addAppender(appender); + } + // ---------------------------------------------------------------------- // Control standard output or error output. // ---------------------------------------------------------------------- diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java new file mode 100644 index 000000000..dceccf027 --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel_PropertyListConfigTest.java @@ -0,0 +1,683 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Level; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import stubs.edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDaoStub; +import stubs.edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryStub; +import stubs.freemarker.cache.TemplateLoaderStub; +import stubs.javax.servlet.ServletContextStub; +import stubs.javax.servlet.http.HttpServletRequestStub; +import stubs.javax.servlet.http.HttpSessionStub; +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; +import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.ObjectPropertyTemplateModel.InvalidConfigurationException; +import freemarker.template.Configuration; + +public class ObjectPropertyTemplateModel_PropertyListConfigTest extends + AbstractTestClass { + + private static File configDir; + + private ObjectPropertyTemplateModel optm; + + private ObjectProperty op; + + private WebappDaoFactoryStub wadf; + private ObjectPropertyDaoStub opDao; + + private ServletContextStub ctx; + private HttpSessionStub session; + private HttpServletRequestStub hreq; + private VitroRequest vreq; + + private IndividualImpl subject; + + private TemplateLoaderStub tl; + + private StringWriter logMessages; + + /** + * In general, we expect no exception, but individual tests may override, + * like this: + * + *
+	 * thrown.expect(InvalidConfigurationException.class);
+	 * thrown.expectMessage("Bozo");
+	 * 
+ */ + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @BeforeClass + public static void createConfigFiles() throws IOException { + configDir = createTempDirectory("configDir"); + createConfigFile("constructQueryMissing"); + createConfigFile("constructQueryMultiple"); + createConfigFile("default"); + createConfigFile("notValidXml"); + createConfigFile("postProcessorClassNotFound"); + createConfigFile("postProcessorClassNotSuitable"); + createConfigFile("postProcessorConstructorThrowsException"); + createConfigFile("postProcessorNameEmpty"); + createConfigFile("postProcessorOK"); + createConfigFile("postProcessorWrongConstructor"); + createConfigFile("selectQueryNodeBlank"); + createConfigFile("selectQueryNodeNotFound"); + createConfigFile("selectQuerySubNodes"); + createConfigFile("selectQueryNoSubNodes"); + createConfigFile("selectQueryCollatedValid"); + createConfigFile("selectQueryCollatedNoSelect"); + createConfigFile("selectQueryCollatedNoOrder"); + createConfigFile("templateNodeIsEmpty"); + createConfigFile("templateNodeNotFound"); + createConfigFile("templateDoesNotExist"); + } + + /** Copy a file from the classpath into the temporary config directory. */ + private static void createConfigFile(String shortName) throws IOException { + String fullName = "testConfig-" + shortName + ".xml"; + Class clazz = ObjectPropertyTemplateModel_PropertyListConfigTest.class; + String contents = readAll(clazz.getResourceAsStream(fullName)); + createFile(configDir, fullName, contents); + } + + @Before + public void setup() { + logMessages = new StringWriter(); + + opDao = new ObjectPropertyDaoStub(); + wadf = new WebappDaoFactoryStub(); + wadf.setObjectPropertyDao(opDao); + + ctx = new ServletContextStub(); + // create paths for all of the files in the temporary config directory. + ctx.setRealPaths("/config", configDir); + // add a path to match the hard-coded default path. + ctx.setRealPath("/config/listViewConfig-default.xml", + ctx.getRealPath("/config/testConfig-default.xml")); + + session = new HttpSessionStub(); + session.setServletContext(ctx); + hreq = new HttpServletRequestStub(); + hreq.setSession(session); + + vreq = new VitroRequest(hreq); + vreq.setWebappDaoFactory(wadf); + + subject = new IndividualImpl(); + + BaseTemplateModel.setServletContext(ctx); + + Configuration fmConfig = new Configuration(); + vreq.setAttribute("freemarkerConfig", fmConfig); + tl = new TemplateLoaderStub(); + tl.createTemplate("propStatement-default.ftl", ""); + fmConfig.setTemplateLoader(tl); + } + + @AfterClass + public static void cleanup() { + if (configDir != null) { + purgeDirectoryRecursively(configDir); + } + } + + // TODO - don't swallow the exception if we can't create a config. + // TODO - baseTemplateModel shouldn't require the servlet context to be set + // statically!!! ServletContext shouldn't be a static field. + + // ---------------------------------------------------------------------- + // The tests + // ---------------------------------------------------------------------- + + // + // Null arguments + // + + @Test(expected = NullPointerException.class) + public void operationIsNull() throws InvalidConfigurationException { + // TODO This should throw a more predictable NullPointerException + optm = new NonCollatingOPTM(null, subject, vreq, false); + } + + @Test(expected = NullPointerException.class) + public void subjectIsNull() throws InvalidConfigurationException { + // TODO This should throw a more predictable NullPointerException + op = buildOperation("default"); + optm = new NonCollatingOPTM(op, null, vreq, false); + } + + @Test(expected = NullPointerException.class) + public void requestIsNull() throws InvalidConfigurationException { + // TODO This should throw a more predictable NullPointerException + op = buildOperation("default"); + optm = new NonCollatingOPTM(op, subject, null, false); + } + + // + // Locating the file. + // + + @Test + public void configFileNotSpecified() throws InvalidConfigurationException { + op = buildOperation("default"); + opDao.setCustomListViewConfigFileName(op, null); + optm = new NonCollatingOPTM(op, subject, vreq, false); + assertEquals("uses default config", true, optm.hasDefaultListView()); + } + + // @Ignore + @Test + public void configFilePathCantBeTranslated() + throws InvalidConfigurationException { + // TODO if we can't translate the path, log the error and use the + // default. + captureLogsFromOPTM(); + op = buildOperation("fileHasNoRealPath"); + optm = new NonCollatingOPTM(op, subject, vreq, false); + + // Throws an exception because we don't test for a null path from the + // ServletContext. + assertLogMessagesContains("no real path", "at java.io.File."); + } + + @Test + public void configFileNotFound() throws InvalidConfigurationException { + captureLogsFromOPTM(); + + op = buildOperation("configFileDoesNotExist"); + + // There should be a real path, but no file at that location. + String bogusFilepath = new File(configDir, "doesNotExist") + .getAbsolutePath(); + String path = "/config/" + opDao.getCustomListViewConfigFileName(op); + ctx.setRealPath(path, bogusFilepath); + + optm = new NonCollatingOPTM(op, subject, vreq, false); + + assertLogMessagesContains("file not found", "Can't find config file"); + } + + @Test + public void configFileNotValidXml() throws InvalidConfigurationException { + suppressSyserr(); + captureLogsFromOPTM(); + + op = buildOperation("notValidXml"); + optm = new NonCollatingOPTM(op, subject, vreq, false); + + assertLogMessagesContains("not valid XML", "SAXParseException"); + } + + // + // Problems with the node + // + + @Test + public void selectQueryNodeIsNotFound() + throws InvalidConfigurationException { + captureLogsFromOPTM(); + + op = buildOperation("selectQueryNodeNotFound"); + optm = new NonCollatingOPTM(op, subject, vreq, false); + + assertLogMessagesContains("no select query", + "Missing select query specification"); + } + + @Test + public void selectQueryNodeIsBlank() throws InvalidConfigurationException { + captureLogsFromOPTM(); + + op = buildOperation("selectQueryNodeBlank"); + optm = new NonCollatingOPTM(op, subject, vreq, false); + + assertLogMessagesContains("blank select query", + "Missing select query specification"); + } + + // + // Problems with the