How to iterate over a list of files and send them as byte arrays?

Hi,

I am trying to find the better way to write a scenario where given a directory containing N files, I can read each one of them and send a post containing the file as a byte array body.

I have written this:

class ManyFilesSimulation extends Simulation {

val httpProtocol = httpConfig
.baseURL(“http://localhost:8090/myprogram/”)

val headers = Map(“Content-Type” → “application/xml”)

val scn = scenario(“Sending messages”)
.repeat(1) {
exec(http(“Posting message”)
.post("/")
.headers(headers)
.byteArrayBody(session => getByteArrayBody(session)))
}

setUp(scn.users(1).ramp(10).protocolConfig(httpProtocol))

val getByteArrayBody = (session: Session) => {
scala.io.Source.fromFile("/tmp/files/file001.xml").map(_.toByte).toArray
}
}

With that code, I can send 1 specified file “/tmp/files/file001.xml”.However, I would like to find a way to read the N files in the directory “files” and send the requests.

I’ve been trying to use feeders. Maybe read a csv containing all filenames, and use it to extract the bytes. But I am not sure about how to code it. Anybody can help?

Regards

What do you want exactly?
Every user sending all of them, of have the file list be a common pool?

I need the file list be in a common pool, so each user will pick one of them and do the request.

So yes, you can use a feeder.

As a Feeder is basically an Iterator[Map[String, Any]], you’re problem is basically to recursively list files.
If you’re not that used to Scala, why not go with commons-io FileUtils?

import scala.collection.JavaConversions._
val feeder = FileUtils.iterateFiles(directory, null, true).map(file => Map(“file” → file))

Nice suggestion. Now it’s working.

By the way, is there a way to use feeders (or other feature) to feed http headers dynamically?

Yes, you can use Gatling EL or pass functions to header method.

Ok. But will the headers be set for every iteration of feeder? I mean, suppose I have a scenario like that:

val scn = scenario(“Sending message”)
.group(“Group 1”) {
feed(feeder)
.exec(
http(“Posting message”)
.post("/")
.byteArrayBody(session => getByteArrayBody(session))
.headers(getHeaders(feeder))
)
}

And suppose feeder has size 10. Will getHeaders() be invoked 10 times or just one? In my execution, getHeaders()is executed only one time, but I would like to change the header values according to values in feeder iterator.

No, feeder is used to populate virtual users with new attributes.

Do you see a way to do this without using feeders?

The first thing is that you didn’t explain your use case.
What are you trying to achieve exactly (not talking about the how but the what)?

My load test scenario:

  • Each request will be a POST with body as a byte array. The content of the body will come from a file.
  • Each request has a custom header whose value comes from the same file used as body. The file is an XML, so a simple parse will be needed to extract the value that will be used in the header.
  • Each request in the simulation must use only one file, until the pool is empty.

Example:

Let’s suppose I have a directory “files” containing:

  • messageFile1.xml
  • messageFile2.xml
  • messageFileN.xml

Suppose the file content is something like:

1 ...

What I want to do is, for each file in the pool, send the content of the file in a POST with a header containing the value at . So, for each request I’ll need to change the body and the headers. Basically I am sending a message as a byte array, and informing the id of that message in the header.

OK, so if you have one single header and not multiple ones, yes, you could use the standard header method that you would populate with a feeder.

Ok. Thanks Stépahne. Now it’s working

Great!