/** @jest-environment node */ import sharp from 'sharp' import { createMultiReferenceChallenge, multiReferenceGrid, multiReferenceImages, multiReferencePrompt, readMultiReferenceChallenge, validateMultiReferenceOutput } from '@/lib/ai-model-multireference' import { verifiedReferenceImageCount } from '@/lib/ai-model-verification-state' jest.mock('next-auth', () => ({ getServerSession: jest.fn() })) jest.mock('@/lib/auth', () => ({ authOptions: {} })) jest.mock('@/lib/prisma', () => ({ prisma: {} })) async function composite(challenge: ReturnType, replacement?: 'repeat-first' | 'reverse' | 'omit-last') { const { columns, rows } = multiReferenceGrid(challenge.references.length) let images = await multiReferenceImages(challenge) if (replacement === 'repeat-first') images = images.map(() => images[0]) if (replacement === 'reverse') images.reverse() if (replacement === 'omit-last') images.pop() return sharp({ create: { width: columns * 512, height: rows * 512, channels: 3, background: '#fff' } }).composite(images.map((image, i) => ({ input: image.buffer, left: i % columns * 512, top: Math.floor(i / columns) * 512 }))).png().toBuffer() } test.each([2, 4, 8])('all %i independently supplied references must match their ordered tiles', async count => { const challenge = createMultiReferenceChallenge(count) expect(readMultiReferenceChallenge(JSON.parse(JSON.stringify(challenge)))).toEqual(challenge) expect(new Set(challenge.references.map(value => `${value.topLeft}/${value.bottomRight}`)).size).toBe(count) const prompt = multiReferencePrompt(challenge) expect(prompt).not.toMatch(/red|blue|green|yellow|红色|蓝色|绿色|黄色/i) const correct = await composite(challenge) await expect(validateMultiReferenceOutput(correct, challenge)).resolves.toMatchObject({ referenceImageCount: count, allReferenceImagesMatched: true, referenceMatches: Array(count).fill(true) }) const padded = await sharp(correct).extend({ top: 100, bottom: 700, left: 60, right: 60, background: '#fff' }).png().toBuffer() await expect(validateMultiReferenceOutput(padded, challenge)).resolves.toMatchObject({ referenceImageCount: count, allReferenceImagesMatched: true }) for (const mutation of ['repeat-first', 'reverse', 'omit-last'] as const) await expect(validateMultiReferenceOutput(await composite(challenge, mutation), challenge)).rejects.toMatchObject({ code: 'verification_output_invalid' }) }) test('invalid counts and duplicated checkpoints are rejected before a model request', () => { for (const count of [0, 1, 9, 2.5]) expect(() => createMultiReferenceChallenge(count)).toThrow() for (const value of [null, { version: 1, references: [] }, { version: 1, references: [{ topLeft: 'red', bottomRight: 'blue' }, { topLeft: 'red', bottomRight: 'blue' }] }]) expect(() => readMultiReferenceChallenge(value)).toThrow() }) test('square-panel layout may include unused cells but cannot omit or replace an input', async () => { const challenge = createMultiReferenceChallenge(2), images = await multiReferenceImages(challenge) const background = Buffer.from('') const image = await sharp(background).composite(images.map((value, i) => ({ input: value.buffer, left: i * 512, top: 0 }))).png().toBuffer() await expect(validateMultiReferenceOutput(image, challenge)).resolves.toMatchObject({ referenceImageCount: 2, referenceMatches: [true, true], referenceGrid: { columns: 2, rows: 2 } }) const missing = await sharp(background).composite([{ input: images[0].buffer, left: 0, top: 0 }]).png().toBuffer() await expect(validateMultiReferenceOutput(missing, challenge)).rejects.toThrow() }) test('a count assertion without per-reference pixel evidence cannot expand the runtime allowance', () => { const base: any = { stage: 'image', status: 'passed', evidence: { referenceImageCount: 8 }, deadlineAt: new Date() } expect(verifiedReferenceImageCount(base)).toBeNull() expect(verifiedReferenceImageCount({ ...base, evidence: { referenceImageCount: 8, multiReferenceRuleVersion: 1, allReferenceImagesMatched: true, referenceMatches: [true] } })).toBeNull() expect(verifiedReferenceImageCount({ ...base, evidence: { referenceImageCount: 4, multiReferenceRuleVersion: 1, allReferenceImagesMatched: true, referenceMatches: [true, true, false, true] } })).toBeNull() expect(verifiedReferenceImageCount({ ...base, evidence: { referenceImageCount: 4, multiReferenceRuleVersion: 1, allReferenceImagesMatched: true, referenceMatches: Array(4).fill(true) } })).toBe(4) })