@exercode/problem-utils 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/cli/runSingleHarness.js.map +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.cjs +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.cjs.map +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.d.ts +2 -0
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.js +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.js.map +1 -1
- package/dist/helpers/runHarnessProcess.cjs.map +1 -1
- package/dist/helpers/runHarnessProcess.d.ts +4 -1
- package/dist/helpers/runHarnessProcess.js.map +1 -1
- package/dist/helpers/spawnWithLimits.cjs +2 -0
- package/dist/helpers/spawnWithLimits.cjs.map +1 -0
- package/dist/helpers/spawnWithLimits.d.ts +38 -0
- package/dist/helpers/spawnWithLimits.js +2 -0
- package/dist/helpers/spawnWithLimits.js.map +1 -0
- package/dist/helpers/spawnWithTimeout.cjs +4 -0
- package/dist/helpers/spawnWithTimeout.cjs.map +1 -0
- package/dist/helpers/spawnWithTimeout.d.ts +21 -0
- package/dist/helpers/spawnWithTimeout.js +4 -0
- package/dist/helpers/spawnWithTimeout.js.map +1 -0
- package/dist/helpers/temporaryProblemDirCopy.cjs +1 -1
- package/dist/helpers/temporaryProblemDirCopy.js +1 -1
- package/dist/presets/command.cjs +1 -1
- package/dist/presets/command.cjs.map +1 -1
- package/dist/presets/command.d.ts +2 -0
- package/dist/presets/command.js +1 -1
- package/dist/presets/command.js.map +1 -1
- package/dist/presets/guiCommand.cjs +2 -2
- package/dist/presets/guiCommand.cjs.map +1 -1
- package/dist/presets/guiCommand.js +2 -2
- package/dist/presets/guiCommand.js.map +1 -1
- package/dist/presets/stdio.cjs +1 -1
- package/dist/presets/stdio.cjs.map +1 -1
- package/dist/presets/stdio.js +1 -1
- package/dist/presets/stdio.js.map +1 -1
- package/dist/types/testCaseResult.cjs +1 -1
- package/dist/types/testCaseResult.cjs.map +1 -1
- package/dist/types/testCaseResult.d.ts +1 -0
- package/dist/types/testCaseResult.js +1 -1
- package/dist/types/testCaseResult.js.map +1 -1
- package/package.json +3 -3
- package/dist/helpers/spawnSyncWithTimeout.cjs +0 -2
- package/dist/helpers/spawnSyncWithTimeout.cjs.map +0 -1
- package/dist/helpers/spawnSyncWithTimeout.d.ts +0 -5
- package/dist/helpers/spawnSyncWithTimeout.js +0 -2
- package/dist/helpers/spawnSyncWithTimeout.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.cjs","names":["z","parseArgs","readProblemMarkdownFrontMatter","readTestCases","path","judgesTestCasesWithoutExpectations","judgeByStaticAnalysis","findEntryPointFile","DecisionCode","findLanguageDefinitionByPath","spawnSyncWithTimeout","snapshotWorkingDirectory","copyTestCaseFileInput","readOutputFiles","judgeAgainstExpectations","cleanWorkingDirectory","fs","copyProblemDirToTemporaryRoot","forciblyRemoveDirectory","EXAMPLE_TEST_CASE_ID_PATTERN"],"sources":["../../src/presets/stdio.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { z } from 'zod';\n\nimport { cleanWorkingDirectory, snapshotWorkingDirectory } from '../helpers/cleanWorkingDirectory.js';\nimport { judgeAgainstExpectations } from '../helpers/compareExpectedOutputFiles.js';\nimport { copyTestCaseFileInput } from '../helpers/copyTestCaseFileInput.js';\nimport { findEntryPointFile } from '../helpers/findEntryPointFile.js';\nimport { findLanguageDefinitionByPath } from '../helpers/findLanguageDefinitionByPath.js';\nimport { judgeByStaticAnalysis } from '../helpers/judgeByStaticAnalysis.js';\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readOutputFiles } from '../helpers/readOutputFiles.js';\nimport {\n judgesTestCasesWithoutExpectations,\n readProblemMarkdownFrontMatter,\n} from '../helpers/readProblemMarkdownFrontMatter.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { spawnSyncWithTimeout } from '../helpers/spawnSyncWithTimeout.js';\nimport { EXAMPLE_TEST_CASE_ID_PATTERN, MAX_STDOUT_LENGTH } from '../helpers/stdioJudgeRules.js';\nimport {\n copyProblemDirToTemporaryRoot,\n forciblyRemoveDirectory,\n forciblyRemoveDirectorySync,\n} from '../helpers/temporaryProblemDirCopy.js';\nimport { DecisionCode } from '../types/decisionCode.js';\n\nconst BUILD_TIMEOUT_SECONDS = 10;\nconst JUDGE_DEFAULT_TIMEOUT_SECONDS = 2;\nconst DEBUG_DEFAULT_TIMEOUT_SECONDS = 10;\n\nconst judgeParamsSchema = z.object({\n language: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nconst debugParamsSchema = judgeParamsSchema.extend({\n stdin: z.string().optional(),\n});\n\ntype DebugParams = z.infer<typeof debugParamsSchema>;\n\n/**\n * A preset judge function using stdin and stdout as test cases.\n *\n * A standard stdio problem must NOT commit a `judge.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `judge.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `judge.ts`:\n * ```bash\n * bun x exercode-problem judge model_answers/java\n * ```\n *\n * Run with the optional parameters:\n * ```bash\n * bun x exercode-problem judge model_answers/java '{ \"language\": \"javascript\" }'\n * ```\n */\nexport async function stdioJudgePreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = judgeParamsSchema.parse(args.params);\n\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n // Without an expectation, a case would accept any run; only custom harnesses may judge input-only\n // cases. A problem judged by manual scoring or the presence of required output files has an\n // expectation of its own. Checked before the static analysis so that an authoring error surfaces\n // regardless of the submission.\n if (!judgesTestCasesWithoutExpectations(problemMarkdownFrontMatter)) {\n for (const testCase of testCases) {\n if (testCase.output === undefined && !(await hasExpectedFiles(testCase.fileOutputPath))) {\n throw new Error(\n `test case ${testCase.id} needs an expected output (${testCase.id}.out or a non-empty ${testCase.id}.fout/)`\n );\n }\n }\n }\n\n const staticAnalysisTestCaseResult = await judgeByStaticAnalysis(args.cwd, problemMarkdownFrontMatter);\n if (staticAnalysisTestCaseResult) {\n printTestCaseResult({ testCaseId: testCases[0]?.id ?? 'prebuild', ...staticAnalysisTestCaseResult });\n return;\n }\n\n const originalMainFilePath = await findEntryPointFile(args.cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(args.cwd);\n prebuiltMainFilePath = await findEntryPointFile(args.cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n try {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n const buildSpawnResult = spawnSyncWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd: args.cwd, encoding: 'utf8', env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n } catch (error) {\n console.error('build error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const cwdSnapshot = await snapshotWorkingDirectory(args.cwd);\n\n if (testCases.length === 0) {\n printTestCaseResult({ testCaseId: 'default', decisionCode: DecisionCode.ACCEPTED });\n }\n\n for (const testCase of testCases) {\n // prepare test case\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, args.cwd);\n if (testCase.fileInputPath) await copyTestCaseFileInput(testCase.fileInputPath, args.cwd);\n\n // run\n const timeoutSeconds =\n typeof problemMarkdownFrontMatter.timeLimitMs === 'number'\n ? problemMarkdownFrontMatter.timeLimitMs / 1000\n : JUDGE_DEFAULT_TIMEOUT_SECONDS;\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = spawnSyncWithTimeout(\n command[0],\n command.slice(1),\n { cwd: args.cwd, encoding: 'utf8', input: testCase.input, env },\n timeoutSeconds\n );\n\n let outputFiles = await readOutputFiles(args.cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n // calculate decision\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n let judgementError: string | undefined;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n } else {\n try {\n const judgement = await judgeAgainstExpectations({\n stdout: spawnResult.stdout,\n expectedStdout: testCase.output,\n fileOutputPath: testCase.fileOutputPath,\n cwd: args.cwd,\n outputFiles,\n });\n if (!judgement.matches) decisionCode = DecisionCode.WRONG_ANSWER;\n outputFiles = judgement.outputFiles;\n } catch (error) {\n // An authoring error (e.g. an oversized expected file) is reported per case, like the command preset does.\n decisionCode = DecisionCode.RUNTIME_ERROR;\n judgementError = error instanceof Error ? error.message : String(error);\n }\n }\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: testCase.input,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: (judgementError ?? spawnResult.stderr).slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n\n // clean up\n await cleanWorkingDirectory(args.cwd, cwdSnapshot);\n\n if (decisionCode !== DecisionCode.ACCEPTED) break;\n }\n}\n\nasync function hasExpectedFiles(fileOutputPath: string | undefined): Promise<boolean> {\n if (fileOutputPath === undefined) return false;\n const dirents = await fs.promises.readdir(fileOutputPath, { withFileTypes: true, recursive: true });\n return dirents.some((dirent) => dirent.isFile());\n}\n\n/**\n * A preset debug function using stdin and stdout as test cases. The answer directory is copied to a\n * temporary directory where it is built and run together with `_shared.fin/` and the first example\n * case's `.fin/`; files the program writes are reported only through `requiredOutputFilePaths`.\n *\n * A standard stdio problem must NOT commit a `debug.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `debug.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `debug.ts`:\n * ```bash\n * bun x exercode-problem debug model_answers/java '{ \"stdin\": \"1 2\" }'\n * ```\n */\nexport async function stdioDebugPreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = debugParamsSchema.parse(args.params);\n\n // Everything (build, input files, run) happens in a disposable copy of the answer directory, so\n // the developer's files are never touched and whatever the submission leaves behind goes with it.\n // The copy keeps the directory hierarchy and links every ancestor `node_modules`, so packages the\n // answer resolves from its parents still resolve.\n // A terminated debug run must not leave the copy behind; `finally` does not run on a signal, so\n // the handlers learn the root as soon as it is created and stay until it is removed.\n let tempRoot: string | undefined;\n const removeOnSignal = (): void => {\n if (tempRoot !== undefined) forciblyRemoveDirectorySync(tempRoot);\n process.exit(1);\n };\n process.once('SIGINT', removeOnSignal);\n process.once('SIGTERM', removeOnSignal);\n try {\n const copy = await copyProblemDirToTemporaryRoot(args.cwd, { onTempRootCreated: (root) => (tempRoot = root) });\n await debugInTemporaryCopy(problemDir, copy.copiedProblemDir, params);\n } finally {\n if (tempRoot !== undefined) await forciblyRemoveDirectory(tempRoot);\n process.off('SIGINT', removeOnSignal);\n process.off('SIGTERM', removeOnSignal);\n }\n}\n\nasync function debugInTemporaryCopy(problemDir: string, cwd: string, params: DebugParams): Promise<void> {\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n\n const originalMainFilePath = await findEntryPointFile(cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(cwd);\n prebuiltMainFilePath = await findEntryPointFile(cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n try {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n const buildSpawnResult = spawnSyncWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd, encoding: 'utf8', env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n } catch (error) {\n console.error('build error', error);\n\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n // A debug run has no test case of its own: it gets the shared input files and the `.fin/` of the\n // first example case (the cases a learner may see), placed the way the judge does. Hidden cases'\n // input files are never handed to learner code.\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, cwd);\n const exampleFileInputPath = testCases.find(\n (testCase) => EXAMPLE_TEST_CASE_ID_PATTERN.test(testCase.id) && testCase.fileInputPath\n )?.fileInputPath;\n if (exampleFileInputPath) {\n await copyTestCaseFileInput(exampleFileInputPath, cwd);\n } else if (testCases.some((testCase) => testCase.fileInputPath)) {\n console.error('debug: no example test case has input files, so the program runs without them');\n }\n\n const timeoutSeconds = Math.max(DEBUG_DEFAULT_TIMEOUT_SECONDS, (problemMarkdownFrontMatter.timeLimitMs ?? 0) / 1000);\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = spawnSyncWithTimeout(\n command[0],\n command.slice(1),\n { cwd, encoding: 'utf8', input: params.stdin, env },\n timeoutSeconds\n );\n\n const outputFiles = await readOutputFiles(cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n }\n\n printTestCaseResult({\n testCaseId: 'debug',\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: params.stdin,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: spawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stdio.cjs","names":["z","parseArgs","readProblemMarkdownFrontMatter","readTestCases","path","judgesTestCasesWithoutExpectations","judgeByStaticAnalysis","findEntryPointFile","DecisionCode","findLanguageDefinitionByPath","spawnWithTimeout","snapshotWorkingDirectory","copyTestCaseFileInput","readOutputFiles","judgeAgainstExpectations","cleanWorkingDirectory","fs","copyProblemDirToTemporaryRoot","forciblyRemoveDirectory","EXAMPLE_TEST_CASE_ID_PATTERN"],"sources":["../../src/presets/stdio.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { z } from 'zod';\n\nimport { cleanWorkingDirectory, snapshotWorkingDirectory } from '../helpers/cleanWorkingDirectory.js';\nimport { judgeAgainstExpectations } from '../helpers/compareExpectedOutputFiles.js';\nimport { copyTestCaseFileInput } from '../helpers/copyTestCaseFileInput.js';\nimport { findEntryPointFile } from '../helpers/findEntryPointFile.js';\nimport { findLanguageDefinitionByPath } from '../helpers/findLanguageDefinitionByPath.js';\nimport { judgeByStaticAnalysis } from '../helpers/judgeByStaticAnalysis.js';\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readOutputFiles } from '../helpers/readOutputFiles.js';\nimport {\n judgesTestCasesWithoutExpectations,\n readProblemMarkdownFrontMatter,\n} from '../helpers/readProblemMarkdownFrontMatter.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { spawnWithTimeout } from '../helpers/spawnWithTimeout.js';\nimport { EXAMPLE_TEST_CASE_ID_PATTERN, MAX_STDOUT_LENGTH } from '../helpers/stdioJudgeRules.js';\nimport {\n copyProblemDirToTemporaryRoot,\n forciblyRemoveDirectory,\n forciblyRemoveDirectorySync,\n} from '../helpers/temporaryProblemDirCopy.js';\nimport { DecisionCode } from '../types/decisionCode.js';\n\nconst BUILD_TIMEOUT_SECONDS = 10;\nconst JUDGE_DEFAULT_TIMEOUT_SECONDS = 2;\nconst DEBUG_DEFAULT_TIMEOUT_SECONDS = 10;\n\nconst judgeParamsSchema = z.object({\n language: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nconst debugParamsSchema = judgeParamsSchema.extend({\n stdin: z.string().optional(),\n});\n\ntype DebugParams = z.infer<typeof debugParamsSchema>;\n\n/**\n * A preset judge function using stdin and stdout as test cases.\n *\n * A standard stdio problem must NOT commit a `judge.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `judge.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `judge.ts`:\n * ```bash\n * bun x exercode-problem judge model_answers/java\n * ```\n *\n * Run with the optional parameters:\n * ```bash\n * bun x exercode-problem judge model_answers/java '{ \"language\": \"javascript\" }'\n * ```\n */\nexport async function stdioJudgePreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = judgeParamsSchema.parse(args.params);\n\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n // Without an expectation, a case would accept any run; only custom harnesses may judge input-only\n // cases. A problem judged by manual scoring or the presence of required output files has an\n // expectation of its own. Checked before the static analysis so that an authoring error surfaces\n // regardless of the submission.\n if (!judgesTestCasesWithoutExpectations(problemMarkdownFrontMatter)) {\n for (const testCase of testCases) {\n if (testCase.output === undefined && !(await hasExpectedFiles(testCase.fileOutputPath))) {\n throw new Error(\n `test case ${testCase.id} needs an expected output (${testCase.id}.out or a non-empty ${testCase.id}.fout/)`\n );\n }\n }\n }\n\n const staticAnalysisTestCaseResult = await judgeByStaticAnalysis(args.cwd, problemMarkdownFrontMatter);\n if (staticAnalysisTestCaseResult) {\n printTestCaseResult({ testCaseId: testCases[0]?.id ?? 'prebuild', ...staticAnalysisTestCaseResult });\n return;\n }\n\n const originalMainFilePath = await findEntryPointFile(args.cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(args.cwd);\n prebuiltMainFilePath = await findEntryPointFile(args.cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n // The build reports the submission's failures in its result; what `spawnWithTimeout` throws is\n // the judge's own failure and ends the run without a verdict.\n const buildSpawnResult = await spawnWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd: args.cwd, env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n cpuTimeSeconds: buildSpawnResult.cpuTimeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n }\n\n const cwdSnapshot = await snapshotWorkingDirectory(args.cwd);\n\n if (testCases.length === 0) {\n printTestCaseResult({ testCaseId: 'default', decisionCode: DecisionCode.ACCEPTED });\n }\n\n for (const testCase of testCases) {\n // prepare test case\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, args.cwd);\n if (testCase.fileInputPath) await copyTestCaseFileInput(testCase.fileInputPath, args.cwd);\n\n // run\n const timeoutSeconds =\n typeof problemMarkdownFrontMatter.timeLimitMs === 'number'\n ? problemMarkdownFrontMatter.timeLimitMs / 1000\n : JUDGE_DEFAULT_TIMEOUT_SECONDS;\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = await spawnWithTimeout(\n command[0],\n command.slice(1),\n { cwd: args.cwd, stdin: testCase.input, env },\n timeoutSeconds\n );\n\n let outputFiles = await readOutputFiles(args.cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n // calculate decision\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n let judgementError: string | undefined;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n } else {\n try {\n const judgement = await judgeAgainstExpectations({\n stdout: spawnResult.stdout,\n expectedStdout: testCase.output,\n fileOutputPath: testCase.fileOutputPath,\n cwd: args.cwd,\n outputFiles,\n });\n if (!judgement.matches) decisionCode = DecisionCode.WRONG_ANSWER;\n outputFiles = judgement.outputFiles;\n } catch (error) {\n // An authoring error (e.g. an oversized expected file) is reported per case, like the command preset does.\n decisionCode = DecisionCode.RUNTIME_ERROR;\n judgementError = error instanceof Error ? error.message : String(error);\n }\n }\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: testCase.input,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: (judgementError ?? spawnResult.stderr).slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n cpuTimeSeconds: spawnResult.cpuTimeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n\n // clean up\n await cleanWorkingDirectory(args.cwd, cwdSnapshot);\n\n if (decisionCode !== DecisionCode.ACCEPTED) break;\n }\n}\n\nasync function hasExpectedFiles(fileOutputPath: string | undefined): Promise<boolean> {\n if (fileOutputPath === undefined) return false;\n const dirents = await fs.promises.readdir(fileOutputPath, { withFileTypes: true, recursive: true });\n return dirents.some((dirent) => dirent.isFile());\n}\n\n/**\n * A preset debug function using stdin and stdout as test cases. The answer directory is copied to a\n * temporary directory where it is built and run together with `_shared.fin/` and the first example\n * case's `.fin/`; files the program writes are reported only through `requiredOutputFilePaths`.\n *\n * A standard stdio problem must NOT commit a `debug.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `debug.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `debug.ts`:\n * ```bash\n * bun x exercode-problem debug model_answers/java '{ \"stdin\": \"1 2\" }'\n * ```\n */\nexport async function stdioDebugPreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = debugParamsSchema.parse(args.params);\n\n // Everything (build, input files, run) happens in a disposable copy of the answer directory, so\n // the developer's files are never touched and whatever the submission leaves behind goes with it.\n // The copy keeps the directory hierarchy and links every ancestor `node_modules`, so packages the\n // answer resolves from its parents still resolve.\n // A terminated debug run must not leave the copy behind; `finally` does not run on a signal, so\n // the handlers learn the root as soon as it is created and stay until it is removed.\n let tempRoot: string | undefined;\n const removeOnSignal = (): void => {\n if (tempRoot !== undefined) forciblyRemoveDirectorySync(tempRoot);\n process.exit(1);\n };\n process.once('SIGINT', removeOnSignal);\n process.once('SIGTERM', removeOnSignal);\n try {\n const copy = await copyProblemDirToTemporaryRoot(args.cwd, { onTempRootCreated: (root) => (tempRoot = root) });\n await debugInTemporaryCopy(problemDir, copy.copiedProblemDir, params);\n } finally {\n if (tempRoot !== undefined) await forciblyRemoveDirectory(tempRoot);\n process.off('SIGINT', removeOnSignal);\n process.off('SIGTERM', removeOnSignal);\n }\n}\n\nasync function debugInTemporaryCopy(problemDir: string, cwd: string, params: DebugParams): Promise<void> {\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n\n const originalMainFilePath = await findEntryPointFile(cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(cwd);\n prebuiltMainFilePath = await findEntryPointFile(cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n // The build reports the submission's failures in its result; what `spawnWithTimeout` throws is\n // the judge's own failure and ends the run without a verdict.\n const buildSpawnResult = await spawnWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd, env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n cpuTimeSeconds: buildSpawnResult.cpuTimeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n }\n\n // A debug run has no test case of its own: it gets the shared input files and the `.fin/` of the\n // first example case (the cases a learner may see), placed the way the judge does. Hidden cases'\n // input files are never handed to learner code.\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, cwd);\n const exampleFileInputPath = testCases.find(\n (testCase) => EXAMPLE_TEST_CASE_ID_PATTERN.test(testCase.id) && testCase.fileInputPath\n )?.fileInputPath;\n if (exampleFileInputPath) {\n await copyTestCaseFileInput(exampleFileInputPath, cwd);\n } else if (testCases.some((testCase) => testCase.fileInputPath)) {\n console.error('debug: no example test case has input files, so the program runs without them');\n }\n\n const timeoutSeconds = Math.max(DEBUG_DEFAULT_TIMEOUT_SECONDS, (problemMarkdownFrontMatter.timeLimitMs ?? 0) / 1000);\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = await spawnWithTimeout(\n command[0],\n command.slice(1),\n { cwd, stdin: params.stdin, env },\n timeoutSeconds\n );\n\n const outputFiles = await readOutputFiles(cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n }\n\n printTestCaseResult({\n testCaseId: 'debug',\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: params.stdin,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: spawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n cpuTimeSeconds: spawnResult.cpuTimeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n}\n"],"mappings":"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"}
|
package/dist/presets/stdio.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{printTestCaseResult as e}from"../helpers/printTestCaseResult.js";import{judgeAgainstExpectations as t}from"../helpers/compareExpectedOutputFiles.js";import{parseArgs as n}from"../helpers/parseArgs.js";import{readTestCases as r}from"../helpers/readTestCases.js";import{copyProblemDirToTemporaryRoot as i,forciblyRemoveDirectory as a,forciblyRemoveDirectorySync as o}from"../helpers/temporaryProblemDirCopy.js";import{findLanguageDefinitionByPath as s}from"../helpers/findLanguageDefinitionByPath.js";import{judgesTestCasesWithoutExpectations as c,readProblemMarkdownFrontMatter as l}from"../helpers/readProblemMarkdownFrontMatter.js";import{EXAMPLE_TEST_CASE_ID_PATTERN as u}from"../helpers/stdioJudgeRules.js";import{DecisionCode as d}from"../types/decisionCode.js";import{cleanWorkingDirectory as f,snapshotWorkingDirectory as p}from"../helpers/cleanWorkingDirectory.js";import{copyTestCaseFileInput as m}from"../helpers/copyTestCaseFileInput.js";import{findEntryPointFile as h}from"../helpers/findEntryPointFile.js";import{judgeByStaticAnalysis as g}from"../helpers/judgeByStaticAnalysis.js";import{readOutputFiles as _}from"../helpers/readOutputFiles.js";import{
|
|
1
|
+
import{printTestCaseResult as e}from"../helpers/printTestCaseResult.js";import{judgeAgainstExpectations as t}from"../helpers/compareExpectedOutputFiles.js";import{parseArgs as n}from"../helpers/parseArgs.js";import{readTestCases as r}from"../helpers/readTestCases.js";import{copyProblemDirToTemporaryRoot as i,forciblyRemoveDirectory as a,forciblyRemoveDirectorySync as o}from"../helpers/temporaryProblemDirCopy.js";import{findLanguageDefinitionByPath as s}from"../helpers/findLanguageDefinitionByPath.js";import{judgesTestCasesWithoutExpectations as c,readProblemMarkdownFrontMatter as l}from"../helpers/readProblemMarkdownFrontMatter.js";import{EXAMPLE_TEST_CASE_ID_PATTERN as u}from"../helpers/stdioJudgeRules.js";import{DecisionCode as d}from"../types/decisionCode.js";import{cleanWorkingDirectory as f,snapshotWorkingDirectory as p}from"../helpers/cleanWorkingDirectory.js";import{copyTestCaseFileInput as m}from"../helpers/copyTestCaseFileInput.js";import{findEntryPointFile as h}from"../helpers/findEntryPointFile.js";import{judgeByStaticAnalysis as g}from"../helpers/judgeByStaticAnalysis.js";import{readOutputFiles as _}from"../helpers/readOutputFiles.js";import{spawnWithTimeout as v}from"../helpers/spawnWithTimeout.js";import y from"node:fs";import b from"node:path";import{z as x}from"zod";const S=x.object({language:x.union([x.string(),x.array(x.string())]).optional()}),C=S.extend({stdin:x.string().optional()});async function w(i){let a=n(process.argv);if(!a.cwd)throw Error(`cwd argument required`);let o=S.parse(a.params),u=await l(i),y=await r(b.join(i,`test_cases`));if(!c(u)){for(let e of y)if(e.output===void 0&&!await T(e.fileOutputPath))throw Error(`test case ${e.id} needs an expected output (${e.id}.out or a non-empty ${e.id}.fout/)`)}let x=await g(a.cwd,u);if(x){e({testCaseId:y[0]?.id??`prebuild`,...x});return}let C=await h(a.cwd,o.language);if(!C){e({testCaseId:y[0]?.id??`prebuild`,decisionCode:d.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,stderr:`main file not found${o.language?`: language: ${o.language}`:``}`});return}let w=s(C);if(!w){e({testCaseId:y[0]?.id??`prebuild`,decisionCode:d.WRONG_ANSWER,stderr:`unsupported language`});return}let E={...process.env,CI:``,FORCE_COLOR:`0`},D;if(w.prebuild)try{await w.prebuild(a.cwd),D=await h(a.cwd,o.language)}catch(t){console.error(`prebuild error`,t),e({testCaseId:y[0]?.id??`prebuild`,decisionCode:d.BUILD_ERROR,stderr:t instanceof Error?t.message:String(t)});return}let O=D??C;if(w.buildCommand){let t=w.buildCommand(O),n=await v(t[0],t.slice(1),{cwd:a.cwd,env:E},10),r=d.ACCEPTED;if(n.status===0?n.timeSeconds>10?r=d.BUILD_TIME_LIMIT_EXCEEDED:(n.stdout.length>5e4||n.stderr.length>5e4)&&(r=d.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED):r=d.BUILD_ERROR,r!==d.ACCEPTED){e({testCaseId:y[0]?.id??`build`,decisionCode:r,exitStatus:n.status??void 0,stdout:n.stdout.slice(0,5e4)||void 0,stderr:n.stderr.slice(0,5e4)||void 0,timeSeconds:n.timeSeconds,cpuTimeSeconds:n.cpuTimeSeconds,memoryBytes:n.memoryBytes});return}}let k=await p(a.cwd);y.length===0&&e({testCaseId:`default`,decisionCode:d.ACCEPTED});for(let n of y){y.shared?.fileInputPath&&await m(y.shared.fileInputPath,a.cwd),n.fileInputPath&&await m(n.fileInputPath,a.cwd);let r=typeof u.timeLimitMs==`number`?u.timeLimitMs/1e3:2,i=w.command(O),o=await v(i[0],i.slice(1),{cwd:a.cwd,stdin:n.input,env:E},r),s=await _(a.cwd,u.requiredOutputFilePaths??[]),c=d.ACCEPTED,l;if(o.status!==0)c=d.RUNTIME_ERROR;else if(o.timeSeconds>r)c=d.TIME_LIMIT_EXCEEDED;else if(o.memoryBytes>(u.memoryLimitByte??1/0))c=d.MEMORY_LIMIT_EXCEEDED;else if(o.stdout.length>5e4||o.stderr.length>5e4)c=d.OUTPUT_SIZE_LIMIT_EXCEEDED;else if(s.length<(u.requiredOutputFilePaths?.length??0))c=d.MISSING_REQUIRED_OUTPUT_FILE_ERROR;else try{let e=await t({stdout:o.stdout,expectedStdout:n.output,fileOutputPath:n.fileOutputPath,cwd:a.cwd,outputFiles:s});e.matches||(c=d.WRONG_ANSWER),s=e.outputFiles}catch(e){c=d.RUNTIME_ERROR,l=e instanceof Error?e.message:String(e)}if(e({testCaseId:n.id,decisionCode:c,exitStatus:o.status??void 0,stdin:n.input,stdout:o.stdout.slice(0,5e4)||void 0,stderr:(l??o.stderr).slice(0,5e4)||void 0,timeSeconds:o.timeSeconds,cpuTimeSeconds:o.cpuTimeSeconds,memoryBytes:o.memoryBytes,outputFiles:s.length>0?s:void 0}),await f(a.cwd,k),c!==d.ACCEPTED)break}}async function T(e){return e!==void 0&&(await y.promises.readdir(e,{withFileTypes:!0,recursive:!0})).some(e=>e.isFile())}async function E(e){let t=n(process.argv);if(!t.cwd)throw Error(`cwd argument required`);let r=C.parse(t.params),s,c=()=>{s!==void 0&&o(s),process.exit(1)};process.once(`SIGINT`,c),process.once(`SIGTERM`,c);try{await D(e,(await i(t.cwd,{onTempRootCreated:e=>s=e})).copiedProblemDir,r)}finally{s!==void 0&&await a(s),process.off(`SIGINT`,c),process.off(`SIGTERM`,c)}}async function D(t,n,i){let a=await l(t),o=await h(n,i.language);if(!o){e({testCaseId:`prebuild`,decisionCode:d.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,stderr:`main file not found${i.language?`: language: ${i.language}`:``}`});return}let c=s(o);if(!c){e({testCaseId:`prebuild`,decisionCode:d.WRONG_ANSWER,stderr:`unsupported language`});return}let f={...process.env,CI:``,FORCE_COLOR:`0`},p;if(c.prebuild)try{await c.prebuild(n),p=await h(n,i.language)}catch(t){console.error(`prebuild error`,t),e({testCaseId:`prebuild`,decisionCode:d.BUILD_ERROR,stderr:t instanceof Error?t.message:String(t)});return}let g=p??o;if(c.buildCommand){let t=c.buildCommand(g),r=await v(t[0],t.slice(1),{cwd:n,env:f},10),i=d.ACCEPTED;if(r.status===0?r.timeSeconds>10?i=d.BUILD_TIME_LIMIT_EXCEEDED:(r.stdout.length>5e4||r.stderr.length>5e4)&&(i=d.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED):i=d.BUILD_ERROR,i!==d.ACCEPTED){e({testCaseId:`build`,decisionCode:i,exitStatus:r.status??void 0,stdout:r.stdout.slice(0,5e4)||void 0,stderr:r.stderr.slice(0,5e4)||void 0,timeSeconds:r.timeSeconds,cpuTimeSeconds:r.cpuTimeSeconds,memoryBytes:r.memoryBytes});return}}let y=await r(b.join(t,`test_cases`));y.shared?.fileInputPath&&await m(y.shared.fileInputPath,n);let x=y.find(e=>u.test(e.id)&&e.fileInputPath)?.fileInputPath;x?await m(x,n):y.some(e=>e.fileInputPath)&&console.error(`debug: no example test case has input files, so the program runs without them`);let S=Math.max(10,(a.timeLimitMs??0)/1e3),C=c.command(g),w=await v(C[0],C.slice(1),{cwd:n,stdin:i.stdin,env:f},S),T=await _(n,a.requiredOutputFilePaths??[]),E=d.ACCEPTED;w.status===0?w.timeSeconds>S?E=d.TIME_LIMIT_EXCEEDED:w.memoryBytes>(a.memoryLimitByte??1/0)?E=d.MEMORY_LIMIT_EXCEEDED:w.stdout.length>5e4||w.stderr.length>5e4?E=d.OUTPUT_SIZE_LIMIT_EXCEEDED:T.length<(a.requiredOutputFilePaths?.length??0)&&(E=d.MISSING_REQUIRED_OUTPUT_FILE_ERROR):E=d.RUNTIME_ERROR,e({testCaseId:`debug`,decisionCode:E,exitStatus:w.status??void 0,stdin:i.stdin,stdout:w.stdout.slice(0,5e4)||void 0,stderr:w.stderr.slice(0,5e4)||void 0,timeSeconds:w.timeSeconds,cpuTimeSeconds:w.cpuTimeSeconds,memoryBytes:w.memoryBytes,outputFiles:T.length>0?T:void 0})}export{E as stdioDebugPreset,w as stdioJudgePreset};
|
|
2
2
|
//# sourceMappingURL=stdio.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","names":[],"sources":["../../src/presets/stdio.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { z } from 'zod';\n\nimport { cleanWorkingDirectory, snapshotWorkingDirectory } from '../helpers/cleanWorkingDirectory.js';\nimport { judgeAgainstExpectations } from '../helpers/compareExpectedOutputFiles.js';\nimport { copyTestCaseFileInput } from '../helpers/copyTestCaseFileInput.js';\nimport { findEntryPointFile } from '../helpers/findEntryPointFile.js';\nimport { findLanguageDefinitionByPath } from '../helpers/findLanguageDefinitionByPath.js';\nimport { judgeByStaticAnalysis } from '../helpers/judgeByStaticAnalysis.js';\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readOutputFiles } from '../helpers/readOutputFiles.js';\nimport {\n judgesTestCasesWithoutExpectations,\n readProblemMarkdownFrontMatter,\n} from '../helpers/readProblemMarkdownFrontMatter.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { spawnSyncWithTimeout } from '../helpers/spawnSyncWithTimeout.js';\nimport { EXAMPLE_TEST_CASE_ID_PATTERN, MAX_STDOUT_LENGTH } from '../helpers/stdioJudgeRules.js';\nimport {\n copyProblemDirToTemporaryRoot,\n forciblyRemoveDirectory,\n forciblyRemoveDirectorySync,\n} from '../helpers/temporaryProblemDirCopy.js';\nimport { DecisionCode } from '../types/decisionCode.js';\n\nconst BUILD_TIMEOUT_SECONDS = 10;\nconst JUDGE_DEFAULT_TIMEOUT_SECONDS = 2;\nconst DEBUG_DEFAULT_TIMEOUT_SECONDS = 10;\n\nconst judgeParamsSchema = z.object({\n language: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nconst debugParamsSchema = judgeParamsSchema.extend({\n stdin: z.string().optional(),\n});\n\ntype DebugParams = z.infer<typeof debugParamsSchema>;\n\n/**\n * A preset judge function using stdin and stdout as test cases.\n *\n * A standard stdio problem must NOT commit a `judge.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `judge.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `judge.ts`:\n * ```bash\n * bun x exercode-problem judge model_answers/java\n * ```\n *\n * Run with the optional parameters:\n * ```bash\n * bun x exercode-problem judge model_answers/java '{ \"language\": \"javascript\" }'\n * ```\n */\nexport async function stdioJudgePreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = judgeParamsSchema.parse(args.params);\n\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n // Without an expectation, a case would accept any run; only custom harnesses may judge input-only\n // cases. A problem judged by manual scoring or the presence of required output files has an\n // expectation of its own. Checked before the static analysis so that an authoring error surfaces\n // regardless of the submission.\n if (!judgesTestCasesWithoutExpectations(problemMarkdownFrontMatter)) {\n for (const testCase of testCases) {\n if (testCase.output === undefined && !(await hasExpectedFiles(testCase.fileOutputPath))) {\n throw new Error(\n `test case ${testCase.id} needs an expected output (${testCase.id}.out or a non-empty ${testCase.id}.fout/)`\n );\n }\n }\n }\n\n const staticAnalysisTestCaseResult = await judgeByStaticAnalysis(args.cwd, problemMarkdownFrontMatter);\n if (staticAnalysisTestCaseResult) {\n printTestCaseResult({ testCaseId: testCases[0]?.id ?? 'prebuild', ...staticAnalysisTestCaseResult });\n return;\n }\n\n const originalMainFilePath = await findEntryPointFile(args.cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(args.cwd);\n prebuiltMainFilePath = await findEntryPointFile(args.cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n try {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n const buildSpawnResult = spawnSyncWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd: args.cwd, encoding: 'utf8', env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n } catch (error) {\n console.error('build error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const cwdSnapshot = await snapshotWorkingDirectory(args.cwd);\n\n if (testCases.length === 0) {\n printTestCaseResult({ testCaseId: 'default', decisionCode: DecisionCode.ACCEPTED });\n }\n\n for (const testCase of testCases) {\n // prepare test case\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, args.cwd);\n if (testCase.fileInputPath) await copyTestCaseFileInput(testCase.fileInputPath, args.cwd);\n\n // run\n const timeoutSeconds =\n typeof problemMarkdownFrontMatter.timeLimitMs === 'number'\n ? problemMarkdownFrontMatter.timeLimitMs / 1000\n : JUDGE_DEFAULT_TIMEOUT_SECONDS;\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = spawnSyncWithTimeout(\n command[0],\n command.slice(1),\n { cwd: args.cwd, encoding: 'utf8', input: testCase.input, env },\n timeoutSeconds\n );\n\n let outputFiles = await readOutputFiles(args.cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n // calculate decision\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n let judgementError: string | undefined;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n } else {\n try {\n const judgement = await judgeAgainstExpectations({\n stdout: spawnResult.stdout,\n expectedStdout: testCase.output,\n fileOutputPath: testCase.fileOutputPath,\n cwd: args.cwd,\n outputFiles,\n });\n if (!judgement.matches) decisionCode = DecisionCode.WRONG_ANSWER;\n outputFiles = judgement.outputFiles;\n } catch (error) {\n // An authoring error (e.g. an oversized expected file) is reported per case, like the command preset does.\n decisionCode = DecisionCode.RUNTIME_ERROR;\n judgementError = error instanceof Error ? error.message : String(error);\n }\n }\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: testCase.input,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: (judgementError ?? spawnResult.stderr).slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n\n // clean up\n await cleanWorkingDirectory(args.cwd, cwdSnapshot);\n\n if (decisionCode !== DecisionCode.ACCEPTED) break;\n }\n}\n\nasync function hasExpectedFiles(fileOutputPath: string | undefined): Promise<boolean> {\n if (fileOutputPath === undefined) return false;\n const dirents = await fs.promises.readdir(fileOutputPath, { withFileTypes: true, recursive: true });\n return dirents.some((dirent) => dirent.isFile());\n}\n\n/**\n * A preset debug function using stdin and stdout as test cases. The answer directory is copied to a\n * temporary directory where it is built and run together with `_shared.fin/` and the first example\n * case's `.fin/`; files the program writes are reported only through `requiredOutputFilePaths`.\n *\n * A standard stdio problem must NOT commit a `debug.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `debug.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `debug.ts`:\n * ```bash\n * bun x exercode-problem debug model_answers/java '{ \"stdin\": \"1 2\" }'\n * ```\n */\nexport async function stdioDebugPreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = debugParamsSchema.parse(args.params);\n\n // Everything (build, input files, run) happens in a disposable copy of the answer directory, so\n // the developer's files are never touched and whatever the submission leaves behind goes with it.\n // The copy keeps the directory hierarchy and links every ancestor `node_modules`, so packages the\n // answer resolves from its parents still resolve.\n // A terminated debug run must not leave the copy behind; `finally` does not run on a signal, so\n // the handlers learn the root as soon as it is created and stay until it is removed.\n let tempRoot: string | undefined;\n const removeOnSignal = (): void => {\n if (tempRoot !== undefined) forciblyRemoveDirectorySync(tempRoot);\n process.exit(1);\n };\n process.once('SIGINT', removeOnSignal);\n process.once('SIGTERM', removeOnSignal);\n try {\n const copy = await copyProblemDirToTemporaryRoot(args.cwd, { onTempRootCreated: (root) => (tempRoot = root) });\n await debugInTemporaryCopy(problemDir, copy.copiedProblemDir, params);\n } finally {\n if (tempRoot !== undefined) await forciblyRemoveDirectory(tempRoot);\n process.off('SIGINT', removeOnSignal);\n process.off('SIGTERM', removeOnSignal);\n }\n}\n\nasync function debugInTemporaryCopy(problemDir: string, cwd: string, params: DebugParams): Promise<void> {\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n\n const originalMainFilePath = await findEntryPointFile(cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(cwd);\n prebuiltMainFilePath = await findEntryPointFile(cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n try {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n const buildSpawnResult = spawnSyncWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd, encoding: 'utf8', env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n } catch (error) {\n console.error('build error', error);\n\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n // A debug run has no test case of its own: it gets the shared input files and the `.fin/` of the\n // first example case (the cases a learner may see), placed the way the judge does. Hidden cases'\n // input files are never handed to learner code.\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, cwd);\n const exampleFileInputPath = testCases.find(\n (testCase) => EXAMPLE_TEST_CASE_ID_PATTERN.test(testCase.id) && testCase.fileInputPath\n )?.fileInputPath;\n if (exampleFileInputPath) {\n await copyTestCaseFileInput(exampleFileInputPath, cwd);\n } else if (testCases.some((testCase) => testCase.fileInputPath)) {\n console.error('debug: no example test case has input files, so the program runs without them');\n }\n\n const timeoutSeconds = Math.max(DEBUG_DEFAULT_TIMEOUT_SECONDS, (problemMarkdownFrontMatter.timeLimitMs ?? 0) / 1000);\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = spawnSyncWithTimeout(\n command[0],\n command.slice(1),\n { cwd, encoding: 'utf8', input: params.stdin, env },\n timeoutSeconds\n );\n\n const outputFiles = await readOutputFiles(cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n }\n\n printTestCaseResult({\n testCaseId: 'debug',\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: params.stdin,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: spawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stdio.js","names":[],"sources":["../../src/presets/stdio.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { z } from 'zod';\n\nimport { cleanWorkingDirectory, snapshotWorkingDirectory } from '../helpers/cleanWorkingDirectory.js';\nimport { judgeAgainstExpectations } from '../helpers/compareExpectedOutputFiles.js';\nimport { copyTestCaseFileInput } from '../helpers/copyTestCaseFileInput.js';\nimport { findEntryPointFile } from '../helpers/findEntryPointFile.js';\nimport { findLanguageDefinitionByPath } from '../helpers/findLanguageDefinitionByPath.js';\nimport { judgeByStaticAnalysis } from '../helpers/judgeByStaticAnalysis.js';\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readOutputFiles } from '../helpers/readOutputFiles.js';\nimport {\n judgesTestCasesWithoutExpectations,\n readProblemMarkdownFrontMatter,\n} from '../helpers/readProblemMarkdownFrontMatter.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { spawnWithTimeout } from '../helpers/spawnWithTimeout.js';\nimport { EXAMPLE_TEST_CASE_ID_PATTERN, MAX_STDOUT_LENGTH } from '../helpers/stdioJudgeRules.js';\nimport {\n copyProblemDirToTemporaryRoot,\n forciblyRemoveDirectory,\n forciblyRemoveDirectorySync,\n} from '../helpers/temporaryProblemDirCopy.js';\nimport { DecisionCode } from '../types/decisionCode.js';\n\nconst BUILD_TIMEOUT_SECONDS = 10;\nconst JUDGE_DEFAULT_TIMEOUT_SECONDS = 2;\nconst DEBUG_DEFAULT_TIMEOUT_SECONDS = 10;\n\nconst judgeParamsSchema = z.object({\n language: z.union([z.string(), z.array(z.string())]).optional(),\n});\n\nconst debugParamsSchema = judgeParamsSchema.extend({\n stdin: z.string().optional(),\n});\n\ntype DebugParams = z.infer<typeof debugParamsSchema>;\n\n/**\n * A preset judge function using stdin and stdout as test cases.\n *\n * A standard stdio problem must NOT commit a `judge.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `judge.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `judge.ts`:\n * ```bash\n * bun x exercode-problem judge model_answers/java\n * ```\n *\n * Run with the optional parameters:\n * ```bash\n * bun x exercode-problem judge model_answers/java '{ \"language\": \"javascript\" }'\n * ```\n */\nexport async function stdioJudgePreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = judgeParamsSchema.parse(args.params);\n\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n // Without an expectation, a case would accept any run; only custom harnesses may judge input-only\n // cases. A problem judged by manual scoring or the presence of required output files has an\n // expectation of its own. Checked before the static analysis so that an authoring error surfaces\n // regardless of the submission.\n if (!judgesTestCasesWithoutExpectations(problemMarkdownFrontMatter)) {\n for (const testCase of testCases) {\n if (testCase.output === undefined && !(await hasExpectedFiles(testCase.fileOutputPath))) {\n throw new Error(\n `test case ${testCase.id} needs an expected output (${testCase.id}.out or a non-empty ${testCase.id}.fout/)`\n );\n }\n }\n }\n\n const staticAnalysisTestCaseResult = await judgeByStaticAnalysis(args.cwd, problemMarkdownFrontMatter);\n if (staticAnalysisTestCaseResult) {\n printTestCaseResult({ testCaseId: testCases[0]?.id ?? 'prebuild', ...staticAnalysisTestCaseResult });\n return;\n }\n\n const originalMainFilePath = await findEntryPointFile(args.cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(args.cwd);\n prebuiltMainFilePath = await findEntryPointFile(args.cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n // The build reports the submission's failures in its result; what `spawnWithTimeout` throws is\n // the judge's own failure and ends the run without a verdict.\n const buildSpawnResult = await spawnWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd: args.cwd, env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: testCases[0]?.id ?? 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n cpuTimeSeconds: buildSpawnResult.cpuTimeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n }\n\n const cwdSnapshot = await snapshotWorkingDirectory(args.cwd);\n\n if (testCases.length === 0) {\n printTestCaseResult({ testCaseId: 'default', decisionCode: DecisionCode.ACCEPTED });\n }\n\n for (const testCase of testCases) {\n // prepare test case\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, args.cwd);\n if (testCase.fileInputPath) await copyTestCaseFileInput(testCase.fileInputPath, args.cwd);\n\n // run\n const timeoutSeconds =\n typeof problemMarkdownFrontMatter.timeLimitMs === 'number'\n ? problemMarkdownFrontMatter.timeLimitMs / 1000\n : JUDGE_DEFAULT_TIMEOUT_SECONDS;\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = await spawnWithTimeout(\n command[0],\n command.slice(1),\n { cwd: args.cwd, stdin: testCase.input, env },\n timeoutSeconds\n );\n\n let outputFiles = await readOutputFiles(args.cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n // calculate decision\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n let judgementError: string | undefined;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n } else {\n try {\n const judgement = await judgeAgainstExpectations({\n stdout: spawnResult.stdout,\n expectedStdout: testCase.output,\n fileOutputPath: testCase.fileOutputPath,\n cwd: args.cwd,\n outputFiles,\n });\n if (!judgement.matches) decisionCode = DecisionCode.WRONG_ANSWER;\n outputFiles = judgement.outputFiles;\n } catch (error) {\n // An authoring error (e.g. an oversized expected file) is reported per case, like the command preset does.\n decisionCode = DecisionCode.RUNTIME_ERROR;\n judgementError = error instanceof Error ? error.message : String(error);\n }\n }\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: testCase.input,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: (judgementError ?? spawnResult.stderr).slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n cpuTimeSeconds: spawnResult.cpuTimeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n\n // clean up\n await cleanWorkingDirectory(args.cwd, cwdSnapshot);\n\n if (decisionCode !== DecisionCode.ACCEPTED) break;\n }\n}\n\nasync function hasExpectedFiles(fileOutputPath: string | undefined): Promise<boolean> {\n if (fileOutputPath === undefined) return false;\n const dirents = await fs.promises.readdir(fileOutputPath, { withFileTypes: true, recursive: true });\n return dirents.some((dirent) => dirent.isFile());\n}\n\n/**\n * A preset debug function using stdin and stdout as test cases. The answer directory is copied to a\n * temporary directory where it is built and run together with `_shared.fin/` and the first example\n * case's `.fin/`; files the program writes are reported only through `requiredOutputFilePaths`.\n *\n * A standard stdio problem must NOT commit a `debug.ts` that only calls this preset: the Exercode\n * server applies this preset automatically when `debug.ts` is absent, and committed copies would\n * drift from the server's defaults.\n *\n * @example\n * Run in a problem directory without `debug.ts`:\n * ```bash\n * bun x exercode-problem debug model_answers/java '{ \"stdin\": \"1 2\" }'\n * ```\n */\nexport async function stdioDebugPreset(problemDir: string): Promise<void> {\n const args = parseArgs(process.argv);\n if (!args.cwd) throw new Error('cwd argument required');\n const params = debugParamsSchema.parse(args.params);\n\n // Everything (build, input files, run) happens in a disposable copy of the answer directory, so\n // the developer's files are never touched and whatever the submission leaves behind goes with it.\n // The copy keeps the directory hierarchy and links every ancestor `node_modules`, so packages the\n // answer resolves from its parents still resolve.\n // A terminated debug run must not leave the copy behind; `finally` does not run on a signal, so\n // the handlers learn the root as soon as it is created and stay until it is removed.\n let tempRoot: string | undefined;\n const removeOnSignal = (): void => {\n if (tempRoot !== undefined) forciblyRemoveDirectorySync(tempRoot);\n process.exit(1);\n };\n process.once('SIGINT', removeOnSignal);\n process.once('SIGTERM', removeOnSignal);\n try {\n const copy = await copyProblemDirToTemporaryRoot(args.cwd, { onTempRootCreated: (root) => (tempRoot = root) });\n await debugInTemporaryCopy(problemDir, copy.copiedProblemDir, params);\n } finally {\n if (tempRoot !== undefined) await forciblyRemoveDirectory(tempRoot);\n process.off('SIGINT', removeOnSignal);\n process.off('SIGTERM', removeOnSignal);\n }\n}\n\nasync function debugInTemporaryCopy(problemDir: string, cwd: string, params: DebugParams): Promise<void> {\n const problemMarkdownFrontMatter = await readProblemMarkdownFrontMatter(problemDir);\n\n const originalMainFilePath = await findEntryPointFile(cwd, params.language);\n if (!originalMainFilePath) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n stderr: `main file not found${params.language ? `: language: ${params.language}` : ''}`,\n });\n return;\n }\n\n const languageDefinition = findLanguageDefinitionByPath(originalMainFilePath);\n if (!languageDefinition) {\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.WRONG_ANSWER,\n stderr: 'unsupported language',\n });\n return;\n }\n\n // `CI` changes affects Chainlit. `FORCE_COLOR` affects Bun.\n const env = { ...process.env, CI: '', FORCE_COLOR: '0' };\n\n let prebuiltMainFilePath: string | undefined;\n\n if (languageDefinition.prebuild) {\n try {\n await languageDefinition.prebuild(cwd);\n prebuiltMainFilePath = await findEntryPointFile(cwd, params.language);\n } catch (error) {\n console.error('prebuild error', error);\n\n printTestCaseResult({\n testCaseId: 'prebuild',\n decisionCode: DecisionCode.BUILD_ERROR,\n stderr: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const mainFilePath = prebuiltMainFilePath ?? originalMainFilePath;\n\n if (languageDefinition.buildCommand) {\n const buildCommand = languageDefinition.buildCommand(mainFilePath);\n\n // The build reports the submission's failures in its result; what `spawnWithTimeout` throws is\n // the judge's own failure and ends the run without a verdict.\n const buildSpawnResult = await spawnWithTimeout(\n buildCommand[0],\n buildCommand.slice(1),\n { cwd, env },\n BUILD_TIMEOUT_SECONDS\n );\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (buildSpawnResult.status !== 0) {\n decisionCode = DecisionCode.BUILD_ERROR;\n } else if (buildSpawnResult.timeSeconds > BUILD_TIMEOUT_SECONDS) {\n decisionCode = DecisionCode.BUILD_TIME_LIMIT_EXCEEDED;\n } else if (\n buildSpawnResult.stdout.length > MAX_STDOUT_LENGTH ||\n buildSpawnResult.stderr.length > MAX_STDOUT_LENGTH\n ) {\n decisionCode = DecisionCode.BUILD_OUTPUT_SIZE_LIMIT_EXCEEDED;\n }\n\n if (decisionCode !== DecisionCode.ACCEPTED) {\n printTestCaseResult({\n testCaseId: 'build',\n decisionCode,\n exitStatus: buildSpawnResult.status ?? undefined,\n stdout: buildSpawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: buildSpawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: buildSpawnResult.timeSeconds,\n cpuTimeSeconds: buildSpawnResult.cpuTimeSeconds,\n memoryBytes: buildSpawnResult.memoryBytes,\n });\n return;\n }\n }\n\n // A debug run has no test case of its own: it gets the shared input files and the `.fin/` of the\n // first example case (the cases a learner may see), placed the way the judge does. Hidden cases'\n // input files are never handed to learner code.\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n if (testCases.shared?.fileInputPath) await copyTestCaseFileInput(testCases.shared.fileInputPath, cwd);\n const exampleFileInputPath = testCases.find(\n (testCase) => EXAMPLE_TEST_CASE_ID_PATTERN.test(testCase.id) && testCase.fileInputPath\n )?.fileInputPath;\n if (exampleFileInputPath) {\n await copyTestCaseFileInput(exampleFileInputPath, cwd);\n } else if (testCases.some((testCase) => testCase.fileInputPath)) {\n console.error('debug: no example test case has input files, so the program runs without them');\n }\n\n const timeoutSeconds = Math.max(DEBUG_DEFAULT_TIMEOUT_SECONDS, (problemMarkdownFrontMatter.timeLimitMs ?? 0) / 1000);\n\n const command = languageDefinition.command(mainFilePath);\n\n const spawnResult = await spawnWithTimeout(\n command[0],\n command.slice(1),\n { cwd, stdin: params.stdin, env },\n timeoutSeconds\n );\n\n const outputFiles = await readOutputFiles(cwd, problemMarkdownFrontMatter.requiredOutputFilePaths ?? []);\n\n let decisionCode: DecisionCode = DecisionCode.ACCEPTED;\n\n if (spawnResult.status !== 0) {\n decisionCode = DecisionCode.RUNTIME_ERROR;\n } else if (spawnResult.timeSeconds > timeoutSeconds) {\n decisionCode = DecisionCode.TIME_LIMIT_EXCEEDED;\n } else if (spawnResult.memoryBytes > (problemMarkdownFrontMatter.memoryLimitByte ?? Number.POSITIVE_INFINITY)) {\n decisionCode = DecisionCode.MEMORY_LIMIT_EXCEEDED;\n } else if (spawnResult.stdout.length > MAX_STDOUT_LENGTH || spawnResult.stderr.length > MAX_STDOUT_LENGTH) {\n decisionCode = DecisionCode.OUTPUT_SIZE_LIMIT_EXCEEDED;\n } else if (outputFiles.length < (problemMarkdownFrontMatter.requiredOutputFilePaths?.length ?? 0)) {\n decisionCode = DecisionCode.MISSING_REQUIRED_OUTPUT_FILE_ERROR;\n }\n\n printTestCaseResult({\n testCaseId: 'debug',\n decisionCode,\n exitStatus: spawnResult.status ?? undefined,\n stdin: params.stdin,\n stdout: spawnResult.stdout.slice(0, MAX_STDOUT_LENGTH) || undefined,\n stderr: spawnResult.stderr.slice(0, MAX_STDOUT_LENGTH) || undefined,\n timeSeconds: spawnResult.timeSeconds,\n cpuTimeSeconds: spawnResult.cpuTimeSeconds,\n memoryBytes: spawnResult.memoryBytes,\n outputFiles: outputFiles.length > 0 ? outputFiles : undefined,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";let e=require("zod");const t=e.z.object({path:e.z.string(),data:e.z.string(),encoding:e.z.literal(`base64`).optional()}),n=e.z.object({testCaseId:e.z.string(),decisionCode:e.z.number().int(),exitStatus:e.z.number().int().optional(),stdin:e.z.string().optional(),stdout:e.z.string().optional(),stderr:e.z.string().optional(),timeSeconds:e.z.number().optional(),memoryBytes:e.z.number().optional(),feedbackMarkdown:e.z.string().optional(),score:e.z.number().optional(),scoreLabel:e.z.string().optional(),outputFiles:e.z.array(t).optional()});exports.TEST_CASE_RESULT_PREFIX=`TEST_CASE_RESULT `,exports.testCaseResultSchema=n;
|
|
1
|
+
"use strict";let e=require("zod");const t=e.z.object({path:e.z.string(),data:e.z.string(),encoding:e.z.literal(`base64`).optional()}),n=e.z.object({testCaseId:e.z.string(),decisionCode:e.z.number().int(),exitStatus:e.z.number().int().optional(),stdin:e.z.string().optional(),stdout:e.z.string().optional(),stderr:e.z.string().optional(),timeSeconds:e.z.number().optional(),cpuTimeSeconds:e.z.number().optional(),memoryBytes:e.z.number().optional(),feedbackMarkdown:e.z.string().optional(),score:e.z.number().optional(),scoreLabel:e.z.string().optional(),outputFiles:e.z.array(t).optional()});exports.TEST_CASE_RESULT_PREFIX=`TEST_CASE_RESULT `,exports.testCaseResultSchema=n;
|
|
2
2
|
//# sourceMappingURL=testCaseResult.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testCaseResult.cjs","names":["z"],"sources":["../../src/types/testCaseResult.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const TEST_CASE_RESULT_PREFIX = 'TEST_CASE_RESULT ';\n\nconst testCaseResultOutputFileSchema = z.object({\n path: z.string(),\n data: z.string(),\n encoding: z.literal('base64').optional(),\n});\n\nexport const testCaseResultSchema = z.object({\n testCaseId: z.string(),\n decisionCode: z.number().int(),\n exitStatus: z.number().int().optional(),\n stdin: z.string().optional(),\n stdout: z.string().optional(),\n stderr: z.string().optional(),\n timeSeconds: z.number().optional(),\n memoryBytes: z.number().optional(),\n feedbackMarkdown: z.string().optional(),\n /** Numeric score of a model-evaluation submission (e.g. an RMSLE value). */\n score: z.number().optional(),\n /** Label of `score` shown to learners (e.g. `RMSLE`). */\n scoreLabel: z.string().optional(),\n outputFiles: z.array(testCaseResultOutputFileSchema).optional(),\n});\n\nexport type TestCaseResult = z.infer<typeof testCaseResultSchema>;\n"],"mappings":"kCAEA,MAEM,EAAiCA,EAAAA,EAAE,OAAO,CAC9C,KAAMA,EAAAA,EAAE,OAAO,EACf,KAAMA,EAAAA,EAAE,OAAO,EACf,SAAUA,EAAAA,EAAE,QAAQ,QAAQ,CAAC,CAAC,SAAS,CACzC,CAAC,EAEY,EAAuBA,EAAAA,EAAE,OAAO,CAC3C,WAAYA,EAAAA,EAAE,OAAO,EACrB,aAAcA,EAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,EAC7B,WAAYA,EAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EACtC,MAAOA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC3B,OAAQA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC5B,OAAQA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"testCaseResult.cjs","names":["z"],"sources":["../../src/types/testCaseResult.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const TEST_CASE_RESULT_PREFIX = 'TEST_CASE_RESULT ';\n\nconst testCaseResultOutputFileSchema = z.object({\n path: z.string(),\n data: z.string(),\n encoding: z.literal('base64').optional(),\n});\n\nexport const testCaseResultSchema = z.object({\n testCaseId: z.string(),\n decisionCode: z.number().int(),\n exitStatus: z.number().int().optional(),\n stdin: z.string().optional(),\n stdout: z.string().optional(),\n stderr: z.string().optional(),\n /** Wall time of the run; time limits are judged by it. */\n timeSeconds: z.number().optional(),\n /**\n * User plus system CPU time of the run, summed over its threads and the processes it waited for.\n * A time limit exceeded whose CPU time reaches the limit would be exceeded on any single CPU,\n * while one whose CPU time stays below it may stem from waiting for a CPU shared with other\n * programs.\n */\n cpuTimeSeconds: z.number().optional(),\n memoryBytes: z.number().optional(),\n feedbackMarkdown: z.string().optional(),\n /** Numeric score of a model-evaluation submission (e.g. an RMSLE value). */\n score: z.number().optional(),\n /** Label of `score` shown to learners (e.g. `RMSLE`). */\n scoreLabel: z.string().optional(),\n outputFiles: z.array(testCaseResultOutputFileSchema).optional(),\n});\n\nexport type TestCaseResult = z.infer<typeof testCaseResultSchema>;\n"],"mappings":"kCAEA,MAEM,EAAiCA,EAAAA,EAAE,OAAO,CAC9C,KAAMA,EAAAA,EAAE,OAAO,EACf,KAAMA,EAAAA,EAAE,OAAO,EACf,SAAUA,EAAAA,EAAE,QAAQ,QAAQ,CAAC,CAAC,SAAS,CACzC,CAAC,EAEY,EAAuBA,EAAAA,EAAE,OAAO,CAC3C,WAAYA,EAAAA,EAAE,OAAO,EACrB,aAAcA,EAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,EAC7B,WAAYA,EAAAA,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EACtC,MAAOA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC3B,OAAQA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAC5B,OAAQA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAE5B,YAAaA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAOjC,eAAgBA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EACpC,YAAaA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EACjC,iBAAkBA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAEtC,MAAOA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAE3B,WAAYA,EAAAA,EAAE,OAAO,CAAC,CAAC,SAAS,EAChC,YAAaA,EAAAA,EAAE,MAAM,CAA8B,CAAC,CAAC,SAAS,CAChE,CAAC"}
|
|
@@ -8,6 +8,7 @@ export declare const testCaseResultSchema: z.ZodObject<{
|
|
|
8
8
|
stdout: z.ZodOptional<z.ZodString>;
|
|
9
9
|
stderr: z.ZodOptional<z.ZodString>;
|
|
10
10
|
timeSeconds: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
cpuTimeSeconds: z.ZodOptional<z.ZodNumber>;
|
|
11
12
|
memoryBytes: z.ZodOptional<z.ZodNumber>;
|
|
12
13
|
feedbackMarkdown: z.ZodOptional<z.ZodString>;
|
|
13
14
|
score: z.ZodOptional<z.ZodNumber>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{z as e}from"zod";const t=`TEST_CASE_RESULT `,n=e.object({path:e.string(),data:e.string(),encoding:e.literal(`base64`).optional()}),r=e.object({testCaseId:e.string(),decisionCode:e.number().int(),exitStatus:e.number().int().optional(),stdin:e.string().optional(),stdout:e.string().optional(),stderr:e.string().optional(),timeSeconds:e.number().optional(),memoryBytes:e.number().optional(),feedbackMarkdown:e.string().optional(),score:e.number().optional(),scoreLabel:e.string().optional(),outputFiles:e.array(n).optional()});export{t as TEST_CASE_RESULT_PREFIX,r as testCaseResultSchema};
|
|
1
|
+
import{z as e}from"zod";const t=`TEST_CASE_RESULT `,n=e.object({path:e.string(),data:e.string(),encoding:e.literal(`base64`).optional()}),r=e.object({testCaseId:e.string(),decisionCode:e.number().int(),exitStatus:e.number().int().optional(),stdin:e.string().optional(),stdout:e.string().optional(),stderr:e.string().optional(),timeSeconds:e.number().optional(),cpuTimeSeconds:e.number().optional(),memoryBytes:e.number().optional(),feedbackMarkdown:e.string().optional(),score:e.number().optional(),scoreLabel:e.string().optional(),outputFiles:e.array(n).optional()});export{t as TEST_CASE_RESULT_PREFIX,r as testCaseResultSchema};
|
|
2
2
|
//# sourceMappingURL=testCaseResult.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testCaseResult.js","names":[],"sources":["../../src/types/testCaseResult.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const TEST_CASE_RESULT_PREFIX = 'TEST_CASE_RESULT ';\n\nconst testCaseResultOutputFileSchema = z.object({\n path: z.string(),\n data: z.string(),\n encoding: z.literal('base64').optional(),\n});\n\nexport const testCaseResultSchema = z.object({\n testCaseId: z.string(),\n decisionCode: z.number().int(),\n exitStatus: z.number().int().optional(),\n stdin: z.string().optional(),\n stdout: z.string().optional(),\n stderr: z.string().optional(),\n timeSeconds: z.number().optional(),\n memoryBytes: z.number().optional(),\n feedbackMarkdown: z.string().optional(),\n /** Numeric score of a model-evaluation submission (e.g. an RMSLE value). */\n score: z.number().optional(),\n /** Label of `score` shown to learners (e.g. `RMSLE`). */\n scoreLabel: z.string().optional(),\n outputFiles: z.array(testCaseResultOutputFileSchema).optional(),\n});\n\nexport type TestCaseResult = z.infer<typeof testCaseResultSchema>;\n"],"mappings":"wBAEA,MAAa,EAA0B,oBAEjC,EAAiC,EAAE,OAAO,CAC9C,KAAM,EAAE,OAAO,EACf,KAAM,EAAE,OAAO,EACf,SAAU,EAAE,QAAQ,QAAQ,CAAC,CAAC,SAAS,CACzC,CAAC,EAEY,EAAuB,EAAE,OAAO,CAC3C,WAAY,EAAE,OAAO,EACrB,aAAc,EAAE,OAAO,CAAC,CAAC,IAAI,EAC7B,WAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EACtC,MAAO,EAAE,OAAO,CAAC,CAAC,SAAS,EAC3B,OAAQ,EAAE,OAAO,CAAC,CAAC,SAAS,EAC5B,OAAQ,EAAE,OAAO,CAAC,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"testCaseResult.js","names":[],"sources":["../../src/types/testCaseResult.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const TEST_CASE_RESULT_PREFIX = 'TEST_CASE_RESULT ';\n\nconst testCaseResultOutputFileSchema = z.object({\n path: z.string(),\n data: z.string(),\n encoding: z.literal('base64').optional(),\n});\n\nexport const testCaseResultSchema = z.object({\n testCaseId: z.string(),\n decisionCode: z.number().int(),\n exitStatus: z.number().int().optional(),\n stdin: z.string().optional(),\n stdout: z.string().optional(),\n stderr: z.string().optional(),\n /** Wall time of the run; time limits are judged by it. */\n timeSeconds: z.number().optional(),\n /**\n * User plus system CPU time of the run, summed over its threads and the processes it waited for.\n * A time limit exceeded whose CPU time reaches the limit would be exceeded on any single CPU,\n * while one whose CPU time stays below it may stem from waiting for a CPU shared with other\n * programs.\n */\n cpuTimeSeconds: z.number().optional(),\n memoryBytes: z.number().optional(),\n feedbackMarkdown: z.string().optional(),\n /** Numeric score of a model-evaluation submission (e.g. an RMSLE value). */\n score: z.number().optional(),\n /** Label of `score` shown to learners (e.g. `RMSLE`). */\n scoreLabel: z.string().optional(),\n outputFiles: z.array(testCaseResultOutputFileSchema).optional(),\n});\n\nexport type TestCaseResult = z.infer<typeof testCaseResultSchema>;\n"],"mappings":"wBAEA,MAAa,EAA0B,oBAEjC,EAAiC,EAAE,OAAO,CAC9C,KAAM,EAAE,OAAO,EACf,KAAM,EAAE,OAAO,EACf,SAAU,EAAE,QAAQ,QAAQ,CAAC,CAAC,SAAS,CACzC,CAAC,EAEY,EAAuB,EAAE,OAAO,CAC3C,WAAY,EAAE,OAAO,EACrB,aAAc,EAAE,OAAO,CAAC,CAAC,IAAI,EAC7B,WAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EACtC,MAAO,EAAE,OAAO,CAAC,CAAC,SAAS,EAC3B,OAAQ,EAAE,OAAO,CAAC,CAAC,SAAS,EAC5B,OAAQ,EAAE,OAAO,CAAC,CAAC,SAAS,EAE5B,YAAa,EAAE,OAAO,CAAC,CAAC,SAAS,EAOjC,eAAgB,EAAE,OAAO,CAAC,CAAC,SAAS,EACpC,YAAa,EAAE,OAAO,CAAC,CAAC,SAAS,EACjC,iBAAkB,EAAE,OAAO,CAAC,CAAC,SAAS,EAEtC,MAAO,EAAE,OAAO,CAAC,CAAC,SAAS,EAE3B,WAAY,EAAE,OAAO,CAAC,CAAC,SAAS,EAChC,YAAa,EAAE,MAAM,CAA8B,CAAC,CAAC,SAAS,CAChE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exercode/problem-utils",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": ":100: A set of utilities for judging programs on Exercode (https://exercode.willbooster.com/).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"exercode",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"@willbooster/oxfmt-config": "1.2.2",
|
|
73
73
|
"@willbooster/oxlint-config": "1.4.8",
|
|
74
74
|
"@willbooster/prettier-config": "10.4.0",
|
|
75
|
-
"@willbooster/wb": "22.1.
|
|
76
|
-
"build-ts": "21.0.
|
|
75
|
+
"@willbooster/wb": "22.1.4",
|
|
76
|
+
"build-ts": "21.0.12",
|
|
77
77
|
"conventional-changelog-conventionalcommits": "10.4.0",
|
|
78
78
|
"lefthook": "2.1.12",
|
|
79
79
|
"oxfmt": "0.65.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:child_process");t=e.__toESM(t,1);let n=require("node:os");n=e.__toESM(n,1);const r=[n.default.platform()===`darwin`?`gtime`:`/usr/bin/time`,`--format`,`%e %M`];function i(e,n,i,a){let o=Date.now(),s=t.default.spawnSync(`timeout`,[a.toFixed(3),...r,e,...n],i),c=Date.now(),l=/(?:^|\n)(\d+\.\d+) (\d+)\s*$/.exec(s.stderr),u=l?s.stderr.slice(0,l.index):s.stderr,d=Number(l?.[1])||(c-o)/1e3,f=Number(l?.[2])*1024||0;return s.status===124?{...s,status:0,stderr:u,timeSeconds:a+.001,memoryBytes:f}:{...s,stderr:u,timeSeconds:d,memoryBytes:f}}exports.spawnSyncWithTimeout=i;
|
|
2
|
-
//# sourceMappingURL=spawnSyncWithTimeout.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawnSyncWithTimeout.cjs","names":["os","child_process"],"sources":["../../src/helpers/spawnSyncWithTimeout.ts"],"sourcesContent":["import child_process from 'node:child_process';\nimport os from 'node:os';\n\nconst TIME_COMMAND = [os.platform() === 'darwin' ? 'gtime' : '/usr/bin/time', '--format', '%e %M'] as const;\n\nexport function spawnSyncWithTimeout(\n command: string,\n args: readonly string[],\n options: child_process.SpawnSyncOptionsWithStringEncoding,\n timeoutSeconds: number\n): child_process.SpawnSyncReturns<string> & { timeSeconds: number; memoryBytes: number } {\n const startTimeMilliseconds = Date.now();\n\n const spawnResult = child_process.spawnSync(\n 'timeout',\n [timeoutSeconds.toFixed(3), ...TIME_COMMAND, command, ...args],\n options\n );\n\n const stopTimeMilliseconds = Date.now();\n\n const match = /(?:^|\\n)(\\d+\\.\\d+) (\\d+)\\s*$/.exec(spawnResult.stderr);\n const stderr = match ? spawnResult.stderr.slice(0, match.index) : spawnResult.stderr;\n const timeSeconds = Number(match?.[1]) || (stopTimeMilliseconds - startTimeMilliseconds) / 1000;\n const memoryBytes = Number(match?.[2]) * 1024 || 0;\n\n // timeout\n if (spawnResult.status === 124) {\n return { ...spawnResult, status: 0, stderr, timeSeconds: timeoutSeconds + 1e-3, memoryBytes };\n }\n\n return { ...spawnResult, stderr, timeSeconds, memoryBytes };\n}\n"],"mappings":"iKAGA,MAAM,EAAe,CAACA,EAAAA,QAAG,SAAS,IAAM,SAAW,QAAU,gBAAiB,WAAY,OAAO,EAEjG,SAAgB,EACd,EACA,EACA,EACA,EACuF,CACvF,IAAM,EAAwB,KAAK,IAAI,EAEjC,EAAcC,EAAAA,QAAc,UAChC,UACA,CAAC,EAAe,QAAQ,CAAC,EAAG,GAAG,EAAc,EAAS,GAAG,CAAI,EAC7D,CACF,EAEM,EAAuB,KAAK,IAAI,EAEhC,EAAQ,+BAA+B,KAAK,EAAY,MAAM,EAC9D,EAAS,EAAQ,EAAY,OAAO,MAAM,EAAG,EAAM,KAAK,EAAI,EAAY,OACxE,EAAc,OAAO,IAAQ,EAAE,IAAM,EAAuB,GAAyB,IACrF,EAAc,OAAO,IAAQ,EAAE,EAAI,MAAQ,EAOjD,OAJI,EAAY,SAAW,IAClB,CAAE,GAAG,EAAa,OAAQ,EAAG,SAAQ,YAAa,EAAiB,KAAM,aAAY,EAGvF,CAAE,GAAG,EAAa,SAAQ,cAAa,aAAY,CAC5D"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import child_process from 'node:child_process';
|
|
2
|
-
export declare function spawnSyncWithTimeout(command: string, args: readonly string[], options: child_process.SpawnSyncOptionsWithStringEncoding, timeoutSeconds: number): child_process.SpawnSyncReturns<string> & {
|
|
3
|
-
timeSeconds: number;
|
|
4
|
-
memoryBytes: number;
|
|
5
|
-
};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import e from"node:child_process";import t from"node:os";const n=[t.platform()===`darwin`?`gtime`:`/usr/bin/time`,`--format`,`%e %M`];function r(t,r,i,a){let o=Date.now(),s=e.spawnSync(`timeout`,[a.toFixed(3),...n,t,...r],i),c=Date.now(),l=/(?:^|\n)(\d+\.\d+) (\d+)\s*$/.exec(s.stderr),u=l?s.stderr.slice(0,l.index):s.stderr,d=Number(l?.[1])||(c-o)/1e3,f=Number(l?.[2])*1024||0;return s.status===124?{...s,status:0,stderr:u,timeSeconds:a+.001,memoryBytes:f}:{...s,stderr:u,timeSeconds:d,memoryBytes:f}}export{r as spawnSyncWithTimeout};
|
|
2
|
-
//# sourceMappingURL=spawnSyncWithTimeout.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawnSyncWithTimeout.js","names":[],"sources":["../../src/helpers/spawnSyncWithTimeout.ts"],"sourcesContent":["import child_process from 'node:child_process';\nimport os from 'node:os';\n\nconst TIME_COMMAND = [os.platform() === 'darwin' ? 'gtime' : '/usr/bin/time', '--format', '%e %M'] as const;\n\nexport function spawnSyncWithTimeout(\n command: string,\n args: readonly string[],\n options: child_process.SpawnSyncOptionsWithStringEncoding,\n timeoutSeconds: number\n): child_process.SpawnSyncReturns<string> & { timeSeconds: number; memoryBytes: number } {\n const startTimeMilliseconds = Date.now();\n\n const spawnResult = child_process.spawnSync(\n 'timeout',\n [timeoutSeconds.toFixed(3), ...TIME_COMMAND, command, ...args],\n options\n );\n\n const stopTimeMilliseconds = Date.now();\n\n const match = /(?:^|\\n)(\\d+\\.\\d+) (\\d+)\\s*$/.exec(spawnResult.stderr);\n const stderr = match ? spawnResult.stderr.slice(0, match.index) : spawnResult.stderr;\n const timeSeconds = Number(match?.[1]) || (stopTimeMilliseconds - startTimeMilliseconds) / 1000;\n const memoryBytes = Number(match?.[2]) * 1024 || 0;\n\n // timeout\n if (spawnResult.status === 124) {\n return { ...spawnResult, status: 0, stderr, timeSeconds: timeoutSeconds + 1e-3, memoryBytes };\n }\n\n return { ...spawnResult, stderr, timeSeconds, memoryBytes };\n}\n"],"mappings":"yDAGA,MAAM,EAAe,CAAC,EAAG,SAAS,IAAM,SAAW,QAAU,gBAAiB,WAAY,OAAO,EAEjG,SAAgB,EACd,EACA,EACA,EACA,EACuF,CACvF,IAAM,EAAwB,KAAK,IAAI,EAEjC,EAAc,EAAc,UAChC,UACA,CAAC,EAAe,QAAQ,CAAC,EAAG,GAAG,EAAc,EAAS,GAAG,CAAI,EAC7D,CACF,EAEM,EAAuB,KAAK,IAAI,EAEhC,EAAQ,+BAA+B,KAAK,EAAY,MAAM,EAC9D,EAAS,EAAQ,EAAY,OAAO,MAAM,EAAG,EAAM,KAAK,EAAI,EAAY,OACxE,EAAc,OAAO,IAAQ,EAAE,IAAM,EAAuB,GAAyB,IACrF,EAAc,OAAO,IAAQ,EAAE,EAAI,MAAQ,EAOjD,OAJI,EAAY,SAAW,IAClB,CAAE,GAAG,EAAa,OAAQ,EAAG,SAAQ,YAAa,EAAiB,KAAM,aAAY,EAGvF,CAAE,GAAG,EAAa,SAAQ,cAAa,aAAY,CAC5D"}
|