From 3f3247184cb192d72c6403ec2a7c9646e5ffcd30 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg <33372913+dstallenberg@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:04:02 +0100 Subject: [PATCH] feat: allow removal of arguments (#211) Next to adding anonymous arguments (even though the function description specified less), it is now possible for arguments to removed (even though the function description specified more). This is usefull for example when dealing with arguments with default values. --- .../resolving/InferenceTypeModelFactory.ts | 12 ++++- .../sampling/JavaScriptRandomSampler.ts | 10 +++- .../sampling/JavaScriptTestCaseSampler.ts | 48 +++++++++++++++---- .../testcase/sampling/generators/Generator.ts | 12 ++++- .../generators/action/CallGenerator.ts | 18 +++++-- tools/javascript/lib/JavaScriptLauncher.ts | 5 +- tools/javascript/lib/commands/test.ts | 35 ++++++++++++++ .../plugins/sampler/RandomSamplerPlugin.ts | 5 +- 8 files changed, 128 insertions(+), 17 deletions(-) diff --git a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts index 584e98b6..1096e642 100644 --- a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts +++ b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts @@ -904,8 +904,9 @@ export class InferenceTypeModelFactory extends TypeModelFactory { originalInvolved: string[] ) { const [objectId, propertyId] = involved; - const [, originalProperty] = originalInvolved; + const [originalObject, originalProperty] = originalInvolved; + const objectElement = elementMap.get(originalObject); const propertyElement = elementMap.get(originalProperty); if (propertyElement === undefined) { @@ -921,6 +922,15 @@ export class InferenceTypeModelFactory extends TypeModelFactory { // add array type to object this._typeModel.addElementType(objectId, relation.id); + if ( + objectElement && + objectElement.type === ElementType.Identifier && + objectElement.name === "arguments" + ) { + // e.g. arguments[0] + // TODO get function parent and add the argument (impossible right now) + } + break; } case ElementType.StringLiteral: { diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts index 788bb72c..5f178778 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts @@ -76,7 +76,10 @@ export class JavaScriptRandomSampler extends JavaScriptTestCaseSampler { stringAlphabet: string, stringMaxLength: number, deltaMutationProbability: number, - exploreIllegalValues: boolean + exploreIllegalValues: boolean, + addRemoveArgumentProbability: number, + addArgumentProbability: number, + removeArgumentProbability: number ) { super( subject, @@ -94,7 +97,10 @@ export class JavaScriptRandomSampler extends JavaScriptTestCaseSampler { stringAlphabet, stringMaxLength, deltaMutationProbability, - exploreIllegalValues + exploreIllegalValues, + addRemoveArgumentProbability, + addArgumentProbability, + removeArgumentProbability ); } diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts index 48d87738..7ffaa785 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts @@ -78,6 +78,10 @@ export abstract class JavaScriptTestCaseSampler extends EncodingSampler { protected _statementPoolEnabled: boolean; protected _statementPoolProbability: number; + protected _addRemoveArgumentProbability: number; + protected _addArgumentProbability: number; + protected _removeArgumentProbability: number; + constructor( sampler: JavaScriptTestCaseSampler, rootContext: RootContext, statementPoolEnabled: boolean, - statementPoolProbability: number + statementPoolProbability: number, + addRemoveArgumentProbability: number, + addArgumentProbability: number, + removeArgumentProbability: number ) { this._sampler = sampler; this._rootContext = rootContext; this._statementPoolEnabled = statementPoolEnabled; this._statementPoolProbability = statementPoolProbability; + this._addRemoveArgumentProbability = addRemoveArgumentProbability; + this._addArgumentProbability = addArgumentProbability; + this._removeArgumentProbability = removeArgumentProbability; } abstract generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts index a63ca57b..fc9d1d09 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts @@ -46,9 +46,21 @@ export abstract class CallGenerator extends Generator { } } - for (let index = 0; index < 10; index++) { - if (prng.nextBoolean(0.05)) { - // TODO make this a config parameter + // 50/50 to either maybe remove or add an argument + if (prng.nextBoolean(this._addRemoveArgumentProbability)) { + // remove args + for (let index = 0; index < arguments_.length; index++) { + if (!prng.nextBoolean(this._removeArgumentProbability)) { + break; + } + arguments_.pop(); + } + } else { + // add args + for (let index = 0; index < 10; index++) { + if (!prng.nextBoolean(this._addArgumentProbability)) { + break; + } arguments_.push(this.sampler.sampleArgument(depth + 1, "anon", "anon")); } } diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 3ea7949e..d6c353a2 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -788,7 +788,10 @@ export class JavaScriptLauncher extends Launcher { this.arguments_.stringAlphabet, this.arguments_.stringMaxLength, this.arguments_.deltaMutationProbability, - this.arguments_.exploreIllegalValues + this.arguments_.exploreIllegalValues, + this.arguments_.addRemoveArgumentProbability, + this.arguments_.addArgumentProbability, + this.arguments_.removeArgumentProbability ); sampler.rootContext = rootContext; diff --git a/tools/javascript/lib/commands/test.ts b/tools/javascript/lib/commands/test.ts index d16c1c17..acd83962 100644 --- a/tools/javascript/lib/commands/test.ts +++ b/tools/javascript/lib/commands/test.ts @@ -121,6 +121,36 @@ export function getTestCommand( type: "number", }); + options.set("add-remove-argument-probability", { + alias: [], + default: 0.5, + description: + "Probability to maybe add an argument as oposed to maybe remove one.", + group: samplingGroup, + hidden: false, + type: "number", + }); + + options.set("add-argument-probability", { + alias: [], + default: 0.1, + description: + "Probability to add one extra anonymous argument (probability to add two args is equal to probablity squared, etc.) (maximum of 10).", + group: samplingGroup, + hidden: false, + type: "number", + }); + + options.set("remove-argument-probability", { + alias: [], + default: 0.1, + description: + "Probability to remove an argument (probability to remove two args is equal to probablity squared, etc.).", + group: samplingGroup, + hidden: false, + type: "number", + }); + options.set("execution-timeout", { alias: [], default: 2000, @@ -187,6 +217,11 @@ export type TestCommandOptions = { typePoolProbability: number; statementPool: boolean; statementPoolProbability: number; + + addRemoveArgumentProbability: number; + addArgumentProbability: number; + removeArgumentProbability: number; + executionTimeout: number; testTimeout: number; diff --git a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts index 85e8085f..e5982d3a 100644 --- a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts +++ b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts @@ -54,7 +54,10 @@ export class RandomSamplerPlugin extends SamplerPlugin { ((this.args)).stringAlphabet, ((this.args)).stringMaxLength, ((this.args)).deltaMutationProbability, - ((this.args)).exploreIllegalValues + ((this.args)).exploreIllegalValues, + ((this.args)).addRemoveArgumentProbability, + ((this.args)).addArgumentProbability, + ((this.args)).removeArgumentProbability ); }