import { z } from "zod"; import type { LeaksReport } from "../types.js"; /** * CI-runnable leak detection for XCTest unit-test bundles. * * Sibling to `detectLeaksInXCUITest`. The orchestration model is the same: * build-for-testing -> launch test bundle -> poll for the runner process -> * capture baseline memgraph -> wait for test to finish -> capture after * memgraph -> diff. The difference is the target process: unit tests run * inside an `xctest` runner (or the app process if a host app is configured), * not the XCUITest host app. Default `processName` reflects that. * * Per-test granularity is achieved by the CALLER invoking the tool once per * test method (passing a different `testCaseFilter` each time). The tool * itself runs ONE `xcodebuild test` invocation per call so the result is * always tied to a single, well-defined before/after pair. */ export declare const detectLeaksInXCTestSchema: z.ZodEffects; project: z.ZodOptional; scheme: z.ZodString; destination: z.ZodDefault; testCaseFilter: z.ZodOptional; processName: z.ZodDefault; outputDir: z.ZodDefault; allowlistPatterns: z.ZodDefault>; skipBuild: z.ZodDefault; runnerStartTimeoutMs: z.ZodDefault; outputHtmlPath: z.ZodOptional; }, "strip", z.ZodTypeAny, { scheme: string; destination: string; processName: string; outputDir: string; allowlistPatterns: string[]; skipBuild: boolean; runnerStartTimeoutMs: number; workspace?: string | undefined; project?: string | undefined; testCaseFilter?: string | undefined; outputHtmlPath?: string | undefined; }, { scheme: string; workspace?: string | undefined; project?: string | undefined; destination?: string | undefined; testCaseFilter?: string | undefined; processName?: string | undefined; outputDir?: string | undefined; allowlistPatterns?: string[] | undefined; skipBuild?: boolean | undefined; runnerStartTimeoutMs?: number | undefined; outputHtmlPath?: string | undefined; }>, { scheme: string; destination: string; processName: string; outputDir: string; allowlistPatterns: string[]; skipBuild: boolean; runnerStartTimeoutMs: number; workspace?: string | undefined; project?: string | undefined; testCaseFilter?: string | undefined; outputHtmlPath?: string | undefined; }, { scheme: string; workspace?: string | undefined; project?: string | undefined; destination?: string | undefined; testCaseFilter?: string | undefined; processName?: string | undefined; outputDir?: string | undefined; allowlistPatterns?: string[] | undefined; skipBuild?: boolean | undefined; runnerStartTimeoutMs?: number | undefined; outputHtmlPath?: string | undefined; }>; export type DetectLeaksInXCTestInput = z.infer; export interface XCTestLeakResult { ok: boolean; /** True when no new (non-allowlisted) ROOT CYCLEs appeared after the test. */ passed: boolean; baselineMemgraph: string; afterMemgraph: string; testCaseFilter?: string; totals: { baselineLeaks: number; afterLeaks: number; leakDelta: number; }; newCycles: Array<{ rootClass: string; chainLength: number; /** True when this cycle matches an allowlist pattern. */ allowlisted: boolean; }>; failureReason?: string; steps: string[]; /** Absolute path to the rendered HTML report when `outputHtmlPath` was set. */ htmlReportPath?: string; } export declare function isAllowlisted(rootClass: string, patterns: string[]): boolean; export declare function countDescendants(children: Array<{ children: unknown[]; }>): number; /** * Build the new-cycles summary by diffing baseline + after reports against the * allowlist. Exposed for testing so the diff logic can be exercised without * spinning up xcodebuild. */ export declare function summarizeNewCycles(baseline: LeaksReport, after: LeaksReport, allowlistPatterns: string[]): { newCycles: XCTestLeakResult["newCycles"]; failingCount: number; }; export declare function detectLeaksInXCTest(input: DetectLeaksInXCTestInput): Promise;