diff --git a/src/differences.ts b/src/differences.ts index b12c4af..78cacba 100644 --- a/src/differences.ts +++ b/src/differences.ts @@ -68,17 +68,23 @@ export class Differences { } /** Extract info from diffkemp-out.yaml loaded to JSON as object (yaml). */ static fromDiffKempOut(yaml: DiffKempOutputFormat) { - // Extracting results for compared functions - let results = Array(); - if (yaml.results.length > 0 && "function" in yaml.results[0]) { - // Results for normal comparison - results = yaml.results as ResultNormalComparisonFormat; - } else { - // Results for sysctl comparison - (yaml.results as ResultSysctlComparisonFormat).forEach((result) => { - results.push(...result.results); + // Extracting results for compared functions. The `results` structure can be nested and may + // contain direct `function` entries or grouped entries (e.g. `sysctl`, `glob_var`) at 'any' + // depth — collect them recursively. + const results: ComparedFunctionOutputFormat[] = []; + const collect = (arr: ResultNormalComparisonFormat[] | ResultSysctlComparisonFormat[]) => { + if (!arr) return; + arr.forEach((item) => { + if ("function" in item && "diffs" in item && Array.isArray(item.diffs)) { + results.push(item); + } + // If this node groups other results, recurse into them. + if ("results" in item) { + collect(item.results); + } }); - } + }; + collect(yaml.results); results.sort((result1, result2) => result1.function.localeCompare(result2.function)); const comparedDiffering = new Map(); results.forEach((result) => { @@ -300,17 +306,17 @@ export interface DifferingInfo { export interface DiffKempOutputFormat { "old-snapshot"?: string; "new-snapshot"?: string; - results: ResultNormalComparisonFormat | ResultSysctlComparisonFormat; + results: ResultNormalComparisonFormat[] | ResultSysctlComparisonFormat[]; definitions?: DKOutDefinitions; } /** Format for results when running compare command without --sysctl parameters. */ -type ResultNormalComparisonFormat = ComparedFunctionOutputFormat[]; +type ResultNormalComparisonFormat = ComparedFunctionOutputFormat | GlobalVarOutputFormat; /** Format for results when running compare command with `--sysctl` parameters. */ -type ResultSysctlComparisonFormat = { +interface ResultSysctlComparisonFormat { sysctl: string; results: ComparedFunctionOutputFormat[]; -}[]; +} /** Format of subpart of `diffkemp-out.yaml` file describing compared function. */ interface ComparedFunctionOutputFormat { @@ -324,6 +330,12 @@ interface ComparedFunctionOutputFormat { }[]; } +/** Format of subpart of `diffkemp-out.yaml` file describing compared global variable. */ +interface GlobalVarOutputFormat { + glob_var: string; + results: ComparedFunctionOutputFormat[]; +} + /** Format of definitions of functions from diffkemp-out.yaml. */ type DKOutDefinitions = Record; /** Format of definition of old/new function from diffkemp-out.yaml. */ diff --git a/tests/differences.test.ts b/tests/differences.test.ts index e54c0f0..c5d05ef 100644 --- a/tests/differences.test.ts +++ b/tests/differences.test.ts @@ -132,3 +132,40 @@ test("it should be possible to extract differences from diffkemp-out.yaml for sy ); expect(differences.getDiffering()).toEqual(["RECLAIM_UNMAP"]); }); + +const EXAMPLE_GLOB_VAR_AND_FUN: DiffKempOutputFormat = { + "old-snapshot": "/old/", + "new-snapshot": "/new/", + results: [ + { function: "a_fun", diffs: [{ function: "X", "old-callstack": [], "new-callstack": [] }] }, + { + glob_var: "g", + results: [ + { function: "b_fun", diffs: [{ function: "Y", "old-callstack": [], "new-callstack": [] }] }, + ], + }, + { function: "c_fun", diffs: [{ function: "Z", "old-callstack": [], "new-callstack": [] }] }, + ], +}; + +test("it should be able to parse output glob_var + functions", () => { + const differences = Differences.fromDiffKempOut(EXAMPLE_GLOB_VAR_AND_FUN); + expect(differences.oldSrcPath).toBe("/old/"); + expect(differences.newSrcPath).toBe("/new/"); + expect(differences.getCompared()).toEqual(["a_fun", "b_fun", "c_fun"]); + expect(differences.comparedDiffering).toEqual( + new Map([ + ["a_fun", ["X"]], + ["b_fun", ["Y"]], + ["c_fun", ["Z"]], + ]), + ); + expect(differences.getDifferingCompared()).toEqual( + new Map([ + ["X", new Set(["a_fun"])], + ["Y", new Set(["b_fun"])], + ["Z", new Set(["c_fun"])], + ]), + ); + expect(differences.getDiffering()).toEqual(["X", "Y", "Z"]); +});