From 8a36578ea8566a66211d3c4e43475b0ea6f3ce1c Mon Sep 17 00:00:00 2001 From: Lukas Petr Date: Sun, 8 Feb 2026 11:46:13 +0100 Subject: [PATCH] Add support for sysctl format of diffkemp-out.yaml Add support for changes in diffkemp-out.yaml which were created in [1]. Also added tests for testing of the `Differences` class. [1] https://github.com/diffkemp/diffkemp/pull/421 --- src/differences.ts | 43 +++++++++--- tests/differences.test.ts | 134 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 tests/differences.test.ts diff --git a/src/differences.ts b/src/differences.ts index b28c291..b12c4af 100644 --- a/src/differences.ts +++ b/src/differences.ts @@ -68,9 +68,20 @@ export class Differences { } /** Extract info from diffkemp-out.yaml loaded to JSON as object (yaml). */ static fromDiffKempOut(yaml: DiffKempOutputFormat) { - yaml.results.sort((result1, result2) => result1.function.localeCompare(result2.function)); + // 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); + }); + } + results.sort((result1, result2) => result1.function.localeCompare(result2.function)); const comparedDiffering = new Map(); - yaml.results.forEach((result) => { + results.forEach((result) => { const cmpFun = result.function; const differingFuns = result.diffs.map((diff) => diff.function).sort(); comparedDiffering.set(cmpFun, differingFuns); @@ -289,21 +300,35 @@ export interface DifferingInfo { export interface DiffKempOutputFormat { "old-snapshot"?: string; "new-snapshot"?: string; - results: { - // Compared function name + results: ResultNormalComparisonFormat | ResultSysctlComparisonFormat; + definitions?: DKOutDefinitions; +} + +/** Format for results when running compare command without --sysctl parameters. */ +type ResultNormalComparisonFormat = ComparedFunctionOutputFormat[]; +/** Format for results when running compare command with `--sysctl` parameters. */ +type ResultSysctlComparisonFormat = { + sysctl: string; + results: ComparedFunctionOutputFormat[]; +}[]; + +/** Format of subpart of `diffkemp-out.yaml` file describing compared function. */ +interface ComparedFunctionOutputFormat { + // Compared function name + function: string; + diffs: { + // Differing function name function: string; - diffs: { - // Differing function name - function: string; - }[]; + "old-callstack": unknown; + "new-callstack": unknown; }[]; - definitions?: DKOutDefinitions; } /** Format of definitions of functions from diffkemp-out.yaml. */ type DKOutDefinitions = Record; /** Format of definition of old/new function from diffkemp-out.yaml. */ export interface DKOutDefinition { + kind: string; old?: { file?: string; line?: number; diff --git a/tests/differences.test.ts b/tests/differences.test.ts new file mode 100644 index 0000000..e54c0f0 --- /dev/null +++ b/tests/differences.test.ts @@ -0,0 +1,134 @@ +/** Test for processing of `diffkemp-out.yaml` file. */ +import { expect, test } from "vitest"; +import { Differences, DiffKempOutputFormat } from "../src/differences.js"; + +const EXAMPLE_FOR_FUNCTIONS: DiffKempOutputFormat = { + "old-snapshot": "/functions/86851c2/8.4/", + "new-snapshot": "/functions/86851c2/8.5/", + results: [ + { + function: "__alloc_disk_node", + diffs: [ + { + function: "kmalloc_node", + "old-callstack": [ + { name: "kzalloc_node", file: "block/genhd.c", line: 1707 }, + { name: "kmalloc_node", file: "./include/linux/slab.h", line: 679 }, + ], + "new-callstack": [ + { name: "kzalloc_node", file: "block/genhd.c", line: 1735 }, + { name: "kmalloc_node", file: "./include/linux/slab.h", line: 721 }, + ], + }, + { + function: "kmalloc_type", + "old-callstack": [ + { name: "kzalloc_node", file: "block/genhd.c", line: 1707 }, + { name: "kmalloc_node", file: "./include/linux/slab.h", line: 679 }, + { name: "kmalloc_type", file: "./include/linux/slab.h", line: 575 }, + ], + "new-callstack": [ + { name: "kzalloc_node", file: "block/genhd.c", line: 1735 }, + { name: "kmalloc_node", file: "./include/linux/slab.h", line: 721 }, + { name: "kmalloc_type", file: "./include/linux/slab.h", line: 599 }, + ], + }, + ], + }, + ], + definitions: { + __alloc_disk_node: { + kind: "function", + old: { line: 1695, file: "block/genhd.c", "end-line": 1746 }, + new: { line: 1723, file: "block/genhd.c", "end-line": 1774 }, + }, + kmalloc_node: { + kind: "function", + old: { line: 564, file: "include/linux/slab.h", "end-line": 580 }, + new: { line: 588, file: "include/linux/slab.h", "end-line": 604 }, + }, + }, +}; + +const EXAMPLE_FOR_SYSCTL: DiffKempOutputFormat = { + "old-snapshot": "/sysctl/86851c2/8.4/", + "new-snapshot": "/sysctl/86851c2/8.5/", + results: [ + { + sysctl: "vm.zone_reclaim_mode", + results: [ + { + function: "__node_reclaim", + diffs: [ + { + function: "RECLAIM_UNMAP", + "old-callstack": [{ name: "RECLAIM_UNMAP (macro)", file: "mm/vmscan.c", line: 4180 }], + "new-callstack": [{ name: "RECLAIM_UNMAP (macro)", file: "mm/vmscan.c", line: 4192 }], + }, + ], + }, + { + function: "node_pagecache_reclaimable", + diffs: [ + { + function: "RECLAIM_UNMAP", + "old-callstack": [{ name: "RECLAIM_UNMAP (macro)", file: "mm/vmscan.c", line: 4149 }], + "new-callstack": [{ name: "RECLAIM_UNMAP (macro)", file: "mm/vmscan.c", line: 4161 }], + }, + ], + }, + ], + }, + ], + definitions: { + __node_reclaim: { + kind: "function", + old: { line: 4168, file: "mm/vmscan.c", "end-line": 4217 }, + new: { line: 4180, file: "mm/vmscan.c", "end-line": 4229 }, + }, + node_pagecache_reclaimable: { + kind: "function", + old: { line: 4138, file: "mm/vmscan.c", "end-line": 4163 }, + new: { line: 4150, file: "mm/vmscan.c", "end-line": 4175 }, + }, + }, +}; + +test("it should be possible to extract differences from diffkemp-out.yaml for functions", () => { + const differences = Differences.fromDiffKempOut(EXAMPLE_FOR_FUNCTIONS); + expect(differences.oldSrcPath).toBe("/functions/86851c2/8.4/"); + expect(differences.newSrcPath).toBe("/functions/86851c2/8.5/"); + expect(differences.getCompared()).toEqual(["__alloc_disk_node"]); + expect(differences.comparedDiffering).toEqual( + new Map([["__alloc_disk_node", ["kmalloc_node", "kmalloc_type"]]]), + ); + expect(differences.getDifferingCompared()).toEqual( + new Map([ + ["kmalloc_node", new Set(["__alloc_disk_node"])], + ["kmalloc_type", new Set(["__alloc_disk_node"])], + ]), + ); + expect(differences.getDiffering()).toEqual(["kmalloc_node", "kmalloc_type"]); + expect(differences.getDefinitionForDiffering("kmalloc_node")).toEqual({ + kind: "function", + old: { line: 564, file: "include/linux/slab.h", "end-line": 580 }, + new: { line: 588, file: "include/linux/slab.h", "end-line": 604 }, + }); +}); + +test("it should be possible to extract differences from diffkemp-out.yaml for sysctl", () => { + const differences = Differences.fromDiffKempOut(EXAMPLE_FOR_SYSCTL); + expect(differences.oldSrcPath).toBe("/sysctl/86851c2/8.4/"); + expect(differences.newSrcPath).toBe("/sysctl/86851c2/8.5/"); + expect(differences.getCompared()).toEqual(["__node_reclaim", "node_pagecache_reclaimable"]); + expect(differences.comparedDiffering).toEqual( + new Map([ + ["__node_reclaim", ["RECLAIM_UNMAP"]], + ["node_pagecache_reclaimable", ["RECLAIM_UNMAP"]], + ]), + ); + expect(differences.getDifferingCompared()).toEqual( + new Map([["RECLAIM_UNMAP", new Set(["__node_reclaim", "node_pagecache_reclaimable"])]]), + ); + expect(differences.getDiffering()).toEqual(["RECLAIM_UNMAP"]); +});