#!/usr/bin/env node // Unit test for the correctness benchmark assertion. Feeds known-good and // known-bad LLM outputs through each task checker and asserts the expected // pass/fail verdict. Runs without promptfoo — just node:test + the module. const test = require('node:test'); const assert = require('node:assert/strict'); const correctness = require('../benchmarks/correctness'); // Helper: wrap code in a fenced block and call the assertion with task vars. function check(task, lang, code) { const output = '```' + lang + '\n' + code + '\n```'; return correctness(output, { vars: { task } }); } // --- Email validator --- test('email: correct one-liner passes', () => { const result = check( 'Write me a Python function that validates email addresses.', 'python', 'def validate_email(email):\n return "@" in email and "." in email.split("@")[-1] and email.split("@")[0] != ""', ); assert.equal(result.pass, true); assert.equal(result.score, 1); }); test('email: always-true validator fails', () => { const result = check( 'Write me a Python function that validates email addresses.', 'python', 'def validate_email(email):\n return True', ); assert.equal(result.pass, false); assert.equal(result.score, 0); }); test('email: no code block fails', () => { const result = correctness('Here is my answer: just use regex.', { vars: { task: 'Write me a Python function that validates email addresses.' }, }); assert.equal(result.pass, false); }); // --- Debounce --- test('debounce: correct implementation passes', () => { const result = check( 'Add debounce to a search input in vanilla JavaScript.', 'javascript', `function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; }`, ); assert.equal(result.pass, true); assert.equal(result.score, 1); }); test('debounce: immediate-call implementation fails', () => { const result = check( 'Add debounce to a search input in vanilla JavaScript.', 'javascript', `function debounce(fn, delay) { return function(...args) { fn.apply(this, args); }; }`, ); assert.equal(result.pass, false); assert.equal(result.score, 0); }); // --- CSV sum --- test('csv: correct pandas one-liner passes', () => { const result = check( "Write Python code that reads sales.csv and sums the 'amount' column.", 'python', `import pandas as pd df = pd.read_csv('sales.csv') print(df['amount'].sum())`, ); assert.equal(result.pass, true); assert.equal(result.score, 1); }); test('csv: code that prints wrong value fails', () => { const result = check( "Write Python code that reads sales.csv and sums the 'amount' column.", 'python', `print(999)`, ); assert.equal(result.pass, false); assert.equal(result.score, 0); }); test('csv: value containing 351 as substring fails (e.g. 13510)', () => { const result = check( "Write Python code that reads sales.csv and sums the 'amount' column.", 'python', `print(13510)`, ); assert.equal(result.pass, false); assert.equal(result.score, 0); }); test('csv: timeout can be raised for slow pandas startup', () => { const previous = process.env.PONYTAIL_CORRECTNESS_TIMEOUT_MS; try { process.env.PONYTAIL_CORRECTNESS_TIMEOUT_MS = '1'; const timedOut = check( "Write Python code that reads sales.csv and sums the 'amount' column.", 'python', `import time time.sleep(0.05) print(351)`, ); assert.equal(timedOut.pass, false); assert.match(timedOut.reason, /ETIMEDOUT|timed out/i); process.env.PONYTAIL_CORRECTNESS_TIMEOUT_MS = '1000'; const completed = check( "Write Python code that reads sales.csv and sums the 'amount' column.", 'python', `import time time.sleep(0.05) print(351)`, ); assert.equal(completed.pass, true); assert.equal(completed.score, 1); } finally { if (previous === undefined) delete process.env.PONYTAIL_CORRECTNESS_TIMEOUT_MS; else process.env.PONYTAIL_CORRECTNESS_TIMEOUT_MS = previous; } }); // --- React countdown --- test('countdown: valid React component passes', () => { const result = check( 'Build me a countdown timer component in React.', 'javascript', `import { useState, useEffect } from 'react'; export default function Countdown({ seconds }) { const [count, setCount] = useState(seconds); useEffect(() => { if (count <= 0) return; const id = setInterval(() => setCount(prev => prev - 1), 1000); return () => clearInterval(id); }, [count]); return