Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/LogExecutor.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/LogExecutor.java
index 4309215..dfde57c 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/LogExecutor.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/LogExecutor.java
@@ -5,6 +5,7 @@
*/
package br.ufrgs.inf.prosoft.requestssimulator;
+import br.ufrgs.inf.prosoft.requestssimulator.requests.DeleteRequest;
import br.ufrgs.inf.prosoft.requestssimulator.requests.GetRequest;
import br.ufrgs.inf.prosoft.requestssimulator.requests.PostRequest;
import br.ufrgs.inf.prosoft.requestssimulator.requests.MultipartRequest;
@@ -60,6 +61,8 @@ public class LogExecutor {
Request request;
if (requestPlan.getMethod().equals("GET")) {
request = gson.fromJson(jsonObject, GetRequest.class);
+ } else if (requestPlan.getMethod().equals("DELETE")) {
+ request = gson.fromJson(jsonObject, DeleteRequest.class);
} else {
JsonElement headers = jsonObject.get("headers");
if (headers != null && headers.getAsString().contains("multipart")) {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java
index e7af81d..7cf014f 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java
@@ -7,7 +7,6 @@ package br.ufrgs.inf.prosoft.requestssimulator;
import br.ufrgs.inf.prosoft.requestssimulator.requests.RequestPlan;
import com.google.gson.Gson;
-import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/DeleteRequest.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/DeleteRequest.java
index 00486d7..d3ca315 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/DeleteRequest.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/DeleteRequest.java
@@ -12,6 +12,7 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -30,6 +31,10 @@ public class DeleteRequest extends Request {
super(requestPlan, session, URL, headers);
}
+ protected DeleteRequest(RequestPlan requestPlan, Session session, String URL, String headers, Collection<String> storeFields) {
+ super(requestPlan, session, URL, headers, storeFields);
+ }
+
@Override
public void fireRequest() {
HttpURLConnection httpURLConnection = null;
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/GetRequest.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/GetRequest.java
index 48b47d8..5ff0844 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/GetRequest.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/GetRequest.java
@@ -12,6 +12,7 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -30,6 +31,10 @@ public class GetRequest extends Request {
super(requestPlan, session, URL, headers);
}
+ protected GetRequest(RequestPlan requestPlan, Session session, String URL, String headers, Collection<String> storeFields) {
+ super(requestPlan, session, URL, headers, storeFields);
+ }
+
@Override
public void fireRequest() {
HttpURLConnection httpURLConnection = null;
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/MultipartRequest.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/MultipartRequest.java
index ad1357e..600699c 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/MultipartRequest.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/MultipartRequest.java
@@ -10,6 +10,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
@@ -41,6 +42,11 @@ public class MultipartRequest extends Request {
this.forms = forms;
}
+ protected MultipartRequest(RequestPlan requestPlan, Session session, String URL, String headers, String forms, Collection<String> storeFields) {
+ super(requestPlan, session, URL, headers, storeFields);
+ this.forms = forms;
+ }
+
protected String getForms() {
return this.forms;
}
@@ -68,7 +74,7 @@ public class MultipartRequest extends Request {
File file = new File(entry.getValue());
multipartEntityBuilder.addBinaryBody(entry.getKey(), file);
} else {
- multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue());
+ multipartEntityBuilder.addTextBody(entry.getKey(), fillPropertyVariable(entry.getValue()));
}
});
HttpEntity httpEntity = multipartEntityBuilder.build();
@@ -80,7 +86,7 @@ public class MultipartRequest extends Request {
try (CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost)) {
int responseCode = closeableHttpResponse.getStatusLine().getStatusCode();
if (responseCode < 400) {
- Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
+ Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(closeableHttpResponse.getEntity().getContent()))) {
String response = bufferedReader.lines().collect(Collectors.joining());
processResponse(response);
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/PostRequest.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/PostRequest.java
index 43bb371..7ab2cbf 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/PostRequest.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/PostRequest.java
@@ -13,6 +13,7 @@ import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -35,6 +36,11 @@ public class PostRequest extends Request {
this.data = data;
}
+ protected PostRequest(RequestPlan requestPlan, Session session, String URL, String data, String headers, Collection<String> storeFields) {
+ super(requestPlan, session, URL, headers, storeFields);
+ this.data = data;
+ }
+
protected String getData() {
return this.data;
}
@@ -54,7 +60,8 @@ public class PostRequest extends Request {
});
connection.setDoOutput(true);
try (OutputStream outputStream = connection.getOutputStream()) {
- outputStream.write(this.data.getBytes());
+ String data = fillPropertyVariable(this.data);
+ outputStream.write(data.getBytes());
}
int responseCode = connection.getResponseCode();
if (responseCode < 400) {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
index c936610..d89a717 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/Request.java
@@ -6,14 +6,19 @@
package br.ufrgs.inf.prosoft.requestssimulator.requests;
import br.ufrgs.inf.prosoft.requestssimulator.Session;
+import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
/**
@@ -25,6 +30,7 @@ public abstract class Request {
private final RequestPlan requestPlan;
private final String URL;
private final String headers;
+ private final Collection<String> storeFields;
private final Session session;
protected Request(RequestPlan requestPlan, Session session, String URL) {
@@ -32,6 +38,15 @@ public abstract class Request {
this.session = session;
this.URL = URL;
this.headers = null;
+ this.storeFields = null;
+ }
+
+ protected Request(RequestPlan requestPlan, Session session, String URL, Collection<String> storeFields) {
+ this.requestPlan = requestPlan;
+ this.session = session;
+ this.URL = URL;
+ this.headers = null;
+ this.storeFields = storeFields;
}
protected Request(RequestPlan requestPlan, Session session, String URL, String headers) {
@@ -39,6 +54,15 @@ public abstract class Request {
this.session = session;
this.URL = URL;
this.headers = headers;
+ this.storeFields = null;
+ }
+
+ protected Request(RequestPlan requestPlan, Session session, String URL, String headers, Collection<String> storeFields) {
+ this.requestPlan = requestPlan;
+ this.session = session;
+ this.URL = URL;
+ this.headers = headers;
+ this.storeFields = storeFields;
}
public String getMethod() {
@@ -69,6 +93,17 @@ public abstract class Request {
return headers.entrySet().stream();
}
+ protected Collection<String> getStoreFields() {
+ return storeFields;
+ }
+
+ private Stream<String> storeFields() {
+ if (this.storeFields == null || this.storeFields.isEmpty()) {
+ return Stream.empty();
+ }
+ return this.storeFields.stream();
+ }
+
public Request pickNextRequest(Session session) {
return this.requestPlan.pickNextRequest(session);
}
@@ -78,36 +113,102 @@ public abstract class Request {
Logger.getGlobal().log(Level.SEVERE, "empty response");
return;
}
- this.requestPlan.storeFields().forEach(new Consumer<String>() {
+ storeFields().forEach(new Consumer<String>() {
private final JsonParser jsonParser;
- private final JsonObject jsonObject;
+ private final JsonElement jsonElement;
{
this.jsonParser = new JsonParser();
- JsonElement jsonElement = this.jsonParser.parse(response);
- if (jsonElement.isJsonObject()) {
- this.jsonObject = this.jsonParser.parse(response).getAsJsonObject();
- } else {
- this.jsonObject = null;
+ this.jsonElement = this.jsonParser.parse(response);
+ }
+
+ class Tokenizer {
+
+ private int index;
+ private final String string;
+
+ public Tokenizer(String string) {
+ this.index = 0;
+ this.string = string;
+ }
+
+ private String getNextToken() {
+ if (!hasMoreTokens()) {
+ return null;
+ }
+ StringBuilder nextToken = new StringBuilder();
+ while (true) {
+ char nextChar = this.string.charAt(this.index);
+ this.index++;
+ nextToken.append(nextChar);
+ if (nextChar == ']') {
+ break;
+ }
+ if (this.index == this.string.length()) {
+ break;
+ }
+ char futureChar = this.string.charAt(this.index);
+ if (futureChar == '#' || futureChar == '[') {
+ break;
+ }
+ }
+ return nextToken.toString();
+ }
+
+ protected boolean hasMoreTokens() {
+ if (this.string == null) {
+ return false;
+ }
+ if (this.string.isEmpty()) {
+ return false;
+ }
+ return this.index < string.length();
}
}
@Override
public void accept(String storeField) {
- String[] storeSequence = storeField.split("#");
- JsonObject jsonObject = this.jsonObject;
- JsonElement jsonElement = null;
-
- for (String storeLevel : storeSequence) {
- jsonElement = jsonObject.get(storeLevel);
+ String tokenVariable;
+ if (storeField.contains("@")) {
+ tokenVariable = storeField.split("@")[1];
+ } else {
+ tokenVariable = storeField;
+ }
+ Tokenizer tokenizer = new Tokenizer(tokenVariable);
+ JsonElement jsonElement = this.jsonElement;
+ while (tokenizer.hasMoreTokens()) {
+ String nextToken = tokenizer.getNextToken();
+ if (nextToken.charAt(0) == '[') {
+ try {
+ Integer index = Integer.valueOf(nextToken.substring(1, nextToken.length() - 1));
+ JsonArray jsonArray = jsonElement.getAsJsonArray();
+ if (index >= jsonArray.size()) {
+ Logger.getGlobal().log(Level.SEVERE, "index error {0}", storeField);
+ return;
+ }
+ jsonElement = jsonArray.get(index);
+ } catch (NumberFormatException ex) {
+ Logger.getGlobal().log(Level.SEVERE, "NumberFormatException {0}", storeField);
+ return;
+ }
+ } else {
+ if (nextToken.charAt(0) == '#') {
+ nextToken = nextToken.substring(1, nextToken.length());
+ }
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ jsonElement = jsonObject.get(nextToken);
+ }
if (jsonElement == null) {
Logger.getGlobal().log(Level.SEVERE, "field {0} not present", storeField);
return;
}
- if (jsonElement.isJsonObject()) {
- jsonObject = jsonElement.getAsJsonObject();
- }
+ }
+ Pattern pattern = Pattern.compile("#\\[(.*?)\\]");
+ Matcher matcher = pattern.matcher(storeField);
+ while (matcher.find()) {
+ String found = matcher.group();
+ storeField = storeField.replace(found, "[$]");
}
String storedValue = jsonElement.getAsString();
storeValue(storeField, storedValue);
@@ -122,13 +223,21 @@ public abstract class Request {
protected String fillPropertyVariable(String property) {
String filledProperty = property;
- if (filledProperty.contains("#")) {
- String storedField = filledProperty.substring(filledProperty.indexOf("#") + 1);
- String storedValue = this.session.getStoredValue(storedField);
- if (storedValue == null) {
- Logger.getGlobal().log(Level.SEVERE, "variable {0} not stored", property);
- } else {
- filledProperty = filledProperty.replace("#" + storedField, storedValue);
+ if (filledProperty.contains("#{")) {
+ Collection<String> matches = new ArrayList<>();
+ Pattern pattern = Pattern.compile("#\\{(.*?)\\}");
+ Matcher matcher = pattern.matcher(property);
+ while (matcher.find()) {
+ matches.add(matcher.group());
+ }
+ for (String storedField : matches) {
+ String fieldName = storedField.substring(2, storedField.length() - 1);
+ String storedValue = this.session.getStoredValue(fieldName);
+ if (storedValue == null) {
+ Logger.getGlobal().log(Level.SEVERE, "variable {0} not stored", storedField);
+ continue;
+ }
+ filledProperty = filledProperty.replace(storedField, storedValue);
}
}
return filledProperty;
@@ -152,6 +261,13 @@ public abstract class Request {
jsonObject.addProperty("reference", this.requestPlan.getReference());
jsonObject.addProperty("URL", getURL());
jsonObject.addProperty("headers", getHeaders());
+ if (storeFields().count() > 0) {
+ JsonArray storeFields = new JsonArray();
+ storeFields().forEach(storeField -> {
+ storeFields.add(storeField);
+ });
+ jsonObject.add("storeFields", storeFields);
+ }
if (this instanceof PostRequest) {
PostRequest postRequest = (PostRequest) this;
jsonObject.addProperty("data", postRequest.getData());
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
index e36c1b6..b889e5b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/requests/RequestPlan.java
@@ -11,6 +11,9 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -22,8 +25,8 @@ public class RequestPlan {
private final String method;
private final String URL;
private final String data;
- private List<RequestPlan> getLinks;
- private List<RequestPlan> postLinks;
+ private List<RequestPlan> readLinks;
+ private List<RequestPlan> writeLinks;
private Collection<String> storeFields;
private Collection<RequestPlan> requirements;
private String headers;
@@ -92,29 +95,29 @@ public class RequestPlan {
}
public Stream<RequestPlan> links() {
- if (this.getLinks == null && this.postLinks == null) {
+ if (this.readLinks == null && this.writeLinks == null) {
return Stream.empty();
}
- if (this.getLinks != null && this.postLinks != null) {
- return Stream.concat(this.getLinks.stream(), this.postLinks.stream());
+ if (this.readLinks != null && this.writeLinks != null) {
+ return Stream.concat(this.readLinks.stream(), this.writeLinks.stream());
}
- if (this.getLinks != null) {
- return this.getLinks.stream();
+ if (this.readLinks != null) {
+ return this.readLinks.stream();
}
- return this.postLinks.stream();
+ return this.writeLinks.stream();
}
public RequestPlan addLink(RequestPlan requestPlan) {
if (requestPlan.getMethod().equals("GET")) {
- if (this.getLinks == null) {
- this.getLinks = new ArrayList<>();
+ if (this.readLinks == null) {
+ this.readLinks = new ArrayList<>();
}
- this.getLinks.add(requestPlan);
+ this.readLinks.add(requestPlan);
} else {
- if (this.postLinks == null) {
- this.postLinks = new ArrayList<>();
+ if (this.writeLinks == null) {
+ this.writeLinks = new ArrayList<>();
}
- this.postLinks.add(requestPlan);
+ this.writeLinks.add(requestPlan);
}
return this;
}
@@ -149,21 +152,21 @@ public class RequestPlan {
public Request pickNextRequest(Session session) {
Random random = new Random();
int probability = random.nextInt(100);
- if ((this.getLinks == null || this.getLinks.isEmpty()) && (this.postLinks == null || this.postLinks.isEmpty())) {
+ if ((this.readLinks == null || this.readLinks.isEmpty()) && (this.writeLinks == null || this.writeLinks.isEmpty())) {
throw new RuntimeException("GET and POST links empty");
}
RequestPlan chosen;
- if (this.getLinks == null || this.getLinks.isEmpty()) {
+ if (this.readLinks == null || this.readLinks.isEmpty()) {
probability = 100;
- } else if (this.postLinks == null || this.postLinks.isEmpty()) {
+ } else if (this.writeLinks == null || this.writeLinks.isEmpty()) {
probability = 0;
}
if (probability < 80) {
- int chosenIndex = random.nextInt(this.getLinks.size());
- chosen = this.getLinks.get(chosenIndex);
+ int chosenIndex = random.nextInt(this.readLinks.size());
+ chosen = this.readLinks.get(chosenIndex);
} else {
- int chosenIndex = random.nextInt(this.postLinks.size());
- chosen = this.postLinks.get(chosenIndex);
+ int chosenIndex = random.nextInt(this.writeLinks.size());
+ chosen = this.writeLinks.get(chosenIndex);
}
return chosen.build(session);
}
@@ -175,31 +178,50 @@ public class RequestPlan {
throw new RuntimeException("URL is empty");
}
String URL = this.URL.replace("$", String.valueOf(randomInt));
+ Pattern pattern = Pattern.compile("#\\{(.*?)\\}");
+ Matcher originalMatcher = pattern.matcher(this.URL);
+ Matcher randomMatcher = pattern.matcher(URL);
+ while (originalMatcher.find() && randomMatcher.find()) {
+ String originalFound = originalMatcher.group();
+ String randomFound = randomMatcher.group();
+ URL = URL.replace(randomFound, originalFound);
+ }
+ Collection<String> storeFields = storeFields()
+ .map(storeField -> storeField.replace("$", String.valueOf(randomInt)))
+ .collect(Collectors.toList());
String headers = null;
if (this.headers != null) {
headers = this.headers.replace("$", String.valueOf(randomInt));
if (this.headers.contains("multipart")) {
String forms = this.forms;
- return new MultipartRequest(this, session, URL, headers, forms);
+ return new MultipartRequest(this, session, URL, headers, forms, storeFields);
}
}
+ if (this.method.equals("DELETE")) {
+ return new DeleteRequest(this, session, URL, headers, storeFields);
+ }
if (this.method.equals("GET")) {
- return new GetRequest(this, session, URL, headers);
+ return new GetRequest(this, session, URL, headers, storeFields);
}
String data = this.data.replace("$", String.valueOf(randomInt));;
- return new PostRequest(this, session, URL, data, headers);
+ return new PostRequest(this, session, URL, data, headers, storeFields);
}
public Request bind(Request request, Session session) {
+ if (request instanceof DeleteRequest) {
+ DeleteRequest deleteRequest = (DeleteRequest) request;
+ return new DeleteRequest(this, session, deleteRequest.getURL(), deleteRequest.getHeaders(), deleteRequest.getStoreFields());
+ }
if (request instanceof GetRequest) {
- return new GetRequest(this, session, request.getURL(), request.getHeaders());
+ GetRequest getRequest = (GetRequest) request;
+ return new GetRequest(this, session, getRequest.getURL(), getRequest.getHeaders(), getRequest.getStoreFields());
}
if (request instanceof PostRequest) {
PostRequest postRequest = (PostRequest) request;
- return new PostRequest(this, session, postRequest.getURL(), postRequest.getData(), postRequest.getHeaders());
+ return new PostRequest(this, session, postRequest.getURL(), postRequest.getData(), postRequest.getHeaders(), postRequest.getStoreFields());
}
MultipartRequest multipartRequest = (MultipartRequest) request;
- return new MultipartRequest(this, session, multipartRequest.getURL(), multipartRequest.getHeaders(), multipartRequest.getForms());
+ return new MultipartRequest(this, session, multipartRequest.getURL(), multipartRequest.getHeaders(), multipartRequest.getForms(), multipartRequest.getStoreFields());
}
@Override