Home | History | Annotate | Download | only in mutators
      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.mutators;
     18 
     19 import dexfuzz.Log;
     20 import dexfuzz.MutationStats;
     21 import dexfuzz.Options;
     22 import dexfuzz.program.MutatableCode;
     23 import dexfuzz.program.Mutation;
     24 
     25 import java.util.List;
     26 import java.util.Random;
     27 
     28 /**
     29  * The base class for all classes that can mutate methods.
     30  */
     31 public abstract class CodeMutator {
     32   /**
     33    * The RNG, passed in by the Program that initialised us.
     34    */
     35   protected Random rng;
     36 
     37   /**
     38    * Used to track which mutations happen.
     39    */
     40   protected MutationStats stats;
     41 
     42   /**
     43    * Used to track mutations that have been applied so far.
     44    */
     45   protected List<Mutation> mutations;
     46 
     47   /**
     48    * The chance, out of 100, that this mutator actually mutates the the program
     49    * when asked to by the Program. The default is 50% chance, but each mutator that
     50    * extends CodeMutator should its own default.
     51    */
     52   protected int likelihood = 50;
     53 
     54   /**
     55    * This constructor is only intended for use in MutationRecorder...
     56    */
     57   public CodeMutator() {
     58 
     59   }
     60 
     61   /**
     62    * Constructor that all subclasses must call...
     63    *
     64    * @param rng The RNG that the Program created.
     65    */
     66   public CodeMutator(Random rng, MutationStats stats, List<Mutation> mutations) {
     67     this.rng = rng;
     68     this.stats = stats;
     69     this.mutations = mutations;
     70 
     71     String name = this.getClass().getSimpleName().toLowerCase();
     72 
     73     if (Options.mutationLikelihoods.containsKey(name)) {
     74       likelihood = Options.mutationLikelihoods.get(name);
     75       Log.info("Set mutation likelihood to " + likelihood
     76           + "% for " + this.getClass().getSimpleName());
     77     }
     78   }
     79 
     80   /**
     81    * When the Program picks a particular mutator to mutate the code, it calls
     82    * this function, that determines if the mutator will actually mutate the code.
     83    * If so, it then calls the mutationFunction() method, that every subclass CodeMutator
     84    * is expected to implement to perform its mutation.
     85    *
     86    * @return If mutation took place.
     87    */
     88   public boolean attemptToMutate(MutatableCode mutatableCode) {
     89     if (shouldMutate(mutatableCode)) {
     90       generateAndApplyMutation(mutatableCode);
     91       return true;
     92     }
     93     Log.info("Skipping mutation.");
     94     return false;
     95   }
     96 
     97   public void forceMutate(Mutation mutation) {
     98     Log.info("Forcing mutation.");
     99     applyMutation(mutation);
    100   }
    101 
    102   public boolean canBeTriggered() {
    103     return (likelihood > 0);
    104   }
    105 
    106   /**
    107    * Randomly determine if the mutator will actually mutate a method, based on its
    108    * provided likelihood of mutation.
    109    *
    110    * @return If the method should be mutated.
    111    */
    112   private boolean shouldMutate(MutatableCode mutatableCode) {
    113     return ((rng.nextInt(100) < likelihood) && canMutate(mutatableCode));
    114   }
    115 
    116   private void generateAndApplyMutation(MutatableCode mutatableCode) {
    117     Mutation mutation = generateMutation(mutatableCode);
    118     // Always save the mutation.
    119     mutations.add(mutation);
    120     applyMutation(mutation);
    121   }
    122 
    123   /**
    124    * A CodeMutator must override this method if there is any reason why could not mutate
    125    * a particular method, and return false in that case.
    126    */
    127   protected boolean canMutate(MutatableCode mutatableCode) {
    128     return true;
    129   }
    130 
    131   protected abstract Mutation generateMutation(MutatableCode mutatableCode);
    132 
    133   protected abstract void applyMutation(Mutation uncastMutation);
    134 
    135   public abstract Mutation getNewMutation();
    136 }
    137