blob: 58e7c88e69b3a4f9304c54df0ef046ed02c7805d [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 the differential-fuzzing library files.
*/
'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const libPath = path.resolve(
path.join(__dirname, '..', 'resources', 'differential_fuzz_library.js'));
const code = fs.readFileSync(libPath, 'utf-8');
// We wire the print function to write to this result variable.
const resultDummy = 'let result; const print = text => { result = text; };';
// The prettyPrinted function from mjsunit is reused in the library.
const prettyPrint = 'let prettyPrinted = value => value;';
const hookedUpCode = resultDummy + prettyPrint + code;
// Runs the library, adds test code and verifies the result.
function testLibrary(testCode, expected) {
// The code isn't structured as a module. The test code is expected to
// evaluate to a result which we store in actual.
const actual = eval(hookedUpCode + testCode);
assert.deepEqual(expected, actual);
}
describe('Differential fuzzing library', () => {
it('prints objects', () => {
testLibrary(
'__prettyPrint([0, 1, 2, 3]); result;',
'[0, 1, 2, 3]');
testLibrary(
'__prettyPrint({0: 1, 2: 3}); result;',
'Object{0: 1, 2: 3}');
testLibrary(
'const o = {}; o.k = 42;__prettyPrint(o); result;',
'Object{k: 42}');
});
it('cuts off deep nesting', () => {
// We print only until a nesting depth of 4.
testLibrary(
'__prettyPrint({0: [1, 2, [3, {4: []}]]}); result;',
'Object{0: [1, 2, [3, Object{4: ...}]]}');
});
it('cuts off long strings', () => {
const long = new Array(66).join('a');
const head = new Array(55).join('a');
const tail = new Array(10).join('a');
testLibrary(
`__prettyPrint("${long}"); result;`,
`${head}[...]${tail}`);
// If the string gets longer, the cut-off version is still the same.
const veryLong = new Array(100).join('a');
testLibrary(
`__prettyPrint("${veryLong}"); result;`,
`${head}[...]${tail}`);
});
it('tracks hash difference', () => {
// Test that we track a hash value for each string we print.
const long = new Array(66).join('a');
testLibrary(
`__prettyPrint("${long}"); __hash;`,
2097980794);
// Test that the hash value differs, also when the cut-off result doesn't.
const veryLong = new Array(100).join('a');
testLibrary(
`__prettyPrint("${veryLong}"); __hash;`,
-428472866);
// Test that repeated calls update the hash.
testLibrary(
`__prettyPrint("${long}");__prettyPrint("${long}"); __hash;`,
-909224493);
});
it('limits extra printing', () => {
// Test that after exceeding the limit for calling extra printing, there
// is no new string printed (in the test case no new result added).
testLibrary(
'for (let i = 0; i < 20; i++) __prettyPrintExtra(i); result;',
'19');
testLibrary(
'for (let i = 0; i < 101; i++) __prettyPrintExtra(i); result;',
'99');
testLibrary(
'for (let i = 0; i < 102; i++) __prettyPrintExtra(i); result;',
'99');
});
it('tracks hash after limit', () => {
// Test that after exceeding the limit for calling extra printing, the
// hash is still updated.
testLibrary(
'for (let i = 0; i < 20; i++) __prettyPrintExtra(i); __hash;',
-945753644);
testLibrary(
'for (let i = 0; i < 101; i++) __prettyPrintExtra(i); __hash;',
1907055979);
testLibrary(
'for (let i = 0; i < 102; i++) __prettyPrintExtra(i); __hash;',
-590842070);
});
});