66 lines
2.5 KiB
TypeScript
66 lines
2.5 KiB
TypeScript
import { exec } from "child_process";
|
|
import { promisify } from "util";
|
|
import path from "path";
|
|
import fs from "fs/promises";
|
|
|
|
const execAsync = promisify(exec);
|
|
|
|
const CPP_STANDARD = process.env.CPP_STANDARD || "c++14";
|
|
const CPP_FLAGS = process.env.CPP_FLAGS || "-Wall -Wno-unused-variable";
|
|
|
|
export async function validateStandardCode(code: string): Promise<void> {
|
|
if (!code?.trim()) {
|
|
throw new Error("标准程序不能为空");
|
|
}
|
|
if (!code.includes("#include") || !code.includes("main")) {
|
|
throw new Error("标准程序必须包含 #include 和 main 函数");
|
|
}
|
|
|
|
const os = await import("os");
|
|
const tempDir = path.join(os.tmpdir(), "testcase_validate_" + Date.now());
|
|
await fs.mkdir(tempDir, { recursive: true });
|
|
|
|
try {
|
|
const cppFile = path.join(tempDir, "test.cpp");
|
|
const exeFile = path.join(tempDir, "test");
|
|
await fs.writeFile(cppFile, code);
|
|
const compileCommand = `g++ -o "${exeFile}" "${cppFile}" -std=${CPP_STANDARD} ${CPP_FLAGS}`;
|
|
await execAsync(compileCommand, { timeout: 10000 });
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
const e = new Error(`编译失败: ${message}`);
|
|
(e as Error & { code?: string }).code = "COMPILATION_ERROR";
|
|
throw e;
|
|
} finally {
|
|
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
}
|
|
}
|
|
|
|
export async function executeStandardCode(code: string, input: string): Promise<string> {
|
|
const os = await import("os");
|
|
const tempDir = path.join(os.tmpdir(), "testcase_run_" + Date.now());
|
|
await fs.mkdir(tempDir, { recursive: true });
|
|
|
|
const cppFile = path.join(tempDir, "solution.cpp");
|
|
const exeFile = path.join(tempDir, "solution");
|
|
const inputFile = path.join(tempDir, "input.txt");
|
|
|
|
try {
|
|
await fs.writeFile(cppFile, code);
|
|
const compileCommand = `g++ -o "${exeFile}" "${cppFile}" -std=${CPP_STANDARD} ${CPP_FLAGS}`;
|
|
await execAsync(compileCommand);
|
|
await fs.writeFile(inputFile, input);
|
|
const executeCommand = `"${exeFile}" < "${inputFile}"`;
|
|
const { stdout, stderr } = await execAsync(executeCommand, { timeout: 10000 });
|
|
if (stderr) console.warn("C++ execution warning:", stderr);
|
|
return stdout.trim();
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
const e = new Error(`程序执行失败: ${message}`);
|
|
(e as Error & { code?: string }).code = "EXECUTION_ERROR";
|
|
throw e;
|
|
} finally {
|
|
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
}
|
|
}
|