001    /*
002     * Copyright 1999-2001,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.latka.junit;
018    
019    // java imports
020    import java.io.File;
021    import java.io.IOException;
022    import java.net.MalformedURLException;
023    import java.net.URL;
024    // jaxp imports
025    import javax.xml.parsers.FactoryConfigurationError;
026    import javax.xml.parsers.ParserConfigurationException;
027    import javax.xml.parsers.SAXParser;
028    import javax.xml.parsers.SAXParserFactory;
029    // latka imports
030    import org.apache.commons.latka.DefaultLatkaEventInfo;
031    import org.apache.commons.latka.Latka;
032    import org.apache.commons.latka.LatkaException;
033    import org.apache.commons.latka.Suite;
034    // log4j imports
035    import org.apache.log4j.Category;
036    // sax imports
037    import org.xml.sax.Attributes;
038    import org.xml.sax.InputSource;
039    import org.xml.sax.SAXException;
040    import org.xml.sax.XMLReader;
041    import org.xml.sax.helpers.DefaultHandler;
042    // junit imports
043    import junit.framework.Test;
044    import junit.framework.TestResult;
045    
046    /**
047     * A JUnit {@link junit.framework.Test Test} which is created by
048     * wrapping a Latka {@link org.apache.commons.latka.Suite Suite}
049     *
050     * @author Chuck Burdick
051     * @author dIon Gillard
052     * @version $Id: JUnitTestAdapter.java 155424 2005-02-26 13:09:29Z dirkv $
053     */
054    public class JUnitTestAdapter implements Test {
055        /** log4j category that output is logged to */
056        private static final Category _log = Category.getInstance(
057            JUnitTestAdapter.class);
058    
059        /** The latka {@link org.apache.commons.latka.Suite Suite} to be run*/
060        private Suite _latkaSuite = null;
061        /** the number of tests in the suite */
062        private int _testCount = 0;
063    
064        /**
065         * Create a Test from a Latka suite and a number of tests
066         *
067         * @param suite The Latka {@link org.apache.commons.latka.Suite}
068         * to be run as a JUnit Test
069         * @param testCount The number of 'request's in the Latka suite
070         */   
071        protected JUnitTestAdapter(Suite suite, int testCount) {
072            _latkaSuite = suite;
073            _testCount = testCount;
074        }
075    
076        /**
077         * Create a Test from a Latka file
078         * @param fileName The name of a readable file in Latka's XML format
079         * @return a JUnit Test, ready to run, or null if the file can't be resolved
080         */   
081        public static Test createTestFromFile(String fileName) {
082            Test result = null;
083            File file = new File(fileName);
084            if (file.exists()) {
085                result = createTestFromFile(file);
086            } else {
087                _log.debug("Input file " + file.getAbsolutePath()
088                    + " does not exist");
089            }
090            return result;
091        }
092    
093        /**
094         * Create a Test from a {@link java.io.File Java file}
095         * @param file A readable java file containing Latka's XML format 
096         * @return a JUnit Test, ready to run, or null if the file can't be resolved
097         */   
098        public static Test createTestFromFile(File file) {
099            Test result = null;
100            try {
101                result = createTestFromURL(file.toURL());
102            } catch (MalformedURLException e) {
103                _log.debug("Could not access input file", e);
104            }
105            return result;
106        }
107    
108        /**
109         * Create a Test from a resource accessible via
110         * the {@link java.lang.ClassLoader#getResource(String) class loader}
111         * @param resourceName A resource accessible by the class loader in Latka's
112         *      XML format
113         * @return a JUnit Test, ready to run, or null if the resource can't be
114         *      resolved
115         */   
116        public static Test createTestFromResource(String resourceName) {
117            Test result = null;
118            ClassLoader loader = JUnitTestAdapter.class.getClassLoader();
119            URL resource = loader.getResource(resourceName);
120            if (resource != null) {
121                result = createTestFromURL(resource);
122            }
123            return result;
124        }
125    
126        /**
127         * Create a Test from a String containing a URL whose
128         * contents are in Latka's XML format
129         * @param url the {@link java.net.URL URL} to fetch
130         * @return a JUnit Test, ready to run, or null if the url can't be resolved
131         */   
132        public static Test createTestFromURL(String url) {
133            Test result = null;
134            try {
135                result = createTestFromURL(new URL(url));
136            } catch (MalformedURLException e) {
137                _log.debug("Unable to create URL " + url, e);
138            }
139            return result;
140        }
141    
142        /**
143         * Create a Test from a URL whose contents are in Latka's XML format
144         * @param url the {@link java.net.URL URL} to fetch
145         * @return a JUnit Test, ready to run, or null if the url can't be resolved
146         */   
147        public static Test createTestFromURL(URL url) {
148            Test result = null;
149            try {
150                InputSource source = new InputSource(url.toString());
151                Suite suite = new Suite(url);
152                result = new JUnitTestAdapter(suite, parse(source));
153            } catch (IOException ioe) {
154                _log.debug("IOException obtaining xml from URL " + url, ioe);
155            } catch (SAXException se) {
156                _log.debug("Problem parsing URL " + url, se);
157            } catch (ParserConfigurationException pce) {
158                _log.debug("Problem determining parser", pce);
159            }
160            return result;
161        }
162    
163        /**
164         * Parse the Latka XML document to count the requests
165         * @param xml The inputsource to parse
166         * @throws IOException When an IO occurs reading the document
167         * @throws SAXException When the document is invalid XML 
168         * @throws FactoryConfigurationError When the SAX Parser factory can't be 
169         *      configured correctly
170         * @throws ParserConfigurationException When the SAX Parser can't be 
171         *      configured correctly
172         * @return the number of tests in the Latka suite
173         */   
174        protected static int parse(InputSource xml) throws IOException, SAXException
175            , FactoryConfigurationError, ParserConfigurationException {
176            int result = 0;
177            XMLReader reader = null;
178            SAXParserFactory factory = SAXParserFactory.newInstance();
179            factory.setValidating(false);   
180            SAXParser parser = factory.newSAXParser();
181            reader = parser.getXMLReader();
182            TestCounter handler = new TestCounter();
183            reader.setContentHandler(handler);
184            reader.parse(xml);
185            result = handler.getCount();
186            return result;
187        }
188    
189        /**
190         * A SAX Handler to count the number of request tags in the document
191         *
192         * @author Chuck Burdick
193         * @author dIon Gillard
194         * @version 
195         * $Id: JUnitTestAdapter.java 155424 2005-02-26 13:09:29Z dirkv $
196         */
197        private static class TestCounter extends DefaultHandler {
198            /** number of requests (ie junit tests) */
199            private int _count = 0;
200          
201            /**
202             * Create a DefaultHandler to count request elements
203             */      
204            public TestCounter() {
205                _count = 0;
206            }
207          
208            /**
209             * process the start of an xml element
210             * @param uri uri
211             * @param localName localName
212             * @param qName qName
213             * @param atts atts
214             */      
215            public void startElement(String uri, String localName, String qName, 
216                                     Attributes atts) {
217                if (qName.equals("request")) {
218                    _count++;
219                }
220            }
221            
222            /**
223             * Provides the number of <request> tags
224             * @return the count of request elements found
225             */      
226            public int getCount() {
227                return _count;
228            }
229        }
230    
231        /**
232         * Provides access, post-parsing, of the number of
233         * request elements in the Latka Suite 
234         * @return the number of test cases in the Latka suite
235         */
236        public int countTestCases() {
237            return _testCount;
238        }
239    
240        /**
241         * Run the test, adding results to the provided 
242         * {@link junit.framework.TestResult TestResult}
243         *
244         * @param r TestResult to accumulate
245         */      
246        public void run(TestResult r) {
247            _log.debug("Attempting to perform latka tests");
248            Latka latka = new Latka();
249            try {
250                latka.runTests(_latkaSuite, new DefaultLatkaEventInfo(new JUnitEventReporter(r)));
251            } catch (LatkaException e) {
252                _log.error("Unable to execute latka tests", e);
253            }
254        }
255    }