mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
judge: pass envirent vars to checker
This commit is contained in:
1 parent
9158550139
commit
abec5fd3ec
11 files changed
+54
-47
No files matched your search
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@hydrooj/hydrojudge",
|
||||
"bin": "bin/hydrojudge.js",
|
||||
"version": "2.12.17",
|
||||
"version": "2.13.0",
|
||||
"main": "package.json",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||
|
||||
@@ -3,36 +3,16 @@ import { findFileSync } from '@hydrooj/utils/lib/utils';
|
||||
import checkers from './checkers';
|
||||
import compile from './compile';
|
||||
import { SystemError } from './error';
|
||||
import { Execute } from './interface';
|
||||
import { CopyInFile } from './sandbox/interface';
|
||||
import { CheckConfig, Execute } from './interface';
|
||||
import { parseFilename } from './utils';
|
||||
|
||||
const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h');
|
||||
|
||||
interface CheckConfig {
|
||||
checker_type: string;
|
||||
stdin: CopyInFile,
|
||||
stdout: CopyInFile,
|
||||
user_stdout: CopyInFile,
|
||||
user_stderr: CopyInFile,
|
||||
copyIn?: Record<string, CopyInFile>,
|
||||
score: number,
|
||||
detail: boolean,
|
||||
}
|
||||
|
||||
export async function check(config: CheckConfig): Promise<[number, number, string]> {
|
||||
if (!checkers[config.checker_type]) throw new SystemError('Unknown checker type {0}', [config.checker_type]);
|
||||
const {
|
||||
code, status, score, message,
|
||||
} = await checkers[config.checker_type]({
|
||||
input: config.stdin,
|
||||
output: config.stdout,
|
||||
user_stdout: config.user_stdout,
|
||||
user_stderr: config.user_stderr,
|
||||
score: config.score,
|
||||
copyIn: config.copyIn || {},
|
||||
detail: config.detail,
|
||||
});
|
||||
} = await checkers[config.checker_type](config);
|
||||
if (code) throw new SystemError('Checker returned {0}.', [code]);
|
||||
return [status, score, message];
|
||||
}
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||
import { SystemError } from './error';
|
||||
import { CheckConfig, CheckResult } from './interface';
|
||||
import { run } from './sandbox';
|
||||
import { CopyInFile } from './sandbox/interface';
|
||||
import { parse } from './testlib';
|
||||
|
||||
interface CheckConfig {
|
||||
input: CopyInFile,
|
||||
output: CopyInFile,
|
||||
user_stdout: CopyInFile,
|
||||
user_stderr: CopyInFile,
|
||||
copyIn: Record<string, CopyInFile>,
|
||||
score: number,
|
||||
detail: boolean,
|
||||
}
|
||||
|
||||
interface CheckResult {
|
||||
status: number,
|
||||
score: number,
|
||||
message: string,
|
||||
code?: number,
|
||||
}
|
||||
|
||||
type Checker = (config: CheckConfig) => Promise<CheckResult>;
|
||||
|
||||
const checkers: Record<string, Checker> = {
|
||||
@@ -129,6 +112,7 @@ const checkers: Record<string, Checker> = {
|
||||
...config.copyIn,
|
||||
},
|
||||
copyOut: ['score', 'message'],
|
||||
env: config.env,
|
||||
});
|
||||
const { message } = files;
|
||||
const score = parseInt(files.score, 10);
|
||||
@@ -196,6 +180,7 @@ const checkers: Record<string, Checker> = {
|
||||
answer: config.output,
|
||||
...config.copyIn,
|
||||
},
|
||||
env: config.env,
|
||||
});
|
||||
if (status === STATUS.STATUS_SYSTEM_ERROR) {
|
||||
return {
|
||||
|
||||
@@ -38,6 +38,7 @@ class JudgeTask {
|
||||
data: any[];
|
||||
folder: string;
|
||||
config: any;
|
||||
env: Record<string, string>;
|
||||
getLang: (name: string) => LangConfig;
|
||||
|
||||
constructor(session: Hydro, request, ws: WebSocket) {
|
||||
@@ -63,6 +64,13 @@ class JudgeTask {
|
||||
this.source = this.request.source;
|
||||
this.tmpdir = path.resolve(getConfig('tmp_dir'), this.host, this.rid);
|
||||
this.clean = [];
|
||||
this.env = {
|
||||
HYDRO_DOMAIN: this.request.domainId.toString(),
|
||||
HYDRO_RECORD: this.rid,
|
||||
HYDRO_LANG: this.lang,
|
||||
HYDRO_USER: this.request.uid.toString(),
|
||||
HYDRO_CONTEST: this.request.tid?.toString() || '',
|
||||
};
|
||||
await Lock.acquire(`${this.host}/${this.source}/${this.rid}`);
|
||||
fs.ensureDirSync(this.tmpdir);
|
||||
tmpfs.mount(this.tmpdir, getConfig('tmpfs_size'));
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import { CopyInFile } from './sandbox/interface';
|
||||
|
||||
export interface Execute {
|
||||
execute: string,
|
||||
clean: Function,
|
||||
copyIn: Record<string, CopyInFile>,
|
||||
time?: number,
|
||||
}
|
||||
|
||||
export interface CompileErrorInfo {
|
||||
stdout?: string,
|
||||
stderr?: string,
|
||||
status?: number
|
||||
}
|
||||
|
||||
export interface CheckConfig {
|
||||
checker_type: string;
|
||||
input: CopyInFile;
|
||||
output: CopyInFile;
|
||||
user_stdout: CopyInFile;
|
||||
user_stderr: CopyInFile;
|
||||
copyIn: Record<string, CopyInFile>;
|
||||
score: number;
|
||||
detail: boolean;
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface CheckResult {
|
||||
status: number,
|
||||
score: number,
|
||||
message: string,
|
||||
code?: number,
|
||||
}
|
||||
@@ -67,14 +67,15 @@ function judgeCase(c: Case, sid: string) {
|
||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||
} else {
|
||||
[status, score, message] = await check({
|
||||
copyIn: ctx.checker.copyIn,
|
||||
stdin: { src: c.input },
|
||||
stdout: { src: c.output },
|
||||
copyIn: ctx.checker.copyIn || {},
|
||||
input: { src: c.input },
|
||||
output: { src: c.output },
|
||||
user_stdout: stdout,
|
||||
user_stderr: stderr,
|
||||
checker_type: ctx.config.checker_type,
|
||||
score: ctxSubtask.subtask.score,
|
||||
detail: ctx.config.detail ?? true,
|
||||
env: ctx.env,
|
||||
});
|
||||
}
|
||||
} else if (status === STATUS.STATUS_RUNTIME_ERROR && code) {
|
||||
|
||||
@@ -97,8 +97,8 @@ export const judge = async (ctx: Context) => {
|
||||
} else {
|
||||
[status, , message] = await check({
|
||||
copyIn: copyInDir(path.resolve(ctx.tmpdir, 'checker')),
|
||||
stdin: { src: input },
|
||||
stdout: { src: stdout },
|
||||
input: { src: input },
|
||||
output: { src: stdout },
|
||||
user_stdout: { src: stdout },
|
||||
user_stderr: { src: stderr },
|
||||
checker_type: ctx.config.checker_type,
|
||||
|
||||
@@ -35,6 +35,7 @@ function judgeCase(c: Case) {
|
||||
time: ctxSubtask.subtask.time * 2 * ctx.executeInteractor.time,
|
||||
memory: ctxSubtask.subtask.memory * 2,
|
||||
copyOut: ['/w/tout?'],
|
||||
env: ctx.env,
|
||||
},
|
||||
);
|
||||
// TODO handle tout (maybe pass to checker?)
|
||||
|
||||
@@ -32,6 +32,7 @@ export interface JudgeTaskInterface {
|
||||
input?: string;
|
||||
clean: Function[];
|
||||
config: Config;
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface RuntimeContext {
|
||||
|
||||
@@ -39,6 +39,7 @@ interface Parameter {
|
||||
copyOut?: string[];
|
||||
copyOutCached?: string[];
|
||||
cacheStdoutAndStderr?: boolean;
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface SandboxAdaptedResult {
|
||||
@@ -72,6 +73,7 @@ function proc({
|
||||
processLimit = getConfig('processLimit'),
|
||||
stdin = '', copyIn = {}, copyOut = [], copyOutCached = [],
|
||||
cacheStdoutAndStderr = false,
|
||||
env = {},
|
||||
}: Parameter = {}): Cmd {
|
||||
if (!supportOptional) {
|
||||
copyOut = (copyOut as string[]).map((i) => (i.endsWith('?') ? i.substr(0, i.length - 1) : i));
|
||||
@@ -84,7 +86,7 @@ function proc({
|
||||
}
|
||||
return {
|
||||
args: parseArgs(execute),
|
||||
env: getConfig('env').split('\n'),
|
||||
env: [...getConfig('env').split('\n'), ...Object.keys(env).map((i) => `${i}=${env[i].replace(/=/g, '\\=')}`)],
|
||||
files: [
|
||||
stdin ? { src: stdin } : { content: '' },
|
||||
{ name: 'stdout', max: Math.floor(1024 * 1024 * size) },
|
||||
|
||||
@@ -150,6 +150,7 @@ async function postInit() {
|
||||
code: string;
|
||||
data: any[];
|
||||
config: any;
|
||||
env: any;
|
||||
input?: string;
|
||||
next: (data: any, id?: number) => void;
|
||||
end: (data: any) => void;
|
||||
@@ -176,6 +177,13 @@ async function postInit() {
|
||||
this.source = this.request.source;
|
||||
this.config = this.request.config;
|
||||
this.input = this.request.input;
|
||||
this.env = {
|
||||
HYDRO_DOMAIN: this.request.domainId.toString(),
|
||||
HYDRO_RECORD: this.rid,
|
||||
HYDRO_LANG: this.lang,
|
||||
HYDRO_USER: this.request.uid.toString(),
|
||||
HYDRO_CONTEST: this.request.tid?.toString() || '',
|
||||
};
|
||||
this.next = getNext(this);
|
||||
this.end = getEnd(this.rid);
|
||||
this.tmpdir = path.resolve(getConfig('tmp_dir'), this.rid);
|
||||
|
||||
Reference in new issue
Block a user