Success!  The ORO Perl5Matcher is not thread-safe.  I checked the mailing list and 
found some comments about Perl5Matcher needing to be accessed via a ThreadLocal 
instance in mult-threaded situations.

This is what I did to ResponseAssertion to fix my problem:

1) I changed the "matcher" static field definition to this:

    public transient static ThreadLocal matcher = 
        new ThreadLocal() 
        {
            protected Object initialValue()
            {
                return new Perl5Matcher();
            }
        };

2) The whole inside of the try block of the #evaluateResponse(SampleResult) method is 
below.  (Sorry, I'm not real swift with diff yet and I can't access CVS anyways -- 
probably due to our firewall).   Some of the changes were for efficiency and 
code-readability -- like converting the responseData to a String only once.  I am also 
rather bothered by the fact that each pattern has to be recompiled all the time.  The 
patterns really should be compiled once and put into a ThreadLocal variable as well 
(or they can be compiled with the Perl5Compiler.READ_ONLY_MASK flag and cached), but I 
felt that would involve too many changes for this e-mail.

            String responseString = new String(response.getResponseData());
            // Get the matcher for this thread
            Perl5Matcher localMatcher = (Perl5Matcher) this.matcher.get();
            Iterator iter = getTestStrings().iterator();
            while (iter.hasNext())
            {
                String pattern = (String)iter.next();
                Pattern compiledPattern = compiler.compile(pattern);
                boolean found;
                if ((CONTAINS & getTestType()) > 0)
                {
                    found = localMatcher.contains(responseString, compiledPattern);
                }
                else
                {
                    found = localMatcher.matches(responseString, compiledPattern);
                }
                pass = not ? !found : found;

                if (!pass)
                {
                    result.setFailure(true);
                    result.setFailureMessage(
                            "Test Failed, expected " + notMessage + failMessage + 
pattern);

                    break;
                }
            }
            if(pass)
            {
                result.setFailure(false);
            }
            result.setError(false);



Thanks for your help and suggestions!  This really was a serious problem, at least for 
me.  I'm guessing it hasn't been found before because most multi-threaded stress-tests 
don't use the response assertion mechanism.  

I'm using it with multiple threads to make sure the user data I entered is valid 
before I start doing stress tests.  Then I'll disable the response assertions for the 
real stress test, although if they are efficient enough I'd like to leave them on to 
let me know if the app starts flaking out under load.  Otherwise I could be getting 
errors and never knowing it (granted, I'd probably be better off just checking the 
server logs, however at least one problem I recently found didn't involve an exception 
situation).

Thanks again!  Let me know when this can be incorporated into a version or release.  
The nightly builds directory hasn't been updated since before Halloween.

Jonathan



**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.
**********************************************************************

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to