You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@jakarta.apache.org by se...@apache.org on 2010/07/08 01:53:11 UTC

svn commit: r961539 - in /jakarta/jmeter/trunk: src/core/org/apache/jmeter/samplers/SampleResult.java src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java xdocs/changes.xml xdocs/usermanual/component_reference.xml

Author: sebb
Date: Wed Jul  7 23:53:10 2010
New Revision: 961539

URL: http://svn.apache.org/viewvc?rev=961539&view=rev
Log:
Bug 49560 - wrong "size in bytes" when following redirections

Modified:
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
    jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
    jakarta/jmeter/trunk/xdocs/changes.xml
    jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java?rev=961539&r1=961538&r2=961539&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java Wed Jul  7 23:53:10 2010
@@ -116,9 +116,11 @@ public class SampleResult implements Ser
 
     private String label = "";// Never return null
 
-    private String resultFileName = ""; // Filename used by ResultSaver
+    /** Filename used by ResultSaver */
+    private String resultFileName = "";
 
-    private String samplerData; // The data used by the sampler
+    /** The data used by the sampler */
+    private String samplerData;
 
     private String threadName = ""; // Never return null
 
@@ -131,7 +133,8 @@ public class SampleResult implements Ser
     private String requestHeaders = "";
 
     // TODO timeStamp == 0 means either not yet initialised or no stamp available (e.g. when loading a results file)
-    private long timeStamp = 0;// the time stamp - can be start or end
+    /** the time stamp - can be start or end */
+    private long timeStamp = 0;
 
     private long startTime = 0;
 
@@ -139,7 +142,8 @@ public class SampleResult implements Ser
 
     private long idleTime = 0;// Allow for non-sample time
 
-    private long pauseTime = 0;// Start of pause (if any)
+    /** Start of pause (if any) */
+    private long pauseTime = 0;
 
     private List<AssertionResult> assertionResults;
 
@@ -150,7 +154,8 @@ public class SampleResult implements Ser
     private boolean success;
 
     //@GuardedBy("this"")
-    private final Set<String> files = new HashSet<String>(); // files that this sample has been saved in
+    /** files that this sample has been saved in */
+    private final Set<String> files = new HashSet<String>();
 
     private String dataEncoding;// (is this really the character set?) e.g.
                                 // ISO-8895-1, UTF-8
@@ -161,16 +166,22 @@ public class SampleResult implements Ser
     // a reference time from the millisecond clock
     private static final long referenceTimeMsClock = System.currentTimeMillis();
 
-    private long time = 0; // elapsed time
+    /** elapsed time */
+    private long time = 0;
 
-    private long latency = 0; // time to first response
+    /** time to first response */
+    private long latency = 0;
 
-    private boolean stopThread = false; // Should thread terminate?
+    /** Should thread terminate? */
+    private boolean stopThread = false;
 
-    private boolean stopTest = false; // Should test terminate?
+    /** Should test terminate? */
+    private boolean stopTest = false;
 
-    private boolean stopTestNow = false; // Should test terminate abruptly?
+    /** Should test terminate abruptly? */
+    private boolean stopTestNow = false;
 
+    /** Is the sampler acting as a monitor? */
     private boolean isMonitor = false;
 
     private int sampleCount = 1;
