generated script mishandles multi-valued request parameters
Distributed load testing framework - Java, Jython, or Clojure scripts.
Brought to you by:
philipa
My app has a form post with a multi-valued parameter The generated Clojure script erroneously uses the same value for all instances of the parameter. See for example the references to token_login2 in the script fragment below:
; Worker thread state is stored in a map using a dynamic var.
(def ^:dynamic *tokens*)
(defn set-token [k v] (set! *tokens* (assoc *tokens* k v)))
(defn token [k] (*tokens* k))
[...]
(defpage page4 "POST login (requests 401-408)." (Test. 400 "Page 4") []
(set-token :token_login2 "Login")
(set-token :token_login2 "")
(set-token :token__sourcePage "HQduFOCJZk6Fw7gPHLMv3_9ey7vdLQ8IuRf--7h2p03EenTfDNNtuw==")
(set-token :token___fp "RbQxcD5ZA1A=")
; Expecting 302 'Found'
(.POST request401 "/t/a/login"
(nvpairs [
"__session_id__" (token :token___session_id__)
"operator.password", "XXXXXXXX"
"login2" (token :token_login2)
"targetURL" (token :token_targetURL)
"operator.username" (token :token_operatorusername)
"login2" (token :token_login2)
"_sourcePage" (token :token__sourcePage)
"__fp" (token :token___fp)])
(nvpairs [
"Content-Type", "application/x-www-form-urlencoded"]))
(.sleep grinder 12)
In the above example, the body of the form post should contain two values for "login2": the string "Login" and the empty string "". Instead, both instances will be the empty string.
Observed using the Grinder 3.9 snapshot, Sun Java 1.6.0_26, and Firefox 11.
Philip Aston remarked to me that the generated Jython scripts may also have the same problem.
Diff:
This is tricky. The form is something like this:
So when parsing the response containing the form, The Grinder has to
do something special to give the second input a different token ID,
and also has to use the right values in the subsequent POST.
The Grinder currently maintains a simple map of the last value seen
for each particular token.
To handle this case, we need to extend the token map so that forms are
handled in a more sophisticated manner. We could proceed as follows.
When looking for hidden inputs, also find with their parent form
For each hidden inputs, hash
(form-action, name, count)into the token key, where count is number of hidden inputs before this one in the form.Add HTTPRecording.getHiddenFormTokens(name, formAction) that
returns a collection of tokens, if they exist. Use this in
ConnectionHandlerImplementation.end()
Adding the form action as key information allows us to distinguish
between cases such as:
Taken together, I think a solution that addresses both of these
problems is worth implementing.
Last edit: Philip Aston 2012-10-14