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/08 01:52:46 UTC

svn commit: r812306 - in /jakarta/jmeter/trunk: bin/ docs/images/screenshots/ docs/images/screenshots/assertion/ src/components/org/apache/jmeter/assertions/ src/components/org/apache/jmeter/visualizers/ src/core/org/apache/jmeter/assertions/ src/core/...

Author: sebb
Date: Mon Sep  7 23:52:46 2009
New Revision: 812306

URL: http://svn.apache.org/viewvc?rev=812306&view=rev
Log:
Added Comparison Assertion & Visualizer
[code copied from branches/java1.5_prototype-was_trunk]

Added:
    jakarta/jmeter/trunk/docs/images/screenshots/assertion/compare.png   (with props)
    jakarta/jmeter/trunk/docs/images/screenshots/comparison_assertion_visualizer.png   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java   (with props)
    jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java   (with props)
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java   (with props)
    jakarta/jmeter/trunk/xdocs/images/screenshots/assertion/compare.png   (with props)
    jakarta/jmeter/trunk/xdocs/images/screenshots/comparison_assertion_visualizer.png   (with props)
Modified:
    jakarta/jmeter/trunk/bin/saveservice.properties
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jakarta/jmeter/trunk/xdocs/changes.xml
    jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: jakarta/jmeter/trunk/bin/saveservice.properties
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/bin/saveservice.properties?rev=812306&r1=812305&r2=812306&view=diff
==============================================================================
--- jakarta/jmeter/trunk/bin/saveservice.properties (original)
+++ jakarta/jmeter/trunk/bin/saveservice.properties Mon Sep  7 23:52:46 2009
@@ -83,6 +83,8 @@
 BSFSamplerGui=org.apache.jmeter.protocol.java.control.gui.BSFSamplerGui
 CacheManager=org.apache.jmeter.protocol.http.control.CacheManager
 CacheManagerGui=org.apache.jmeter.protocol.http.gui.CacheManagerGui
+CompareAssertion=org.apache.jmeter.assertions.CompareAssertion
+ComparisonVisualizer=org.apache.jmeter.visualizers.ComparisonVisualizer
 ConfigTestElement=org.apache.jmeter.config.ConfigTestElement
 ConstantThroughputTimer=org.apache.jmeter.timers.ConstantThroughputTimer
 ConstantTimer=org.apache.jmeter.timers.ConstantTimer
@@ -221,6 +223,7 @@
 StatGraphVisualizer=org.apache.jmeter.visualizers.StatGraphVisualizer
 StatVisualizer=org.apache.jmeter.visualizers.StatVisualizer
 SubscriberSampler=org.apache.jmeter.protocol.jms.sampler.SubscriberSampler
+SubstitutionElement=org.apache.jmeter.assertions.SubstitutionElement
 Summariser=org.apache.jmeter.reporters.Summariser
 SummariserGui=org.apache.jmeter.reporters.gui.SummariserGui
 SummaryReport=org.apache.jmeter.visualizers.SummaryReport

