Skip to content
Snippets Groups Projects
Select Git revision
  • c35150cb7e5a01eee1920e6a0e59e8e2b00ad2ca
  • master default protected
  • hai
  • isaac
  • CheHao
  • Eldar
  • mpriymak
  • master-before-merging-with-hai
  • master-before-merging-with-isaac
  • rmi-working-before-merging-with-isaac
  • all-code-merged-by-hai-v1
11 results

ApplicationMain.java

Blame
  • Forked from Ho Dac Hai / COMP90015-DSAss2-InfinityMonkeys-remaster
    Source project has a limited visibility.
    Fuzzer.java 12.16 KiB
    import java.io.IOException;
    import java.io.FileOutputStream;
    import java.io.PrintWriter;
    
    import java.lang.reflect.Array;
    import java.util.ArrayList;
    import java.util.Random;
    
    
    /* a stub for your team's fuzzer */
    public class Fuzzer {
    
        private static final String OUTPUT_FILE = "fuzz.txt";
        
        // The percentage of outputs that will start with a full stack
        private static final int STACK_FULL_PERCENTAGE = 10;
        // The percentage of inputs that will be incorrect
        private static final int INPUT_ERROR_PERCENTAGE = 5;
        // The percentage of instructions that will be incorrect
        private static final int LINE_ERROR_PERCENTAGE = 5;
        // Limit on generation of inputs
        private static final int NUMBER_TO_GENERATE = 10;
        // Instruction number range for each input
        private static final int INSTRUCTION_MIN = 0;
        private static final int INSTRUCTION_MAX = 100;
        // Maximum variable name length
        private static final int VAR_NAME_LENGTH_MAX = 100;
        private static final int VAR_ASCII_MIN = 33;
        private static final int VAR_ASCII_MAX = 127;
        // Variable range
        private static final int VAR_MIN = -2147483648;
        private static final int VAR_MAX = 2147483647;
        // Maximum number of items in stack
        private static final int MAX_STACK_SIZE = 512;
    
        // Random number generator
        private static Random rand = new Random(System.currentTimeMillis());
    
        private static ArrayList<String> vars = new ArrayList<>();
    
        public static void main(String[] args) throws IOException {
            System.out.println(Instruction.getBNF());
            FileOutputStream out = null;
            PrintWriter pw = null;
    
            try {
                out = new FileOutputStream(OUTPUT_FILE);
                pw = new PrintWriter(out);
                
                /* We just print one instruction.
                   Hint: you might want to make use of the instruction
                   grammar which is effectively encoded in Instruction.java */
                // pw.print(getStaticTests());
                pw.println(generateMultipleInputs());
                
            }catch (Exception e){
                e.printStackTrace(System.err);
                System.exit(1);
            }finally{
                if (pw != null){
                    pw.flush();
                }
                if (out != null){
                    out.close();
                }
            }
    
        }
    
        /***
         * Generates a list of different inputs for the program
         *
         * @return list of input strings
         */
        private static String generateMultipleInputs(){
            // Initiate variables
            StringBuilder result = new StringBuilder();
    
            // For debugging purposes
            int generated = 0;
    
            // Loop to create list of inputs
            while (generated < NUMBER_TO_GENERATE) {
                // Determine if the line will be correct or not
                result.append(generateInput(false,
                                            INSTRUCTION_MAX));
                // Increment generated
                generated += 1;
            }
            return result.toString();
        }
    
        /***
         * Generates a line of input for the program
         *
         * @param correct flag, which determines if the line will be correctly formulated
         * @param numInstructions for the line
         * @return the concatenated input for the program as a string
         */
        private static String generateInput(boolean correct, long numInstructions){
            int stackSize = 0;
            int counter = 0;
    
            StringBuilder result = new StringBuilder();
    
            if (rand.nextInt(100) < STACK_FULL_PERCENTAGE) {
                for ( int i = 0 ; i < MAX_STACK_SIZE ; i++ ) {
                    result.append(completeInstruction(true, Instruction.PUSH));
                    stackSize++;
                }
            }
    
            if (correct) {
                while (counter < numInstructions) {
                    Instruction newInstr = Instruction.getRandomInstruction(stackSize);
                    stackSize = stackSize + newInstr.getStackChange();
                    result.append(completeInstruction(true, newInstr));
                    counter += 1;
                }
            } else {
                while (counter < numInstructions) {
                    Instruction newInstr;
                    if (rand.nextInt(100) < LINE_ERROR_PERCENTAGE){
                        newInstr = Instruction.getRandomInstruction(2);
                        result.append(completeInstruction(false, newInstr));
                    } else {
                        newInstr = Instruction.getRandomInstruction(stackSize);
                        result.append(completeInstruction(true, newInstr));
                    }
                    stackSize = stackSize + newInstr.getStackChange();
                    if (stackSize < 0){
                        stackSize = 0;
                    }
    
                    counter += 1;
                }
            }
            return result.toString();
        }
    
        /***
         * Adds parameters to an individual instruction
         *
         * @param correct flag
         * @param instruction type
         * @return string with parameter
         */
        private static String completeInstruction(boolean correct, Instruction instruction){
            
            String name = "";
            switch (instruction) {
                case PUSH:
                    if (correct) {
                        // If correct, generate as usual
                        name = " " + ((Integer) randomRange(VAR_MIN, VAR_MAX)).toString();
                    } else {
                        // If incorrect, increase the range to outside +- int31_t
                        name = " " + ((Long) (randomRange(-1,1)*((long) VAR_MAX + (long) randomRange(0, VAR_MAX)))).toString();
                    }
                    break;
                case LOAD:
                case REM:
                    // If not correct, make up a name not in the list
                    if (!correct){
                        name = generateName();
                    }
                    // If no variables, return empty string
                    else if (vars.size() == 0){
                        return "";
                    }
                    // Otherwise, get a variable name from the list
                    else {
                        int index = rand.nextInt(vars.size());
                        name = " " + vars.get(index);
                        vars.remove(index);
                    }
                    break;
                case STORE:
                    // Make up a name
                    name = name + generateName();
                    vars.add(name);
                    name = " " + name;
                    break;
                case SAVE:
                    name = " " + generateName() + ".txt";
                    break;
                case PLUS:
                case SUB:
                case MULT:
                case DIV:
                case POP:
                case LIST:
                case PRINT:
                    break;
            }
            return instruction.getOpcode() + name + "\n";
        }
    
        /***
         * Generates a random name not longer than VAR_NAME_LENGTH_MAX
         * Characters are bounded by ASCII indexes at VAR_ASCII_MIN and VAR_ASCII_MAX
         *
         * @return the name generated
         */
        private static String generateName(){
            StringBuilder name = new StringBuilder();
            int counter = 0;
            // Randomise the length of the string
            int length = rand.nextInt(VAR_NAME_LENGTH_MAX);
    
            // Add random bounded characters to string
            while (counter < length){
                name.append((char) randomRange(VAR_ASCII_MIN, VAR_ASCII_MAX));
                counter += 1;
            }
            return name.toString();
        }
    
        private static int randomRange(int min, int max){
            // Remove negatives and get around int limitations
            if (min == VAR_MIN){
                return 2* (rand.nextInt(max) + (min/2));
            } else if (min < 0){
                max = max - min;
                return rand.nextInt(max) + min;
            }
            return min + rand.nextInt(max - min);
        }
    
        /***
         * Get the desired static boundary tests
         *
         * @return a string containing all of the boundary tests' instructions
         */
        private static String getStaticTests() {
            // Note. Some operations will crash dc if performed, so they cannot be tested
            // Examples include *, /, -, +, pop, store operations on empty stack
    
            StringBuilder result = new StringBuilder();
    
            // Test opreations that need variables on no variables defined
            result.append(Instruction.LIST.getOpcode() + "\n");
            result.append(Instruction.LOAD.getOpcode() + " VAR1\n");
            result.append(Instruction.REM.getOpcode() + " VAR1\n");
    
            // Test operations that use stack on empty stack
            result.append(Instruction.PRINT.getOpcode() + "\n");
    
            // Prep for next tests
            result.append(Instruction.PUSH.getOpcode() + " 5\n");
            result.append(Instruction.STORE.getOpcode() + " VAR1\n");
            result.append(Instruction.PUSH.getOpcode() + " 10\n");
            result.append(Instruction.STORE.getOpcode() + " VAR2\n");
            result.append(Instruction.SAVE.getOpcode() + "\n");
    
            // Test incorrect arguements for operation
            result.append(Instruction.LOAD.getOpcode() + " VAR3\n");
    
            // Test Variables stored and used corectly
            result.append(Instruction.LIST.getOpcode() + "\n");
            result.append(Instruction.PRINT.getOpcode() + "\n");
            result.append(Instruction.LOAD.getOpcode() + " VAR2\n");
            result.append(Instruction.LOAD.getOpcode() + " VAR1\n");
            result.append(Instruction.PRINT.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
            result.append(Instruction.PRINT.getOpcode() + "\n");
            result.append(Instruction.REM.getOpcode() + " VAR2\n");
            result.append(Instruction.LIST.getOpcode() + "\n");
            result.append(Instruction.LOAD.getOpcode() + " VAR2\n");
            result.append(Instruction.PRINT.getOpcode() + "\n");
            result.append(Instruction.STORE.getOpcode() + " VAR1\n");
            result.append(Instruction.LIST.getOpcode() + "\n");
            result.append(Instruction.LOAD.getOpcode() + " VAR1\n");
            result.append(Instruction.STORE.getOpcode() + " VAR1\n");
            result.append(Instruction.LIST.getOpcode() + "\n");
            result.append(Instruction.REM.getOpcode() + " VAR1\n");
    
            // Test Plus operation
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MIN + "\n");
            result.append(Instruction.PLUS.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.PUSH.getOpcode() + " 1\n");
            result.append(Instruction.PLUS.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
    
            // Test Subtract operation
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.SUB.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
            result.append(Instruction.PUSH.getOpcode() + " 1\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MIN + "\n");
            result.append(Instruction.SUB.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
    
            // Test Divide operation
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.DIV.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
            result.append(Instruction.PUSH.getOpcode() + " 1\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MIN + "\n");
            result.append(Instruction.DIV.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
    
            // Test Multiply operation
            result.append(Instruction.PUSH.getOpcode() + " "+ VAR_MAX + "\n");
            result.append(Instruction.PUSH.getOpcode() + " 2\n");
            result.append(Instruction.MULT.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
            result.append(Instruction.PUSH.getOpcode() + " 2\n");
            result.append(Instruction.PUSH.getOpcode() + " "+ Math.floorDiv(VAR_MIN, 2) + "\n");
            result.append(Instruction.MULT.getOpcode() + "\n");
            result.append(Instruction.POP.getOpcode() + "\n");
    
            return result.toString();
        }
    
    }