com.google.javascript.jscomp.fuzzing.AbstractFuzzer.java Source code

Java tutorial

Introduction

Here is the source code for com.google.javascript.jscomp.fuzzing.AbstractFuzzer.java

Source

/*
 * Copyright 2013 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.javascript.jscomp.fuzzing;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.CodePrinter;
import com.google.javascript.rhino.Node;

import org.json.JSONObject;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;

/**
 * UNDER DEVELOPMENT. DO NOT USE!
 */
abstract class AbstractFuzzer {
    protected FuzzingContext context;

    AbstractFuzzer(FuzzingContext context) {
        this.context = context;
    }

    protected JSONObject getOwnConfig() {
        Preconditions.checkNotNull(context.config);
        return context.config.optJSONObject(getConfigName());
    }

    /**
     * Decide if the budget is enough
     */
    protected abstract boolean isEnough(int budget);

    /**
     * @param budget When the budget is not enough, it will try to generate a node
     * with minimal budget
     */
    protected abstract Node generate(int budget, Set<Type> types);

    protected Node generate(int budget) {
        return generate(budget, supportedTypes());
    }

    protected Node[] distribute(int budget, AbstractFuzzer[] fuzzers) {
        Preconditions.checkArgument(fuzzers.length > 0);
        int numNodes = fuzzers.length;
        int[] subBudgets = new int[numNodes];
        Arrays.fill(subBudgets, 0);
        if (budget > 3 * numNodes) {
            // when the budget is much greater than numNodes
            double[] rands = new double[numNodes];
            double sum = 0;
            for (int i = 0; i < numNodes; i++) {
                rands[i] = context.random.nextDouble();
                sum += rands[i];
            }
            for (int i = 0; i < numNodes; i++) {
                double additionalBudget = budget / sum * rands[i];
                subBudgets[i] += additionalBudget;
                budget -= additionalBudget;
            }
        }
        while (budget > 0) {
            subBudgets[context.random.nextInt(numNodes)]++;
            budget--;
        }
        Node[] nodes = new Node[numNodes];
        for (int i = 0; i < numNodes; i++) {
            nodes[i] = fuzz(fuzzers[i], subBudgets[i]);
        }
        return nodes;
    }

    protected Node fuzz(AbstractFuzzer fuzzer, int budget) {
        return fuzzer.generate(budget);
    }

    protected abstract String getConfigName();

    protected int generateLength(int budget) {
        return context.random.nextInt((int) (budget * getOwnConfig().optDouble("maxLength")) + 1);
    }

    public static String getPrettyCode(Node root) {
        CodePrinter.Builder builder = new CodePrinter.Builder(root);
        builder.setPrettyPrint(true);
        builder.setLineBreak(true);
        return builder.build();
    }

    /**
     * @return All types by default. Subclasses may override to limit the
     * supported types
     */
    protected Set<Type> supportedTypes() {
        return Sets.immutableEnumSet(EnumSet.allOf(Type.class));
    }
}