@@ -202,37 +213,45 @@ public class SampleResult implements Ser
     }
 
     /**
-     * Construct a 'parent' result for an already-existing result, essentially
-     * cloning it
-     *
-     * @param res
-     *            existing sample result
+     * Copy constructor.
+     * 
+     * @param res existing sample result
      */
     public SampleResult(SampleResult res) {
-        //TODO - why not just copy all the fields? Do we need the calculations that some of the set() methods perform?
-        //TODO - why are the following not copied:
-        // assertionResults, bytes, idleTime, latency, parent,pauseTime,resultFileName,sampleCount,samplerData,saveConfig
-        // stopTest, stopThread, subResults,threadName
-        setStartTime(res.getStartTime());
-        setEndTime(res.getStartTime());
-        // was setElapsed(0) which is the same as setStartTime=setEndTime=now
-
-        setSampleLabel(res.getSampleLabel());
-        setRequestHeaders(res.getRequestHeaders());
-        setResponseData(res.getResponseData());
-        setResponseCode(res.getResponseCode());
-        setSuccessful(res.isSuccessful());
-        setResponseMessage(res.getResponseMessage());
-        setDataType(res.getDataType());
-        setResponseHeaders(res.getResponseHeaders());
-        setContentType(res.getContentType());
-        setDataEncoding(res.getDataEncodingNoDefault());
-        setURL(res.getURL());
-
-        setGroupThreads(res.getGroupThreads());
-        setAllThreads(res.getAllThreads());
-
-        addSubResult(res); // this will add res.getTime() to getTime().
+        allThreads = res.allThreads;//OK
+        assertionResults = res.assertionResults;// TODO ??
+        bytes = res.bytes;
+        contentType = res.contentType;//OK
+        dataEncoding = res.dataEncoding;//OK
+        dataType = res.dataType;//OK
+        endTime = res.endTime;//OK
+        // files is created automatically, and applies per instance
+        groupThreads = res.groupThreads;//OK
+        idleTime = res.idleTime;
+        isMonitor = res.isMonitor;
+        label = res.label;//OK
+        latency = res.latency;
+        location = res.location;//OK
+        parent = res.parent; // TODO ??
+        pauseTime = res.pauseTime;
+        requestHeaders = res.requestHeaders;//OK
+        responseCode = res.responseCode;//OK
+        responseData = res.responseData;//OK
+        responseHeaders = res.responseHeaders;//OK
+        responseMessage = res.responseMessage;//OK
+        // Don't copy this; it is per instance resultFileName = res.resultFileName;
+        sampleCount = res.sampleCount;
+        samplerData = res.samplerData;
+        saveConfig = res.saveConfig;
+        startTime = res.startTime;//OK
+        stopTest = res.stopTest;
+        stopTestNow = res.stopTestNow;
+        stopThread = res.stopThread;
+        subResults = res.subResults; // TODO ??
+        success = res.success;//OK
+        threadName = res.threadName;//OK
+        time = res.time;
+        timeStamp = res.timeStamp;
     }
 
     public boolean isStampedAtStart() {
@@ -460,21 +479,36 @@ public class SampleResult implements Ser
         return assertionResults.toArray(new AssertionResult[0]);
     }
 
+    /**
+     * Add a subresult and adjust the parent byte count and end-time.
+     * 
+     * @param subResult
+     */
     public void addSubResult(SampleResult subResult) {
         String tn = getThreadName();
         if (tn.length()==0) {
             tn=Thread.currentThread().getName();//TODO do this more efficiently
             this.setThreadName(tn);
         }
-        subResult.setThreadName(tn);
-        if (subResults == null) {
-            subResults = new ArrayList<SampleResult>();
-        }
-        subResults.add(subResult);
+        subResult.setThreadName(tn); // TODO is this really necessary?
+
         // Extend the time to the end of the added sample
         setEndTime(Math.max(getEndTime(), subResult.getEndTime()));
         // Include the byte count for the added sample
         setBytes(getBytes() + subResult.getBytes());
+        addRawSubResult(subResult);
+    }
+    
+    /**
+     * Add a subresult to the collection without updating any parent fields.
+     * 
+     * @param subResult
+     */
+    public void addRawSubResult(SampleResult subResult){
+        if (subResults == null) {
+            subResults = new ArrayList<SampleResult>();
+        }
+        subResults.add(subResult);
         subResult.setParent(this);
     }
 