Added: jakarta/jmeter/trunk/docs/images/screenshots/assertion/compare.png
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/images/screenshots/assertion/compare.png?rev=812306&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/trunk/docs/images/screenshots/assertion/compare.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: jakarta/jmeter/trunk/docs/images/screenshots/comparison_assertion_visualizer.png
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/images/screenshots/comparison_assertion_visualizer.png?rev=812306&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/trunk/docs/images/screenshots/comparison_assertion_visualizer.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.assertions;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.jmeter.engine.event.LoopIterationEvent;
+import org.apache.jmeter.engine.event.LoopIterationListener;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.testbeans.TestBean;
+import org.apache.jmeter.testelement.AbstractTestElement;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.oro.text.regex.StringSubstitution;
+import org.apache.oro.text.regex.Util;
+
+public class CompareAssertion extends AbstractTestElement implements Assertion, TestBean, Serializable,
+		LoopIterationListener {
+
+    private static final long serialVersionUID = 240L;
+    
+	private transient List<SampleResult> responses;
+
+	private transient final StringSubstitution emptySub = new StringSubstitution("");
+
+	private boolean compareContent = true;
+
+	private long compareTime = -1;
+
+	private Collection<SubstitutionElement> stringsToSkip;
+
+	public CompareAssertion() {
+		super();
+	}
+
+	public AssertionResult getResult(SampleResult response) {
+		responses.add(response);
+		if (responses.size() > 1) {
+			CompareAssertionResult result = new CompareAssertionResult(getName());
+			compareContent(result);
+			compareTime(result);
+			return result;
+		} else
+			return new AssertionResult(getName());
+	}
+
+	private void compareTime(CompareAssertionResult result) {
+		if (compareTime >= 0) {
+			Iterator<SampleResult> iter = responses.iterator();
+			long prevTime = -1;
+			SampleResult prevResult = null;
+			boolean success = true;
+			while (iter.hasNext()) {
+				SampleResult sResult = iter.next();
+				long currentTime = sResult.getTime();
+				if (prevTime != -1) {
+					success = Math.abs(prevTime - currentTime) <= compareTime;
+					prevResult = sResult;
+				}
+				if (!success) {
+					result.setFailure(true);
+                    StringBuffer buf = new StringBuffer();
+                    appendResultDetails(buf, prevResult);
+                    buf.append("Response Time: ").append(prevTime);
+					result.addToBaseResult(buf.toString());
+					buf = new StringBuffer();
+                    appendResultDetails(buf, sResult);
+					buf.append("Response Time: ").append(currentTime);
+					result.addToSecondaryResult(buf.toString());
+					result.setFailureMessage("Responses differ in response time by more than "+compareTime+" ms");
+					break;
+				}
+				prevResult = sResult;
+				prevTime = currentTime;
+			}
+		}
+	}
+
+    private void compareContent(CompareAssertionResult result) {
+		if (compareContent) {
+			Iterator<SampleResult> iter = responses.iterator();
+			String prevContent = null;
+			SampleResult prevResult = null;
+			boolean success = true;
+			while (iter.hasNext()) {
+				SampleResult sResult = iter.next();
+				String currentContent = sResult.getResponseDataAsString();
+				currentContent = filterString(currentContent);
+				if (prevContent != null) {
+					success = prevContent.equals(currentContent);
+				}
+				if (!success) {
+					result.setFailure(true);
+                    StringBuffer buf = new StringBuffer();
+                    appendResultDetails(buf, prevResult);
+					buf.append(prevContent);
+					result.addToBaseResult(buf.toString());
+					buf = new StringBuffer();
+					appendResultDetails(buf, sResult);
+					buf.append(currentContent);
+					result.addToSecondaryResult(buf.toString());
+					result.setFailureMessage("Responses differ in content");
+					break;
+				}
+				prevResult = sResult;
+				prevContent = currentContent;
+			}
+		}
+	}
+
+    private void appendResultDetails(StringBuffer buf, SampleResult result) {
+        final String samplerData = result.getSamplerData();
+        if (samplerData != null){
+            buf.append(samplerData.trim());
+        }
+        buf.append("\n");
+        final String requestHeaders = result.getRequestHeaders();
+        if (requestHeaders != null){
+            buf.append(requestHeaders);
+        }
+        buf.append("\n\n");        
+    }
+
+	private String filterString(String content) {
+		if (stringsToSkip == null || stringsToSkip.size() == 0) {
+			return content;
+		} else {
+			for (SubstitutionElement regex : stringsToSkip) {
+				emptySub.setSubstitution(regex.getSubstitute());
+				content = Util.substitute(JMeterUtils.getMatcher(), JMeterUtils.getPatternCache().getPattern(regex.getRegex()),
+						emptySub, content, Util.SUBSTITUTE_ALL);
+			}
+		}
+		return content;
+	}
+
+	public void iterationStart(LoopIterationEvent iterEvent) {
+		responses = new LinkedList<SampleResult>();
+	}
+
+	public void iterationEnd(LoopIterationEvent iterEvent) {
+		responses = null;
+	}
+
+	/**
+	 * @return Returns the compareContent.
+	 */
+	public boolean isCompareContent() {
+		return compareContent;
+	}
+
+	/**
+	 * @param compareContent
+	 *            The compareContent to set.
+	 */
+	public void setCompareContent(boolean compareContent) {
+		this.compareContent = compareContent;
+	}
+
+	/**
+	 * @return Returns the compareTime.
+	 */
+	public long getCompareTime() {
+		return compareTime;
+	}
+
+	/**
+	 * @param compareTime
+	 *            The compareTime to set.
+	 */
+	public void setCompareTime(long compareTime) {
+		this.compareTime = compareTime;
+	}
+
+	/**
+	 * @return Returns the stringsToSkip.
+	 */
+	public Collection<SubstitutionElement> getStringsToSkip() {
+		return stringsToSkip;
+	}
+
+	/**
+	 * @param stringsToSkip
+	 *            The stringsToSkip to set.
+	 */
+	public void setStringsToSkip(Collection<SubstitutionElement> stringsToSkip) {
+		this.stringsToSkip = stringsToSkip;
+	}
+
+}

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertion.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.assertions;
+
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+
+import org.apache.jmeter.testbeans.BeanInfoSupport;
+import org.apache.jmeter.testbeans.gui.TableEditor;
+
+public class CompareAssertionBeanInfo extends BeanInfoSupport {
+
+	public CompareAssertionBeanInfo() {
+		super(CompareAssertion.class);
+		createPropertyGroup("compareChoices", new String[] { "compareContent", "compareTime" });
+		createPropertyGroup("comparison_filters", new String[]{"stringsToSkip"});
+		PropertyDescriptor p = property("compareContent");
+		p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+		p.setValue(DEFAULT, Boolean.TRUE);
+		p.setValue(NOT_EXPRESSION, Boolean.TRUE);
+		p = property("compareTime");
+		p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+		p.setValue(DEFAULT, new Long(-1));
+		p.setValue(NOT_EXPRESSION, Boolean.FALSE);	
+		p = property("stringsToSkip");
+		p.setPropertyEditorClass(TableEditor.class);
+		p.setValue(TableEditor.CLASSNAME,SubstitutionElement.class.getName());
+		p.setValue(TableEditor.HEADERS,new String[]{"Regex String","Substitution"}); // TODO I18n
+		p.setValue(TableEditor.OBJECT_PROPERTIES, // These are the names of the get/set methods
+		        new String[]{SubstitutionElement.REGEX, SubstitutionElement.SUBSTITUTE});
+		p.setValue(NOT_UNDEFINED,Boolean.TRUE);
+		p.setValue(DEFAULT,new ArrayList<Object>());
+		p.setValue(MULTILINE,Boolean.TRUE);
+		
+	}
+
+}

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionBeanInfo.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties Mon Sep  7 23:52:46 2009
@@ -0,0 +1,24 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You under the Apache License, Version 2.0
+#   (the "License"); you may not use this file except in compliance with
+#   the License.  You may obtain a copy of the License at
+# 
+#       http://www.apache.org/licenses/LICENSE-2.0
+# 
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+displayName=Compare Assertion
+compareChoices.displayName=Select Comparison Operators
+compareContent.displayName=Compare Content
+compareContent.shortDescription=Verify that all Samplers within the Controller return the same data
+compareTime.displayName=Compare Time
+compareTime.shortDescription=Verify that all Samplers' return times are within a given number of milliseconds
+comparison_filters.displayName=Comparison Filters
+stringsToSkip.displayName=Regular Expression Substitutions
+stringsToSkip.shortDescription=Regular expressions to match elements of response data to be substituted when comparing

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/CompareAssertionResources.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,39 @@
+package org.apache.jmeter.assertions;
+
+import org.apache.jmeter.testelement.AbstractTestElement;
+
+public class SubstitutionElement extends AbstractTestElement {
+	private static final long serialVersionUID = 1;
+	
+	// These constants are used both for the JMX file and for the setters/getters
+	public static final String REGEX = "regex"; // $NON-NLS-1$
+	
+	public static final String SUBSTITUTE = "substitute"; // $NON-NLS-1$
+
+	public SubstitutionElement() {
+		super();
+	}
+	
+	public String getRegex()
+	{
+		return getProperty(REGEX).getStringValue();
+	}
+	
+	public void setRegex(String regex)
+	{
+		setProperty(REGEX,regex);
+	}
+	
+	public String getSubstitute()
+	{
+		return getProperty(SUBSTITUTE).getStringValue();
+	}
+	
+	public void setSubstitute(String sub)
+	{
+		setProperty(SUBSTITUTE,sub);
+	}
+	
+	
+
+}

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/assertions/SubstitutionElement.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.visualizers;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import org.apache.jmeter.assertions.AssertionResult;
+import org.apache.jmeter.assertions.CompareAssertionResult;
+import org.apache.jmeter.samplers.Clearable;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
+
+public class ComparisonVisualizer extends AbstractVisualizer implements Clearable {
+	private JTree resultsTree;
+
+	private DefaultTreeModel treeModel;
+
+	private DefaultMutableTreeNode root;
+
+	private JTextPane base, secondary;
+
+	public ComparisonVisualizer() {
+		super();
+		init();
+	}
+
+	public void add(SampleResult sample) {
+
+		DefaultMutableTreeNode currNode = new DefaultMutableTreeNode(sample);
+		treeModel.insertNodeInto(currNode, root, root.getChildCount());
+		if (root.getChildCount() == 1) {
+			resultsTree.expandPath(new TreePath(root));
+		}
+	}
+
+	public String getLabelResource() {
+		return "comparison_visualizer_title";
+	}
+
+	private void init() {
+		setLayout(new BorderLayout());
+		setBorder(makeBorder());
+		add(makeTitlePanel(), BorderLayout.NORTH);
+		JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+		split.add(getTreePanel());
+		split.add(getSideBySidePanel());
+		add(split, BorderLayout.CENTER);
+	}
+
+	private JComponent getSideBySidePanel() {
+		JPanel main = new JPanel(new GridLayout(1, 2));
+		JScrollPane base = new JScrollPane(getBaseTextPane());
+		base.setPreferredSize(base.getMinimumSize());
+		JScrollPane secondary = new JScrollPane(getSecondaryTextPane());
+		secondary.setPreferredSize(secondary.getMinimumSize());
+		main.add(base);
+		main.add(secondary);
+		main.setPreferredSize(main.getMinimumSize());
+		return main;
+	}
+
+	private JTextPane getBaseTextPane() {
+		base = new JTextPane();
+		return base;
+	}
+
+	private JTextPane getSecondaryTextPane() {
+		secondary = new JTextPane();
+		return secondary;
+	}
+
+	private JComponent getTreePanel() {
+		root = new DefaultMutableTreeNode("Root");
+		treeModel = new DefaultTreeModel(root);
+		resultsTree = new JTree(treeModel);
+		resultsTree.setCellRenderer(new TreeNodeRenderer());
+		resultsTree.setCellRenderer(new TreeNodeRenderer());
+		resultsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		resultsTree.addTreeSelectionListener(new Selector());
+		resultsTree.setRootVisible(false);
+		resultsTree.setShowsRootHandles(true);
+
+		JScrollPane treePane = new JScrollPane(resultsTree);
+		treePane.setPreferredSize(new Dimension(150, 50));
+		JPanel panel = new JPanel(new GridLayout(1, 1));
+		panel.add(treePane);
+		return panel;
+	}
+
+	private class Selector implements TreeSelectionListener {
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
+		 */
+		public void valueChanged(TreeSelectionEvent e) {
+			try {
+				DefaultMutableTreeNode node = (DefaultMutableTreeNode) resultsTree.getLastSelectedPathComponent();
+				SampleResult sr = (SampleResult) node.getUserObject();
+				AssertionResult[] results = sr.getAssertionResults();
+				CompareAssertionResult result = null;
+				for (AssertionResult r : results) {
+					if (r instanceof CompareAssertionResult) {
+						result = (CompareAssertionResult) r;
+						break;
+					}
+				}
+				if (result == null)
+					result = new CompareAssertionResult();
+				base.setText(result.getBaseResult());
+				secondary.setText(result.getSecondaryResult());
+			} catch (Exception err) {
+				base.setText("Invalid Node " + err);
+				secondary.setText("Invalid Node " + err);
+			}
+			base.setCaretPosition(0);
+			secondary.setCaretPosition(0);
+		}
+
+	}
+
+	public void clearData() {
+		while (root.getChildCount() > 0) {
+			// the child to be removed will always be 0 'cos as the nodes are
+			// removed the nth node will become (n-1)th
+			treeModel.removeNodeFromParent((DefaultMutableTreeNode) root.getChildAt(0));
+			base.setText("");
+			secondary.setText("");
+		}
+	}
+
+}

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/ComparisonVisualizer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java (added)
+++ jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.visualizers;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.apache.jmeter.samplers.SampleResult;
+
+/**
+ * Tree cell renderer used by ComparisonVisualizer.
+ */
+public class TreeNodeRenderer extends DefaultTreeCellRenderer {
+
+	public TreeNodeRenderer() {
+		super();
+	}
+	
+	@Override
+    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
+			boolean leaf, int row, boolean focus) {
+		super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, focus);
+		Object obj = ((DefaultMutableTreeNode) value).getUserObject();
+		if(obj instanceof SampleResult)
+		{
+			if (!((SampleResult) obj).isSuccessful()) {
+				this.setForeground(Color.red);
+			}
+		}
+		return this;
+	}
+
+}

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/components/org/apache/jmeter/visualizers/TreeNodeRenderer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java?rev=812306&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java (added)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java Mon Sep  7 23:52:46 2009
@@ -0,0 +1,76 @@
+package org.apache.jmeter.assertions;
+
+
+public class CompareAssertionResult extends AssertionResult {
+	private static final long serialVersionUID = 1;
+	
+	private transient final ResultHolder comparedResults = new ResultHolder();
+
+	/**
+	 * For testing only
+	 * @deprecated Use the other ctor
+	 */
+	@Deprecated
+    public CompareAssertionResult() { // needs to be public for testing
+		super();
+	}
+
+	public CompareAssertionResult(String name) {
+		super(name);
+	}
+	
+	public void addToBaseResult(String resultData)
+	{
+		comparedResults.addToBaseResult(resultData);
+	}
+	
+	public void addToSecondaryResult(String resultData)
+	{
+		comparedResults.addToSecondaryResult(resultData);
+	}
+	
+	public String getBaseResult()
+	{
+		return comparedResults.baseResult;
+	}
+	
+	public String getSecondaryResult()
+	{
+		return comparedResults.secondaryResult;
+	}
+
+	private static class ResultHolder
+	{
+		private String baseResult;
+		private String secondaryResult;
+		
+		public ResultHolder()
+		{
+			
+		}
+		
+		public void addToBaseResult(String r)
+		{
+			if(baseResult == null)
+			{
+				baseResult = r;
+			}
+			else
+			{
+				baseResult = baseResult + "\n\n" + r;
+			}
+		}
+		
+		public void addToSecondaryResult(String r)
+		{
+			if(secondaryResult == null)
+			{
+				secondaryResult = r;
+			}
+			else
+			{
+				secondaryResult = secondaryResult + "\n\n" + r;
+			}
+		}
+	}
+}

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/assertions/CompareAssertionResult.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=812306&r1=812305&r2=812306&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Mon Sep  7 23:52:46 2009
@@ -127,6 +127,7 @@
 column_number=Column number of CSV file | next | *alias
 compare=Compare
 comparefilt=Compare filter
