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