/* * #! * Ontopia TMRAP * #- * 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.utils.tmrap; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import javax.servlet.ServletException; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URIFragmentLocator; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.entry.TopicMaps; import net.ontopia.topicmaps.nav2.utils.NavigatorUtils; import net.ontopia.topicmaps.utils.NullResolvingExternalReferenceHandler; import net.ontopia.topicmaps.xml.CanonicalXTMWriter; import net.ontopia.topicmaps.xml.XTMTopicMapReader; 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.FakeServletConfig; import net.ontopia.utils.ontojsp.FakeServletContext; import net.ontopia.utils.ontojsp.FakeServletRequest; import net.ontopia.utils.ontojsp.FakeServletResponse; 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.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @RunWith(Parameterized.class) public class TMRAPTestCase { private final static String testdataDirectory = "tmrap"; @Parameters public static Collection generateTests() throws IOException { TestFileUtils.transferTestInputDirectory(testdataDirectory + "/topicmaps"); String source = TestFileUtils.getTestInputFile(testdataDirectory, "tests.xml"); InputStream in = StreamUtils.getInputStream(source); // Parse the test configuration file to get all the test descriptors. try { XMLReader parser = DefaultXMLReaderFactory.createXMLReader(); TMRAPTestCaseContentHandler handler = new TMRAPTestCaseContentHandler(); handler.register(parser); parser.parse(new InputSource(in)); return handler.getTestDescriptors(); } catch (SAXException e) { throw new OntopiaRuntimeException(e); } catch (MalformedURLException e) { throw new OntopiaRuntimeException(e); } catch (IOException e) { throw new OntopiaRuntimeException(e); } } // --- Test case class private String base; private TMRAPTestDescriptor descriptor; public TMRAPTestCase(TMRAPTestDescriptor descriptor) { this.base = TestFileUtils.getTestdataOutputDirectory() + testdataDirectory + File.separator; this.descriptor = descriptor; } /** * Run an error test, i.e. a test that is meant to fail with some given * exception class. */ private void runErrorTest() { try { runRapServlet(base, new PrintWriter(new StringWriter()), descriptor.getUri(), false, false); Assert.fail("Expected to fail with: " + descriptor.getExpectedException() + " but executed without errors."); } catch (Exception e) { String eName = e.getClass().getName(); Assert.assertTrue("Expected to fail with: " + descriptor.getExpectedException() + " but failed with " + eName + " instead.", eName.equals(descriptor .getExpectedException())); } } @Test public void testFile() throws IOException, ServletException { if (descriptor.getId() == null) { runErrorTest(); return; } TestFileUtils.verifyDirectory(base, "out"); TestFileUtils.verifyDirectory(base, "cxtm"); String id = descriptor.getId(); // Path to the output. String out = base + "out" + File.separator + id + ".xtm"; // Path to the canonicalized output. String cxtm = base + "cxtm" + File.separator + id + ".cxtm"; // Path to the baseline. String baseline = TestFileUtils.getTestInputFile(testdataDirectory, "baseline", id + ".cxtm"); PrintWriter pw = new PrintWriter(new FileWriter(out)); runRapServlet(base, pw, descriptor.getUri(), descriptor.getEdit(), descriptor.getView()); pw.close(); // FIXME: When other syntaxes are supported, the Reader must take the // chosen syntax into account. XTMTopicMapReader xtmReader = new XTMTopicMapReader(new File(out)); xtmReader.setExternalReferenceHandler( new NullResolvingExternalReferenceHandler()); // Import the tm. TopicMapIF importedTM = xtmReader.read(); filterUnifyingTopics(importedTM); // Canonicalize the reimported tm. FileOutputStream fos = new FileOutputStream(cxtm); (new CanonicalXTMWriter(fos)).write(importedTM); fos.close(); // NOTE: Only for observational purposes when making tests. // (new LTMTopicMapWriter(new FileOutputStream(base + "ltm" + File.separator // + id + ".ltm"))).write(importedTM); // Compare 'out' with 'baseline'. Assert.assertTrue("The output of the test with id " + id + " does not match the baseline: " + cxtm + " " + baseline, FileUtils.compareFileToResource(cxtm, baseline)); } /** * A unifying topic is generated when a topic occurrs in multiple topicmaps * of a TMRAP query. * It has source locator with a time stamp, which makes testing harder since * it makes the output vary over time. * This method removes those source locators. * @param topicMap The topic map to remove the source locators from. */ public static void filterUnifyingTopics(TopicMapIF topicMap) { Collection topics = topicMap.getTopics(); Iterator topicsIt = topics.iterator(); while (topicsIt.hasNext()) { TopicIF currentTopic = (TopicIF)topicsIt.next(); Collection removables = new ArrayList(); Collection sources = currentTopic.getItemIdentifiers(); Iterator sourcesIt = sources.iterator(); while (sourcesIt.hasNext()) { LocatorIF currentLocator = (LocatorIF)sourcesIt.next(); if (currentLocator instanceof URIFragmentLocator && currentLocator.getAddress().indexOf("unifying-topic") != -1) removables.add(currentLocator); } Iterator removablesIt = removables.iterator(); while (removablesIt.hasNext()) { LocatorIF currentLocator = (LocatorIF)removablesIt.next(); currentTopic.removeItemIdentifier(currentLocator); } } } /** * Run RapServlet at a given base directory writing to a given PrintWriter. * @param base The base directory of the test. * @param responseWriter Handles the output. * @param uriString The source URI which defines the TMRAP query. * @throws ServletException * @throws IOException */ private static void runRapServlet(String base, PrintWriter responseWriter, String uriString, boolean edit, boolean view) throws ServletException, IOException { int queryIndex = uriString.indexOf('?'); if (queryIndex == -1) queryIndex = uriString.length(); String parameterPart = (queryIndex == 0 || queryIndex == uriString.length()) ? "" : uriString.substring(queryIndex + 1); uriString = uriString.substring(0, queryIndex); HashMap params = TMRAPTestUtils.tokenizeParameters(parameterPart); params.put("server_name", "TMRAP Test Suite"); if (edit) params.put("edit_uri", "http://localhost:8080/ontopoly/topicTypeConfig.ted?tm=%tmid%&id=%topicid%"); if (view) params.put("view_uri", "http://localhost:8080/omnigator/models/topic_complete.jsp?tm=%tmid%&id=%topicid%"); Hashtable paramsTable = TMRAPTestUtils.tabularizeParameters(params); FakeServletContext servletContext = new FakeServletContext(base, new Hashtable(), Collections.singletonMap("source_config", TestFileUtils.getTestInputFile(testdataDirectory, "WEB-INF/config/tm-sources.xml"))); FakeServletConfig servletConfig = new FakeServletConfig(servletContext, paramsTable); FakeServletRequest servletRequest = new FakeServletRequest(FakeServletRequest.transform(paramsTable)); FakeServletResponse servletResponse = new FakeServletResponse(responseWriter); RAPServlet rapServlet = new RAPServlet(); rapServlet.init(servletConfig); rapServlet.doGet(servletRequest, servletResponse, uriString); TopicMaps.forget(NavigatorUtils.getTopicMapRepository(servletContext)); if (servletResponse.getStatus() != 200) throw new ServletException("Error in running RAP servlet: " + servletResponse.getStatus() + " " + servletResponse.getMessage()); } }