fuzzing.spec.ts 8.05 KiB
import { CalculatorType } from "../src/compute-node";
import { Session } from "../src/index";
import { MacrorugoCompound } from "../src/macrorugo/macrorugo_compound";
import { Nub } from "../src/nub";
import { CloisonAval } from "../src/pab/cloison_aval";
import { Pab } from "../src/pab/pab";
import { ParamDefinition } from "../src/param/param-definition";
import { Props } from "../src/props";
import { SectionNub } from "../src/section/section_nub";
import { CreateStructure } from "../src/structure/factory_structure";
import { ParallelStructure } from "../src/structure/parallel_structure";
import { checkResultConsistency, SetJasmineCurrentSpec } from "./test_func";
/**
 * Fuzzing or fuzz testing is an automated software testing technique that involves providing invalid,
 * unexpected, or random data as inputs to a computer program.
 * Here each calculator is fed with random parameters and each parameter is calculated.
 * We inspect the result that should return finite numbers or at least one error message.
/**
 * Number of test entries by Calculator (Each parameter is calculated for each test entrie)
const fuzzyCfg = {
    nTests: 4, // Number of test entries by Calculator (Each parameter is calculated for each test entrie)
    propInvertedPrm: 0, // Number of parameters inverted (for getting very small numbers on a proportion of parameters)
    Pab: {
        poolMax: 10, // Maximum number of pools in a Pab
        structureMax: 3 // Maximum number of structures in each cloison
    ParallelStructure: {
        structureMax: 1 // Maximum number of structure in ParallelStructure and its derivated
// Modules that should not be tested
const nubsNotTested: CalculatorType[] = [
    CalculatorType.Structure,
    CalculatorType.Section,
    CalculatorType.CloisonAval
const nubsWithStructures: CalculatorType[] = [
    CalculatorType.ParallelStructure,
    CalculatorType.Dever,
    CalculatorType.Cloisons
const nubsWithSection: CalculatorType[] = [
    CalculatorType.RegimeUniforme,
    CalculatorType.SectionParametree,
    CalculatorType.CourbeRemous
const calTypes =
    Object.keys(CalculatorType)
        .filter((key: any) =>
            isNaN(Number(CalculatorType[key]))
        ).map((e) => +e);
function randomizeParameter(p: ParamDefinition) {
    p.singleValue = Math.max(-1E6, p.domain.minValue)
        + Math.random()
        * (
            Math.min(1E6, p.domain.maxValue)
            - Math.max(-1E6, p.domain.minValue)
    if (Math.random() < fuzzyCfg.propInvertedPrm) {
        p.singleValue = 1 / p.currentValue;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
} function printPrms(n: Nub): string { let s = ""; if (n.calculatedParam !== undefined) { s = "Calc(" + n.calculatedParam.symbol + ") "; } for (const p of n.parameterIterator) { if (p.visible) { s += p.symbol + "=" + p.currentValue + " "; } } return s; } function addRandomStructures(ps: ParallelStructure, nStMax: number = 10) { const nSt = Math.floor(Math.random() * nStMax) + 1; for (let i = 0; i < nSt; i++) { const lois = ps.getLoisAdmissiblesArray(); const rndLoi = lois[Math.floor(Math.random() * lois.length)]; ps.addChild(CreateStructure(rndLoi)); } } function setRandomSection(sn: SectionNub) { const newSect = Session.getInstance().createSection( Math.floor(Math.random() * 4) + 1 ); sn.setSection(newSect); } function setPab(pab: Pab, nClMax = 30, nStMax = 3) { const nCl = Math.floor(Math.random() * nClMax) + 1; for (let i = 0; i < nCl; i++) { pab.addChild(Session.getInstance().createNub(new Props({ calcType: CalculatorType.Cloisons }))); addRandomStructures(pab.children[pab.children.length - 1], nStMax); } pab.downWall = Session.getInstance().createNub(new Props({ calcType: CalculatorType.CloisonAval })) as CloisonAval; addRandomStructures(pab.downWall, nStMax); } function setMacrorugoCompound(n: MacrorugoCompound) { n.properties.setPropValue("inclinedApron", Math.random() > 0.5); } function CreateTestNub(iCalType: number): Nub { const n = Session.getInstance().createNub( new Props({ calcType: iCalType }) ); if (nubsWithStructures.includes(iCalType)) { addRandomStructures(n as ParallelStructure, fuzzyCfg.ParallelStructure.structureMax); } if (nubsWithSection.includes(iCalType)) { setRandomSection(n as SectionNub); } if (iCalType === CalculatorType.CourbeRemous) { n.properties.setPropValue( "methodeResolution", Math.floor(Math.random() * 3) // Euler, RK4, Trapèzes ); } if (iCalType === CalculatorType.Pab) { setPab(n as Pab, fuzzyCfg.Pab.poolMax, fuzzyCfg.Pab.structureMax); } if (iCalType === CalculatorType.MacroRugoCompound) { setMacrorugoCompound(n as MacrorugoCompound); } for (const p of n.parameterIterator) { if (p.visible) { randomizeParameter(p);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} } return n; } SetJasmineCurrentSpec(); const nubs: Nub[] = []; let iNub: number = 0; let bHouston: boolean = true; // Houston, we have a problem... describe("Fuzz testing", () => { beforeAll(() => { iNub = 0; Session.getInstance().clear(); }); afterAll(() => { if (bHouston) { const sessionJson = Session.getInstance().serialise(); // tslint:disable-next-line:no-console console.debug(sessionJson); } }); for (const iCalType of calTypes) { // if ([CalculatorType.MacroRugoCompound].includes(iCalType)) { if (!nubsNotTested.includes(iCalType)) { describe(CalculatorType[iCalType], () => { for (let i = 0; i < fuzzyCfg.nTests; i++) { describe(`Test ${i}`, () => { beforeAll(() => { // tslint:disable-next-line:no-console console.debug( // tslint:disable-next-line:max-line-length `iNub=${iNub} Class=${nubs[iNub].constructor.name} Type=${CalculatorType[nubs[iNub].calcType]} uid=${nubs[iNub].uid}` ); }); afterAll(() => { iNub++; }); nubs.push(CreateTestNub(iCalType)); // List available calculable parameters const calcPrms: ParamDefinition[] = nubs[iNub].calculableParameters; if (calcPrms.length === 0) { // No calculable paramter such as in Ssection Paramétrée // Use one fake parameter for running the thing once for (const p of nubs[iNub].parameterIterator) { calcPrms.push(p); break; } } for (const p of calcPrms) { describe(`Calc(${p.symbol})`, () => { p.setCalculated(); beforeAll(() => { p.setCalculated(); }); afterEach(() => { const currentSpec: any = jasmine.getEnv().currentSpec; if (currentSpec.failedExpectations.length > 0) { Session.getInstance().unserialiseSingleNub(nubs[iNub].serialise()); bHouston = true; } }); it(printPrms(nubs[iNub]), () => { const r = nubs[iNub].CalcSerie(); checkResultConsistency(nubs[iNub], r); }); }); } }); iNub++;
211212213214215216
} }); } } });