From 151155c59dd6aac20c73e63756f9f099510f5163 Mon Sep 17 00:00:00 2001 From: Matthew Hague <matthew.hague@rhul.ac.uk> Date: Tue, 10 Nov 2020 19:13:21 +0000 Subject: [PATCH] Add support for constructing arrays in the logs Currently only for constructing "safe" arrays that you want to use as arguments to student code -- no failure messages provided if construction fails beyond the normal java reflection exceptions. Use Character[] cs = new Character[] { 'A', 'B', 'C' }; Object arr = codeTester.constructArray(char.class, cs); codeTester.construct("StudentClass", arr); An example would be if you want a log char[] c0 = new char[] { 'A', 'B', 'C' }; StudentClass sc0 = new StudentClass(c0); which is better than StudentClass sc0 = new StudentClass([c@a82324234); which it shows if you just passed "new char[] { 'A', 'B', 'C' }". --- .../uk/ac/rhul/cs/javatester/CodeTester.java | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/ac/rhul/cs/javatester/CodeTester.java b/src/main/java/uk/ac/rhul/cs/javatester/CodeTester.java index b7c6be0..53f9b16 100644 --- a/src/main/java/uk/ac/rhul/cs/javatester/CodeTester.java +++ b/src/main/java/uk/ac/rhul/cs/javatester/CodeTester.java @@ -5,6 +5,7 @@ import java.io.File; import java.lang.ClassLoader; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -280,6 +281,26 @@ public class CodeTester { throw new BaseTester.FailedTestException(expandMsg(msg)); } + /** + * Attempts to construct an array and log it + * + * @param klass the type of the array (can be e.g. int.class for + * primitives) + * @param values the values to fill array with + * @return the array + */ + public Object constructArray(Class<?> klass, Object[] values) { + Object array = Array.newInstance(klass, values.length); + for (int i = 0; i < values.length; i++) { + Array.set(array, i, values[i]); + } + + recordConstructArray(array, values); + + return array; + } + + /** * Convenience for constructMsg with default messages */ @@ -655,6 +676,28 @@ public class CodeTester { setLastCall("new " + className + "(" + paramsString + ")"); } + /** + * Record construction of an array with given values + * + * The values will be converted to (internal) variable names if they + * are object already constructed by this object. Else we rely on + * the toString method returning something useful. + */ + private void recordConstructArray(Object array, Object[] values) { + String name = getNewVariableName(array); + String className = getClassString(array.getClass()); + String valuesString = getParamsString(values); + + if (getIsRecording()) { + lines.add(className + " " + name + + " = new " + className + + " { " + valuesString + " }"); + } + + setLastCall("new " + className + " { " + valuesString + " }"); + } + + /** * Record a call method object with given params. */ @@ -748,6 +791,8 @@ public class CodeTester { if (name == null) { if (p instanceof String) name = "\"" + p + "\""; + else if (p instanceof Character) + name = "'" + p + "'"; else name = p.toString(); } @@ -787,7 +832,14 @@ public class CodeTester { if (Character.isUpperCase(c)) sb.append(Character.toLowerCase(c)); } - return sb.toString(); + + String base = sb.toString(); + + // primitive arrays will be empty this way + if (base.isEmpty()) + return Character.toString(className.charAt(0)); + else + return base; } /** -- GitLab