Jmeter - using url encode and groovy functions together - groovy

I have a groovy function
${__groovy(import groovy.time.TimeCategory; def now = new Date(); use(TimeCategory) { def nowPlusOneYear = now + 12.month - 1.day; return nowPlusOneYear.format('dd/MM/YYYY')},)}
This function returns a value. The value needs to be encoded. Tried using
${__urlencode(${__groovy(import groovy.time.TimeCategory; def now = new Date(); use(TimeCategory) { def nowPlusOneYear = now + 12.month - 1.day; return nowPlusOneYear.format('dd/MM/YYYY')},)}
But this is not the right way. Could someone help me with an appropriate solution.
Regards,
Ajith

The easiest option is just performing the URL encoding directly in Groovy via URLEncoder class:
${__groovy(import groovy.time.TimeCategory; def now = new Date(); use(TimeCategory) { def nowPlusOneYear = now + 12.month - 1.day; return URLEncoder.encode(nowPlusOneYear.format('dd/MM/YYYY')\, 'UTF-8')},)}
Alternatively you can store the result into a JMeter Variable
${__groovy(import groovy.time.TimeCategory; def now = new Date(); use(TimeCategory) { def nowPlusOneYear = now + 12.month - 1.day; return nowPlusOneYear.format('dd/MM/YYYY')},myDate)}
and then call the urlencode() function on that variable:
${__urlencode(${myDate})}
More information: Apache Groovy - Why and How You Should Use It

Related

groovy - replace values in json when loading from jmx

I have a piece a code as below. This is loading data from JMX to monitoring tool. Unfortunately, there are some 'NaN' values, which are not read properly by monitoring tool, and this interrupts transfer. My intention is to replace 'on fly' values 'NaN' to 'null'.
Has anybody any idea how to do it?
BR
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.security.PrivilegedAction;
def hostName = hostProps.get("system.hostname")
def jmxPort = "10002"
def query = "Hadoop:service=hiveserver2,name=hiveserver2"
def metricsURL = "http://${hostName}:${jmxPort}/jmx?qry=${query}"
def ad = true
public class FetchMetrics implements PrivilegedAction {
def url;
public FetchMetrics(String url) {
this.url = url;
}
public Object run() {
URL urlObject = new URL(url);
def con = (HttpURLConnection) urlObject.openConnection();
return con.getInputStream();
}
}
lc = new LoginContext("Client");
lc.login();
Subject subject = lc.getSubject();
PrivilegedAction action = new FetchMetrics(metricsURL);
def metrics = Subject.doAsPrivileged(subject, action, null);
def jsonSlurper = new JsonSlurper()
def deviceMetrics = jsonSlurper.parse(metrics)
// Hit out endpoint and get our metrics
//deviceMetrics = jsonSlurper.parse(new URL(metricsURL))
deviceMetrics.'beans'[0].each {
println it
}
return 0
simplest way to use LAX json slurper, however it will parse NaN as a string "NaN"...
import groovy.json.JsonSlurper
import groovy.json.JsonParserType
import groovy.json.JsonBuilder
def jsonSlurper = new JsonSlurper().setType( JsonParserType.LAX )
def json = jsonSlurper.parseText('{ "a":111, "b": NaN}')
println new JsonBuilder(json).toPrettyString()
prints
{
"a": 111,
"b": "NaN"
}

Groovy throws MissingPropertyException when calling getter method

I'm writing a small Groovy script for Hybris.
For reasons unknown when I attempt to call .getCronExpression() Groovy tries to get a property named getCron.
Script execution has failed [reason: groovy.lang.MissingPropertyException: No such property: getCron for class: de.hybris.platform.cronjob.model.TriggerModel]
The getter which I try to call exists on the class.
def methods = TriggerModel.declaredMethods.findAll { !it.synthetic }.name
println methods;
//[getDaysOfWeek, getWeekInterval, setDaysOfWeek, setWeekInterval, getRelative, getJob, setActivationTime, setMaxAcceptableDelay, getTimeTable, setActive, setJob, getCronJob, getActivationTime, setDateRange, getDateRange, getMaxAcceptableDelay, getCronExpression, setCronExpression, setCronJob, getActive, setRelative, setDay, setHour, setMinute, setSecond, getHour, getMinute, getSecond, getYear, getMonth, setYear, setMonth, getDay]
Code part:
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} IS true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
}
Update: the project uses hybris 5.7
Replacing the getter with the variable name fixed the issue.
Replace-
def x = at.getCronExpression(); // error
with
def xam = at.cronExpression; // working
Complete working groovy-
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active}='1'");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def xam = at.cronExpression; // working
}
}
Can you share your groovy part where you are loading activeTriggers?
I created a sample groovy to load Triggers and print CronExpression for 1st object and it worked like a charm.
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
flexibleQuery = new FlexibleSearchQuery("select {pk} from {Trigger}");
flexibleSearchService = spring.getBean("flexibleSearchService")
activeTriggers = flexibleSearchService.search(flexibleQuery).getResult();
def at = activeTriggers.get(0);
def x = at.getCronExpression();
OUTPUT
0 0 0/4 * * ? *
AFTER PO EDITED THE QUESTION I still don't see getCronExpression error, I believe you were calling the function on a different object then TriggerModel. Though there were some syntax errors in your groovy, a working version of the copy is as below. (Tested on 1905 version)
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} = true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS!=null && activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
println x;
}
}

