Files
usenet-indexer/tests/unit/rules/rule_set.spec.ts
T
Daan MeijerandClaude Opus 5.5 d773c91ad0
Test and deploy / test (push) Successful in 29s
Test and deploy / deploy (push) Skipped
Rebuild: phase 1 modules from the current app, ordered by pipeline stage
lib/nntp (XOVER client, Xref, GROUP), lib/headers (subjects, file keys,
segments from overview lines; the yEnc path stays behind for phase 2),
lib/release (identity, random names, now in lib), lib/files (aggregator,
volume names), lib/rules (posting tools, owner by priority, release
verdicts), lib/chunks (release chunk codec). Their unit tests came along;
new ones for codec, rules and volumes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:08:44 +02:00

57 lines
3.1 KiB
TypeScript

import { test } from '@japa/runner'
import { DEFAULT_RULES, RuleSet, ownerOf, uploadTool, explored } from '#lib/rules/index'
import { sevenZipVolume } from '#lib/files/index'
const rules = new RuleSet({ ...DEFAULT_RULES, samplePercent: 0, priorities: {}, droppedSignatures: ['nyuu\talt.binaries.misc'] })
const file = (name: string, totalParts: number, firstMessageId: string, group = 'alt.binaries.ath') => ({ name, totalParts, groups: [group], firstMessageId })
const NGPOST = 'b94268bc702040f7b811d5318f727e4f@ngPost'
const NYUU = 'FmFwIaTpGgUiSfYcMwFlMeRo-1790637260478@nyuu'
test.group('rules / owner', () => {
test('a crosspost belongs to the indexed group with the lowest priority, whatever the Xref order', ({ assert }) => {
const priorities = { 'alt.binaries.boneless': 1, 'alt.binaries.ath': 3, 'alt.binaries.added.later': 1001 }
assert.equal(ownerOf(['alt.binaries.ath', 'alt.binaries.boneless'], priorities), 'alt.binaries.boneless')
assert.equal(ownerOf(['alt.binaries.added.later', 'alt.binaries.ath'], priorities), 'alt.binaries.ath')
assert.equal(ownerOf(['alt.binaries.not.indexed'], priorities), null)
})
})
test.group('rules / verdicts', () => {
test('a readable file keeps its whole release', ({ assert }) => {
assert.deepEqual(rules.judge('k', [file('Hs7dKq2LmZ9xWv3RtYp1Qa.part01.rar', 50, NGPOST), file('Some.Show.S01E01.1080p.nfo', 1, NGPOST)]), { rule: null })
})
test('random names: per-article with few parts, garbage by tool or signature, else kept', ({ assert }) => {
assert.include(rules.judge('k', [file('Hs7dKq2LmZ9xWv3RtYp1Qa', 2, NYUU)]), { rule: 'per-article', key: 'nyuu' })
assert.include(rules.judge('k', [file('Hs7dKq2LmZ9xWv3RtYp1Qa.part01.rar', 50, NGPOST)]), { rule: 'garbage', key: 'ngPost alt.binaries.ath' })
assert.include(rules.judge('k', [file('Hs7dKq2LmZ9xWv3RtYp1Qa.part01.rar', 50, NYUU, 'alt.binaries.misc')]), { rule: 'garbage', key: 'nyuu alt.binaries.misc' })
assert.deepEqual(rules.judge('k', [file('Hs7dKq2LmZ9xWv3RtYp1Qa.part01.rar', 50, NYUU)]), { rule: null })
})
})
test.group('rules / upload tools', () => {
test('posting tools are told apart by their Message-IDs', ({ assert }) => {
assert.equal(uploadTool(NYUU), 'nyuu')
assert.equal(uploadTool(NGPOST), 'ngPost')
assert.equal(uploadTool('part1of69.lOlWzvSHabJCBTVrs0ts@AdultPoster.local'), 'partNofM')
assert.equal(uploadTool('DLugnv3ZrVBv8Z9I69nU_19o112@JBinUp.local'), 'JBinUp')
assert.equal(uploadTool('t3Y4mV92YCp0McxDc5@zLZlsw.RYqes'), 'random')
assert.equal(uploadTool(null), 'other')
})
test('the sampled share is stable per key and about the percentage', ({ assert }) => {
assert.equal(explored('some-release', 2), explored('some-release', 2))
const kept = Array.from({ length: 10_000 }, (_, i) => explored(`release-${i}`, 2)).filter(Boolean).length
assert.isAbove(kept, 150)
assert.isBelow(kept, 250)
})
})
test.group('files / volumes', () => {
test('7z volume numbers', ({ assert }) => {
assert.equal(sevenZipVolume('x.7z.001'), 1)
assert.equal(sevenZipVolume('x.7z'), 0)
assert.isNull(sevenZipVolume('x.rar'))
})
})