blob: 31fe9898c870fd877321d44e1795b4a9db7c195a [file] [log] [blame]
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for differential fuzzing.
*/
'use strict';
const assert = require('assert');
const program = require('commander');
const sinon = require('sinon');
const helpers = require('./helpers.js');
const scriptMutator = require('../script_mutator.js');
const sourceHelpers = require('../source_helpers.js');
const random = require('../random.js');
const { DifferentialFuzzMutator, DifferentialFuzzSuppressions } = require(
'../mutators/differential_fuzz_mutator.js');
const { DifferentialScriptMutator } = require(
'../differential_script_mutator.js');
const sandbox = sinon.createSandbox();
function testMutators(settings, mutatorClass, inputFile, expectedFile) {
const source = helpers.loadTestData('differential_fuzz/' + inputFile);
const mutator = new mutatorClass(settings);
mutator.mutate(source);
const mutated = sourceHelpers.generateCode(source);
helpers.assertExpectedResult(
'differential_fuzz/' + expectedFile, mutated);
}
describe('Differential fuzzing', () => {
beforeEach(() => {
// Zero settings for all mutators.
this.settings = scriptMutator.defaultSettings();
for (const key of Object.keys(this.settings)) {
this.settings[key] = 0.0;
}
// By default, deterministically use all mutations of differential
// fuzzing.
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 1.0;
this.settings['DIFF_FUZZ_TRACK_CAUGHT'] = 1.0;
// Fake fuzzer being called with --input_dir flag.
this.oldInputDir = program.input_dir;
program.input_dir = helpers.BASE_DIR;
});
afterEach(() => {
sandbox.restore();
program.input_dir = this.oldInputDir;
});
it('applies suppressions', () => {
// This selects the first random variable when replacing .arguments.
sandbox.stub(random, 'single').callsFake(a => a[0]);
testMutators(
this.settings,
DifferentialFuzzSuppressions,
'suppressions.js',
'suppressions_expected.js');
});
it('adds extra printing', () => {
testMutators(
this.settings,
DifferentialFuzzMutator,
'mutations.js',
'mutations_expected.js');
});
it('does no extra printing', () => {
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 0.0;
testMutators(
this.settings,
DifferentialFuzzMutator,
'exceptions.js',
'exceptions_expected.js');
});
it('runs end to end', () => {
// Don't choose any zeroed settings or IGNORE_DEFAULT_PROB in try-catch
// mutator. Choose using original flags with >= 2%.
const chooseOrigFlagsProb = 0.2;
sandbox.stub(random, 'choose').callsFake((p) => p >= chooseOrigFlagsProb);
// Fake build directory from which two json configurations for flags are
// loaded.
const env = {
APP_DIR: 'test_data/differential_fuzz',
GENERATE: process.env.GENERATE,
};
sandbox.stub(process, 'env').value(env);
// Fake loading resources and instead load one fixed fake file for each.
sandbox.stub(sourceHelpers, 'loadResource').callsFake(() => {
return helpers.loadTestData('differential_fuzz/fake_resource.js');
});
// Load input files.
const files = [
'differential_fuzz/input1.js',
'differential_fuzz/input2.js',
];
const sources = files.map(helpers.loadTestData);
// Apply top-level fuzzing, with all probabilistic configs switched off.
this.settings['DIFF_FUZZ_EXTRA_PRINT'] = 0.0;
this.settings['DIFF_FUZZ_TRACK_CAUGHT'] = 0.0;
const mutator = new DifferentialScriptMutator(
this.settings, helpers.DB_DIR);
const mutated = mutator.mutateMultiple(sources);
helpers.assertExpectedResult(
'differential_fuzz/combined_expected.js', mutated.code);
// Flags for v8_foozzie.py are calculated from v8_fuzz_experiments.json and
// v8_fuzz_flags.json in test_data/differential_fuzz.
const expectedFlags = [
'--first-config=ignition',
'--second-config=ignition_turbo',
'--second-d8=d8',
'--second-config-extra-flags=--foo1',
'--second-config-extra-flags=--foo2',
'--first-config-extra-flags=--flag1',
'--second-config-extra-flags=--flag1',
'--first-config-extra-flags=--flag2',
'--second-config-extra-flags=--flag2',
'--first-config-extra-flags=--flag3',
'--second-config-extra-flags=--flag3',
'--first-config-extra-flags=--flag4',
'--second-config-extra-flags=--flag4'
];
assert.deepEqual(expectedFlags, mutated.flags);
});
});