+comparison_visualizer_title=Comparison Assertion Visualizer
 config_element=Config Element
 config_save_settings=Configure
 configure_wsdl=Configure
@@ -490,6 +491,7 @@
 menu_post_processors=Post Processors
 menu_pre_processors=Pre Processors
 menu_response_based_modifiers=Response Based Modifiers
+menu_tables=Table
 menu_timer=Timer
 metadata=MetaData
 method=Method\:

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=812306&r1=812305&r2=812306&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Mon Sep  7 23:52:46 2009
@@ -124,11 +124,13 @@
 <ul>
 <li>Bug 47398 - SampleEvents are sent twice over RMI in distributed testing and non gui mode</li>
 <li>Added DataStrippingSample sender - supports "Stripped" and "StrippedBatch" modes.</li>
+<li>Added Comparison Assertion Visualizer</li>
 </ul>
 
 <h3>Assertions, Config, Pre- &amp; Post-Processors</h3>
 <ul>
 <li>Bug 47338 - XPath Extractor forces retrieval of document DTD</li>
+<li>Added Comparison Assertion</li>
 </ul>
 
 <h3>Functions</h3>

Added: jakarta/jmeter/trunk/xdocs/images/screenshots/assertion/compare.png
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/images/screenshots/assertion/compare.png?rev=812306&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/trunk/xdocs/images/screenshots/assertion/compare.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: jakarta/jmeter/trunk/xdocs/images/screenshots/comparison_assertion_visualizer.png
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/images/screenshots/comparison_assertion_visualizer.png?rev=812306&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/trunk/xdocs/images/screenshots/comparison_assertion_visualizer.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=812306&r1=812305&r2=812306&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Mon Sep  7 23:52:46 2009
@@ -2456,6 +2456,16 @@
  </properties>
 </component>
 
