Here is a much cleaner (IMHO) fix for the Assertion Results threading problem. Could someone else try this out and see how it works for them? It works fine for me in both GUI and non-GUI mode.
This fix also avoids the problem that Scott found with the previous fix when running in non-GUI mode. I'm sorry I didn't catch that before you all did, but I didn't even know that there was a non-GUI mode until recently. The below fix assumes a "clean" (without my previous fixes) 1.8 version of ResponseAssertion.java. 1) The compilerMatcher static field replaces the current compiler and matcher static fields. 2) The #evaluateResponse method is a replacement for the existing one. 3) The CompilerMatcher static member class is new. One note about this: The benefit of the caching of the compiled patterns here is not proven, only assumed. Some people, including myself, don't like to add complexity without demonstrating a need for it. In this case, I really need to move onto other work that will provide benefit to my company and the added complexity was quite minimal given the perceived benefit. If someone else feels it is important to demonstrate that looking up a cached compiled pattern truly is cheaper than recompiling the pattern each time, I would be happy if they would do that. Otherwise, I don't think the added complexity is enough to warrant it at this point. Cheers, Jonathan P.S. I'll be on vacation until Friday 2002-01-03. I'll be interested to hear about other people's success or unsuccess with this patch at that time. (I'm expecting only success :-) private transient static ThreadLocal compilerMatcher = new ThreadLocal() { protected Object initialValue() { return new CompilerMatcher(); } }; /** * Make sure the response satisfies the specified assertion requirements. * @param response an instance of SampleResult * @return an instance of AssertionResult */ private AssertionResult evaluateResponse(SampleResult response) { boolean pass = true; boolean not = (NOT & getTestType()) > 0; AssertionResult result = new AssertionResult(); try { String responseString = new String(response.getResponseData()); // Get the CompilerMatcher for this thread CompilerMatcher localCompilerMatcher = (CompilerMatcher) this.compilerMatcher.get(); Iterator iter = getTestStrings().iterator(); while (iter.hasNext()) { String stringPattern = (String) iter.next(); boolean found; if ((CONTAINS & getTestType()) > 0) { found = localCompilerMatcher .contains(responseString, stringPattern); } else { found = localCompilerMatcher .matches(responseString, stringPattern); } pass = not ? !found : found; if (!pass) { result.setFailure(true); result.setFailureMessage( "Test Failed, expected " + notMessage + failMessage + stringPattern); break; } } if(pass) { result.setFailure(false); } result.setError(false); } catch(MalformedPatternException e) { result.setError(true); result.setFailure(false); result.setFailureMessage("Bad test configuration"+e); } return result; } /** * Performs regular expression matching and compiled regular expression * pattern caching. * * This static member class is *not* thread-safe so it must be * accessed from a java.lang.ThreadLocal instance for multi-thread usage. * ThreadLocal causes slightly extra memory usage, but allows for faster * thread-safe processing than synchronization would afford. */ public static class CompilerMatcher { private Perl5Compiler compiler = new Perl5Compiler(); private Perl5Matcher matcher = new Perl5Matcher(); private Map compiledPatterns = new HashMap(); /** * Returns true if the compiled version of the patternString regular * expression argument matches the aString argument. */ public boolean matches(String aString, String patternString) throws MalformedPatternException { return this.matcher.matches(aString, this.getTestPattern(patternString)); } /** * Returns true if the compiled version of the patternString regular * expression argument is contained in the aString argument. */ public boolean contains(String aString, String patternString) throws MalformedPatternException { return this.matcher.contains(aString, this.getTestPattern(patternString)); } /** * Compiles and caches a regexp pattern for the given string pattern. * This would be of no benefit (and may bloat memory usage) if the * string pattern arg is never the same. But for this usage that * won't be the case. */ private Pattern getTestPattern(String stringPattern) throws MalformedPatternException { Pattern pattern = (Pattern) compiledPatterns.get(stringPattern); if (pattern == null) { pattern = compiler.compile(stringPattern); compiledPatterns.put(stringPattern, pattern); log.debug("Compiled and cached a pattern: '" + stringPattern + "' - " + Thread.currentThread()); } return pattern; } } ********************************************************************** 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]>