/* * Copyright (c) 2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.junit; import java.util.*; import java.io.*; import org.knopflerfish.service.junit.*; import org.osgi.framework.*; import junit.framework.*; import java.lang.reflect.*; public class JUnitServiceImpl implements JUnitService { JUnitServiceImpl() { } public void runTest(PrintWriter out, TestSuite suite) throws IOException { ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); runTestXML(out, suite); out.flush (); } finally { Thread.currentThread().setContextClassLoader(oldLoader); } } public void runTestXML(PrintWriter out, TestSuite suite) throws IOException { out.println(""); out.println(""); out.print(""); dumpSystemProps(out); try { runTestCase(out, suite); } catch (Exception e) { out.println(" "); toXMLException(e, out); out.println(" "); } out.println(""); } void dumpSystemProps(PrintWriter out) throws IOException { dumpProps(out, System.getProperties(), "System.properties"); Hashtable props = new Hashtable(); copyBCProp(props, Constants.FRAMEWORK_VENDOR); copyBCProp(props, Constants.FRAMEWORK_VERSION); copyBCProp(props, Constants.FRAMEWORK_OS_NAME); copyBCProp(props, Constants.FRAMEWORK_PROCESSOR); copyBCProp(props, Constants.FRAMEWORK_OS_VERSION); copyBCProp(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT); dumpProps(out, props, "Framework.properties"); } void copyBCProp(Hashtable props, String name) { String s = Activator.bc.getProperty(name); if(s != null) { props.put(name, s); } else { props.put(name, "[null]"); } } void dumpProps(PrintWriter out, Dictionary props, String name) throws IOException { out.println(""); try { for(Enumeration e = props.keys(); e.hasMoreElements(); ) { String key = (String)e.nextElement(); Object val = props.get(key); out.print(" "); out.print(""); out.println(""); } } catch (Exception e) { out.println(""); } out.println(""); } protected void runTestCase(PrintWriter out, TestSuite suite) throws Exception { out.println(" "); String desc = getBeanString(suite, "getDescription", ""); out.print(" "); out.print(""); out.println(""); String docurl = getBeanString(suite, "getDocURL", ""); out.print(" "); out.print(""); out.println(""); try { System.out.println("run test on " + suite); TestResult tr = new TestResult(); long start = System.currentTimeMillis(); suite.run(tr); long stop = System.currentTimeMillis(); toXMLSuite(suite, tr, stop - start, out, 2); toXMLResult(tr, out); } finally { out.println(" "); } } public TestSuite getTestSuite(final String id, final String subid) { Object obj = null; try { ServiceReference[] srl = Activator.bc.getServiceReferences(null, "(service.pid=" + id + ")"); if(srl == null || srl.length == 0) { obj = new TestCase("No id=" + id) { public void runTest() { throw new IllegalArgumentException("No test with id=" + id); } }; } if(srl != null && srl.length != 1) { obj = new TestCase("Multiple id=" + id) { public void runTest() { throw new IllegalArgumentException("More than one test with id=" + id); } }; } if(obj == null) { obj = Activator.bc.getService(srl[0]); } } catch (Exception e) { obj = new TestCase("Bad filter syntax id=" + id) { public void runTest() { throw new IllegalArgumentException("Bad syntax id=" + id); } }; } if(!(obj instanceof Test)) { final Object oldObj = obj; obj = new TestCase("ClassCastException") { public void runTest() { throw new ClassCastException("Service implements " + oldObj.getClass().getName() + " instead of " + Test.class.getName()); } }; } Test test = (Test)obj; TestSuite suite; if(subid != null && !"".equals(subid)) { Test subtest = findTest(test, subid); if(subtest != null) { test = subtest; } else { test = new TestCase("IllegalArgumentException") { public void runTest() { throw new ClassCastException("subtest " + subid + " not found"); } }; } } if(test instanceof TestSuite) { suite = (TestSuite)test; } else { suite = new TestSuite(id); suite.addTest(test); } return suite; } protected Test findTest(Test test, String id) { if(test instanceof TestSuite) { TestSuite ts = (TestSuite)test; if(id.equals(ts.getName()) || id.equals(ts.getClass().getName())) { return ts; } for(int i = 0; i < ts.testCount(); i++) { Test child = ts.testAt(i); Test r = findTest(child, id); if(r != null) { return r; } } } if(test instanceof TestCase) { TestCase tc = (TestCase)test; if(id.equals(tc.getName())) { return tc; } } if(id.equals(test.getClass().getName())) { return test; } return null; } protected static String indent(int n) { StringBuffer sb = new StringBuffer(); while(n --> 0) { sb.append(" "); } return sb.toString(); } protected void toXMLSuite(TestSuite suite, TestResult tr, long time, PrintWriter out, int n) throws IOException { out.print(indent(n) + " "); for(int i = 0; i < suite.testCount(); i++) { Test test = suite.testAt(i); String clazz = test.getClass().getName(); String name = null; if(test instanceof TestCase) { name = ((TestCase)test).getName(); } if(name == null) { name = clazz; } if(test instanceof TestSuite) { toXMLSuite((TestSuite)test, tr, 0, out, n + 1); } else { out.print(indent(n) + " "); String desc = getBeanString(test, "getDescription", ""); out.print(" "); out.print(""); out.println(""); out.println(""); } } out.println(indent(n) + " "); } String getTestCaseStatus(TestResult tr, Test test) { for(Enumeration e = tr.failures(); e.hasMoreElements(); ) { TestFailure tf = (TestFailure)e.nextElement(); if(tf.failedTest() == test) { return "failed"; } } for(Enumeration e = tr.errors(); e.hasMoreElements(); ) { TestFailure tf = (TestFailure)e.nextElement(); if(tf.failedTest() == test) { return "error"; } } return "passed"; } protected void toXMLResult(TestResult tr, PrintWriter out) throws IOException { out.println(" "); if(tr.failureCount() > 0 ) { out.println(" "); for(Enumeration e = tr.failures(); e.hasMoreElements(); ) { TestFailure tf = (TestFailure)e.nextElement(); toXMLFailure(tf, out); } out.println(" "); } if(tr.errorCount() > 0 ) { out.println(" "); for(Enumeration e = tr.errors(); e.hasMoreElements(); ) { TestFailure tf = (TestFailure)e.nextElement(); toXMLFailure(tf, out); } out.println(" "); } out.println(" "); } void toXMLFailure(TestFailure tf, PrintWriter out) throws IOException { out.println(" "); out.print(" "); out.println(" "); } protected String escape(String s) { if(s == null) { return null; } s = s .replace('<', '[') .replace('>', ']') .replace('\"', '\''); s = replace(s, "&", "&"); return s; } protected void toXMLError(AssertionFailedError af, PrintWriter out) throws IOException { out.println(" "); toXMLException(af, out); out.println(" "); } protected void toXMLException(Throwable t, PrintWriter out) throws IOException { out.print(" "); out.print(""); } static String getBeanString(Object target, String methodName, String defVal) { String val = defVal; try { Method m = target.getClass().getMethod(methodName, new Class[] { }); val = (String)m.invoke(target, null); } catch (Exception e) { return defVal; } return val; } /** * Replace all occurances of a substring with another string. * *

* The returned string will shrink or grow as necessary, depending on * the lengths of v1 and v2. *

* *

* Implementation note: This method avoids using the standard String * manipulation methods to increase execution speed. * Using the replace method does however * include two new operations in the case when matches are found. *

* * * @param s Source string. * @param v1 String to be replaced with v2. * @param v2 String replacing v1. * @return Modified string. If any of the input strings are null, * the source string s will be returned unmodified. * If v1.length == 0, v1.equals(v2) or * no occurances of v1 is found, also * return s unmodified. */ public static String replace(final String s, final String v1, final String v2) { // return quick when nothing to do if(s == null || v1 == null || v2 == null || v1.length() == 0 || v1.equals(v2)) { return s; } int ix = 0; int v1Len = v1.length(); int n = 0; // count number of occurances to be able to correctly size // the resulting output char array while(-1 != (ix = s.indexOf(v1, ix))) { n++; ix += v1Len; } // No occurances at all, just return source string if(n == 0) { return s; } // Set up an output char array of correct size int start = 0; int v2Len = v2.length(); char[] r = new char[s.length() + n * (v2Len - v1Len)]; int rPos = 0; // for each occurance, copy v2 where v1 used to be while(-1 != (ix = s.indexOf(v1, start))) { while(start < ix) r[rPos++] = s.charAt(start++); for(int j = 0; j < v2Len; j++) { r[rPos++] = v2.charAt(j); } start += v1Len; } // ...and add all remaining chars ix = s.length(); while(start < ix) r[rPos++] = s.charAt(start++); // ..ouch. this hurts. return new String(r); } }