requests-simulator

store Cookies, log time, symbolic plans, json file read, exit

4/28/2019 6:42:47 AM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
index 69f2de8..7ebea54 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Profile.java
@@ -26,9 +26,13 @@ public class Profile {
     public Profile(Map<String, RequestPlan> urlHasRequestPlan) {
         this.urlHasRequestPlan = urlHasRequestPlan;
         Map<String, RequestPlan> rootsReferences = new HashMap<>(this.urlHasRequestPlan);
-        this.urlHasRequestPlan.values().forEach(requestPlan -> {
+        this.urlHasRequestPlan.forEach((reference, requestPlan) -> {
+            if (reference.charAt(0) == '*') {
+                rootsReferences.remove(reference);
+                return;
+            }
             if (requestPlan.links().count() == 0) {
-                rootsReferences.remove(requestPlan.getReference());
+                rootsReferences.remove(reference);
                 return;
             }
             requestPlan.links().forEach(linkReference -> {
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 7cf014f..6d8855f 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/ProfileReader.java
@@ -10,9 +10,8 @@ import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -20,8 +19,6 @@ import java.util.Map;
 import java.util.function.Consumer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  *
@@ -30,19 +27,21 @@ import java.util.stream.Stream;
 public class ProfileReader {
 
     public static Profile parseFile(String profilePath) {
-        String fileContent = null;
-        try (Stream<String> lines = Files.lines(Paths.get(profilePath))) {
-            fileContent = lines.collect(Collectors.joining());
-        } catch (IOException ex) {
-            Logger.getLogger(ProfileReader.class.getName()).log(Level.SEVERE, null, ex);
+        FileReader fileReader = null;
+        try {
+            fileReader = new FileReader(profilePath);
+        } catch (FileNotFoundException ex) {
+            Logger.getLogger(ProfileReader.class.getName()).log(Level.SEVERE, "File not found");
+            System.exit(1);
         }
         Map<String, RequestPlan> urlHasRequestPlan = new HashMap<>();
         Gson gson = new Gson();
         JsonParser jsonParser = new JsonParser();
-        JsonObject jsonObject = jsonParser.parse(fileContent).getAsJsonObject();
+        JsonObject jsonObject = jsonParser.parse(fileReader).getAsJsonObject();
         jsonObject.entrySet().forEach(entry -> {
             RequestPlan requestPlan = gson.fromJson(entry.getValue(), RequestPlan.class);
-            urlHasRequestPlan.put(entry.getKey(), requestPlan);
+            requestPlan.setReference(entry.getKey());
+            urlHasRequestPlan.put(requestPlan.getReference(), requestPlan);
         });
         jsonObject.entrySet().forEach(entry -> {
             RequestPlan requestPlan = urlHasRequestPlan.get(entry.getKey());
@@ -50,8 +49,8 @@ public class ProfileReader {
             JsonObject jsonRequestPlan = entry.getValue().getAsJsonObject();
             JsonElement linksReferencesElement = jsonRequestPlan.get("linksReferences");
             if (linksReferencesElement != null) {
-                linksReferencesElement.getAsJsonArray().forEach(array -> {
-                    linksReferences.add(array.getAsString());
+                linksReferencesElement.getAsJsonArray().forEach(linkElement -> {
+                    linksReferences.add(linkElement.getAsString());
                 });
                 linksReferences.forEach(new Consumer<String>() {
                     @Override
@@ -59,13 +58,16 @@ public class ProfileReader {
                         RequestPlan link;
                         if (linkReference.charAt(0) == '*') {
                             link = urlHasRequestPlan.get(linkReference.substring(1));
+                            if (link == null) {
+                                throw new RuntimeException("link not declared: " + linkReference);
+                            }
                             link.links().forEach(referenceToCopy -> {
                                 accept(referenceToCopy.getReference());
                             });
                         } else {
                             link = urlHasRequestPlan.get(linkReference);
                             if (link == null) {
-                                throw new RuntimeException("link not declared");
+                                throw new RuntimeException("link not declared: " + linkReference);
                             }
                             requestPlan.addLink(link);
                         }
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 d3ca315..f1cfc8e 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
@@ -13,6 +13,7 @@ import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -51,6 +52,8 @@ public class DeleteRequest extends Request {
             int responseCode = connection.getResponseCode();
             if (responseCode < 400) {
                 Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
+                List<String> setCookies = connection.getHeaderFields().get("Set-Cookie");
+                storeCookies(setCookies);
                 try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                     String response = bufferedReader.lines().collect(Collectors.joining());
                     processResponse(response);
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 5ff0844..819fb63 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
@@ -13,6 +13,7 @@ import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -51,6 +52,8 @@ public class GetRequest extends Request {
             int responseCode = connection.getResponseCode();
             if (responseCode < 400) {
                 Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
+                List<String> setCookies = connection.getHeaderFields().get("Set-Cookie");
+                storeCookies(setCookies);
                 try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                     String response = bufferedReader.lines().collect(Collectors.joining());
                     processResponse(response);
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 600699c..e1901f1 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,8 +10,10 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -54,9 +56,9 @@ public class MultipartRequest extends Request {
     public Stream<Map.Entry<String, String>> forms() {
         Map<String, String> forms = new HashMap<>();
         if (this.forms != null) {
-            String[] formsPairs = this.forms.split("; ");
+            String[] formsPairs = this.forms.split("&");
             for (String formPair : formsPairs) {
-                String[] pair = formPair.split(": ");
+                String[] pair = formPair.split("=");
                 forms.put(pair[0], pair[1]);
             }
         }
@@ -87,6 +89,10 @@ public class MultipartRequest extends Request {
                 int responseCode = closeableHttpResponse.getStatusLine().getStatusCode();
                 if (responseCode < 400) {
                     Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
+                    List<String> setCookies = Arrays.asList(closeableHttpResponse.getHeaders("Set-Cookie")).stream()
+                            .map(header -> header.getName() + "=" + header.getValue())
+                            .collect(Collectors.toList());
+                    storeCookies(setCookies);
                     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 7ab2cbf..f55bbed 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
@@ -14,6 +14,7 @@ import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -66,6 +67,8 @@ public class PostRequest extends Request {
             int responseCode = connection.getResponseCode();
             if (responseCode < 400) {
                 Logger.getGlobal().log(Level.INFO, "{0} on {1} {2}", new Object[]{responseCode, getMethod(), stringURL});
+                List<String> setCookies = connection.getHeaderFields().get("Set-Cookie");
+                storeCookies(setCookies);
                 try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                     String response = bufferedReader.lines().collect(Collectors.joining());
                     processResponse(response);
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 d89a717..20b8896 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
@@ -13,6 +13,7 @@ import com.google.gson.JsonParser;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.function.Consumer;
 import java.util.logging.Level;
@@ -104,15 +105,41 @@ public abstract class Request {
         return this.storeFields.stream();
     }
 
+    private Stream<String> storeCookies() {
+        return this.requestPlan.storeCookies();
+    }
+
     public Request pickNextRequest(Session session) {
         return this.requestPlan.pickNextRequest(session);
     }
 
+    protected void storeCookies(List<String> cookies) {
+        if (storeCookies().count() == 0) {
+            return;
+        }
+        Map<String, String> map = new HashMap<>();
+        cookies.stream().forEach(cookieGroup -> {
+            String[] cookiePairs = cookieGroup.split("; ");
+            for (String cookiePair : cookiePairs) {
+                String[] pair = cookiePair.split("=");
+                if (pair.length > 1) {
+                    map.put(pair[0], pair[1]);
+                }
+            }
+        });
+        storeCookies().forEach(storeCookie -> {
+            storeValue(storeCookie, map.get(storeCookie));
+        });
+    }
+
     protected void processResponse(String response) {
         if (response == null || response.isEmpty()) {
             Logger.getGlobal().log(Level.SEVERE, "empty response");
             return;
         }
+        if (storeFields().count() == 0) {
+            return;
+        }
         storeFields().forEach(new Consumer<String>() {
 
             private final JsonParser jsonParser;
@@ -268,6 +295,13 @@ public abstract class Request {
             });
             jsonObject.add("storeFields", storeFields);
         }
+        if (storeCookies().count() > 0) {
+            JsonArray storeCookies = new JsonArray();
+            storeCookies().forEach(storeCookie -> {
+                storeCookies.add(storeCookie);
+            });
+            jsonObject.add("storeCookies", storeCookies);
+        }
         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 b889e5b..6aa7a0f 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
@@ -8,7 +8,9 @@ package br.ufrgs.inf.prosoft.requestssimulator.requests;
 import br.ufrgs.inf.prosoft.requestssimulator.Session;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Random;
 import java.util.regex.Matcher;
@@ -25,9 +27,11 @@ public class RequestPlan {
     private final String method;
     private final String URL;
     private final String data;
+    private String reference;
     private List<RequestPlan> readLinks;
     private List<RequestPlan> writeLinks;
     private Collection<String> storeFields;
+    private Collection<String> storeCookies;
     private Collection<RequestPlan> requirements;
     private String headers;
     private String forms;
@@ -44,6 +48,12 @@ public class RequestPlan {
         this.data = data;
     }
 
+    private RequestPlan(String method, String URL, String data) {
+        this.method = method;
+        this.URL = URL;
+        this.data = data;
+    }
+
     public static RequestPlan get(String URL) {
         return new RequestPlan(URL);
     }
@@ -52,12 +62,24 @@ public class RequestPlan {
         return new RequestPlan(URL, data);
     }
 
+    public static RequestPlan delete(String URL, String data) {
+        return new RequestPlan("DELETE", URL, data);
+    }
+
     public String getMethod() {
         return this.method;
     }
 
+    public RequestPlan setReference(String reference) {
+        this.reference = reference;
+        return this;
+    }
+
     public String getReference() {
-        return this.method + "@" + this.URL;
+        if (this.reference == null) {
+            return method + "@" + this.URL;
+        }
+        return this.reference;
     }
 
     public RequestPlan addHeader(String header) {
@@ -148,12 +170,19 @@ public class RequestPlan {
         }
         return this.storeFields.stream();
     }
+    
+    protected Stream<String> storeCookies() {
+        if (this.storeCookies == null || this.storeCookies.isEmpty()) {
+            return Stream.empty();
+        }
+        return this.storeCookies.stream();
+    }
 
     public Request pickNextRequest(Session session) {
         Random random = new Random();
         int probability = random.nextInt(100);
         if ((this.readLinks == null || this.readLinks.isEmpty()) && (this.writeLinks == null || this.writeLinks.isEmpty())) {
-            throw new RuntimeException("GET and POST links empty");
+            throw new RuntimeException("GET and POST links empty: " + this.URL);
         }
         RequestPlan chosen;
         if (this.readLinks == null || this.readLinks.isEmpty()) {
@@ -172,26 +201,27 @@ public class RequestPlan {
     }
 
     public Request build(Session session) {
-        Random random = new Random();
-        int randomInt = random.nextInt() & Integer.MAX_VALUE;
         if (this.URL == null || this.URL.isEmpty()) {
             throw new RuntimeException("URL is empty");
         }
-        String URL = this.URL.replace("$", String.valueOf(randomInt));
-        Pattern pattern = Pattern.compile("#\\{(.*?)\\}");
+        String URL = replaceOptionals(this.URL);
+        HashMap<String, Integer> map = new HashMap<>();
+        URL = replaceRandoms(URL, map);
+        Pattern pattern = Pattern.compile("#\\{(.*?)\\[(.*?)\\](.*?)\\}");
         Matcher originalMatcher = pattern.matcher(this.URL);
         Matcher randomMatcher = pattern.matcher(URL);
-        while (originalMatcher.find() && randomMatcher.find()) {
+        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)))
+                .map(storeField -> replaceRandoms(storeField, map))
                 .collect(Collectors.toList());
         String headers = null;
         if (this.headers != null) {
-            headers = this.headers.replace("$", String.valueOf(randomInt));
+            headers = replaceOptionals(this.headers);
+            headers = replaceRandoms(headers, map);
             if (this.headers.contains("multipart")) {
                 String forms = this.forms;
                 return new MultipartRequest(this, session, URL, headers, forms, storeFields);
@@ -203,10 +233,60 @@ public class RequestPlan {
         if (this.method.equals("GET")) {
             return new GetRequest(this, session, URL, headers, storeFields);
         }
-        String data = this.data.replace("$", String.valueOf(randomInt));;
+        String data = replaceOptionals(this.data);
+        data = replaceRandoms(data, map);
         return new PostRequest(this, session, URL, data, headers, storeFields);
     }
 
+    private String replaceRandoms(String data) {
+        return replaceRandoms(data, new HashMap<>());
+    }
+
+    private String replaceRandoms(String data, Map<String, Integer> map) {
+        Random random = new Random();
+        Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
+        Matcher randomMatcher = pattern.matcher(data);
+        while (randomMatcher.find()) {
+            String randomFound = randomMatcher.group();
+            String randomTrimmed = randomFound.substring(2, randomFound.length() - 1);
+            int randomInt;
+            if (map.containsKey(randomFound)) {
+                randomInt = map.get(randomFound);
+            } else {
+                String[] split = randomTrimmed.split("-");
+                int from = Integer.valueOf(split[0]);
+                int to = Integer.valueOf(split[1]);
+                randomInt = random.nextInt(to - from + 1) + from;
+                map.put(randomFound, randomInt);
+            }
+            data = data.replace(randomFound, String.valueOf(randomInt));
+        }
+        int randomInt;
+        if (map.containsKey("$")) {
+            randomInt = map.get("$");
+        } else {
+            randomInt = random.nextInt() & Integer.MAX_VALUE;
+            map.put("$", randomInt);
+        }
+        data = data.replace("$", String.valueOf(randomInt));
+        return data;
+    }
+
+    private String replaceOptionals(String data) {
+        Pattern pattern = Pattern.compile("<(.*?)>");
+        Matcher matcher = pattern.matcher(data);
+        Random random = new Random();
+        while (matcher.find()) {
+            String options = matcher.group();
+            String optionsTrimmed = options.substring(1, options.length() - 1);
+            String[] split = optionsTrimmed.split("\\|");
+            int nextInt = random.nextInt(split.length);
+            String choice = split[nextInt];
+            data = data.replace(options, choice);
+        }
+        return data;
+    }
+
     public Request bind(Request request, Session session) {
         if (request instanceof DeleteRequest) {
             DeleteRequest deleteRequest = (DeleteRequest) request;
diff --git a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
index c7a363f..eab37e3 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/requestssimulator/Session.java
@@ -48,10 +48,16 @@ public class Session {
         Random random = new Random();
         Request request = null;
         int probability = 0;
-        while (probability < 50) {
-            request = pickNextRequest(request);
+        while (probability < 70) {
+            try {
+                request = pickNextRequest(request);
+            } catch (RuntimeException ex) {
+                break;
+            }
             request.fire();
-            this.logs.add(request.toJsonObject());
+            JsonObject logRequest = request.toJsonObject();
+            logRequest.addProperty("time", System.currentTimeMillis());
+            this.logs.add(logRequest);
             probability = random.nextInt(100);
         }
     }