How to loop through an array of strings Gatling during scenario building - scala

I'm trying to loop through an array of products (Strings) in order to execute a call for each of them but I'm mismatching some types during scenario building, here is an example of what I'm trying to do:
val createAddToCart: ScenarioBuilder = scenario("Add to cart").exec(CartRequest.addToCart())
This is my CartRequest object:
def addToCart(): Unit (???) = {
for (product <- products) {
addToCart(product)
}
}
def addToCart(productId:String): ChainBuilder =
{
exec(http("addToCart")
.post(addToCartUrl)
.headers(authHeaders)
.body(generateRequestBodyForProduct(productId)).asJson
.check(bodyString.saveAs("body"))
).exec(
session => {
body = session("body").as[String]
println("response body " + body)
session
}
)
}
def generateRequestBodyForProduct(productId: String): Body with (Expression[String]) =
{
StringBody("{ \"productId\": \"" + productId + "\"," +
" \"qty\": " + 1 + " , " +
"\"storeId\": \"" + storeId + "\"}")
}
Obviously, I'm having problems calling CartRequest.addToCart() due to type mismatching (Unit to ChainBuilder).
Is there a way to execute and return the addToCart method as a list of scenarios?
I hope I explained myself well.
Thanks for your time.

First, you don't look like a Scala developper. You should probably use the new Java DSL available since Gatling 3.7.
Then, you're not using the Gatling constructs properly.
your for loop should be a Gatling foreach instead
the dynamic productId in your request body should be resolved with Gatling Expression Language => "{ \"productId\": \"#{productId}\", \"qty\": " + 1 + " , " + "\"storeId\": \"" + storeId + "\"}"

Related

How can I resolve error : Linq query cannot be translated.?

#Karney. this is my code
var customerMachineId = wcDataContext.Customers.Where(x =>
x.UserId.Equals(currentUser.Result.Id)).Select(x =>
x.MachineId).ToList();
var customers1 = (from customer in wcDataContext.Customers
join machine in wcDataContext.Machineinfo
on customer.MachineId equals machine.MachineId
where customerMachineId.Contains(customer.MachineId)
select new UserMachineInfo
{
Mac1 = machine.Mac1,
Mac2 = machine.Mac2,
MachineId = machine.MachineId,
MachineName = machine.MachineName,
UserId = customer.UserId,
UserName = customer.User.FirstName.ToString() + " " + customer.User.LastName.ToString()
//UserName = (customer.User.FirstName + " " + customer.User.LastName).ToString()}
.OrderBy(ti => ti.Inner.FirstName.ToString() + " " + ti.Inner.LastName.ToString())' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToList.
The error is given while querying data in jQuery datatables. I was trying to search data in a jQuery datatable. How can I rewrite this query to resolve error?

JPQL. JPA Query. How to get size of named parameter collection

I'm trying to define custom method in repository interface
public interface RequestRepository extends JpaRepository<Request, Long> {
#Query("SELECT r FROM Request r " +
"LEFT JOIN FETCH r.pathParams pp " +
"WHERE r.responseCode = :code " +
"AND r.requestMethod = :method " +
"AND r.requestPath = :path " +
"AND r.requestBody = :body " +
"AND r.apiDetails = :apidetails " +
"AND (pp IN :pathparams OR r.pathParams IS EMPTY) " +
"AND SIZE(r.pathParams) = :pathparamssize "
)
Optional<Request> findByDetails(
#Param("code") String code,
#Param("method") RequestMethod method,
#Param("path") String path,
#Param("body") RequestBody body,
#Param("apidetails") ApiDetails apidetails,
#Param("pathparams") Set<PathParam> pathparams,
#Param("pathparamssize") Integer pathparamssize
);
}
It works, but I believe it can be done in better way
As you can see I declared redundant parameter "pathparamssize" (IMO)
I tried to do that like "AND SIZE(r.pathParams) = SIZE(:pathparams) " but it doesn't want to work with "SIZE(:pathparams)"
can you please advise something?
many thanks in advance

ServiceStack Ormlite Deserialize Array for In Clause

I am storing some query criteria in the db via a ToJson() on the object that contains all the criteria. A simplified example would be:
{"FirstName" :[ {Operator: "=", Value: "John"}, { Operator: "in", Value:" ["Smith", "Jones"]"}], "SomeId": [Operator: "in", Value: "[1,2,3]" }]}
The lists are either string, int, decimal or date. These all map to the same class/table so it is easy via reflection to get FirstName or SomeId's type.
I'm trying to create a where clause based on this information:
if (critKey.Operator == "in")
{
wb.Values.Add(keySave + i, (object)ConvertList<Members>(key,
(string)critKey.Value));
wb.WhereClause = wb.WhereClause + " And {0} {1} (#{2})".Fmt(critKey.Column,
critKey.Operator, keySave + i);
}
else
{
wb.Values.Add(keySave + i, (object)critKey.Value);
wb.WhereClause = wb.WhereClause + " And {0} {1} #{2}".Fmt(critKey.Column, critKey.Operator, keySave + i);
}
It generates something like this (example from my tests, yes I know the storenumber part is stupid):
Email = #Email0 And StoreNumber = #StoreNumber0 And StoreNumber in (#StoreNumber1)
I'm running into an issue with the lists. Is there a nice way to do this with any of the ormlite tools instead of doing this all by hand? The where clause generates fine except when dealing with lists. I'm trying to make it generic but having a hard time on that part.
Second question maybe related but I can't seem to find how to use parameters with in. Coming from NPoco you can do (colum in #0, somearray)` but I cant' seem to find out how to do this without using Sql.In.
I ended up having to write my own parser as it seems ormlite doesn't support have the same support for query params for lists like NPoco. Basically I'd prefer to be able to do this:
Where("SomeId in #Ids") and pass in a parameter but ended up with this code:
listObject = ConvertListObject<Members>(key, (string)critKey.Value);
wb.WhereClause = wb.WhereClause + " And {0} {1} ({2})"
.Fmt(critKey.Column, critKey.Operator,listObject.EscapedList(ColumnType<Members>(key)));
public static string EscapedList(this List<object> val, Type t)
{
var escapedList = "";
if (t == typeof(int) || t == typeof(float) || t == typeof(decimal))
{
escapedList = String.Join(",", val.Select(x=>x.ToString()));
} else
{
escapedList = String.Join(",", val.Select(x=>"'" + x.ToString() + "'"));
}
return escapedList;
}
I'd like to see other answers especially if I'm missing something in ormlite.
When dealing with lists you can use the following example
var storeNumbers = new [] { "store1", "store2", "store3" };
var ev = Db.From<MyClass>
.Where(p => storeNumbers.Contains(p => p.StoreNumber));
var result = Db.Select(ev);

