How to reference other files that are used in Azure Load Test (such as PDFs)

Labelle, Christopher 0 Reputation points
2024-01-18T19:27:57.4833333+00:00

I have a JMeter script that uses a pdf and converts it to a byte array to be used in a http request using the following code: vars.put("pdfBase64", new File("filename.pdf").bytes.encodeBase64().toString());

I have filename.pdf in the same directory as my jmx file and when I run the script locally in GUI mode, the file is found successfully. However, when I upload the script to Azure Load Test using the following in my config file:

version: v0.1
testId: 99fe0bdf-6fcb-4229-af1b-fca57de60d2e
displayName: testname
description: testname
testPlan: testname.jmx
testType: JMX
engineInstances: 1
configurationFiles:
- filename.pdf
splitAllCSVs: False
failureCriteria: []
autoStop:
  errorPercentage: 90
  timeWindow: 60

I get an error in the logs during runtime in the form of

javax.script.ScriptException: java.io.FileNotFoundException: filename.pdf (No such file or directory)
	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320) ~[groovy-jsr223-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:71) ~[groovy-jsr223-3.0.11.jar:3.0.11]
	at javax.script.CompiledScript.eval(CompiledScript.java:93) ~[java.scripting:?]
	at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:217) ~[ApacheJMeter_core.jar:5.5]
	at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:45) ~[ApacheJMeter_components.jar:5.5]
	at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:978) ~[ApacheJMeter_core.jar:5.5]
	at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:561) ~[ApacheJMeter_core.jar:5.5]
	at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.5]
	at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.5]
	at java.lang.Thread.run(Thread.java:840) ~[?:?]
Caused by: java.io.FileNotFoundException: filename.pdf (No such file or directory)
	at java.io.FileInputStream.open0(Native Method) ~[?:?]
	at java.io.FileInputStream.open(FileInputStream.java:216) ~[?:?]
	at java.io.FileInputStream.<init>(FileInputStream.java:157) ~[?:?]
	at org.codehaus.groovy.runtime.ResourceGroovyMethods.getBytes(ResourceGroovyMethods.java:670) ~[groovy-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.runtime.dgm$1065.doMethodInvoke(Unknown Source) ~[groovy-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.reflection.GeneratedMetaMethod$Proxy.doMethodInvoke(GeneratedMetaMethod.java:83) ~[groovy-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.runtime.metaclass.MethodMetaProperty$GetBeanMethodMetaProperty.getProperty(MethodMetaProperty.java:76) ~[groovy-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:63) ~[groovy-3.0.11.jar:3.0.11]
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:329) ~[groovy-3.0.11.jar:3.0.11]
	at Script1.run(Script1.groovy:1) ~[?:?]
	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317) ~[groovy-jsr223-3.0.11.jar:3.0.11]
	... 9 more

So my question is: why can't Azure Load Test locate the file that I've referenced in the config file. Is there a different directory structure setup under the hood of Azure Load Test that I'm not aware of? How do I go about resolving this issue?

Azure Load Testing
Azure Load Testing
An Azure service that enables developers and testers to generate insights on how to improve the performance, scalability, and capacity usage of their application
39 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Labelle, Christopher 0 Reputation points
    2024-03-01T20:20:29.07+00:00

    I've solved the issue.

    TL;DR: The solution is to store the necessary files as blobs in a storage account container in Azure, and access from there with a Shared Access Token/Signature.

    1. Create a storage account in Azure.
    2. Create a storage container in the newly created storage account.
      1. The storage container is where you can actually store all the files (as blobs) that are needed by your script.
      2. Note: It is advisable that the access tier for blobs stored in the container is set to 'Hot (Inferred)' so that the file is retrieved from the container as fast as possible.
    3. If, like me, you need the storage container's access level to be private, you'll need to create a shared access token/signature (SAS) to access the files, rather than just hitting the url for the container/file.
      1. Note: The SAS should be for the entire container, rather than for each individual file.
    4. SASs don't have an infinite lifespan, so, rather than manually creating new SASs and updating the reference in your script, it is advisable to automate a process that creates a new SAS every day at a certain time and store the value in a key vault.
      1. This can be accomplished with a function app.
      2. The function app should:
        1. Create new SAS (can be accomplished with Azure.Identity and Azure.Storage.Blobs NuGet packages).
        2. Delete current SAS secret value in KeyVault if exists.
        3. Purge SAS secret value in KeyVault if deleted.
        4. Set SAS secret value in KeyVault.
        5. For accessing KeyVault with code, you will need to use NuGet packages Azure.Identity and Azure.Security.KeyVault.Secrets. Use this link for more information.
    5. From there, you can give your Azure Load Test resource access to the key vault, and then use code in your script to access the key vault via the key vault secret URI.

    Here is an example on how to access key vault from JMeter code:

    Create a 'User Defined Variables' config element, and use ${_GetSecret(secretUri)} to retrieve the most current SAS value.