Modified: jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?rev=961539&r1=961538&r2=961539&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java (original)
+++ jakarta/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java Wed Jul  7 23:53:10 2010
@@ -1038,22 +1038,15 @@ public abstract class HTTPSamplerBase ex
 
     /**
      * Download the resources of an HTML page.
-     * <p>
-     * If createContainerResult is true, the returned result will contain one
-     * subsample for each request issued, including the original one that was
-     * passed in. It will otherwise look exactly like that original one.
-     * <p>
-     * If createContainerResult is false, one subsample will be added to the
-     * provided result for each requests issued.
-     *
+     * 
      * @param res
      *            result of the initial request - must contain an HTML response
      * @param container
-     *            for storing the results
+     *            for storing the results, if any
      * @param frameDepth
      *            Depth of this target in the frame structure. Used only to
      *            prevent infinite recursion.
-     * @return "Container" result with one subsample per request issued
+     * @return res if no resources exist, otherwise the "Container" result with one subsample per request issued
      */
     protected HTTPSampleResult downloadPageResources(HTTPSampleResult res, HTTPSampleResult container, int frameDepth) {
         Iterator<URL> urls = null;
@@ -1079,11 +1072,7 @@ public abstract class HTTPSamplerBase ex
 
         // Iterate through the URLs and download each image:
         if (urls != null && urls.hasNext()) {
-            if (container == null) {
-                res = new HTTPSampleResult(res);
-            } else {
-                res = container;
-            }
+            res = container;
 
             // Get the URL matcher
             String re=getEmbeddedUrlRE();
@@ -1098,7 +1087,7 @@ public abstract class HTTPSamplerBase ex
                 }
             }
             while (urls.hasNext()) {
-                Object binURL = urls.next();
+                Object binURL = urls.next(); // See catch clause below
                 try {
                     URL url = (URL) binURL;
                     if (url == null) {
@@ -1123,7 +1112,7 @@ public abstract class HTTPSamplerBase ex
                         res.addSubResult(binRes);
                         res.setSuccessful(res.isSuccessful() && binRes.isSuccessful());
                     }
-                } catch (ClassCastException e) {
+                } catch (ClassCastException e) { // TODO can this happen?
                     res.addSubResult(errorResult(new Exception(binURL + " is not a correct URI"), res));
                     res.setSuccessful(false);
                     continue;
@@ -1219,6 +1208,7 @@ public abstract class HTTPSamplerBase ex
      */
     protected HTTPSampleResult followRedirects(HTTPSampleResult res, int frameDepth) {
         HTTPSampleResult totalRes = new HTTPSampleResult(res);
+        totalRes.addRawSubResult(res);
         HTTPSampleResult lastRes = res;
 
         int redirect;

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=961539&r1=961538&r2=961539&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Wed Jul  7 23:53:10 2010
@@ -79,6 +79,11 @@ JMSConfigGui has been renamed as JMSSamp
 This does not affect existing test plans.
 </p>
 
+<p>
+The constructor public SampleResult(SampleResult res) has been changed to become a true "copy constructor".
+It no longer calls addSubResult(). This may possibly affect some 3rd party add-ons.
+</p>
+
 <h2>Bug fixes</h2>
 
 <h3>HTTP Samplers and Proxy</h3>
@@ -92,6 +97,7 @@ This does not affect existing test plans
 <li>Bug 46901 - HTTP Sampler does not process var/func refs correctly in first file parameter</li>
 <li>Bug 43678 - Handle META tag http-equiv charset?</li>
 <li>Bug 49294 - Images not downloaded from redirected-to pages</li>
+<li>Bug 49560 - wrong "size in bytes" when following redirections</li>
 </ul>
 
 <h3>Other Samplers</h3>

Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=961539&r1=961538&r2=961539&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Wed Jul  7 23:53:10 2010
@@ -193,13 +193,16 @@ https.default.protocol=SSLv3
 		<property name="Follow Redirects" required="Yes">
 		This only has any effect if "Redirect Automatically" is not enabled.
 		If set, the JMeter sampler will check if the response is a redirect and follow it if so.
-		The redirect response will appear as an additional sample.
+		The initial redirect and further responses will appear as additional samples.
+        The URL and data fields of the parent sample will be taken from the final (non-redirected)
+        sample, but the parent byte count and elapsed time include all samples.
+        The latency is taken from the initial response (versions of JMeter after 2.3.4 - previously it was zero).
 		Note that the HttpClient sampler may log the following message:<br/>
 		"Redirect requested but followRedirects is disabled"<br/>
 		This can be ignored.
         <br/>
         In versions after 2.3.4, JMeter will collapse paths of the form '/../segment' in
-        both absolute and relative URLs. For example http://host/one/../two => http://host/two.
+        both absolute and relative redirect URLs. For example http://host/one/../two => http://host/two.
         If necessary, this behaviour can be suppressed by setting the JMeter property
         <code>httpsampler.redirect.removeslashdotdot=false</code>
 		</property>
@@ -315,7 +318,7 @@ JMeter 2.1.2 introduces the a new proper
  If the HTTPResponse.parser property is not set, JMeter reverts to the previous behaviour,
  i.e. only text/html responses will be scanned</p>
 <b>Emulating slow connections (HttpClient only):</b><br></br>
-The HttpClient version of the sampler supports emulation of slow connections; see the following entries in jmeter.proerties:
+The HttpClient version of the sampler supports emulation of slow connections; see the following entries in jmeter.properties:
 <pre>
 # Define characters per second > 0 to emulate slow connections
 #httpclient.socket.http.cps=0



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