Replace characters in foreach variable

Here is the code:
def readEntityMultipleTimes(entityName: String, pathPrefix: String = "") = {
val plural = entityName + "s"
exec(http(s"Geting all $plural")
.get(pathPrefix + plural)
.check(status is 200)
.check(jsonPath("$[*].id").findAll.saveAs("entityIds"))
).exec(s => {
if (logLevel >= 2) println("\nids:\n" + s("entityIds"))
s
})
.pause(interval millis)
.foreach("${entityIds}", "entityId") {
repeat(readEntityNumber) {
exec(http(s"Getting one $entityName")
.get(pathPrefix + plural + "/${entityId}")
.check(status is 200)
)
}
}
}
The issue is that entityId may contain a space and it fails the HTTP GET request. I need the spaces to be replaced with %20.
I tried the gatling EL ${entityId.replaceAll(\" \", \"%20\")}"
or ${java.net.URLEncoder.encode(entityId)}
I guess the suggested way is to get the entityId from the session and do the stuff in Scala, but this variable is dynamically created for each loop iteration, so I am not sure where to put the "session lambda" (session => ...)
Gatling EL syntax is limited and you can't place any Scala code in there.
You indeed have to pass a function.
.get(session => pathPrefix + plural + URLEncoder.encode(session("entityId").as[String])))

Entity Framework - Table-Valued Functions - Parameter Already Exists

I am using table-valued functions with Entity Framework 5. I just received this error:
A parameter named 'EffectiveDate' already exists in the parameter collection. Parameter names must be unique in the parameter collection. Parameter name: parameter
It is being caused by me joining the calls to table-valued functions taking the same parameter.
Is this a bug/limitation with EF? Is there a workaround? Right now I am auto-generating the code (.edmx file).
It would be really nice if Microsoft would make parameter names unique, at least on a per-context basis.
I've created an issue for this here.
In the meantime, I was able to get this to work by tweaking a few functions in the .Context.tt file, so that it adds a GUID to each parameter name at runtime:
private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption) {
if (typeMapper.IsComposable(edmFunction))
{
#>
[EdmFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")]
<#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#>
{ var guid = Guid.NewGuid().ToString("N"); <#+
codeStringGenerator.WriteFunctionParameters(edmFunction, " + guid", WriteFunctionParameter);
#>
<#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#>
} <#+
}
else
{
#>
<#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#>
{ <#+
codeStringGenerator.WriteFunctionParameters(edmFunction, "", WriteFunctionParameter);
#>
<#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#>
} <#+
if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption))
{
WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true);
}
} }
...
public void WriteFunctionParameters(EdmFunction edmFunction, string nameSuffix, Action<string, string, string, string> writeParameter)
{
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
{
var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", " + parameter.FunctionParameterName + ")";
var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\"" + nameSuffix + ", typeof(" + parameter.RawClrTypeName + "))";
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
}
}
...
public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
{
var parameters = _typeMapper.GetParameters(edmFunction);
return string.Format(
CultureInfo.InvariantCulture,
"return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
edmFunction.NamespaceName,
edmFunction.Name,
string.Join(", ", parameters.Select(p => "#" + p.EsqlParameterName + "\" + guid + \"").ToArray()),
_code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
}
Not a bug. Maybe a limitation or an omission. Apparently this use case has never been taken into account. EF could use auto-created parameter names, but, yeah, it just doesn't.
You'll have to resort to calling one of the functions with .AsEnumerable(). For some reason, this must be the first function in the join (as I have experienced). If you call the second function with .AsEnumerable() it is still translated to SQL and the name collision still occurs.