ranges:dates samples each active group's posting dates from the news server (group_dates) and estimates every range's date (ranges.est_date). ranges:capture --from --to marks a window's ranges of every group for the corpus. The corpus fill takes capture ranges in priority order, done ones too, and remembers complete ones (ranges.stored_at). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
76 lines
2.9 KiB
TypeScript
76 lines
2.9 KiB
TypeScript
import { test } from '@japa/runner'
|
|
import type { Overview } from '#lib/nntp/index'
|
|
import {
|
|
estimateDate,
|
|
medianDate,
|
|
monotone,
|
|
sampleCount,
|
|
samplePoints,
|
|
} from '#services/group_dates'
|
|
|
|
const now = new Date('2026-10-25T10:00:00Z')
|
|
const overview = (n: number, date: string): Overview => [n, { subject: 's', from: 'f', date }]
|
|
const day = (d: string) => new Date(`${d}T00:00:00Z`)
|
|
|
|
test.group('group dates', () => {
|
|
test('the median of the plausible Date headers, or null for too few', ({ assert }) => {
|
|
const slice = [
|
|
overview(1, 'Mon, 02 Mar 2015 10:00:00 +0000'),
|
|
overview(2, 'Tue, 03 Mar 2015 10:00:00 GMT'),
|
|
overview(3, 'Wed, 04 Mar 2015 10:00:00 UTC'),
|
|
// A broken clock, a future one, and junk: left out.
|
|
overview(4, 'Sat, 01 Jan 1980 00:00:00 +0000'),
|
|
overview(5, 'Fri, 01 Jan 2027 00:00:00 +0000'),
|
|
overview(6, 'not a date'),
|
|
overview(7, 'Thu, 05 Mar 2015 10:00:00 +0100'),
|
|
]
|
|
assert.equal(medianDate(slice, now)!.toISOString(), '2015-03-04T10:00:00.000Z')
|
|
assert.isNull(medianDate(slice.slice(0, 2), now))
|
|
assert.isNull(medianDate([], now))
|
|
})
|
|
|
|
test('sample points span low to high, the last slice ending at high', ({ assert }) => {
|
|
assert.deepEqual(samplePoints(100, 1099, 5, 100), [100, 325, 550, 775, 1000])
|
|
assert.deepEqual(samplePoints(100, 150, 5, 100), [100])
|
|
assert.equal(sampleCount(0, 161e9, 500e6), 323)
|
|
assert.equal(sampleCount(0, 1000, 500e6), 16)
|
|
assert.equal(sampleCount(0, 10e12, 500e6), 1000)
|
|
})
|
|
|
|
test('the curve drops a spike, raises a dip, and keeps the order', ({ assert }) => {
|
|
const curve = monotone([
|
|
{ article: 300, postedAt: day('2015-03-01') },
|
|
{ article: 100, postedAt: day('2015-01-01') },
|
|
// One poster's clock in the future for a whole slice.
|
|
{ article: 200, postedAt: day('2019-06-01') },
|
|
// Old crossposts: earlier than the sample before.
|
|
{ article: 400, postedAt: day('2014-12-01') },
|
|
{ article: 500, postedAt: day('2015-05-01') },
|
|
])
|
|
assert.deepEqual(
|
|
curve.map((s) => [s.article, s.postedAt.toISOString().slice(0, 10)]),
|
|
[
|
|
[100, '2015-01-01'],
|
|
[300, '2015-03-01'],
|
|
[400, '2015-03-01'],
|
|
[500, '2015-05-01'],
|
|
]
|
|
)
|
|
})
|
|
|
|
test('a date is interpolated between the samples around it and clamped beyond them', ({
|
|
assert,
|
|
}) => {
|
|
const curve = [
|
|
{ article: 100, postedAt: day('2015-01-01') },
|
|
{ article: 300, postedAt: day('2015-03-02') },
|
|
{ article: 500, postedAt: day('2015-05-01') },
|
|
]
|
|
assert.equal(estimateDate(curve, 200)!.toISOString().slice(0, 10), '2015-01-31')
|
|
assert.equal(estimateDate(curve, 300)!.toISOString().slice(0, 10), '2015-03-02')
|
|
assert.equal(estimateDate(curve, 1)!.toISOString().slice(0, 10), '2015-01-01')
|
|
assert.equal(estimateDate(curve, 900)!.toISOString().slice(0, 10), '2015-05-01')
|
|
assert.isNull(estimateDate([], 200))
|
|
})
|
|
})
|