You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2009/09/22 17:10:49 UTC

svn commit: r817689 - /jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java

Author: sebb
Date: Tue Sep 22 15:10:49 2009
New Revision: 817689

URL: http://svn.apache.org/viewvc?rev=817689&view=rev
Log:
Use threadStarted() to set up common variables for the sample() method
Improve handling of InvocationTargetException

Modified:
    jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java

Modified: jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java?rev=817689&r1=817688&r2=817689&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java (original)
+++ jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java Tue Sep 22 15:10:49 2009
@@ -25,7 +25,6 @@
 import java.util.Enumeration;
 
 import junit.framework.AssertionFailedError;
-import junit.framework.ComparisonFailure;
 import junit.framework.Protectable;
 import junit.framework.TestCase;
 import junit.framework.TestFailure;
@@ -34,6 +33,7 @@
 import org.apache.jmeter.samplers.AbstractSampler;
 import org.apache.jmeter.samplers.Entry;
 import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testelement.ThreadListener;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
 import org.junit.After;
@@ -48,7 +48,7 @@
  * constructor first. If the test class does not declare a string
  * constructor, the sampler will try empty constructor.
  */
-public class JUnitSampler extends AbstractSampler {
+public class JUnitSampler extends AbstractSampler implements ThreadListener {
 
     private static final Logger log = LoggingManager.getLoggerForClass();
 
@@ -75,15 +75,21 @@
     private static final String TEARDOWN = "tearDown";
 
     /// the Method objects for setUp and tearDown methods
-    private transient Method SETUP_METHOD = null;
-    private transient Method TDOWN_METHOD = null;
-    private boolean checkStartUpTearDown = false;
+    private transient Method SETUP_METHOD;
+    private transient Method TDOWN_METHOD;
 
     // The TestCase to run
-    private transient TestCase TEST_INSTANCE = null;
+    private transient TestCase TEST_INSTANCE;
     // The test object; same as TEST_INSTANCE for JUnit3 tests
-    // but different for JUnit4 tests
-    private transient Object TEST_OBJECT = null;
+    // but different for JUnit4 tests which use a wrapper
+    private transient Object TEST_OBJECT;
+
+    // The method name to be invoked
+    private transient String methodName;
+    // The name of the class containing the method
+    private transient String className;
+    // The wrapper used to invoke the method
+    private transient Protectable protectable;
 
     public JUnitSampler(){
     }
@@ -93,20 +99,17 @@
      * @param testObject
      */
     private void initMethodObjects(Object testObject){
-        if (!this.checkStartUpTearDown && !getDoNotSetUpTearDown()) {
-            if (SETUP_METHOD == null) {
-                SETUP_METHOD = getJunit4() ? 
-                    getMethodWithAnnotation(testObject, Before.class) 
-                    : 
-                    getMethod(testObject, SETUP);
-            }
-            if (TDOWN_METHOD == null) {
-                TDOWN_METHOD = getJunit4() ?
-                    getMethodWithAnnotation(testObject, After.class)
-                    :
-                    getMethod(testObject, TEARDOWN);
-            }
-            this.checkStartUpTearDown = true;
+        SETUP_METHOD = null;
+        TDOWN_METHOD = null;
+        if (!getDoNotSetUpTearDown()) {
+            SETUP_METHOD = getJunit4() ? 
+                getMethodWithAnnotation(testObject, Before.class) 
+                : 
+                getMethod(testObject, SETUP);
+            TDOWN_METHOD = getJunit4() ?
+                getMethodWithAnnotation(testObject, After.class)
+                :
+                getMethod(testObject, TEARDOWN);
         }
     }
 
@@ -352,188 +355,90 @@
     /** @{inheritDoc} */
     public SampleResult sample(Entry entry) {
         SampleResult sresult = new SampleResult();
-        String rlabel = getConstructorString();
-        if (rlabel.length()== 0) {
-            rlabel = JUnitSampler.class.getName();
-        }
         sresult.setSampleLabel(getName());// Bug 41522 - don't use rlabel here
-        final String methodName = getMethod();
-        final String className = getClassname();
         sresult.setSamplerData(className + "." + methodName);
-        // check to see if the test class is null. if it is, we create
-        // a new instance. this should only happen at the start of a
-        // test run
-        if (this.TEST_OBJECT == null) {
-            this.TEST_OBJECT = getClassInstance(className,rlabel);
-        }
-        if (this.TEST_OBJECT != null){
-            initMethodObjects(this.TEST_OBJECT);
-            final Method m = getMethod(this.TEST_OBJECT,methodName);
+        sresult.setDataType(SampleResult.TEXT);
+        // Assume success
+        sresult.setSuccessful(true);
+        sresult.setResponseMessage(getSuccess());
+        sresult.setResponseCode(getSuccessCode());
+        if (this.TEST_INSTANCE != null){
             // create a new TestResult
             TestResult tr = new TestResult();
-            long timeout = 0L;
-            Class<? extends Throwable> expectedException = null;
-            if (getJunit4()){
-                try {
-                    TEST_INSTANCE = new AnnotatedTestCase();
-                } catch (SecurityException e) {
-                    log.error(e.getLocalizedMessage(),e);
-                    return sresult;
-                } catch( NoSuchMethodException e) {
-                    log.error(e.getLocalizedMessage(),e);
-                    return sresult;
-                }            
-                Test annotation = m.getAnnotation(Test.class);
-                if(null != annotation) {
-                    expectedException = annotation.expected();
-                    timeout = annotation.timeout();
-                }
-            } else {
-                this.TEST_INSTANCE = (TestCase) this.TEST_OBJECT;
-            }
-            this.TEST_INSTANCE.setName(methodName);
+            final TestCase theClazz = this.TEST_INSTANCE;
             try {
-
-                if (!getDoNotSetUpTearDown() && SETUP_METHOD != null){
-                    try {
-                        SETUP_METHOD.invoke(this.TEST_OBJECT,new Object[0]);
-                    } catch (InvocationTargetException e) {
-                        tr.addFailure(this.TEST_INSTANCE,
-                                new AssertionFailedError(e.getMessage()));
-                    } catch (IllegalAccessException e) {
-                        tr.addFailure(this.TEST_INSTANCE,
-                                new AssertionFailedError(e.getMessage()));
-                    } catch (IllegalArgumentException e) {
-                        tr.addFailure(this.TEST_INSTANCE,
-                                new AssertionFailedError(e.getMessage()));
-                    }
+                if (SETUP_METHOD != null){
+                    SETUP_METHOD.invoke(this.TEST_OBJECT,new Object[0]);
                 }
-                final TestCase theClazz = this.TEST_INSTANCE;
-                tr.startTest(this.TEST_INSTANCE);
                 sresult.sampleStart();
+                tr.startTest(this.TEST_INSTANCE);
                 // Do not use TestCase.run(TestResult) method, since it will
                 // call setUp and tearDown. Doing that will result in calling
                 // the setUp and tearDown method twice and the elapsed time
                 // will include setup and teardown.
-                Throwable thrown = null;
-                if (getJunit4()){
-                    try {
-                        theClazz.runBare();
-                    } catch(Throwable t) {
-                        thrown = t;
-                    }
-                } else { 
-                    Protectable p = new Protectable() {
-                        public void protect() throws Throwable {
-                            m.invoke(theClazz,new Object[0]);
-                        }
-                    };
-                    tr.runProtected(theClazz, p);
-                }
+                tr.runProtected(theClazz, protectable);
                 tr.endTest(this.TEST_INSTANCE);
                 sresult.sampleEnd();
-                if (getJunit4()){
-                    if(null == thrown) {
-                        if (expectedException != None.class) {
-                            tr.addFailure(
-                                    this.TEST_INSTANCE,
-                                new AssertionFailedError(
-                                    "No error was generated for a test case which specifies an error."));
-                            throw new Exception(
-                                "Unexpected lack of exception from the test case: "
-                                    + getMethod());
-                        }
-                        else {
-                            //this is a pass condition
-                        }
-                    }
-                    else {
-                        //unravel 1x.  InvocationTargetException wraps the real exception.
-                        thrown = thrown.getCause();
-                        if (expectedException.isAssignableFrom(thrown.getClass()))
-    //                            && thrown.getClass().isAssignableFrom(expectedException))
-                        {
-                            //The test actually passed
-                            log.debug("Test passed for " + getMethod());
-                        } else {
-                            tr.addFailure(this.TEST_INSTANCE, new AssertionFailedError("The wrong exception was thrown from the test case"));
-                            throw new Exception("The wrong exception was thrown from the test case");
-                        }
-                    }
-                    if( timeout > 0L && timeout < sresult.getTime()) {
-                        tr.addFailure(this.TEST_INSTANCE, new AssertionFailedError("Test took longer than speficied timeout."));
-                    }
-                }
-                if (!getDoNotSetUpTearDown() && TDOWN_METHOD != null){
+                if (TDOWN_METHOD != null){
                     TDOWN_METHOD.invoke(TEST_OBJECT,new Object[0]);
                 }
             } catch (InvocationTargetException e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
+                Throwable cause = e.getCause();
+                if (cause instanceof AssertionFailedError){
+                    log.warn("AFE:"+cause.toString());
+                    tr.addFailure(theClazz, (AssertionFailedError) cause);                        
+                } else {
+                    log.warn("ANY:"+e.toString()+" "+cause);
+                    tr.addError(theClazz, e);                        
+                }
             } catch (IllegalAccessException e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
-            } catch (ComparisonFailure e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
+                tr.addError(theClazz, e);
             } catch (IllegalArgumentException e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
-            } catch (Exception e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
-            } catch (Throwable e) {
-                sresult.setResponseCode(getErrorCode());
-                sresult.setResponseMessage(getError());
-                sresult.setResponseData(e.getMessage().getBytes());
-                sresult.setSuccessful(false);
+                tr.addError(theClazz, e);
             }
             if ( !tr.wasSuccessful() ){
                 sresult.setSuccessful(false);
                 StringBuffer buf = new StringBuffer();
-                buf.append( getFailure() );
-                Enumeration<?> en = tr.errors();
-                while (en.hasMoreElements()){
-                    Object item = en.nextElement();
-                    if (getAppendError() && item instanceof TestFailure) {
+                Enumeration<TestFailure> en;
+                if (getAppendError()) {
+                    en = tr.failures();
+                    if (en.hasMoreElements()){
+                        sresult.setResponseCode(getFailureCode());
+                        buf.append( getFailure() );
+                        buf.append("\n");                        
+                    }
+                    while (en.hasMoreElements()){
+                        TestFailure item = en.nextElement();
                         buf.append( "Trace -- ");
-                        buf.append( ((TestFailure)item).trace() );
+                        buf.append( item.trace() );
                         buf.append( "Failure -- ");
-                        buf.append( ((TestFailure)item).toString() );
-                    } else if (getAppendException() && item instanceof Throwable) {
-                        buf.append( ((Throwable)item).getMessage() );
+                        buf.append( item.toString() );
+                        buf.append("\n");
+                    }
+                    en = tr.errors();
+                    if (en.hasMoreElements()){
+                        sresult.setResponseCode(getErrorCode());
+                        buf.append( getError() );
+                        buf.append("\n");                        
+                    }
+                    while (en.hasMoreElements()){
+                        TestFailure item = en.nextElement();
+                        buf.append( "Trace -- ");
+                        buf.append( item.trace() );
+                        buf.append( "Error -- ");
+                        buf.append( item.toString() );
+                        buf.append("\n");
                     }
                 }
                 sresult.setResponseMessage(buf.toString());
-                sresult.setRequestHeaders(buf.toString());
-                sresult.setResponseCode(getFailureCode());
-            } else {
-                // this means there's no failures
-                sresult.setSuccessful(true);
-                sresult.setResponseMessage(getSuccess());
-                sresult.setResponseCode(getSuccessCode());
-                sresult.setResponseData("Not Applicable".getBytes());
             }
         } else {
             // we should log a warning, but allow the test to keep running
             sresult.setSuccessful(false);
             // this should be externalized to the properties
             sresult.setResponseMessage("failed to create an instance of the class");
+            sresult.setResponseCode(getErrorCode());
         }
-        sresult.setBytes(0);
-        sresult.setContentType("text");
-        sresult.setDataType("Not Applicable");
-        sresult.setRequestHeaders("Not Applicable");
         return sresult;
     }
 
@@ -636,15 +541,112 @@
         return null;
     }
     
+    /*
+     * Wrapper to convert a JUnit4 class into a TestCase
+     * 
+     *  TODO - work out how to convert JUnit4 assertions so they are treated as failures rather than errors
+     */
     private class AnnotatedTestCase extends TestCase {
-        private final Method m;
-        public AnnotatedTestCase() throws SecurityException, NoSuchMethodException {
-            m = TEST_OBJECT.getClass().getMethod(getMethod(), (Class[])null);
+        private final Method method;
+        private final Class<? extends Throwable> expectedException;
+        private final long timeout;
+        public AnnotatedTestCase(Method method, Class<? extends Throwable> expectedException2, long timeout) {
+            this.method = method;
+            this.expectedException = expectedException2;
+            this.timeout = timeout;
         }
         
         @Override
         protected void runTest() throws Throwable {
-            m.invoke(TEST_OBJECT, (Object[])null);
+            try {
+                long start = System.currentTimeMillis();
+                method.invoke(TEST_OBJECT, (Object[])null);
+                if (expectedException != None.class) {
+                    throw new AssertionFailedError(
+                    "No error was generated for a test case which specifies an error.");
+                }
+                if (timeout > 0){
+                    long elapsed = System.currentTimeMillis() - start;
+                    if (elapsed > timeout) {
+                        throw new AssertionFailedError("Test took longer than the specified timeout.");
+                    }
+                }
+            } catch (InvocationTargetException e) {
+                Throwable thrown = e.getCause();
+                if (thrown == null) { // probably should not happen
+                    throw e;
+                }
+                if (expectedException == None.class){
+                    throw thrown;                    
+                }
+                if (!expectedException.isAssignableFrom(thrown.getClass())){
+                    throw new AssertionFailedError("The wrong exception was thrown from the test case");
+                }
+            }
+        }
+    }
+
+    public void threadFinished() {
+    }
+
+    /**
+     * Set up all variables that don't change between samples.
+     */
+    public void threadStarted() {
+        TEST_OBJECT = null;
+        TEST_INSTANCE = null;
+        methodName = getMethod();
+        className = getClassname();
+        final Method m;
+        protectable = null;
+        String rlabel = getConstructorString();
+        if (rlabel.length()== 0) {
+            rlabel = JUnitSampler.class.getName();
+        }
+        this.TEST_OBJECT = getClassInstance(className,rlabel);
+        if (this.TEST_OBJECT != null){
+            initMethodObjects(this.TEST_OBJECT);
+            m = getMethod(this.TEST_OBJECT,methodName);
+            if (getJunit4()){
+                Class<? extends Throwable> expectedException = None.class;
+                long timeout = 0;
+                Test annotation = m.getAnnotation(Test.class);
+                if(null != annotation) {
+                    expectedException = annotation.expected();
+                    timeout = annotation.timeout();
+                }
+                final AnnotatedTestCase at = new AnnotatedTestCase(m, expectedException, timeout);
+                TEST_INSTANCE = at;
+                protectable = new Protectable() {
+                    public void protect() throws Throwable {
+                        at.runTest();
+                    }
+                };
+            } else {
+                this.TEST_INSTANCE = (TestCase) this.TEST_OBJECT;
+                final Object theClazz = this.TEST_OBJECT; // Must be final to create instance
+                protectable = new Protectable() {
+                    public void protect() throws Throwable {
+                        try {
+                            m.invoke(theClazz,new Object[0]);
+                        } catch (InvocationTargetException e) {
+                            /*
+                             * Calling a method via reflection results in wrapping any
+                             * Exceptions in ITE; unwrap these here so runProtected can
+                             * allocate them correctly.
+                             */
+                            Throwable t = e.getCause();
+                            if (t != null) {
+                                throw t;
+                            }
+                            throw e;
+                        }
+                    }
+                };
+            }
+            if (this.TEST_INSTANCE != null){
+                this.TEST_INSTANCE.setName(methodName);
+            }
         }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org