diff --git a/classes/swen90006/machine/BoundaryTests.class b/classes/swen90006/machine/BoundaryTests.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/BugException.class b/classes/swen90006/machine/BugException.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/InvalidInstructionException.class b/classes/swen90006/machine/InvalidInstructionException.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/Machine.class b/classes/swen90006/machine/Machine.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/NoReturnValueException.class b/classes/swen90006/machine/NoReturnValueException.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/PartitioningTests.class b/classes/swen90006/machine/PartitioningTests.class old mode 100644 new mode 100755 diff --git a/classes/swen90006/machine/SimpleDriver.class b/classes/swen90006/machine/SimpleDriver.class old mode 100644 new mode 100755 diff --git a/mutants/mutant-1/swen90006/machine/BugException.java b/mutants/mutant-1/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-1/swen90006/machine/InvalidInstructionException.java b/mutants/mutant-1/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-1/swen90006/machine/Machine.java b/mutants/mutant-1/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..7bc6c5c8212d8096f83fcc54f16736dda6fb4191 --- a/mutants/mutant-1/swen90006/machine/Machine.java +++ b/mutants/mutant-1/swen90006/machine/Machine.java @@ -237,7 +237,7 @@ public class Machine } else if (toks[0].equals(INSTRUCTION_RETURN)){ int rs = parseReg(toks[1]); count++; - return regs[rs]; + return Math.abs(regs[rs]); } else if (toks[0].equals(INSTRUCTION_LOAD)){ if (toks.length != 4){ throw new InvalidInstructionException(); diff --git a/mutants/mutant-1/swen90006/machine/NoReturnValueException.java b/mutants/mutant-1/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-1/swen90006/machine/SimpleDriver.java b/mutants/mutant-1/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-2/swen90006/machine/BugException.java b/mutants/mutant-2/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-2/swen90006/machine/InvalidInstructionException.java b/mutants/mutant-2/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-2/swen90006/machine/Machine.java b/mutants/mutant-2/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..511c04ab54619aaa178cc1cc6b5a40b69eefd059 --- a/mutants/mutant-2/swen90006/machine/Machine.java +++ b/mutants/mutant-2/swen90006/machine/Machine.java @@ -83,7 +83,7 @@ public class Machine private void do_load(int dest, int src, int offs) { if (regs[src] + offs > MAX_ADDR){ /* no op */ - }else if(regs[src] + offs < 0){ + }else if(regs[src] + offs <= 0){ /* no op */ }else{ regs[dest] = memory[regs[src] + offs]; diff --git a/mutants/mutant-2/swen90006/machine/NoReturnValueException.java b/mutants/mutant-2/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-2/swen90006/machine/SimpleDriver.java b/mutants/mutant-2/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-3/swen90006/machine/BugException.java b/mutants/mutant-3/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-3/swen90006/machine/InvalidInstructionException.java b/mutants/mutant-3/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-3/swen90006/machine/Machine.java b/mutants/mutant-3/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..bc76510f5a37026b3503ff5ea34eebd26fa7d15d --- a/mutants/mutant-3/swen90006/machine/Machine.java +++ b/mutants/mutant-3/swen90006/machine/Machine.java @@ -170,7 +170,7 @@ public class Machine int pc = 0; final int progLength = instructions.size(); while(true){ - if (pc < 0 || pc >= progLength){ + if (pc < 0 && pc >= progLength){ /* will cause NoReturnValueException to be thrown * but that is not a bug and and indeed is what the * VM is supposed to do if the pc becomes negative, @@ -278,7 +278,7 @@ public class Machine if (regs[ra] == 0){ pc = pc + offs; }else{ - pc = pc + 1; + pc = pc / 1; } count++; continue; /* avoid default increment the pc below */ diff --git a/mutants/mutant-3/swen90006/machine/NoReturnValueException.java b/mutants/mutant-3/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-3/swen90006/machine/SimpleDriver.java b/mutants/mutant-3/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-4/swen90006/machine/BugException.java b/mutants/mutant-4/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-4/swen90006/machine/InvalidInstructionException.java b/mutants/mutant-4/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-4/swen90006/machine/Machine.java b/mutants/mutant-4/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..eb7249fbb435213fb71a654147ec88aca585d522 --- a/mutants/mutant-4/swen90006/machine/Machine.java +++ b/mutants/mutant-4/swen90006/machine/Machine.java @@ -140,7 +140,7 @@ public class Machine private void validate_reg(int reg) throws InvalidInstructionException { - if (reg < 0 || reg > MAX_REG) { + if (reg < 0 || reg >= MAX_REG) { throw new InvalidInstructionException(); } } diff --git a/mutants/mutant-4/swen90006/machine/NoReturnValueException.java b/mutants/mutant-4/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-4/swen90006/machine/SimpleDriver.java b/mutants/mutant-4/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-5/swen90006/machine/BugException.java b/mutants/mutant-5/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-5/swen90006/machine/InvalidInstructionException.java b/mutants/mutant-5/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-5/swen90006/machine/Machine.java b/mutants/mutant-5/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..a56907ab061d2c2cdfa9b43385b06b0bcd136701 --- a/mutants/mutant-5/swen90006/machine/Machine.java +++ b/mutants/mutant-5/swen90006/machine/Machine.java @@ -148,7 +148,7 @@ public class Machine private void validate_offset(int offset) throws InvalidInstructionException { - if (offset < -MAX_ADDR || offset > MAX_ADDR) { + if (offset < -MAX_ADDR || offset >= MAX_ADDR) { throw new InvalidInstructionException(); } } diff --git a/mutants/mutant-5/swen90006/machine/NoReturnValueException.java b/mutants/mutant-5/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/mutants/mutant-5/swen90006/machine/SimpleDriver.java b/mutants/mutant-5/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/src/swen90006/machine/BugException.java b/src/swen90006/machine/BugException.java old mode 100644 new mode 100755 diff --git a/src/swen90006/machine/InvalidInstructionException.java b/src/swen90006/machine/InvalidInstructionException.java old mode 100644 new mode 100755 diff --git a/src/swen90006/machine/Machine.java b/src/swen90006/machine/Machine.java old mode 100644 new mode 100755 index 9bf57316d1c736ea2bd1c62bd6df3c6c0282f331..92d3b56553b579c2419f7ff1245bcee45f1af3f8 --- a/src/swen90006/machine/Machine.java +++ b/src/swen90006/machine/Machine.java @@ -3,301 +3,301 @@ package swen90006.machine; import java.util.Arrays; import java.util.List; -public class Machine +public class Machine { - /** arithmetic instructions each take three registers as arguments with the - * destination register appearing first - */ - - /** add rd rs1 rs2 =~ rd = rs1 + rs2 */ - public static final String INSTRUCTION_ADD = "add"; - - /** sub rd rs1 rs2 =~ rd = rs1 - rs2 */ - public static final String INSTRUCTION_SUBTRACT = "sub"; - - /** mul rd rs1 rs2 =~ rd = rs1 * rs2 */ - public static final String INSTRUCTION_MULT = "mul"; - - /** div rd rs1 rs2 =~ rd = rs1 / rs2 */ - public static final String INSTRUCTION_DIVIDE = "div"; - - /** ret rs =~ return rs */ - public static final String INSTRUCTION_RETURN = "ret"; - - /** ldr rd rs offs =~ rd = rs[offs] */ - public static final String INSTRUCTION_LOAD = "ldr"; - - /** str ra offs rb =~ ra[offs] = rb */ - public static final String INSTRUCTION_STORE = "str"; - - /** mov rd val =~ rd = val */ - public static final String INSTRUCTION_MOVE = "mov"; - - /** jmp offs =~ pc = pc + offs */ - public static final String INSTRUCTION_JUMP = "jmp"; - - /** jz ra offs =~ if (ra == 0) pc = pc + offs else pc = pc + 1 */ - public static final String INSTRUCTION_JZ = "jz"; - - public static final int NUM_REGS = 32; - public static final int MAX_REG = (NUM_REGS - 1); - public static final int MEMORY_SIZE = 65536; /* 4 x as much memory as a 64 */ - public static final int MAX_ADDR = MEMORY_SIZE-1; - - private int[] memory; - private int[] regs; - - private int count = 0; /* counts number of instructions executed so far */ - - public Machine() - { - memory = new int[MEMORY_SIZE]; - regs = new int[NUM_REGS]; - count = 0; - } - - private void do_add(int dest, int src1, int src2) - { - regs[dest] = regs[src1] + regs[src2]; - } - - private void do_sub(int dest, int src1, int src2) - { - regs[dest] = regs[src1] - regs[src2]; - } - - private void do_mult(int dest, int src1, int src2) - { - regs[dest] = regs[src1] * regs[src2]; - } - - private void do_div(int dest, int src1, int src2) - { - if (regs[src2] == 0){ - /* no op */ - }else{ - regs[dest] = regs[src1] / regs[src2]; + /** arithmetic instructions each take three registers as arguments with the + * destination register appearing first + */ + + /** add rd rs1 rs2 =~ rd = rs1 + rs2 */ + public static final String INSTRUCTION_ADD = "add"; + + /** sub rd rs1 rs2 =~ rd = rs1 - rs2 */ + public static final String INSTRUCTION_SUBTRACT = "sub"; + + /** mul rd rs1 rs2 =~ rd = rs1 * rs2 */ + public static final String INSTRUCTION_MULT = "mul"; + + /** div rd rs1 rs2 =~ rd = rs1 / rs2 */ + public static final String INSTRUCTION_DIVIDE = "div"; + + /** ret rs =~ return rs */ + public static final String INSTRUCTION_RETURN = "ret"; + + /** ldr rd rs offs =~ rd = rs[offs] */ + public static final String INSTRUCTION_LOAD = "ldr"; + + /** str ra offs rb =~ ra[offs] = rb */ + public static final String INSTRUCTION_STORE = "str"; + + /** mov rd val =~ rd = val */ + public static final String INSTRUCTION_MOVE = "mov"; + + /** jmp offs =~ pc = pc + offs */ + public static final String INSTRUCTION_JUMP = "jmp"; + + /** jz ra offs =~ if (ra == 0) pc = pc + offs else pc = pc + 1 */ + public static final String INSTRUCTION_JZ = "jz"; + + public static final int NUM_REGS = 32; + public static final int MAX_REG = (NUM_REGS - 1); + public static final int MEMORY_SIZE = 65536; /* 4 x as much memory as a 64 */ + public static final int MAX_ADDR = MEMORY_SIZE-1; + + private int[] memory; + private int[] regs; + + private int count = 0; /* counts number of instructions executed so far */ + + public Machine() + { + memory = new int[MEMORY_SIZE]; + regs = new int[NUM_REGS]; + count = 0; } - } - - private void do_load(int dest, int src, int offs) { - if (regs[src] + offs > MAX_ADDR){ - /* no op */ - }else if(regs[src] + offs < 0){ - /* no op */ - }else{ - regs[dest] = memory[regs[src] + offs]; + + private void do_add(int dest, int src1, int src2) + { + regs[dest] = regs[src1] + regs[src2]; } - } - - private void do_store(int a, int offs, int b) { - if (regs[a] + offs > MAX_ADDR){ - /* no op */ - }else if(regs[a] + offs < 0){ - /* no op */ - }else{ - memory[regs[a] + offs] = regs[b]; + + private void do_sub(int dest, int src1, int src2) + { + regs[dest] = regs[src1] - regs[src2]; } - } - private void do_move(int rd, int val){ - regs[rd] = val; - } + private void do_mult(int dest, int src1, int src2) + { + regs[dest] = regs[src1] * regs[src2]; + } - private int parseReg(String s) throws InvalidInstructionException - { - if (s.length() < 2){ - throw new InvalidInstructionException(); + private void do_div(int dest, int src1, int src2) + { + if (regs[src2] == 0){ + /* no op */ + }else{ + regs[dest] = regs[src1] / regs[src2]; + } } - if (s.charAt(0) != 'r'){ - throw new InvalidInstructionException(); + + private void do_load(int dest, int src, int offs) { + if (regs[src] + offs > MAX_ADDR){ + /* no op */ + }else if(regs[src] + offs < 0){ + /* no op */ + }else{ + regs[dest] = memory[regs[src] + offs]; + } } - String numstr = s.substring(1); - int num = 0; - try { - num = Integer.parseInt(numstr); - } catch (Exception e){ - throw new InvalidInstructionException(); + + private void do_store(int a, int offs, int b) { + if (regs[a] + offs > MAX_ADDR){ + /* no op */ + }else if(regs[a] + offs < 0){ + /* no op */ + }else{ + memory[regs[a] + offs] = regs[b]; + } } - validate_reg(num); - return num; - } - - private int parseOffset(String s) - throws InvalidInstructionException - { - int num = 0; - try { - num = Integer.parseInt(s); - } catch (Exception e){ - throw new InvalidInstructionException(); + + private void do_move(int rd, int val){ + regs[rd] = val; } - validate_offset(num); - return num; - } + private int parseReg(String s) throws InvalidInstructionException + { + if (s.length() < 2){ + throw new InvalidInstructionException(); + } + if (s.charAt(0) != 'r'){ + throw new InvalidInstructionException(); + } + String numstr = s.substring(1); + int num = 0; + try { + num = Integer.parseInt(numstr); + } catch (Exception e){ + throw new InvalidInstructionException(); + } + validate_reg(num); + return num; + } - private void validate_reg(int reg) - throws InvalidInstructionException - { - if (reg < 0 || reg > MAX_REG) { - throw new InvalidInstructionException(); + private int parseOffset(String s) + throws InvalidInstructionException + { + int num = 0; + try { + num = Integer.parseInt(s); + } catch (Exception e){ + throw new InvalidInstructionException(); + } + validate_offset(num); + return num; } - } - private void validate_offset(int offset) - throws InvalidInstructionException - { - if (offset < -MAX_ADDR || offset > MAX_ADDR) { - throw new InvalidInstructionException(); + + private void validate_reg(int reg) + throws InvalidInstructionException + { + if (reg < 0 || reg > MAX_REG) { + throw new InvalidInstructionException(); + } } - } - - /** Execute an assembly program. - * - * @param prog is the program to execute as an iterable collection of strings, - * each of which is a single instruction. - * @return the program's return value. - * @throws Exception when program has unrecognised or - * invalid instructions, or when it returns no result when it finishes - */ - int execute(List<String> instructions) - throws InvalidInstructionException, - NoReturnValueException - { - - int instructionsExecuted = 0; - int pc = 0; - final int progLength = instructions.size(); - while(true){ - if (pc < 0 || pc >= progLength){ - /* will cause NoReturnValueException to be thrown - * but that is not a bug and and indeed is what the - * VM is supposed to do if the pc becomes negative, - * since in this case the program's execution - * finishes early without a return value having - * been produced. */ - break; - } - String inst = instructions.get(pc); - /* strip leading and trailing whitespace */ - inst = inst.toLowerCase().replaceAll("^\\s+","").replaceAll("\\s+$",""); - /* strip out any comments */ - String[] toks = inst.split(";"); - inst = toks[0]; - - /* check for blank lines */ - if (inst.equals("")){ - pc = pc + 1; - count++; - continue; - } - - instructionsExecuted++; - /* now tokenize by splitting on whitespace */ - toks = inst.split("\\s+"); - - /* check minimum number of tokens */ - if (toks.length < 2){ - throw new InvalidInstructionException(); - } - - if (toks[0].equals(INSTRUCTION_ADD)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int rs1 = parseReg(toks[2]); - int rs2 = parseReg(toks[3]); - do_add(rd,rs1,rs2); - } else if (toks[0].equals(INSTRUCTION_SUBTRACT)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int rs1 = parseReg(toks[2]); - int rs2 = parseReg(toks[3]); - do_sub(rd,rs1,rs2); - } else if (toks[0].equals(INSTRUCTION_MULT)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int rs1 = parseReg(toks[2]); - int rs2 = parseReg(toks[3]); - do_mult(rd,rs1,rs2); - } else if (toks[0].equals(INSTRUCTION_DIVIDE)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int rs1 = parseReg(toks[2]); - int rs2 = parseReg(toks[3]); - do_div(rd,rs1,rs2); - } else if (toks[0].equals(INSTRUCTION_RETURN)){ - int rs = parseReg(toks[1]); - count++; - return regs[rs]; - } else if (toks[0].equals(INSTRUCTION_LOAD)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int rs = parseReg(toks[2]); - int offs = parseOffset(toks[3]); - do_load(rd,rs,offs); - } else if (toks[0].equals(INSTRUCTION_STORE)){ - if (toks.length != 4){ - throw new InvalidInstructionException(); - } - int ra = parseReg(toks[1]); - int offs = parseOffset(toks[2]); - int rb = parseReg(toks[3]); - do_store(ra,offs,rb); - } else if (toks[0].equals(INSTRUCTION_MOVE)){ - if (toks.length != 3){ - throw new InvalidInstructionException(); - } - int rd = parseReg(toks[1]); - int offs = parseOffset(toks[2]); - do_move(rd,offs); - } else if (toks[0].equals(INSTRUCTION_JUMP)){ - if (toks.length != 2){ - throw new InvalidInstructionException(); - } - int offs = parseOffset(toks[1]); - pc = pc + offs; - count++; - continue; /* avoid default increment of pc below */ - } else if (toks[0].equals(INSTRUCTION_JZ)){ - if (toks.length != 3){ - throw new InvalidInstructionException(); - } - int ra = parseReg(toks[1]); - int offs = parseOffset(toks[2]); - if (regs[ra] == 0){ - pc = pc + offs; - }else{ - pc = pc + 1; - } - count++; - continue; /* avoid default increment the pc below */ - } else { - System.err.println("Unrecognised instruction: " + inst); - throw new InvalidInstructionException(); - } - count++; - pc = pc + 1; + + private void validate_offset(int offset) + throws InvalidInstructionException + { + if (offset < -MAX_ADDR || offset > MAX_ADDR) { + throw new InvalidInstructionException(); + } } - /* got here without returning already... */ - throw new NoReturnValueException(); - } + /** Execute an assembly program. + * + * @param prog is the program to execute as an iterable collection of strings, + * each of which is a single instruction. + * @return the program's return value. + * @throws Exception when program has unrecognised or + * invalid instructions, or when it returns no result when it finishes + */ + int execute(List<String> instructions) + throws InvalidInstructionException, + NoReturnValueException + { + + int instructionsExecuted = 0; + int pc = 0; + final int progLength = instructions.size(); + while(true){ + if (pc < 0 || pc >= progLength){ + /* will cause NoReturnValueException to be thrown + * but that is not a bug and and indeed is what the + * VM is supposed to do if the pc becomes negative, + * since in this case the program's execution + * finishes early without a return value having + * been produced. */ + break; + } + String inst = instructions.get(pc); + /* strip leading and trailing whitespace */ + inst = inst.toLowerCase().replaceAll("^\\s+","").replaceAll("\\s+$",""); + /* strip out any comments */ + String[] toks = inst.split(";"); + inst = toks[0]; - /** - * get the number of instructions successfully executed by the VM so far - */ - public int getCount(){ - return count; - } + /* check for blank lines */ + if (inst.equals("")){ + pc = pc + 1; + count++; + continue; + } + + instructionsExecuted++; + /* now tokenize by splitting on whitespace */ + toks = inst.split("\\s+"); + + /* check minimum number of tokens */ + if (toks.length < 2){ + throw new InvalidInstructionException(); + } + + if (toks[0].equals(INSTRUCTION_ADD)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int rs1 = parseReg(toks[2]); + int rs2 = parseReg(toks[3]); + do_add(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_SUBTRACT)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int rs1 = parseReg(toks[2]); + int rs2 = parseReg(toks[3]); + do_sub(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_MULT)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int rs1 = parseReg(toks[2]); + int rs2 = parseReg(toks[3]); + do_mult(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_DIVIDE)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int rs1 = parseReg(toks[2]); + int rs2 = parseReg(toks[3]); + do_div(rd,rs1,rs2); + } else if (toks[0].equals(INSTRUCTION_RETURN)){ + int rs = parseReg(toks[1]); + count++; + return regs[rs]; + } else if (toks[0].equals(INSTRUCTION_LOAD)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int rs = parseReg(toks[2]); + int offs = parseOffset(toks[3]); + do_load(rd,rs,offs); + } else if (toks[0].equals(INSTRUCTION_STORE)){ + if (toks.length != 4){ + throw new InvalidInstructionException(); + } + int ra = parseReg(toks[1]); + int offs = parseOffset(toks[2]); + int rb = parseReg(toks[3]); + do_store(ra,offs,rb); + } else if (toks[0].equals(INSTRUCTION_MOVE)){ + if (toks.length != 3){ + throw new InvalidInstructionException(); + } + int rd = parseReg(toks[1]); + int offs = parseOffset(toks[2]); + do_move(rd,offs); + } else if (toks[0].equals(INSTRUCTION_JUMP)){ + if (toks.length != 2){ + throw new InvalidInstructionException(); + } + int offs = parseOffset(toks[1]); + pc = pc + offs; + count++; + continue; /* avoid default increment of pc below */ + } else if (toks[0].equals(INSTRUCTION_JZ)){ + if (toks.length != 3){ + throw new InvalidInstructionException(); + } + int ra = parseReg(toks[1]); + int offs = parseOffset(toks[2]); + if (regs[ra] == 0){ + pc = pc + offs; + }else{ + pc = pc + 1; + } + count++; + continue; /* avoid default increment the pc below */ + } else { + System.err.println("Unrecognised instruction: " + inst); + throw new InvalidInstructionException(); + } + count++; + pc = pc + 1; + } + + /* got here without returning already... */ + throw new NoReturnValueException(); + } + + /** + * get the number of instructions successfully executed by the VM so far + */ + public int getCount(){ + return count; + } } diff --git a/src/swen90006/machine/NoReturnValueException.java b/src/swen90006/machine/NoReturnValueException.java old mode 100644 new mode 100755 diff --git a/src/swen90006/machine/SimpleDriver.java b/src/swen90006/machine/SimpleDriver.java old mode 100644 new mode 100755 diff --git a/test/swen90006/machine/BoundaryTests.java b/test/swen90006/machine/BoundaryTests.java old mode 100644 new mode 100755 index 61ce1ca647f325fbf452047408c1e22d9befcb99..84bd4c05426f58682183be0d2295e212460185e5 --- a/test/swen90006/machine/BoundaryTests.java +++ b/test/swen90006/machine/BoundaryTests.java @@ -1,5 +1,7 @@ package swen90006.machine; +import java.io.File; +import java.io.IOException; import java.util.List; import java.util.ArrayList; import java.nio.charset.Charset; @@ -8,83 +10,570 @@ import java.nio.file.Files; import java.nio.file.FileSystems; import org.junit.*; + import static org.junit.Assert.*; -public class BoundaryTests -{ - //Any method annotated with "@Before" will be executed before each test, - //allowing the tester to set up some shared resources. - @Before public void setUp() - { - } - - //Any method annotated with "@After" will be executed after each test, - //allowing the tester to release any shared resources used in the setup. - @After public void tearDown() - { - } - - //Any method annotation with "@Test" is executed as a test. - @Test public void aTest() - { - //the assertEquals method used to check whether two values are - //equal, using the equals method - final int expected = 2; - final int actual = 1 + 1; - assertEquals(expected, actual); - } - - @Test public void anotherTest() - { - List<String> list = new ArrayList<String>(); - list.add("a"); - list.add("b"); - - //the assertTrue method is used to check whether something holds. - assertTrue(list.contains("a")); - } - - //Test test opens a file and executes the machine - @Test public void aFileOpenTest() - { - final List<String> lines = readInstructions("examples/array.s"); - Machine m = new Machine(); - assertEquals(m.execute(lines), 45); - } - - //To test an exception, specify the expected exception after the @Test - @Test(expected = java.io.IOException.class) - public void anExceptionTest() - throws Throwable - { - throw new java.io.IOException(); - } - - //This test should fail. - //To provide additional feedback when a test fails, an error message - //can be included - @Test public void aFailedTest() - { - //include a message for better feedback - final int expected = 2; - final int actual = 1 + 2; - assertEquals("Some failure message", expected, actual); - } - - //Read in a file containing a program and convert into a list of - //string instructions - private List<String> readInstructions(String file) - { - Charset charset = Charset.forName("UTF-8"); - List<String> lines = null; - try { - lines = Files.readAllLines(FileSystems.getDefault().getPath(file), charset); - } - catch (Exception e){ - System.err.println("Invalid input file! (stacktrace follows)"); - e.printStackTrace(System.err); - System.exit(1); - } - return lines; - } -} + +public class BoundaryTests { + /* + * Any method annotated with "@Before" will be executed before each test, + * allowing the tester to set up some shared resources. + **/ + @Before + public void setUp() { + } + + /* + * Any method annotated with "@After" will be executed after each test, + * allowing the tester to release any shared resources used in the setup. + **/ + @After + public void tearDown() { + } + + + //******************************* EC1 ******************************** + /* + * boundary : no RET instruction + * on point : no RET instruction + */ + @Test(expected = NoReturnValueException.class) + public void onPointEC1Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 10"); + machineExeLines(lines); + } + + /* + * boundary : no RET instruction + * off point : one RET instruction + */ + @Test + public void offPointEC1Test() { + List<String> lines = new ArrayList<String>(); + lines.add("RET R0"); + machineExeLines(lines); + assertEquals(0, machineExeLines(lines)); + } + + + //******************************* EC2 ******************************** + /* + * boundary : more than one RET instructions + * on point : two RET instruction + */ + @Test + public void onPointEC2Test() { + List<String> lines = new ArrayList<String>(); + final int expected = -10; + lines.add("MOV R1 " + expected); + lines.add("RET R1"); + lines.add("MOV R2 " + expected * 10); + lines.add("RET R2"); + assertEquals(expected, machineExeLines(lines)); + } + + + //******************************* EC3 ******************************** + /* + * boundary: i < 0 + * on point: i = 0 + * */ + @Test + public void onPointEC3Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 0"); + lines.add("RET R0"); + assertEquals(0, machineExeLines(lines)); + } + + /* + * boundary: i < 0 + * off point: i = -1 + * */ + @Test(expected = InvalidInstructionException.class) + public void offPointEC3Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R-1 0"); + machineExeLines(lines); + } + + + //******************************* EC4 ******************************** + /* + * boundary: i > 31 + * on point: i = 31 + * */ + @Test + public void onPointEC4Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R31 -2"); + lines.add("RET R31"); + assertEquals(-2, machineExeLines(lines)); + } + + /* + * boundary: i > 31 + * off point: i = 32 + * */ + @Test(expected = InvalidInstructionException.class) + public void offPointEC4Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R32 0"); + machineExeLines(lines); + } + + + //******************************* EC5 ******************************** + /* + * boundary: val < -65535 + * on point: val = -65535 + * */ + @Test + public void onPointEC5Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 -65535"); + lines.add("RET R1"); + assertEquals(-65535, machineExeLines(lines)); + } + + /* + * boundary: val < -65535 + * off point: val = -65536 + * */ + @Test(expected = InvalidInstructionException.class) + public void offPointEC5Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 -65536"); + lines.add("RET R1"); + machineExeLines(lines); + } + + + //******************************* EC6 ******************************** + /* + * boundary: val > 65535 + * on point: val = 65535 + * */ + @Test + public void onPointEC6Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 65535"); + lines.add("RET R1"); + assertEquals(65535, machineExeLines(lines)); + } + + /* + * boundary: val > 65535 + * off point: val = 65536 + * */ + @Test(expected = InvalidInstructionException.class) + public void offPointEC6Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 65536"); + lines.add("RET R1"); + machineExeLines(lines); + } + + + //******************************* EC7 ******************************** + /* + * boundary: regV <= -(2^31) + * on point: regV = -(2^31) + * */ + + /* + * boundary: regV <= -(2^31) + * off point: regV = -(2^31 + 1) + * */ + + //EC7 cannot give a test + + + //******************************* EC8 ******************************** + /* + * boundary: regV >= 2^31 + * on point: regV = 2^31 + * */ + + /* + * boundary: regV >= 2^31 + * off point: regV = 2^31 + 1 + * */ + + //EC8 cannot give a test + + + //******************************* EC9 ******************************** + /* + * boundary: ADD > 0 + * off point: one ADD + * */ + @Test + public void offPointEC9Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("ADD R1 R1 R1"); + lines.add("RET R1"); + assertEquals("Wrong ADD result.", 2, machineExeLines(lines)); + } + + + //******************************* EC10 ******************************** + /* + * boundary: SUB > 0 + * off point: one SUB + * */ + @Test + public void offPointEC10Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("SUB R1 R1 R1"); + lines.add("RET R1"); + assertEquals("Wrong SUB result.", 0, machineExeLines(lines)); + } + + + //******************************* EC11 ******************************** + /* + * boundary: MUL > 0 + * off point: one MUL + * */ + @Test + public void offPointEC11Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("MUL R1 R1 R1"); + lines.add("RET R1"); + assertEquals("Wrong MUL result.", 1, machineExeLines(lines)); + } + + + //******************************* EC12 ******************************** + /* + * boundary: div by 0 + * on point: divisor = 0 + * */ + @Test + public void onPointEC12Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 0"); + lines.add("MOV R0 3"); + lines.add("DIV R0 R0 R1"); + lines.add("RET R0"); + assertEquals(3, machineExeLines(lines)); + } + + /* + * boundary: div by 0 + * off point one: divisor = 1 + * return a normal value + * */ + @Test + public void offPointOneEC12Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("MOV R0 -3"); + lines.add("DIV R0 R0 R1"); + lines.add("RET R0"); + assertEquals(-3, machineExeLines(lines)); + } + + /* + * boundary: div by 0 + * off point two: divisor = -1 + * return a normal value + * */ + @Test + public void offPointTwoEC12Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 -1"); + lines.add("MOV R0 3"); + lines.add("DIV R0 R0 R1"); + lines.add("RET R0"); + assertEquals(-3, machineExeLines(lines)); + + } + + + //EC13 has no test + + + //******************************* EC14 ******************************** + /* + * boundary: MOV > 0 + * on point: one MOV + * */ + @Test + public void onPointEC14Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("RET R0"); + assertEquals("Wrong ADD result.", 1, machineExeLines(lines)); + } + + + //******************************* EC15 ******************************** + /* + * boundary: RET undefined reg + * on point: RET undefined reg + * return a normal value + * */ + @Test + public void onPointEC15Test() { + List<String> lines = new ArrayList<String>(); + lines.add("RET R0"); + assertEquals(0, machineExeLines(lines)); + } + + /* + * boundary: RET undefined reg + * off point: RET defined reg + * return a normal value + * */ + @Test + public void offPointEC15Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("RET R0"); + assertEquals("Wrong RET result.", 1, machineExeLines(lines)); + } + + + //EC16 has no test + + + //******************************* EC17 ******************************** + /* + * test for JMP + * boundary: val = 0 + * on point: val = 0 + * cause an infinite loop + * but can not have a test case since it will loop forever + * */ + + + //******************************* EC18 ******************************** + /* + * boundary: val < 0 && |val| > _pc + * off point one: val = -1 && _pc = 0 + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void offPointEC18Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JMP -1"); + lines.add("RET R0"); + machineExeLines(lines); + } + + + //******************************* EC19 ******************************** + /* + * boundary: val > pc_ && val > 0 + * off point one: val = 1 && _pc = 0 + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void offPointEC19Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JMP 1"); + machineExeLines(lines); + } + + + //******************************* EC20 ******************************** + /* + * boundary: _pc <= v <= pc_ && v != 0 + * off point: v = pc_ = _pc = 1 + * return a normal value + * */ + @Test + public void offPointEC20Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("JMP 1"); + lines.add("MOV R0 2"); + lines.add("RET R0"); + assertEquals("Wrong JMP result.", 2, machineExeLines(lines)); + } + + + //******************************* EC21 ******************************** + /* + * test for JZ + * boundary: val = 0 + * on point: val = 0 + * cause an infinite loop + * but can not have a test case since it will loop forever + * */ + + + //******************************* EC22 ******************************** + /* + * boundary: val < 0 && |val| > _pc + * off point one: val = -1 && _pc = 0 + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void offPointEC22Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JZ R0 -1"); + lines.add("RET R0"); + machineExeLines(lines); + } + + + + + //******************************* EC23 ******************************** + /* + * boundary: val > pc_ && val > 0 + * off point one: val = 1 && _pc = 0 + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void offPointEC23Test() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JZ R0 1"); + machineExeLines(lines); + } + + + //******************************* EC24 ******************************** + /* + * boundary: _pc <= v <= pc_ && v != 0 + * off point: v = pc_ = _pc = 1 + * return a normal value + * */ + @Test + public void offPointEC24Test() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("JZ R0 3"); + lines.add("SUB R0 R0 R0"); + lines.add("MOV R0 2"); + lines.add("RET R0"); + assertEquals("Wrong JMP result.", 2, machineExeLines(lines)); + } + + + //******************************* EC25 ******************************** + /* + * test for LDR + * boundary: b + v <= -(2^31) + * on point: b + v = -(2^31) + * stop the programme and print out the error + * / + + /* + * boundary: b + v <= -(2^31) + * off point: b + v = -(2^31 + 1) + * stop the programme and print out the error + * */ + + //EC25 cannot give a test + + + //******************************* EC26 ******************************** + /* + * test for LDR + * boundary: b + v in -(2^31-1) ... (2^31-1) + * on point one: b + v = -(2^31-1) + * return a normal value + * */ + + /* + * test for LDR + * boundary: b + v in -(2^31-1) ... (2^31-1) + * on point two: b + v = (2^31-1) + * return a normal value + * */ + + + //******************************* EC27 ******************************** + /* + * test for LDR + * boundary: b + v >= 2^31 + * on point: b + v = 2^31 + * stop the programme and print out the error + */ + + /* + * test for LDR + * boundary: b + v >= 2^31 + * off point: b + v = 2^31 + 1 + * stop the programme and print out the error + */ + + //EC27 can not test here + + + //******************************* EC28 ******************************** + /* + * test for STR + * boundary: b + v <= -(2^31) + * on point: b + v = -(2^31) + * stop the programme and print out the error + * / + + /* + * boundary: b + v <= -(2^31) + * off point: b + v = -(2^31 + 1) + * stop the programme and print out the error + * */ + + //EC28 cannot give a test + + + //******************************* EC29 ******************************** + /* + * test for STR + * boundary: b + v in -(2^31-1) ... (2^31-1) + * on point one: b + v = -(2^31-1) + * return a normal value + * */ + + /* + * test for STR + * boundary: b + v in -(2^31-1) ... (2^31-1) + * on point two: b + v = (2^31-1) + * return a normal value + * */ + + + //******************************* EC30 ******************************** + /* + * test for STR + * boundary: b + v >= 2^31 + * on point: b + v = 2^31 + * stop the programme and print out the error + */ + + /* + * test for STR + * boundary: b + v >= 2^31 + * off point: b + v = 2^31 + 1 + * stop the programme and print out the error + */ + + //EC30 can not test here + + + /* + * Machine executes input lines + * */ + private int machineExeLines(List<String> lines) { + Machine m = new Machine(); + return m.execute(lines); + } +} \ No newline at end of file diff --git a/test/swen90006/machine/PartitioningTests.java b/test/swen90006/machine/PartitioningTests.java old mode 100644 new mode 100755 index 5494b44f4615351a610fc7b0b649d30b4b2d0a40..41092c667f213710f4a9d78c892c70a838509538 --- a/test/swen90006/machine/PartitioningTests.java +++ b/test/swen90006/machine/PartitioningTests.java @@ -1,5 +1,7 @@ package swen90006.machine; +import java.io.File; +import java.io.IOException; import java.util.List; import java.util.ArrayList; import java.nio.charset.Charset; @@ -8,83 +10,475 @@ import java.nio.file.Files; import java.nio.file.FileSystems; import org.junit.*; + import static org.junit.Assert.*; -public class PartitioningTests -{ - //Any method annotated with "@Before" will be executed before each test, - //allowing the tester to set up some shared resources. - @Before public void setUp() - { - } - - //Any method annotated with "@After" will be executed after each test, - //allowing the tester to release any shared resources used in the setup. - @After public void tearDown() - { - } - - //Any method annotation with "@Test" is executed as a test. - @Test public void aTest() - { - //the assertEquals method used to check whether two values are - //equal, using the equals method - final int expected = 2; - final int actual = 1 + 1; - assertEquals(expected, actual); - } - - @Test public void anotherTest() - { - List<String> list = new ArrayList<String>(); - list.add("a"); - list.add("b"); - - //the assertTrue method is used to check whether something holds. - assertTrue(list.contains("a")); - } - - //Test test opens a file and executes the machine - @Test public void aFileOpenTest() - { - final List<String> lines = readInstructions("examples/array.s"); - Machine m = new Machine(); - assertEquals(m.execute(lines), 45); - } - - //To test an exception, specify the expected exception after the @Test - @Test(expected = java.io.IOException.class) - public void anExceptionTest() - throws Throwable - { - throw new java.io.IOException(); - } - - //This test should fail. - //To provide additional feedback when a test fails, an error message - //can be included - @Test public void aFailedTest() - { - //include a message for better feedback - final int expected = 2; - final int actual = 1 + 2; - assertEquals("Some failure message", expected, actual); - } - - //Read in a file containing a program and convert into a list of - //string instructions - private List<String> readInstructions(String file) - { - Charset charset = Charset.forName("UTF-8"); - List<String> lines = null; - try { - lines = Files.readAllLines(FileSystems.getDefault().getPath(file), charset); - } - catch (Exception e){ - System.err.println("Invalid input file! (stacktrace follows)"); - e.printStackTrace(System.err); - System.exit(1); - } - return lines; - } -} + +public class PartitioningTests { + /* + * Any method annotated with "@Before" will be executed before each test, + * allowing the tester to set up some shared resources. + **/ + @Before + public void setUp() { + } + + /* + * Any method annotated with "@After" will be executed after each test, + * allowing the tester to release any shared resources used in the setup. + **/ + @After + public void tearDown() { + } + + /* + * EC1 + * test for no RET instruction + * if there is no RET instruction + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void noRetTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 10"); + machineExeLines(lines); + } + + /* + * EC2 + * test for more than one RET instructions + * return the value of first RET + * */ + @Test + public void multiRetTest() { + List<String> lines = new ArrayList<String>(); + final int expected = -10; + lines.add("MOV R0 " + expected); + lines.add("RET R0"); + lines.add("MOV R1 " + expected * 10); + lines.add("RET R1"); + assertEquals(expected, machineExeLines(lines)); + } + + /* + * EC3 + * test for the index i of a register less than 0 + * if i < 0 + * throw the InvalidInstructionException + * */ + @Test(expected = InvalidInstructionException.class) + public void smallRegIndexTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R-1 0"); + machineExeLines(lines); + } + + /* + * EC4 + * test for the index i of a register bigger than 31 + * if i > 31 + * throw the InvalidInstructionException + * */ + @Test(expected = InvalidInstructionException.class) + public void bigRegIndexTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R32 0"); + machineExeLines(lines); + } + + /* + * EC5 + * test for the value val + * use MOV for an example + * if val < -65535 + * throw the InvalidInstructionException + * */ + @Test(expected = InvalidInstructionException.class) + public void smallValTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 -65536"); + lines.add("RET R1"); + machineExeLines(lines); + } + + /* + * EC6 + * test for the value val + * use MOV for an example + * if val > 65535 + * throw the InvalidInstructionException + * */ + @Test(expected = InvalidInstructionException.class) + public void bigValTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 65536"); + lines.add("RET R1"); + machineExeLines(lines); + } + + /* + * EC7 + * test for the value of a register + * if regV < -(2^31) + 1 + * stop the function, show the error + * EC7 cannot give a test + * + @Test + public void smallRegVTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 -2"); + lines.add("MOV R1 2"); + int minRegV = 2; + + for (int i = 0; i < 30; i++) { + lines.add("MUL R0 R0 R1"); + minRegV *= 2; + } + //regV_of_R0 = -(2^31), minRegV = -(2^31) + minRegV += 1; + lines.add("MUL R0 R0 R1"); + lines.add("RET R0"); + assertEquals("The value of register if overflow.", minRegV, machineExeLines(lines)); + //System.exit(1); + }*/ + + /* + * EC8 + * test for the value of a register + * if regV > 2^31 + * stop the function, show the error + * + @Test + public void bigRegVTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 2"); + lines.add("MOV R1 2"); + int maxRegV = 2; + + for (int i = 0; i < 30; i++) { + lines.add("MUL R0 R0 R1"); + maxRegV *= 2; + } + //regV_of_R0 = (2^31), minRegV = (2^31) + + lines.add("MUL R0 R0 R1"); + lines.add("RET R0"); + assertEquals("The value of register if overflow.", maxRegV, machineExeLines(lines)); + //System.exit(1); + }*/ + + /* + * EC9 + * test for ADD + * return a normal value + * */ + @Test + public void addNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("ADD R0 R0 R0"); + lines.add("RET R0"); + assertEquals("Wrong ADD result.", 2, machineExeLines(lines)); + } + + /* + * EC10 + * test for SUB + * return a normal value + * */ + @Test + public void subNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("SUB R0 R0 R0"); + lines.add("RET R0"); + assertEquals("Wrong SUB result.", 0, machineExeLines(lines)); + } + + /* + * EC11 + * test for MUL + * return a normal value + * */ + @Test + public void mulNoramlTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("MUL R0 R0 R0"); + lines.add("RET R0"); + assertEquals("Wrong MUL result.", 1, machineExeLines(lines)); + } + + /* + * EC12 + * test for DIV + * if divisor = 0 + * return a normal value (still the value of the dividend) + * */ + @Test + public void divByZeroTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 0"); + lines.add("MOV R0 -3"); + lines.add("DIV R0 R0 R1"); + lines.add("RET R0"); + assertEquals(-3, machineExeLines(lines)); + } + + /* + * EC13 + * test for DIV + * if divisor != 0 + * return a normal value + * */ + @Test + public void divByNonZeroTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("MOV R0 3"); + lines.add("DIV R0 R0 R1"); + lines.add("RET R0"); + assertEquals(3, machineExeLines(lines)); + } + + /* + * EC14 + * test for MOV + * return a normal value + * */ + @Test + public void movNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("RET R0"); + assertEquals("Wrong ADD result.", 1, machineExeLines(lines)); + } + + /* + * EC15 + * test for RET + * if the register is undefined + * return a normal value + * */ + @Test + public void retUndefinedTest() { + List<String> lines = new ArrayList<String>(); + lines.add("RET R0"); + assertEquals(0, machineExeLines(lines)); + } + + /* + * EC16 + * test for RET + * if the register is defined + * return a normal value + * */ + @Test + public void retNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("RET R0"); + assertEquals("Wrong RET result.", 1, machineExeLines(lines)); + } + + /* + * EC17 + * test for JMP + * if val = 0 + * cause an infinite loop + * but can not have a test case since it will loop forever + * */ + + /* + * EC18 + * test for JMP + * if v < 0 && |v| > the amount of previous pc count + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void jmpMinusPCNoReturnTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JMP -1"); + lines.add("RET R0"); + machineExeLines(lines); + } + + /* + * EC19 + * test for JMP + * if v > 0 && v > the amount of pc count above + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void jmpPositivePCNoReturnTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JMP 2"); + lines.add("RET R0"); + machineExeLines(lines); + } + + /* + * EC20 + * test for JMP + * if _pc <= v <= pc_ && v != 0 + * return a normal value + * */ + @Test + public void jmpNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("JMP 2"); + lines.add("MOV R0 1"); + lines.add("MOV R0 2"); + lines.add("RET R0"); + assertEquals("Wrong JMP result.", 2, machineExeLines(lines)); + } + + /* + * EC21 + * test for JZ + * if val = 0 + * cause an infinite loop + * but can not have a test case since it will loop forever + * */ + + /* + * EC22 + * test for JZ + * if v < 0 && |v| > the amount of previous pc count + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void jzMinusPCNoReturnTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JZ R0 -1"); + lines.add("RET R0"); + machineExeLines(lines); + } + + /* + * EC23 + * test for JZ + * if v > 0 && v > the amount of pc count above + * throw the NoReturnValueException + * */ + @Test(expected = NoReturnValueException.class) + public void jzPositivePCNoReturnTest() + throws Throwable { + List<String> lines = new ArrayList<String>(); + lines.add("JZ R0 2"); + lines.add("RET R0"); + machineExeLines(lines); + } + + /* + * EC24 + * test for JZ + * if _pc <= v <= pc_ && v != 0 + * return a normal value + * */ + @Test + public void jzNormalTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R1 1"); + lines.add("JZ R1 3"); + lines.add("SUB R1 R1 R1"); + lines.add("MOV R1 2"); + lines.add("RET R1"); + assertEquals("Wrong JMP result.", 2, machineExeLines(lines)); + } + + /* + * EC25 + * test for LDR + * if b + v <= -(2^31) + * stop the programme and print out the error + * + @Test + public void ldrSmallAddressTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 2"); + lines.add("MOV R1 2"); + lines.add("MOV R2 2"); + int m = 2; + + for (int i = 0; i < 29; i++) { + lines.add("MUL R0 R0 R2"); + lines.add("MUL R1 R1 R2"); + m *= 2; + } + System.out.println(m); + lines.add("LDR R0 R1 -65535"); + lines.add("RET R0"); + machineExeLines(lines); + }*/ + + /* + * EC26 + * test for LDR + * if b + v in -(2^31-1) ... (2^31-1) + * return a normal value + * */ + @Test + public void ldrNormalAddressTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("MOV R1 2"); + lines.add("LDR R0 R1 -2"); + lines.add("RET R0"); + assertEquals("Wrong LDR result.", 0, machineExeLines(lines)); + } + + /* + * EC27 + * test for LDR + * if b + v >= 2^31 + * stop the programme and print out the error + */ + + /* + * EC28 + * test for STR + * if b + v <= -(2^31) + * stop the programme and print out the error + */ + + /* + * EC29 + * test for STR + * if b + v in -(2^31-1) ... (2^31-1) + * return a normal value + * */ + @Test + public void strNormalAddressTest() { + List<String> lines = new ArrayList<String>(); + lines.add("MOV R0 1"); + lines.add("MOV R1 2"); + lines.add("STR R0 -1 R1"); + lines.add("RET R0"); + machineExeLines(lines); + } + + /* + * EC30 + * test for STR + * if b + v >= 2^31 + * stop the programme and print out the error + */ + + + /* + * Machine executes input lines + * */ + private int machineExeLines(List<String> lines) { + Machine m = new Machine(); + return m.execute(lines); + } +} \ No newline at end of file