1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-07-26 19:04:38 +02:00
Files
misskey/packages-private/diagnostics-backend/test/render-md.test.ts
2026-07-23 21:46:19 +09:00

131 lines
5.2 KiB
TypeScript

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { expect, test } from 'vitest';
import { pairedDeltaSummary } from 'diagnostics-shared/stats';
import { renderMemoryReportMarkdown } from '../src/report/markdown';
import type { MemoryReport } from '../src/types';
const fixturesDir = join(import.meta.dirname, 'fixtures');
async function loadFixture(name: string) {
return JSON.parse(await readFile(join(fixturesDir, `${name}.json`), 'utf8')) as MemoryReport;
}
function replacePssSamples(report: MemoryReport, values: number[]) {
const templates = structuredClone(report.samples);
report.samples = values.map((Pss, index) => {
const sample = structuredClone(templates[index % templates.length]);
sample.round = index + 1;
sample.phases.afterGc.memoryUsage.Pss = Pss;
const privateClean = sample.phases.afterGc.memoryUsage.Private_Clean;
sample.phases.afterGc.memoryUsage.Private_Dirty = Pss - privateClean;
return sample;
});
report.sampleCount = report.samples.length;
return report;
}
function findMetricRow(markdown: string, metric: string) {
const row = markdown.split('\n').find(line => line.startsWith(`| **${metric}**`));
if (row === undefined) throw new Error(`expected memory report to contain a ${metric} row`);
return row;
}
/**
* 出力をゴールデンファイルで固定する。
* 意図的に変更したときは `vitest -u` で更新し、__snapshots__ の差分もレビューすること。
*/
test('renders the backend memory report', async () => {
const markdown = renderMemoryReportMarkdown(await loadFixture('base'), await loadFixture('head'), {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
});
await expect(markdown).toMatchFileSnapshot('./__snapshots__/render-md.md');
});
test('throws when filtering leaves fewer than two heap snapshots per side', async () => {
const base = await loadFixture('base');
const head = await loadFixture('head');
for (const report of [base, head]) {
for (const sample of report.samples.slice(0, -1)) {
sample.phases.afterGc.heapSnapshot = null;
}
}
expect(() => renderMemoryReportMarkdown(base, head, {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
})).toThrow('At least two samples per side are required');
});
test('omits a paired-looking PSS delta that stays within observed noise', async () => {
const base = replacePssSamples(await loadFixture('base'), [290_000, 292_900, 295_800, 298_700, 301_600]);
const head = replacePssSamples(await loadFixture('head'), [292_900, 296_300, 298_700, 301_600, 290_000]);
expect(pairedDeltaSummary(
base.samples,
head.samples,
sample => sample.phases.afterGc.memoryUsage.Pss,
).median).toBe(2_900);
const markdown = renderMemoryReportMarkdown(base, head, {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
});
expect(markdown).not.toContain('| **PSS** |');
expect(markdown).toContain('<small><i>Only metrics showing significant changes are displayed.</i></small>');
expect(markdown).not.toContain('⚠️ **Warning**: Memory usage (PSS)');
});
test('keeps the convergence warning without suppressing table colour or the PSS warning', async () => {
const base = await loadFixture('base');
const head = await loadFixture('head');
base.samples[0].phases.afterGc.memoryStability.converged = false;
const markdown = renderMemoryReportMarkdown(base, head, {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
});
const memorySection = markdown.slice(0, markdown.indexOf('### V8 Heap Snapshot Statistics'));
expect(memorySection).not.toContain('inconclusive');
expect(findMetricRow(markdown, 'PSS')).toContain('\\color{orange}');
expect(markdown).toContain('⚠️ **Measurement warning**: 1 memory sample did not converge.');
expect(markdown).not.toContain('results are marked inconclusive');
expect(markdown).toContain('⚠️ **Warning**: Memory usage (PSS)');
});
test('throws for an undersampled memory comparison', async () => {
const base = await loadFixture('base');
const head = await loadFixture('head');
base.samples = base.samples.slice(0, 1);
head.samples = head.samples.slice(0, 1);
expect(() => renderMemoryReportMarkdown(base, head, {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
})).toThrow('At least two samples per side are required');
});
test('renders an unavailable percentage when the base median is zero', async () => {
const base = await loadFixture('base');
const head = await loadFixture('head');
for (const sample of base.samples) sample.phases.afterGc.memoryUsage.External = 0;
const markdown = renderMemoryReportMarkdown(base, head, {
baseHeapSnapshotUrl: 'https://example.invalid/base',
headHeapSnapshotUrl: 'https://example.invalid/head',
});
expect(findMetricRow(markdown, 'External')).toContain('<br>-');
expect(markdown).toContain('| Metric | @&nbsp;Base | @&nbsp;Head | Δ | MAD |');
expect(markdown).not.toContain('| Metric | @&nbsp;Base | @&nbsp;Head | Δ | MAD | Result |');
});