/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.sms.monitor.internal.config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.util.List; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.SchemaOutputResolver; import javax.xml.bind.UnmarshalException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEventHandler; import javax.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Result; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.Difference; import org.custommonkey.xmlunit.XMLUnit; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.opennms.sms.monitor.internal.MobileSequenceConfigBuilder; import org.opennms.sms.monitor.internal.MobileSequenceConfigBuilder.MobileSequenceTransactionBuilder; import org.opennms.sms.monitor.session.UniqueNumber; import org.opennms.test.FileAnticipator; import org.smslib.USSDSessionStatus; import org.w3c.dom.Document; import org.xml.sax.SAXException; public class SequenceXmlTest { private FileAnticipator m_fileAnticipator; private MobileSequenceConfig m_smsSequence; private JAXBContext m_context; private Marshaller m_marshaller; private Unmarshaller m_unmarshaller; static private class TestOutputResolver extends SchemaOutputResolver { private final File m_schemaFile; public TestOutputResolver(File schemaFile) { m_schemaFile = schemaFile; } public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { return new StreamResult(m_schemaFile); } } @Before public void setUp() throws Exception { m_fileAnticipator = new FileAnticipator(); MobileSequenceConfigBuilder bldr = new MobileSequenceConfigBuilder(); bldr.variable("amount", UniqueNumber.class).parameter("min", 1).parameter("max", 15); bldr.ussdRequest("req-balance-transfer", "ACM0", "*327*${recipient}*${amount}#").withTransactionLabel("ussd-transfer").withGatewayId("ACM0") .expectUssdResponse("balance-conf-resp") .onGateway("ACM0") .withSessionStatus(USSDSessionStatus.FURTHER_ACTION_REQUIRED) .matching("^Transfiere L ${amount} al ${recipient}$"); MobileSequenceTransactionBuilder transBldr = bldr.ussdRequest("conf-transfer", "ACM0", "1"); transBldr.withTransactionLabel("req-conf").withGatewayId("ACM0") .expectUssdResponse("processing") .onGateway("ACM0") .withSessionStatus(USSDSessionStatus.NO_FURTHER_ACTION_REQUIRED) .matching("^.*Su transaccion se esta procesando.*$"); transBldr.expectSmsResponse("transferred") .onGateway("ACM0") .matching("^.*le ha transferido L ${amount}.*$") .srcMatches("+3746"); m_smsSequence = bldr.getSequence(); m_context = JAXBContext.newInstance( MobileSequenceConfig.class, SmsSequenceRequest.class, UssdSequenceRequest.class, SmsSequenceResponse.class, UssdSequenceResponse.class, SmsFromRecipientResponseMatcher.class, SmsSourceMatcher.class, TextResponseMatcher.class, UssdSessionStatusMatcher.class ); m_marshaller = m_context.createMarshaller(); m_marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m_marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MobileSequenceNamespacePrefixMapper()); m_unmarshaller = m_context.createUnmarshaller(); m_unmarshaller.setSchema(null); XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreWhitespace(true); XMLUnit.setIgnoreAttributeOrder(true); XMLUnit.setNormalize(true); } @After public void tearDown() throws Exception { m_fileAnticipator.tearDown(); } @Test public void generateSchema() throws Exception { File schemaFile = m_fileAnticipator.expecting("mobile-sequence.xsd"); m_context.generateSchema(new TestOutputResolver(schemaFile)); printFile(schemaFile); if (m_fileAnticipator.isInitialized()) { m_fileAnticipator.deleteExpected(); } } @Test public void generateXML() throws Exception { // Marshal the test object to an XML string StringWriter objectXML = new StringWriter(); m_marshaller.marshal(m_smsSequence, objectXML); System.err.println(objectXML.toString()); } @Test(expected=UnmarshalException.class) public void readInvalidXML() throws Exception { File exampleFile = new File(ClassLoader.getSystemResource("invalid-sequence.xml").getFile()); ValidationEventHandler handler = new DefaultValidationEventHandler(); m_unmarshaller.setEventHandler(handler); MobileSequenceConfig s = (MobileSequenceConfig)m_unmarshaller.unmarshal(exampleFile); System.err.println("sequence = " + s); assertTransactionParentsSet(s); } @Test(expected=UnmarshalException.class) public void readPoorlyFormedXML() throws Exception { File exampleFile = new File(ClassLoader.getSystemResource("poorly-formed-sequence.xml").getFile()); ValidationEventHandler handler = new DefaultValidationEventHandler(); m_unmarshaller.setEventHandler(handler); MobileSequenceConfig s = (MobileSequenceConfig)m_unmarshaller.unmarshal(exampleFile); System.err.println("sequence = " + s); assertTransactionParentsSet(s); } @Test public void readAnotherSampleXML() throws Exception { File exampleFile = new File(ClassLoader.getSystemResource("alternate-ping-sequence.xml").getFile()); ValidationEventHandler handler = new DefaultValidationEventHandler(); m_unmarshaller.setEventHandler(handler); MobileSequenceConfig s = (MobileSequenceConfig)m_unmarshaller.unmarshal(exampleFile); System.err.println("sequence = " + s); assertTransactionParentsSet(s); } @Test public void readXML() throws Exception { File exampleFile = new File(ClassLoader.getSystemResource("ussd-balance-sequence.xml").getFile()); ValidationEventHandler handler = new DefaultValidationEventHandler(); m_unmarshaller.setEventHandler(handler); MobileSequenceConfig s = (MobileSequenceConfig)m_unmarshaller.unmarshal(exampleFile); System.err.println("sequence = " + s); assertTransactionParentsSet(s); } @Test public void validateXML() throws Exception { // Marshal the test object to an XML string StringWriter objectXML = new StringWriter(); m_marshaller.marshal(m_smsSequence, objectXML); // Read the example XML from src/test/resources StringBuffer exampleXML = getXmlBuffer("ussd-balance-sequence.xml"); System.err.println("========================================================================"); System.err.println("Object XML:"); System.err.println("========================================================================"); System.err.print(objectXML.toString()); System.err.println("========================================================================"); System.err.println("Example XML:"); System.err.println("========================================================================"); System.err.print(exampleXML.toString()); DetailedDiff myDiff = getDiff(objectXML, exampleXML); assertEquals("number of XMLUnit differences between the example XML and the mock object XML is 0", 0, myDiff.getAllDifferences().size()); } @Test public void validateAgainstSchema() throws Exception { File schemaFile = m_fileAnticipator.expecting("mobile-sequence.xsd"); m_context.generateSchema(new TestOutputResolver(schemaFile)); printFile(schemaFile); SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(schemaFile); Validator validator = schema.newValidator(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setNamespaceAware(true); DocumentBuilder parser = dbFactory.newDocumentBuilder(); File sequenceFile = new File(ClassLoader.getSystemResource("ussd-balance-sequence.xml").getFile()); printFile(sequenceFile); Document document = parser.parse(sequenceFile); validator.validate(new DOMSource(document)); if (m_fileAnticipator.isInitialized()) { m_fileAnticipator.deleteExpected(); } } @Test public void tryFactory() throws Exception { File exampleFile = new File(ClassLoader.getSystemResource("ussd-balance-sequence.xml").getFile()); MobileSequenceConfig sequence = SequenceConfigFactory.getInstance().getSequenceForFile(exampleFile); assertEquals("ussd-transfer", sequence.getTransactions().iterator().next().getLabel()); } @SuppressWarnings("unchecked") private DetailedDiff getDiff(StringWriter objectXML, StringBuffer exampleXML) throws SAXException, IOException { DetailedDiff myDiff = new DetailedDiff(XMLUnit.compareXML(exampleXML.toString(), objectXML.toString())); List<Difference> allDifferences = myDiff.getAllDifferences(); if (allDifferences.size() > 0) { for (Difference d : allDifferences) { System.err.println(d); } } return myDiff; } private void assertTransactionParentsSet(MobileSequenceConfig s) { for ( MobileSequenceTransaction t : s.getTransactions() ) { assertEquals(s, t.getSequenceConfig()); } } private StringBuffer getXmlBuffer(String fileName) throws IOException { StringBuffer xmlBuffer = new StringBuffer(); File xmlFile = new File(ClassLoader.getSystemResource("ussd-balance-sequence.xml").getFile()); assertTrue("ussd-balance-sequence.xml is readable", xmlFile.canRead()); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(xmlFile), "UTF-8")); String line; while (true) { line = reader.readLine(); if (line == null) { reader.close(); break; } xmlBuffer.append(line).append("\n"); } return xmlBuffer; } private void printFile(File file) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); StringBuilder sb = new StringBuilder(); String line = null; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } System.err.println(sb.toString()); } }