diff --git a/tool/src/main/java/migt/Check.java b/tool/src/main/java/migt/Check.java index 91cfa16..6db86b1 100644 --- a/tool/src/main/java/migt/Check.java +++ b/tool/src/main/java/migt/Check.java @@ -111,32 +111,48 @@ public Check(JSONObject json_check) throws ParsingException { break; case "is in": this.op = CheckOps.IS_IN; - JSONArray jsonArr = json_check.getJSONArray("is in"); - Iterator it = jsonArr.iterator(); - while (it.hasNext()) { - String act_enc = (String) it.next(); - value_list.add(act_enc); + if (json_check.has("use variable")) { + // inside "is in" a string with the name of the var is expected + this.op_val = json_check.getString("is in"); + } else { + JSONArray jsonArr = json_check.getJSONArray("is in"); + Iterator it = jsonArr.iterator(); + + while (it.hasNext()) { + String act_enc = (String) it.next(); + value_list.add(act_enc); + } } break; case "is not in": this.op = CheckOps.IS_NOT_IN; - JSONArray jsonArr2 = json_check.getJSONArray("is not in"); - Iterator it2 = jsonArr2.iterator(); - - while (it2.hasNext()) { - String act_enc = (String) it2.next(); - value_list.add(act_enc); + if (json_check.has("use variable")) { + // inside "is not in" a string with the name of the var is expected + this.op_val = json_check.getString("is not in"); + } else { + JSONArray jsonArr2 = json_check.getJSONArray("is not in"); + Iterator it2 = jsonArr2.iterator(); + + while (it2.hasNext()) { + String act_enc = (String) it2.next(); + value_list.add(act_enc); + } } break; case "is subset of": this.op = IS_SUBSET_OF; - JSONArray jsonArr3 = json_check.getJSONArray("is subset of"); - Iterator it3 = jsonArr3.iterator(); - - while (it3.hasNext()) { - String act_enc = (String) it3.next(); - value_list.add(act_enc); + if (json_check.has("use variable")) { + // inside "is subset of" a string with the name of the var is expected + this.op_val = json_check.getString("is subset of"); + } else { + JSONArray jsonArr3 = json_check.getJSONArray("is subset of"); + Iterator it3 = jsonArr3.iterator(); + + while (it3.hasNext()) { + String act_enc = (String) it3.next(); + value_list.add(act_enc); + } } break; case "json schema compliant": @@ -231,7 +247,14 @@ private boolean execute_regex(String input) throws ParsingException { * @throws ParsingException if something wrong is found wrt the language */ private boolean execute_http(HTTPReqRes message, - boolean isRequest) throws ParsingException { + boolean isRequest, + List vars) throws ParsingException { + + if (use_variable) { + Var v = Tools.getVariableByName(op_val, vars); + op_val = v.get_value_string(); + } + String msg_str = ""; if (this.in == null) { throw new ParsingException("from tag in checks is null"); @@ -328,13 +351,34 @@ private String url_decode(String string) { * @return the result of the execution * @throws ParsingException if something wrong is found wrt the language */ - private boolean execute_json() throws ParsingException { + private boolean execute_json(List vars) throws ParsingException { DecodeOperation_API tmp = ((DecodeOperation_API) this.imported_api); if (isParamCheck) { throw new ParsingException("Cannot execute a 'check param' in a json, please use 'check'"); } + Var v = null; + + if (use_variable) { + // Substitute to the op_val variable (that contains the name), the value of the variable + v = Tools.getVariableByName(op_val, vars); + + // TODO: check for variable type and check operation compatibility + switch (v.getType()) { + case STRING: + op_val = v.get_value_string(); + break; + case JSON_ARRAY: // if the variable is a json array, substitute the value_list + for (Object el : ((JSONArray) v.value).toList()) { + value_list.add(el.toString()); // TODO check for unwanted scenarios when converting to string + } + break; + default: + throw new ParsingException("Invalid variable type to be used in check"); + } + } + String j = ""; switch (in) { @@ -578,11 +622,8 @@ public boolean execute(HTTPReqRes message, boolean isRequest, List vars) throws ParsingException { - if (use_variable) { - // Substitute to the op_val variable (that contains the name), the value of the variable - op_val = Tools.getVariableByName(op_val, vars).value; - } - result = execute_http(message, isRequest); + + result = execute_http(message, isRequest, vars); return result; } @@ -592,26 +633,18 @@ public boolean execute(HTTPReqRes message, * @param vars the variables of the actual operation (test) */ public void execute(List vars) throws ParsingException { - if (use_variable) { - // Substitute to the op_val variable (that contains the name), the value of the variable - op_val = Tools.getVariableByName(op_val, vars).value; - - // URL-decode variable value - // when a string contains a "+" character then, it is replaced with a space. - op_val = url_decode(op_val); - } - if (imported_api instanceof Operation_API) { // If is inside a standard Operation result = execute_http( ((Operation_API) imported_api).message, - ((Operation_API) imported_api).is_request + ((Operation_API) imported_api).is_request, + vars ); } else if (imported_api instanceof DecodeOperation_API) { // if inside a decode operation switch (((DecodeOperation_API) imported_api).type) { case JWT: - result = execute_json(); + result = execute_json(vars); break; case NONE: //TODO diff --git a/tool/src/main/java/migt/EditOperation.java b/tool/src/main/java/migt/EditOperation.java index 36ea98a..0e74689 100644 --- a/tool/src/main/java/migt/EditOperation.java +++ b/tool/src/main/java/migt/EditOperation.java @@ -301,10 +301,7 @@ public void execute_decodeOperation_API(List vars) throws ParsingException String to_save = XML.getTagValaue(edited_xml, xml_action_name, xml_occurrency); - Var v = new Var(); - v.name = save_as; - v.isMessage = false; - v.value = to_save; + Var v = new Var(save_as, to_save); vars.add(v); break; } @@ -312,10 +309,7 @@ public void execute_decodeOperation_API(List vars) throws ParsingException String to_save = XML.getTagAttributeValue(edited_xml, xml_tag, xml_action_name, xml_occurrency); - Var v = new Var(); - v.name = save_as; - v.isMessage = false; - v.value = to_save; + Var v = new Var(save_as, to_save); vars.add(v); break; } @@ -395,10 +389,7 @@ public void execute_decodeOperation_API(List vars) throws ParsingException break; } - Var v = new Var(); - v.name = save_as; - v.isMessage = false; - v.value = val; + Var v = new Var(save_as, val); vars.add(v); break; } @@ -538,11 +529,7 @@ public void execute(List vars) throws ParsingException { // If a variable value has to be used, read the value of the variable at execution time if (!use.equals("")) { Var v = getVariableByName(use, vars); - if (!v.isMessage) { - value = v.value; - } else { - throw new ParsingException("Error while using variable, expected text var, got message var"); - } + value = v.get_value_string(); } if (imported_api instanceof DecodeOperation_API) { diff --git a/tool/src/main/java/migt/ExecuteTrack.java b/tool/src/main/java/migt/ExecuteTrack.java index 908c35c..38e2888 100644 --- a/tool/src/main/java/migt/ExecuteTrack.java +++ b/tool/src/main/java/migt/ExecuteTrack.java @@ -208,9 +208,7 @@ public void run() { continue; } case SET_VAR: { - Var v = new Var(); - v.name = action.elem; - v.value = action.content; + Var v = new Var(action.elem, action.content); listener.onSetVar(v); continue; } diff --git a/tool/src/main/java/migt/MessageOperation.java b/tool/src/main/java/migt/MessageOperation.java index e10fe1c..4211e12 100644 --- a/tool/src/main/java/migt/MessageOperation.java +++ b/tool/src/main/java/migt/MessageOperation.java @@ -113,7 +113,8 @@ public MessageOperation(JSONObject message_op_json) throws ParsingException { */ public static String getAdding(MessageOperation m, List vars) throws ParsingException { if (!m.use.isEmpty()) { - return getVariableByName(m.use, vars).value; + Var v = getVariableByName(m.use, vars); + return v.get_value_string(); } else { return m.to; @@ -336,10 +337,7 @@ public Operation execute(Operation op) throws ParsingException { } } - Var v = new Var(); - v.name = mop.save_as; - v.isMessage = false; - v.value = value; + Var v = new Var(mop.save_as, value); op.api.vars.add(v); break; } @@ -347,15 +345,14 @@ public Operation execute(Operation op) throws ParsingException { String tmp = new String(op.api.message.getBody(op.api.is_request), StandardCharsets.UTF_8); pattern = Pattern.compile(mop.what); matcher = pattern.matcher(tmp); - Var v = new Var(); + Var v = null; while (matcher.find()) { - v.name = mop.save_as; - v.isMessage = false; - v.value = matcher.group(); + v = new Var(mop.save_as, matcher.group()); break; } - op.api.vars.add(v); + if (v != null) + op.api.vars.add(v); break; } case URL: { @@ -378,10 +375,7 @@ public Operation execute(Operation op) throws ParsingException { matched.split("=")[1] : matched; - Var v = new Var(); - v.name = mop.save_as; - v.isMessage = false; - v.value = value; + Var v = new Var(mop.save_as, value); op.api.vars.add(v); } break; diff --git a/tool/src/main/java/migt/Operation.java b/tool/src/main/java/migt/Operation.java index f5a3612..3939fff 100644 --- a/tool/src/main/java/migt/Operation.java +++ b/tool/src/main/java/migt/Operation.java @@ -270,52 +270,50 @@ public List executeSessionOps(Test t, //TODO add this to the input api of O switch (sop.action) { case SAVE: - Var v = new Var(); - v.name = sop.as; - v.isMessage = false; - v.value = ""; + String value = ""; switch (sop.target) { case TRACK: for (SessionTrackAction sa : t.getSession(sop.from_session).track .getStasFromMarkers(sop.at, sop.to, sop.is_from_included, sop.is_to_included)) { - v.value += sa.toString() + "\n"; + value += sa.toString() + "\n"; } break; case LAST_ACTION: - v.value = session.last_action.toString(); + value = session.last_action.toString(); break; case LAST_ACTION_ELEM: - v.value = session.last_action.elem; + value = session.last_action.elem; break; case LAST_ACTION_ELEM_PARENT: - v.value = findParentDiv(session.last_action.elem); + value = findParentDiv(session.last_action.elem); break; case LAST_CLICK: - v.value = session.last_click.toString(); + value = session.last_click.toString(); break; case LAST_CLICK_ELEM: - v.value = session.last_click.elem; + value = session.last_click.elem; break; case LAST_CLICK_ELEM_PARENT: - v.value = findParentDiv(session.last_click.elem); + value = findParentDiv(session.last_click.elem); break; case LAST_OPEN: - v.value = session.last_open.toString(); + value = session.last_open.toString(); break; case LAST_OPEN_ELEM: - v.value = session.last_open.elem; + value = session.last_open.elem; break; case LAST_URL: - v.value = session.last_url; + value = session.last_url; break; case ALL_ASSERT: for (SessionTrackAction sa : t.getSession(sop.from_session).track.getTrack()) { if (sa.isAssert) { - v.value += sa + "\n"; + value += sa + "\n"; } } break; } + Var v = new Var(sop.as, value); updated_vars.add(v); break; @@ -430,9 +428,9 @@ public void execute() { if (api.is_request) { if (!replace_request_name.equals("")) { try { + Var v = getVariableByName(replace_request_name, api.vars); + processed_message = v.get_value_message(); applicable = true; - processed_message = getVariableByName(replace_request_name, api.vars).message; - //return op; } catch (ParsingException e) { e.printStackTrace(); applicable = false; @@ -442,9 +440,9 @@ public void execute() { } else { if (!replace_response_name.equals("")) { try { + Var v = getVariableByName(replace_response_name, api.vars); + processed_message = v.get_value_message(); applicable = true; - processed_message = getVariableByName(replace_response_name, api.vars).message; - //return op; } catch (ParsingException e) { e.printStackTrace(); applicable = false; @@ -491,10 +489,10 @@ public void execute() { } if (!save_name.equals("")) { - Var v = new Var(); - v.name = save_name; - v.isMessage = true; - v.message = api.is_request ? api.message.getRequest() : api.message.getResponse(); + Var v = new Var( + save_name, + api.is_request ? api.message.getRequest() : api.message.getResponse() + ); api.vars.add(v); } } diff --git a/tool/src/main/java/migt/Test.java b/tool/src/main/java/migt/Test.java index 3b838e7..df46316 100644 --- a/tool/src/main/java/migt/Test.java +++ b/tool/src/main/java/migt/Test.java @@ -278,7 +278,11 @@ public void logTest(String log_folder) { test_log_content += "Variables: \n"; for (Var v : vars) { - test_log_content += v.name = v.value + "\n"; + try { + test_log_content += v.name = v.value + "\n"; + } catch (Exception e) { + e.printStackTrace(); + } } File test_log = new File(test_log_path); diff --git a/tool/src/main/java/migt/Tools.java b/tool/src/main/java/migt/Tools.java index ea7b94b..2ea6bbc 100644 --- a/tool/src/main/java/migt/Tools.java +++ b/tool/src/main/java/migt/Tools.java @@ -354,7 +354,9 @@ public static String buildStringWithVars(List vars, String s) throws Parsin while (m.find()) { String act_match = m.group(); act_match = act_match.replaceAll("\\$", ""); - req_var.put(act_match, getVariableByName(act_match, vars).value); + + Var v = getVariableByName(act_match, vars); + req_var.put(act_match, v.get_value_string()); } if (req_var.isEmpty()) { @@ -756,10 +758,21 @@ public static String editJson(EditOperation.Jwt_action action, //TODO: check if set also adds in case it is not found break; case SAVE: - Var v = new Var(); - v.name = save_as; - v.isMessage = false; - v.value = JsonPath.read(content, j_path); //TODO could rise errors + Object to_save = JsonPath.read(content, j_path); + + Var v = null; + if (to_save instanceof String) { + v = new Var(save_as, (String) to_save); + } else if (to_save instanceof Double) { + v = new Var(save_as, ((Double) to_save).toString()); + } else if (to_save instanceof Integer) { + v = new Var(save_as, ((Integer) to_save).toString()); + } else if (to_save instanceof net.minidev.json.JSONArray) { + v = new Var(save_as, ((net.minidev.json.JSONArray) to_save).toJSONString()); + } else { + throw new RuntimeException("Invalid type of saving variable"); + } + vars.add(v); break; } diff --git a/tool/src/main/java/migt/Var.java b/tool/src/main/java/migt/Var.java index b09ef77..188fd1e 100644 --- a/tool/src/main/java/migt/Var.java +++ b/tool/src/main/java/migt/Var.java @@ -1,26 +1,106 @@ package migt; +import org.json.JSONArray; + /** * The class storing the variables used in the test and sessions */ public class Var { public String name; - public String value; - public byte[] message; - public boolean isMessage; // tells if a variable contains a message + public Object value; /** - * Istantiate a Var object + * Instantiate a Var object */ public Var() { this.name = ""; this.value = ""; - this.isMessage = false; } - public Var(String name, String value, Boolean isMessage) { + /** + * Constructor for variables that have a String Value + * + * @param name the name of the var + * @param value the String value of the var + */ + public Var(String name, String value) { + this.name = name; + this.value = value; + } + + /** + * Constructor for variables that have a message value + * + * @param name the name of the variable + * @param message the value of the message as String + */ + public Var(String name, byte[] message) { + this.name = name; + this.value = message; + } + + /** + * Constructor for variable that have a JSON array value + * + * @param name the name of the variable + * @param value the value of the JSON array + */ + public Var(String name, JSONArray value) { this.name = name; this.value = value; - this.isMessage = isMessage; + } + + /** + * Get the type of the value of the variable + * + * @return the type of the value of the variable + */ + public VarType getType() { + if (value instanceof String) { + return VarType.STRING; + } else if (value instanceof byte[]) { + return VarType.MESSAGE; + } else if (value instanceof JSONArray) { + return VarType.JSON_ARRAY; + } else { + throw new RuntimeException("The type of the variable is not valid"); + } + } + + /** + * Use this function to get the value of this variable expecting that it is a String + * + * @return the string value of this variable only if it is a string + * @throws ParsingException if the value of this variable is not a string + */ + public String get_value_string() throws ParsingException { + if (this.getType() != VarType.STRING) { + throw new ParsingException("Variable " + this.name + "'s value is not a string"); + } + + return (String) value; + } + + /** + * Use this function to get the value of this variable expecting that it is storing an HTTP message + * + * @return the http message in byte[] format + * @throws ParsingException if the value of the variable is not a message + */ + public byte[] get_value_message() throws ParsingException { + if (this.getType() != VarType.MESSAGE) { + throw new ParsingException("Variable " + this.name + "'s value is not a message"); + } + + return (byte[]) value; + } + + /** + * Enum containing all the possible types of variables + */ + public enum VarType { + STRING, + MESSAGE, + JSON_ARRAY } } diff --git a/tool/src/test/java/Checks_Test.java b/tool/src/test/java/Checks_Test.java index d608638..d6a9980 100644 --- a/tool/src/test/java/Checks_Test.java +++ b/tool/src/test/java/Checks_Test.java @@ -1,4 +1,5 @@ import migt.*; +import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -184,7 +185,7 @@ void test_check_use_variable() throws ParsingException { "}"; List vars = new ArrayList(); - vars.add(new Var("variablename", "abc", false)); + vars.add(new Var("variablename", "abc")); Check c = initCheck_json(check_str); c.execute(vars); @@ -202,7 +203,7 @@ void test_check_use_variable_wrong() throws ParsingException { "}"; List vars = new ArrayList(); - vars.add(new Var("variablename", "ac", false)); + vars.add(new Var("variablename", "ac")); Check c = initCheck_json(check_str); c.execute(vars); @@ -265,6 +266,48 @@ void test_check_json_array_is_subset_of_ok() throws ParsingException { assertTrue(c.getResult()); } + @Test + @DisplayName("check") + void test_check_json_array_is_subset_of_variable_ok() throws ParsingException { + Var v = new Var("var1", new JSONArray("[\"123\", \"abc\",\"cde\", \"altro\"]")); + + String check_str = "{\n" + + " \"in\": \"header\",\n" + + " \"check\": \"$.pageInfo.entry\",\n" + + " \"is subset of\": \"var1\",\n" + + " \"use variable\": true\n" + + "}"; + + Check c = initCheck_json(check_str); + + List vars = new ArrayList(); + vars.add(v); + + c.execute(vars); + assertTrue(c.getResult()); + } + + @Test + @DisplayName("check") + void test_check_json_array_is_subset_of_variable_not_ok() throws ParsingException { + Var v = new Var("var1", new JSONArray("[\"123\", \"abc\",\"fgh\", \"altro\"]")); + + String check_str = "{\n" + + " \"in\": \"header\",\n" + + " \"check\": \"$.pageInfo.entry\",\n" + + " \"is subset of\": \"var1\",\n" + + " \"use variable\": true\n" + + "}"; + + Check c = initCheck_json(check_str); + + List vars = new ArrayList(); + vars.add(v); + + c.execute(vars); + assertFalse(c.getResult()); + } + @Test @DisplayName("check") void test_check_json_array_is_subset_of_wrong() throws ParsingException { diff --git a/tool/src/test/java/Utils_Test.java b/tool/src/test/java/Utils_Test.java index a6d73c9..eb04f17 100644 --- a/tool/src/test/java/Utils_Test.java +++ b/tool/src/test/java/Utils_Test.java @@ -16,16 +16,10 @@ public class Utils_Test { @DisplayName("Testing build string with vars") void testBuildStringWithVars() throws ParsingException { List vars = new ArrayList<>(); - Var v = new Var(); - v.name = "questo"; - v.isMessage = false; - v.value = "provona"; + Var v = new Var("questo", "provona"); vars.add(v); - Var v2 = new Var(); - v2.name = "qualcosaltro"; - v2.isMessage = false; - v2.value = "prova"; + Var v2 = new Var("qualcosaltro", "prova"); vars.add(v2); String s = "test da aggiungere $questo$ e poi $qualcosaltro$"; @@ -38,16 +32,10 @@ void testBuildStringWithVars() throws ParsingException { assertEquals("test da aggiungere provona e poi prova", res); s = "open | https://$var3$$var4$ |"; - Var v3 = new Var(); - v3.name = "var3"; - v3.isMessage = false; - v3.value = "www.youtube.com"; + Var v3 = new Var("var3", "www.youtube.com"); vars.add(v3); - Var v4 = new Var(); - v4.name = "var4"; - v4.isMessage = false; - v4.value = "/link/a/caso"; + Var v4 = new Var("var4", "/link/a/caso"); vars.add(v4); res = Tools.buildStringWithVars(vars, s); diff --git a/tool/src/test/java/Var_Test.java b/tool/src/test/java/Var_Test.java new file mode 100644 index 0000000..b735143 --- /dev/null +++ b/tool/src/test/java/Var_Test.java @@ -0,0 +1,43 @@ +import migt.HTTPReqRes; +import migt.ParsingException; +import migt.Var; +import org.json.JSONArray; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Var_Test { + + @Test + void test_var_string() throws ParsingException { + Var v = new Var("prova", "provona"); + + assertEquals(v.name, "prova"); + assertEquals(v.value, "provona"); + assertEquals(v.getType(), Var.VarType.STRING); + } + + @Test + void test_var_message() throws ParsingException { + + HTTPReqRes message = HTTPReqRes_Test.initMessage_ok(); + + Var v = new Var("prova", message.getRequest()); + + assertEquals(v.name, "prova"); + assertEquals(v.value, message.getRequest()); + assertEquals(v.get_value_message(), message.getRequest()); + assertEquals(v.getType(), Var.VarType.MESSAGE); + } + + @Test + void test_var_json_array() { + JSONArray ja = new JSONArray("[\"first\", \"second\"]"); + + Var v = new Var("var1", ja); + + assertEquals(v.name, "var1"); + assertEquals(v.value, ja); + assertEquals(v.getType(), Var.VarType.JSON_ARRAY); + } +}