first commit
Some checks failed
Some checks failed
This commit is contained in:
65
app/lib/testcase-backend/runner.ts
Normal file
65
app/lib/testcase-backend/runner.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
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(() => {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user