1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dexfuzz.program; 18 19 import dexfuzz.Log; 20 import dexfuzz.program.mutators.CodeMutator; 21 22 import java.io.BufferedReader; 23 import java.io.BufferedWriter; 24 import java.io.IOException; 25 26 /** 27 * Responsible for serializing mutations, allowing replay of mutations, and searching 28 * for a minimal set of mutations. 29 */ 30 public class MutationSerializer { getMutationString(Mutation mutation)31 public static String getMutationString(Mutation mutation) { 32 StringBuilder builder = new StringBuilder(); 33 builder.append(mutation.mutatorClass.getCanonicalName()).append(" "); 34 builder.append(mutation.mutatableCodeIdx).append(" "); 35 builder.append(mutation.getString()); 36 return builder.toString(); 37 } 38 writeMutation(BufferedWriter writer, Mutation mutation)39 public static void writeMutation(BufferedWriter writer, Mutation mutation) throws IOException { 40 // Write out the common fields. 41 writer.write(mutation.mutatorClass.getCanonicalName() + " " 42 + mutation.mutatableCodeIdx + " "); 43 44 // Use the mutation's own function to write out the rest of the fields. 45 writer.write(mutation.getString() + "\n"); 46 } 47 48 @SuppressWarnings("unchecked") readMutation(BufferedReader reader)49 public static Mutation readMutation(BufferedReader reader) throws IOException { 50 String line = reader.readLine(); 51 String[] fields = null; 52 if (line != null) { 53 fields = line.split(" "); 54 } else { 55 Log.errorAndQuit("Could not read line during mutation loading."); 56 } 57 58 // Read the mutator's class name 59 String mutatorClassName = fields[0]; 60 61 // Get the class for that mutator 62 Class<? extends CodeMutator> mutatorClass = null; 63 try { 64 mutatorClass = (Class<? extends CodeMutator>) Class.forName(mutatorClassName); 65 } catch (ClassNotFoundException e) { 66 Log.errorAndQuit("Cannot find a mutator class called: " + mutatorClassName); 67 } 68 69 Mutation mutation = null; 70 try { 71 mutation = mutatorClass.newInstance().getNewMutation(); 72 } catch (InstantiationException e) { 73 Log.errorAndQuit("Unable to instantiate " + mutatorClassName 74 + " using default constructor."); 75 } catch (IllegalAccessException e) { 76 Log.errorAndQuit("Unable to access methods in " + mutatorClassName + "."); 77 } 78 79 if (mutation == null) { 80 Log.errorAndQuit("Unable to get Mutation for Mutator: " + mutatorClassName); 81 } 82 83 // Populate the common fields of the mutation. 84 mutation.mutatorClass = mutatorClass; 85 // The Program must set this later, using the mutatable_code_idx 86 // into its list of MutatableCodes. 87 mutation.mutatableCode = null; 88 mutation.mutatableCodeIdx = Integer.parseInt(fields[1]); 89 90 // Use the mutation's own method to read the rest of the fields. 91 mutation.parseString(fields); 92 93 return mutation; 94 } 95 } 96