Save test case properties if any of the assertions fail

How to save the test case properties if any of the assertions fail within this groovy script step?
Below is example code:
// define properties required for the script to run.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def dataFolder = groovyUtils.projectPath
def vTIDAPI = testRunner.testCase.getPropertyValue("vTIDAPI")
def vTIDDB = testRunner.testCase.getPropertyValue("vTIDDB")
def RefAPI = testRunner.testCase.getPropertyValue("RefAPI")
def RefDB = testRunner.testCase.getPropertyValue("RefDB")
def AmountAPI = testRunner.testCase.getPropertyValue("AmountAPI")
def AmountDB = testRunner.testCase.getPropertyValue("AmountDB")
def CurrencyAPI = testRunner.testCase.getPropertyValue("CurrencyAPI")
def CurrencyDB = testRunner.testCase.getPropertyValue("CurrencyDB")
assert vTIDAPI == vTIDDB
assert RefAPI == RefDB
assert AmountAPI == AmountDB
assert CurrencyAPI == CurrencyDB
Here is the Groovy Script which does compare the given set of properties and on any of the assertion failure, writes the properties to a given file.
You need to change the value of property file name to be stored for variable propFileName variable.
Add more properties to be asserted in the form of key:value pairs format if needed
//Provide / edit the file name to store properties
def propFileName = '/tmp/testCase.properties'
//Define the properties to be matched or asserted ; add more properties if needed
def props = [ 'vTIDAPI':'vTIDDB', 'RefAPI':'RefDB', 'AmountAPI': 'AmountDB', 'CurrencyAPI': 'CurrencyDB']
/**
* Do not edit beyond this point
*/
def writeTestCasePropertiesToFile = {
//Get the test case properties as Properties object
def properties = context.testCase.properties.keySet().inject([:]){map, key -> map[key] = context.testCase.getPropertyValue(key); map as Properties}
log.info properties
assert properties instanceof Properties
properties?.store(new File(propFileName).newWriter(), null)
}
def myAssert = { arg1, arg2 ->
context.testCase.getPropertyValue(arg1) == context.testCase.getPropertyValue(arg2) ? null : "${arg1} value does not match with ${arg2}"
}
def failureMessage = new StringBuffer()
props.collect{ null == myAssert(it.key, it.value) ?: failureMessage.append(myAssert(it.key, it.value)).append('\n')}
if(failureMessage.toString()) {
log.error "Assertion failures:\n ${failureMessage.toString()}"
writeTestCasePropertiesToFile()
throw new Error(failureMessage.toString())
} else {
log.info 'Assertions passed'
}
EDIT: Based on the OP comments
Replace def myAssert = ... with below code fragment.
def myAssert = { arg1, arg2 ->
def actual = context.testCase.getPropertyValue(arg1)
def expected = context.testCase.getPropertyValue(arg2)
actual == expected ? null : "${arg1} value does not match with ${arg2} - api ${actual} vs db ${expected}"
}

Initializing AssetManager in Groovy Console

