diff options
| author | XmiliaH <45106915+XmiliaH@users.noreply.github.com> | 2024-08-18 19:54:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-18 10:54:22 -0700 |
| commit | 31d17782f038e76e64cd8bf461e19c5817444a86 (patch) | |
| tree | dd3cdf97a9764926910d34b9d0b2196d7b89ac6a /chapter12/src/test/java | |
| parent | f246f90378ad4274c46952ffb1c5d71abbdc7341 (diff) | |
| download | Simple-31d17782f038e76e64cd8bf461e19c5817444a86.tar.gz Simple-31d17782f038e76e64cd8bf461e19c5817444a86.zip | |
Update fuzzer for chapter 12. (#104)
Diffstat (limited to 'chapter12/src/test/java')
| -rw-r--r-- | chapter12/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java | 2 | ||||
| -rw-r--r-- | chapter12/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java | 108 |
2 files changed, 73 insertions, 37 deletions
diff --git a/chapter12/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/chapter12/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index ab5c9bbd..3512d2e9 100644 --- a/chapter12/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/chapter12/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -135,7 +135,7 @@ public class Evaluator { case ConstantNode cons -> cons(cons); case AddNode add -> vall(add.in(1)) + vall(add.in(2)); case AddFNode add -> vald(add.in(1)) + vald(add.in(2)); - case BoolNode.EQF eq -> Objects.equals(val(eq.in(1)), val(eq.in(2))) ? 1L : 0L; + case BoolNode.EQF eq -> vald(eq.in(1)) == vald(eq.in(2)) ? 1L : 0L; case BoolNode.LEF le -> vald(le.in(1)) <= vald(le.in(2)) ? 1L : 0L; case BoolNode.LTF lt -> vald(lt.in(1)) < vald(lt.in(2)) ? 1L : 0L; case BoolNode.EQ eq -> Objects.equals(val(eq.in(1)), val(eq.in(2))) ? 1L : 0L; diff --git a/chapter12/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java b/chapter12/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java index 053be297..b8437b50 100644 --- a/chapter12/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java +++ b/chapter12/src/test/java/com/seaofnodes/simple/fuzzer/ScriptGenerator.java @@ -22,6 +22,7 @@ public class ScriptGenerator { private static final int MAX_NAME_LENGTH = 10; private static final int MAX_BLOCK_DEPTH = 4; private static final int MAX_EXPRESSION_DEPTH = 10; + private static final int MAX_SUFFIX_RECURSIVE_DEPTH = 10; /** * Number of spaces per indentation @@ -68,7 +69,7 @@ public class ScriptGenerator { } private static class TypeStruct extends Type { - record Field (String name, Type type) {} + record Field (String name, Type type, TypeStruct struct) {} final Field[] fields; final TypeNullable nullable = new TypeNullable(this); TypeStruct(String name, Field[] fields) { @@ -89,9 +90,22 @@ public class ScriptGenerator { } - private static final Type TYPE_INT = new Type("int"); private static final Type TYPE_FLT = new Type("flt"); + private static class TypeInt extends Type { + + TypeInt() { + super("int"); + } + + @Override + boolean isa(Type other) { + return super.isa(other) || other == TYPE_FLT; + } + } + + private static final Type TYPE_INT = new TypeInt(); + private static class Variable { final String name; @@ -414,17 +428,18 @@ public class ScriptGenerator { public int genStruct() { var name = getStructName(); var fields = new TypeStruct.Field[generateInvalid() ? 0 : random.nextInt(10)]; + var struct = new TypeStruct(name, fields); sb.append("struct ").append(name).append(" {\n"); indentation += INDENTATION; for (int i=0; i<fields.length; i++) { var fieldName = getRandomName(); - var type = generateInvalid() ? getType() : (random.nextBoolean() ? TYPE_INT : TYPE_FLT); + var type = getType(); printIndentation().append(type.name).append(" ").append(fieldName).append(";\n"); - fields[i] = new TypeStruct.Field(fieldName.toString(), type); + fields[i] = new TypeStruct.Field(fieldName.toString(), type, struct); } indentation -= INDENTATION; printIndentation().append("}"); - structs.add(new TypeStruct(name, fields)); + structs.add(struct); return 0; } @@ -518,7 +533,7 @@ public class ScriptGenerator { */ public int genIf() { sb.append("if("); - genExpression(TYPE_INT); + genExpression(TYPE_INT, true); sb.append(") "); var stop = genStatementBlock(); if ((stop & FLAG_IF_WITHOUT_ELSE) == 0 && random.nextInt(10) > 3) { @@ -564,7 +579,7 @@ public class ScriptGenerator { */ public int genWhile() { sb.append("while("); - genExpression(TYPE_INT); + genExpression(TYPE_INT, true); sb.append(") "); loopDepth++; genStatementBlock(); @@ -590,17 +605,17 @@ public class ScriptGenerator { indentation += INDENTATION; String name = getVarName(); printIndentation().append("int ").append(name).append("="); - genExpression(TYPE_INT); + genExpression(TYPE_INT, true); sb.append(";\n"); addVariable(name, TYPE_INT); printIndentation().append("while(").append(name).append("<"); - genExpression(TYPE_INT); + genExpression(TYPE_INT, true); sb.append(") {\n"); indentation += INDENTATION; depth--; loopDepth++; printIndentation().append(name).append("=").append(name).append("+"); - genExpression(TYPE_INT); + genExpression(TYPE_INT, true); sb.append(";\n"); genStatements(); loopDepth--; @@ -624,7 +639,7 @@ public class ScriptGenerator { sb.append(generateInvalid() ? getRandomName() : type.name).append(" ").append(name); if (!(type instanceof TypeNullable) || random.nextBoolean()) { sb.append("="); - genExpression(type); + genExpression(type, true); } sb.append(";"); addVariable(name, type); @@ -659,7 +674,7 @@ public class ScriptGenerator { declared = field.type; } sb.append("="); - genExpression(declared); + genExpression(declared, true); sb.append(";"); return 0; } @@ -671,7 +686,7 @@ public class ScriptGenerator { public int genReturn() { var type = getType(); sb.append("return "); - genExpression(type); + genExpression(type, true); sb.append(";"); return FLAG_STOP; } @@ -680,70 +695,91 @@ public class ScriptGenerator { * Generate a binary expression. * This method does not care about operator precedence. */ - public void genExpression(Type type) { - if (generateInvalid()) type = getType(); + public void genExpression(Type type, boolean change) { + if (change && generateInvalid()) type = getType(); if (type != TYPE_INT && type != TYPE_FLT) { - genUnary(type); + genUnary(type, false); return; } var num = randLog(MAX_BINARY_EXPRESSIONS_PER_EXPRESSION); while(num-->0) { - genUnary(type); + genUnary(type, false); sb.append(BINARY_OP[random.nextInt(BINARY_OP.length)]); } - genUnary(type); + genUnary(type, false); } /** * Generate a unary expression. */ - public void genUnary(Type type) { - if (generateInvalid()) type = getType(); + public void genUnary(Type type, boolean change) { + if (change && generateInvalid()) type = getType(); if (type != TYPE_INT && type != TYPE_FLT) { - genSuffix(type); + genSuffix(type, false); return; } var num = randLog(MAX_UNARY_EXPRESSIONS_PER_EXPRESSION); while(num-->0) { sb.append(UNARY_OP[random.nextInt(UNARY_OP.length)]); } - genSuffix(type); + genSuffix(type, false); + } + + public TypeStruct.Field getField(Type type) { + int n=0; + for (var s: structs) { + for (var f: s.fields) { + if (f.type.isa(type)) n++; + } + } + if (n==0) return null; + n = random.nextInt(n); + for (var s: structs) { + for (var f: s.fields) { + if (f.type.isa(type)) if (n--==0) return f; + } + } + throw new AssertionError(); } /** * Generate */ - public void genSuffix(Type type) { - if (generateInvalid()) type = getType(); - if ((type == TYPE_INT || type == TYPE_FLT) && random.nextBoolean()) { - var t = getType(); + public void genSuffix(Type type, boolean change) { + genSuffixRecursive(type, change, MAX_SUFFIX_RECURSIVE_DEPTH); + } + + public void genSuffixRecursive(Type type, boolean change, int depth) { + if (change && generateInvalid()) type = getType(); + if (depth > 0 && random.nextBoolean()) { if (generateInvalid()) { var field = getRandomName(); - genPrimary(t); + var t = getType(); + genSuffixRecursive(t, true, depth-1); sb.append(".").append(field); return; - } else if (t instanceof TypeStruct s && s.fields.length > 0) { - var field = s.fields[random.nextInt(s.fields.length)]; - if (field.type == TYPE_INT || field.type == TYPE_FLT) { - genPrimary(t); + } else { + var field = getField(type); + if (field != null) { + genSuffixRecursive(field.struct, true, depth-1); sb.append(".").append(field.name); return; } } } - genPrimary(type); + genPrimary(type, false); } /** * Generate a primary expression. */ - public void genPrimary(Type type) { - if (generateInvalid()) type = getType(); + public void genPrimary(Type type, boolean change) { + if (change && generateInvalid()) type = getType(); var rand = random.nextInt(10); if (rand == 0 && exprDepth != 0) { sb.append("("); exprDepth--; - genExpression(type); + genExpression(type, false); exprDepth++; sb.append(")"); } else if (rand < 6) { @@ -758,7 +794,7 @@ public class ScriptGenerator { */ public void genConst(Type type) { if (generateInvalid()) type = getType(); - if (type == TYPE_INT) { + if (type == TYPE_INT || (type == TYPE_FLT && random.nextBoolean())) { var rand = random.nextInt(10); switch (rand) { case 0 -> sb.append("true"); |