+<component name="Comparison Assertion Visualizer" index="&sect-num;.3.19"  width="777" height="266" screenshot="comparison_assertion_visualizer.png">
+<description>
+The Comparison Assertion Visualizer shows the results of any <complink name="Compare Assertion"/> elements.
+</description>
+ <properties>
+ <property name="Name" required="Yes">Descriptive name for this element that is shown in the tree.
+ </property>
+ </properties>
+</component>
+
 <a href="#">^</a>
 
 </section>
@@ -3394,6 +3404,23 @@
 <p>For futher details of all the methods available on each of the above variables, please check the Javadoc</p>
 </component>
 
+<component name="Compare Assertion" index="&sect-num;.5.11"  width="292" height="296" screenshot="assertion/compare.png">
+<description>
+The Compare Assertion can be used to compare sample results within its scope.
+Either the contents or the elapsed time can be compared, and the contents can be filtered before comparison.
+The assertion comparisons can be seen in the <complink name="Comparison Assertion Visualizer"/>.
+</description>
+<properties>
+    <property name="Name" required="No">Descriptive name for this element that is shown in the tree.</property>
+    <property name="Compare Content" required="Yes">Whether or not to compare the content (response data)</property>
+    <property name="Compare Time" required="Yes">If the value is >=0, then check if the time difference is no greater than the value. 
+    I.e. if the value is 0, then the times must be exactly equal.</property>
+    <property name="Comparison Filters" required="No">Filters can be used to remove strings from the content comparison.
+    For example, if the page has a time-stamp, it might be matched with: "Time: \d\d:\d\d:\d\d" and replaced with a dummy fixed time "Time: HH:MM:SS".
+    </property>
+</properties>
+</component>
+
 <a href="#">^</a>
 
 </section>



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