My goal is to programmatically move assets. I have found that AssetManager has a moveAsset method. However, I am having issues initializing an AssetManager object in my groovy script. Below is the code I am working with. How do I initialize a non-null AssetManager object?
import javax.jcr.query.*
import com.day.cq.dam.api.*
def query = createSQL2Query("/content/dam/3d-renders/application-notes/wcc-migration") //CHANGE THIS
def result = query.execute()
def rows = result.rows
rows.each { row ->
Resource res = resourceResolver.getResource(null,row.path)
AssetManager am = res.adaptTo(AssetManager.class)
am.getAsset('/content/dam/3d-renders/application-notes/wcc-migration/Q60_ILL000347_iAPP.psd')
println res.path + ' ' + am
//am.moveAsset('/content/dam/3d-renders/application-notes/wcc-migration/2015/Q3X-Color-Mark-Sensing.psd','/content/dam/3d-renders/test-folder/Q3X-Color-Mark-Sensing.psd')
}
def createSQL2Query(startPage) {
def queryManager = session.workspace.queryManager
def statement = "select * from [nt:base] as p where (isdescendantnode (p, '$startPage')) and p.[jcr:primaryType] = 'dam:Asset'"
def query = queryManager.createQuery(statement, Query.JCR_SQL2)
query
}
Try getting your asset manager like this:
AssetManager am = resourceResolver.adaptTo(AssetManager.class)
ResourceResolver implements Adaptable, the interface where the adaptTo(Class) method is defined.

Modifying the file contents of a zipfile entry

I would like to update the contents of text file located inside a zipfile.
I cannot find out how to do this, and the code below is not working properly.
May thanks for any help!!
import java.util.zip.ZipFile
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
String zipFileFullPath = "C:/path/to/myzipfile/test.zip"
ZipFile zipFile = new ZipFile(zipFileFullPath)
ZipEntry entry = zipFile.getEntry ( "someFile.txt" )
if(entry){
InputStream input = zipFile.getInputStream(entry)
BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8"))
String s = null
StringBuffer sb = new StringBuffer()
while ((s=br.readLine())!=null){
sb.append(s)
}
sb.append("adding some text..")
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileFullPath))
out.putNextEntry(new ZipEntry("someFile.txt"));
int length
InputStream fin = new ByteArrayInputStream(sb.toString().getBytes("UTF8"))
while((length = fin.read(sb)) > 0)
{
out.write(sb, 0, length)
}
out.closeEntry()
}
Just some slight modifications to #Opal's answer, I've just:
used groovy methods where possible
packaged in a method
Groovy Snippet
void updateZipEntry(String zipFile, String zipEntry, String newContent){
def zin = new ZipFile(zipFile)
def tmp = File.createTempFile("temp_${System.nanoTime()}", '.zip')
tmp.withOutputStream { os ->
def zos = new ZipOutputStream(os)
zin.entries().each { entry ->
def isReplaced = entry.name == zipEntry
zos.putNextEntry(isReplaced ? new ZipEntry(zipEntry) : entry)
zos << (isReplaced ? newContent.getBytes('UTF8') : zin.getInputStream(entry).bytes )
zos.closeEntry()
}
zos.close()
}
zin.close()
assert new File(zipFile).delete()
tmp.renameTo(zipFile)
}
Usage
updateZipEntry('/tmp/file.zip', 'META-INF/web.xml', '<foobar>new content!</foobar>')
What exactly isn't working? Is there any exception thrown?
As far as I know it's not possible to modify a zip file in situ. The following script rewrites the file and if desired entry is processed - modifies it.
import java.util.zip.*
def zipIn = new File('lol.zip')
def zip = new ZipFile(zipIn)
def zipTemp = File.createTempFile('out', 'zip')
zipTemp.deleteOnExit()
def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
def toModify = 'lol.txt'
for(e in zip.entries()) {
if(!e.name.equalsIgnoreCase(toModify)) {
zos.putNextEntry(e)
zos << zip.getInputStream(e).bytes
} else {
zos.putNextEntry(new ZipEntry(toModify))
zos << 'lollol\n'.bytes
}
zos.closeEntry()
}
zos.close()
zipIn.delete()
zipTemp.renameTo(zipIn)
UPDATE
I wasn't right. It's possible to modify zip file in situ, but Your solution will omit other files that were zipped. The output file will contain only one single file - the file You wanted to modify. I also suppose that You file was corrupted because of not invoking close() on out.
Below is You script slightly modified (more groovier):
import java.util.zip.*
def zipFileFullPath = 'lol.zip'
def zipFile = new ZipFile(zipFileFullPath)
def entry = zipFile.getEntry('lol.txt')
if(entry) {
def input = zipFile.getInputStream(entry)
def br = new BufferedReader(new InputStreamReader(input, 'UTF-8'))
def sb = new StringBuffer()
sb << br.text
sb << 'adding some text..'
def out = new ZipOutputStream(new FileOutputStream(zipFileFullPath))
out.putNextEntry(new ZipEntry('lol.txt'))
out << sb.toString().getBytes('UTF8')
out.closeEntry()
out.close()
}

Resources