feat: merge woj-runner resources
This commit is contained in:
parent
b77c968409
commit
062c5ef964
2
resource/runner/.gitignore
vendored
Normal file
2
resource/runner/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.mark.*
|
||||
*.zip
|
2
resource/runner/framework/scripts/.gitignore
vendored
Normal file
2
resource/runner/framework/scripts/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/libwoj_sandbox.so
|
||||
/woj_launcher
|
15
resource/runner/framework/scripts/setup.sh
Executable file
15
resource/runner/framework/scripts/setup.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
|
||||
rm -rf woj-sandbox
|
||||
git clone https://github.com/WHUPRJ/woj-sandbox.git >/dev/null 2>&1 || exit 1
|
||||
cd woj-sandbox && ./build_libseccomp.sh || exit 1
|
||||
|
||||
mkdir -p build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release || exit 1
|
||||
make -j || exit 1
|
||||
|
||||
cd ../..
|
||||
cp woj-sandbox/build/libwoj_sandbox.so . || exit 1
|
||||
cp woj-sandbox/build/woj_launcher . || exit 1
|
||||
rm -rf woj-sandbox
|
1
resource/runner/framework/template/.gitignore
vendored
Normal file
1
resource/runner/framework/template/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/testlib
|
10
resource/runner/framework/template/Judger.mk
Normal file
10
resource/runner/framework/template/Judger.mk
Normal file
@ -0,0 +1,10 @@
|
||||
FCMP = $(TESTLIB)/checkers/fcmp
|
||||
HCMP = $(TESTLIB)/checkers/hcmp
|
||||
LCMP = $(TESTLIB)/checkers/lcmp
|
||||
NCMP = $(TESTLIB)/checkers/ncmp
|
||||
NYESNO = $(TESTLIB)/checkers/nyesno
|
||||
RCMP4 = $(TESTLIB)/checkers/rcmp4
|
||||
RCMP6 = $(TESTLIB)/checkers/rcmp6
|
||||
RCMP9 = $(TESTLIB)/checkers/rcmp9
|
||||
WCMP = $(TESTLIB)/checkers/wcmp
|
||||
YESNO = $(TESTLIB)/checkers/yesno
|
2
resource/runner/framework/template/c.mk
Normal file
2
resource/runner/framework/template/c.mk
Normal file
@ -0,0 +1,2 @@
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -pipe -Wall -lm -std=c99 -DONLINE_JUDGE
|
2
resource/runner/framework/template/cpp.mk
Normal file
2
resource/runner/framework/template/cpp.mk
Normal file
@ -0,0 +1,2 @@
|
||||
CXX = g++
|
||||
CFLAGS = -O2 -pipe -Wall -lm -std=c++20 -DONLINE_JUDGE
|
7
resource/runner/framework/template/default/c.Makefile
Normal file
7
resource/runner/framework/template/default/c.Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
include ${TEMPLATE}/c.mk ${TEMPLATE}/Judger.mk
|
||||
|
||||
compile:
|
||||
$(CC) $(CFLAGS) -o $(PREFIX)/user/$(USER_PROG).out $(PREFIX)/user/$(USER_PROG).$(LANG)
|
||||
|
||||
judge:
|
||||
$($(CMP)) $(PREFIX)/data/input/$(TEST_NUM).input $(PREFIX)/user/$(TEST_NUM).out.usr $(PREFIX)/data/output/$(TEST_NUM).output > $(PREFIX)/user/$(TEST_NUM).judge 2>&1
|
7
resource/runner/framework/template/default/cpp.Makefile
Normal file
7
resource/runner/framework/template/default/cpp.Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
include ${TEMPLATE}/cpp.mk ${TEMPLATE}/Judger.mk
|
||||
|
||||
compile:
|
||||
$(CXX) $(CFLAGS) -o $(PREFIX)/user/$(USER_PROG).out $(PREFIX)/user/$(USER_PROG).$(LANG)
|
||||
|
||||
judge:
|
||||
$($(CMP)) $(PREFIX)/data/input/$(TEST_NUM).input $(PREFIX)/user/$(TEST_NUM).out.usr $(PREFIX)/data/output/$(TEST_NUM).output > $(PREFIX)/user/$(TEST_NUM).judge 2>&1
|
8
resource/runner/framework/template/setup.sh
Executable file
8
resource/runner/framework/template/setup.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -x
|
||||
rm -rf testlib
|
||||
git clone https://github.com/MikeMirzayanov/testlib.git >/dev/null 2>&1 || exit 1
|
||||
rm -rf testlib/.git
|
||||
rm -rf testlib/tests
|
||||
cd testlib/checkers || exit 1
|
||||
parallel clang++ -Ofast -march=native -Wall -pipe -I.. {}.cpp -o {} ::: fcmp hcmp lcmp ncmp nyesno rcmp4 rcmp6 rcmp9 wcmp yesno
|
5
resource/runner/problem/example/.gitignore
vendored
Normal file
5
resource/runner/problem/example/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/judge/*.out
|
||||
/data/input/2.*
|
||||
/data/input/4.*
|
||||
/data/output/2.*
|
||||
/data/output/4.*
|
64
resource/runner/problem/example/README.md
Normal file
64
resource/runner/problem/example/README.md
Normal file
@ -0,0 +1,64 @@
|
||||
# 示例题目
|
||||
|
||||
## 文件构成
|
||||
|
||||
```
|
||||
.
|
||||
├── config.json # 题目配置信息
|
||||
├── data # 数据目录
|
||||
│ ├── input # 输入数据
|
||||
│ │ ├── (x).input # 第 x 组输入数据
|
||||
│ │ └── ...
|
||||
│ └── output # 输出数据
|
||||
│ ├── (x).output # 第 x 组输出数据
|
||||
│ └── ...
|
||||
└── judge # 评测脚本目录
|
||||
├── c.Makefile # (optional) 自定义评测脚本
|
||||
├── prebuild.Makefile # (optional) 题目初始化脚本
|
||||
└── ...
|
||||
```
|
||||
|
||||
## 详细说明
|
||||
|
||||
### 题目配置信息
|
||||
|
||||
```json5
|
||||
{
|
||||
"Runtime": {
|
||||
// 运行时配置
|
||||
"TimeLimit": 1000, // 时间限制 (ms)
|
||||
"MemoryLimit": 16, // 内存限制 (MB)
|
||||
"NProcLimit": 1 // 进(线)程 限制
|
||||
},
|
||||
"Languages": [
|
||||
{"Lang": "c", "Type": "custom", "Script": "XYZ.Makefile", "Cmp": ""},
|
||||
{"Lang": "cpp", "Type": "default", "Script": "", "Cmp": "NCMP"}
|
||||
], // 支持的语言
|
||||
"Tasks": [
|
||||
// 评测点信息
|
||||
{"Id": 1, "Points": 25}, // 第一个评测点,分值 25 分,使用 ./data/1.? 为测试数据
|
||||
{"Id": 2, "Points": 25},
|
||||
{"Id": 3, "Points": 25},
|
||||
{"Id": 4, "Points": 25}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 评测脚本
|
||||
|
||||
见注释
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
17
resource/runner/problem/example/config.json
Normal file
17
resource/runner/problem/example/config.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"Runtime": {
|
||||
"TimeLimit": 1000,
|
||||
"MemoryLimit": 16,
|
||||
"NProcLimit": 1
|
||||
},
|
||||
"Languages": [
|
||||
{"Lang": "c", "Type": "custom", "Script": "XYZ.Makefile", "Cmp": ""},
|
||||
{"Lang": "cpp", "Type": "default", "Script": "", "Cmp": "NCMP"}
|
||||
],
|
||||
"Tasks": [
|
||||
{"Id": 1, "Points": 25},
|
||||
{"Id": 2, "Points": 25},
|
||||
{"Id": 3, "Points": 25},
|
||||
{"Id": 4, "Points": 25}
|
||||
]
|
||||
}
|
1
resource/runner/problem/example/data/input/1.input
Normal file
1
resource/runner/problem/example/data/input/1.input
Normal file
@ -0,0 +1 @@
|
||||
1 2
|
1
resource/runner/problem/example/data/input/3.input
Normal file
1
resource/runner/problem/example/data/input/3.input
Normal file
@ -0,0 +1 @@
|
||||
-1 -2
|
1
resource/runner/problem/example/data/output/1.output
Normal file
1
resource/runner/problem/example/data/output/1.output
Normal file
@ -0,0 +1 @@
|
||||
3
|
1
resource/runner/problem/example/data/output/3.output
Normal file
1
resource/runner/problem/example/data/output/3.output
Normal file
@ -0,0 +1 @@
|
||||
-3
|
22
resource/runner/problem/example/judge/XYZ.Makefile
Normal file
22
resource/runner/problem/example/judge/XYZ.Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
# 默认环境变量有 PREFIX, TEMPLATE, TESTLIB
|
||||
include ${TEMPLATE}/c.mk ${TEMPLATE}/Judger.mk
|
||||
|
||||
# 评测分四个阶段
|
||||
# 1. prebuild: 用于提前生成测试数据、评测器、spj等工具,runner 只执行一次
|
||||
# 只有 ./data, ./judge 目录可见
|
||||
# 2. compile: 用于编译用户提交的程序
|
||||
# 只有 ./user/$(USER_PROG).$(LANG) 和 ./judge 目录可见
|
||||
# 3. run: 运行用户程序
|
||||
# 只有 ./data/input/*.input 和 ./user/$(USER_PROG).out 可见
|
||||
# 用户输出存放于 ./user/?.out.usr
|
||||
# 使用 woj-sandbox 运行,等效于 $(PREFIX)/user/$(USER_PROG).out < $(PREFIX)/data/input/$(TEST_NUM).input > $(PREFIX)/user/$(TEST_NUM).out.usr
|
||||
# 4. judge: 用于判定输出结果 环境变量 TEST_NUM 表示当前测试点编号
|
||||
# 所有目录 ./data ./judge ./user 可见
|
||||
|
||||
compile:
|
||||
$(CC) $(CFLAGS) -o $(PREFIX)/user/$(USER_PROG).out $(PREFIX)/user/$(USER_PROG).$(LANG) $(PREFIX)/judge/gadget.c
|
||||
|
||||
judge:
|
||||
# Rename on *.out.usr or *.judge is not allowed
|
||||
sed '/gadgets/d' $(PREFIX)/user/$(TEST_NUM).out.usr > $(PREFIX)/user/$(TEST_NUM).out.usr1
|
||||
$(NCMP) $(PREFIX)/data/input/$(TEST_NUM).input $(PREFIX)/user/$(TEST_NUM).out.usr1 $(PREFIX)/data/output/$(TEST_NUM).output > $(PREFIX)/user/$(TEST_NUM).judge 2>&1
|
3
resource/runner/problem/example/judge/gadget.c
Normal file
3
resource/runner/problem/example/judge/gadget.c
Normal file
@ -0,0 +1,3 @@
|
||||
#include<stdio.h>
|
||||
void construct() __attribute__((constructor(101)));
|
||||
void construct() { puts("Greetings from gadgets..."); }
|
9
resource/runner/problem/example/judge/gen.cpp
Normal file
9
resource/runner/problem/example/judge/gen.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "testlib.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
registerGen(argc, argv, 1);
|
||||
|
||||
println(rnd.next(-1000000000, 1000000000), rnd.next(-1000000000, 1000000000));
|
||||
}
|
12
resource/runner/problem/example/judge/prebuild.Makefile
Normal file
12
resource/runner/problem/example/judge/prebuild.Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
include ${TEMPLATE}/c.mk ${TEMPLATE}/Judger.mk
|
||||
|
||||
prebuild:
|
||||
clang++ -I$(TESTLIB) -Ofast -o $(PREFIX)/judge/gen.out $(PREFIX)/judge/gen.cpp
|
||||
@if [ ! -f $(PREFIX)/data/input/2.input ]; then \
|
||||
$(PREFIX)/judge/gen.out > $(PREFIX)/data/input/2.input; \
|
||||
python3 -c "print(sum(map(int, input().split())))" < $(PREFIX)/data/input/2.input > $(PREFIX)/data/output/2.output; \
|
||||
fi
|
||||
@if [ ! -f $(PREFIX)/data/input/4.input ]; then \
|
||||
$(PREFIX)/judge/gen.out > $(PREFIX)/data/input/4.input; \
|
||||
python3 -c "print(sum(map(int, input().split())))" < $(PREFIX)/data/input/4.input > $(PREFIX)/data/output/4.output; \
|
||||
fi
|
10
resource/runner/scripts/common.sh
Executable file
10
resource/runner/scripts/common.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
COLOR_RED="\e[0;31m"
|
||||
COLOR_GREEN="\e[0;32m"
|
||||
COLOR_YELLOW="\e[0;33m"
|
||||
COLOR_NONE="\e[0m"
|
||||
|
||||
function log_info() { echo -e "${COLOR_GREEN}$*${COLOR_NONE}" 1>&2; }
|
||||
function log_warn() { echo -e "${COLOR_YELLOW}$*${COLOR_NONE}" 1>&2; }
|
||||
function log_error() { echo -e "${COLOR_RED}$*${COLOR_NONE}" 1>&2; }
|
51
resource/runner/scripts/prepare_container.sh
Executable file
51
resource/runner/scripts/prepare_container.sh
Executable file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. common.sh
|
||||
|
||||
cd "$(dirname "$0")"/../ || exit 1
|
||||
|
||||
if [ -f ./.mark.docker ]; then
|
||||
log_warn "Docker containers already prepared"
|
||||
log_warn "If you want to re-prepare the containers, please remove the file `pwd`/.mark.docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Full
|
||||
cat <<EOF >ubuntu-full.Dockerfile
|
||||
FROM ubuntu:22.04
|
||||
WORKDIR /woj/
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y gcc g++ clang make cmake autoconf m4 libtool gperf git parallel python3 && apt-get clean && rm -rf /var/lib/apt/lists
|
||||
|
||||
# Copy source code
|
||||
RUN mkdir -p /woj/framework && mkdir -p /woj/problem
|
||||
COPY framework /woj/framework
|
||||
|
||||
# Build
|
||||
RUN cd /woj/framework/template && ./setup.sh
|
||||
RUN cd /woj/framework/scripts && ./setup.sh
|
||||
|
||||
# Environment
|
||||
ENV WOJ_LAUNCHER=/woj/framework/scripts/woj_launcher
|
||||
ENV WOJ_SANDBOX=/woj/framework/scripts/libwoj_sandbox.so
|
||||
ENV TEMPLATE=/woj/framework/template
|
||||
ENV TESTLIB=/woj/framework/template/testlib
|
||||
ENV PREFIX=/woj/problem
|
||||
EOF
|
||||
docker build -t woj/ubuntu-full -f ubuntu-full.Dockerfile . || exit 1
|
||||
rm ubuntu-full.Dockerfile
|
||||
|
||||
# Tiny
|
||||
cat <<EOF >ubuntu-run.Dockerfile
|
||||
FROM woj/ubuntu-full:latest AS builder
|
||||
FROM ubuntu:22.04
|
||||
WORKDIR /woj/problem
|
||||
RUN mkdir -p /woj/framework/scripts
|
||||
COPY --from=builder /woj/framework/scripts/libwoj_sandbox.so /woj/framework/scripts/
|
||||
COPY --from=builder /woj/framework/scripts/woj_launcher /woj/framework/scripts/
|
||||
EOF
|
||||
docker build -t woj/ubuntu-run -f ubuntu-run.Dockerfile . || exit 1
|
||||
rm ubuntu-run.Dockerfile
|
||||
|
||||
touch ./.mark.docker
|
75
resource/runner/scripts/problem.sh
Executable file
75
resource/runner/scripts/problem.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. common.sh
|
||||
|
||||
# get_problem_info
|
||||
# extract language info and limits
|
||||
# $1: workspace
|
||||
# $2: problem name
|
||||
# $3: language
|
||||
# exports: Info_Script, Info_Cmp, Info_Num, Info_Limit_Time, Info_Limit_Memory, Info_Limit_NProc
|
||||
function get_problem_info() {
|
||||
local err
|
||||
|
||||
if [ ! -f "$1/problem/$2/config.json" ]; then
|
||||
log_error "problem $2 not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
parse_language_info "$1" "$2" "$3"
|
||||
err=$?
|
||||
if [ "$err" -ne 0 ]; then
|
||||
return "$err"
|
||||
fi
|
||||
|
||||
parse_limits "$1" "$2"
|
||||
err=$?
|
||||
if [ "$err" -ne 0 ]; then
|
||||
return "$err"
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_language_info() {
|
||||
export Info_Script
|
||||
export Info_Cmp
|
||||
|
||||
local lang_config
|
||||
local lang_type
|
||||
local lang_script
|
||||
|
||||
lang_config=$(jq ".Languages[] | select(.Lang == \"$3\")" "$1/problem/$2/config.json")
|
||||
if [ -z "$lang_config" ]; then
|
||||
log_error "language $3 is not supported"
|
||||
return 1
|
||||
fi
|
||||
|
||||
Info_Cmp=$(echo "$lang_config" | jq -r ".Cmp")
|
||||
|
||||
lang_type=$(echo "$lang_config" | jq -r ".Type")
|
||||
lang_script=$(echo "$lang_config" | jq -r ".Script")
|
||||
|
||||
if [ "$lang_type" == "custom" ]; then
|
||||
Info_Script="/woj/problem/judge/$lang_script"
|
||||
elif [ "$lang_type" == "default" ]; then
|
||||
Info_Script="/woj/framework/template/default/$3.Makefile"
|
||||
else
|
||||
log_warn "Config file might be corrupted!"
|
||||
log_error "Unknown language type: $lang_type"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_limits() {
|
||||
export Info_Limit_Time
|
||||
export Info_Limit_Memory
|
||||
export Info_Limit_NProc
|
||||
export Info_Num
|
||||
|
||||
local cfg
|
||||
cfg="$1/problem/$2/config.json"
|
||||
|
||||
Info_Limit_Time=$(jq ".Runtime.TimeLimit" "$cfg")
|
||||
Info_Limit_Memory=$(jq ".Runtime.MemoryLimit" "$cfg")
|
||||
Info_Limit_NProc=$(jq ".Runtime.NProcLimit" "$cfg")
|
||||
Info_Num=$(jq ".Tasks | length" "$1/problem/$2/config.json")
|
||||
}
|
30
resource/runner/scripts/problem_compile.sh
Executable file
30
resource/runner/scripts/problem_compile.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
|
||||
. "$WORKSPACE"/scripts/run_timeout.sh
|
||||
. "$WORKSPACE"/scripts/common.sh
|
||||
. "$WORKSPACE"/scripts/problem.sh
|
||||
|
||||
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
|
||||
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_problem_info "$WORKSPACE" "$1" "$3"
|
||||
|
||||
SRC_FILE="$WORKSPACE"/user/"$2"/"$2"."$3"
|
||||
EXE_FILE="$WORKSPACE"/user/"$2"/"$2".out
|
||||
LOG_FILE="$WORKSPACE"/user/"$2"/"$2".compile.log
|
||||
|
||||
rm -f "$EXE_FILE" && touch "$EXE_FILE"
|
||||
|
||||
export TIMEOUT=${4:-60}
|
||||
docker_run \
|
||||
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
|
||||
-v "$SRC_FILE":/woj/problem/user/"$2"."$3":ro \
|
||||
-v "$EXE_FILE":/woj/problem/user/"$2".out \
|
||||
-e USER_PROG="$2" \
|
||||
-e LANG="$3" \
|
||||
woj/ubuntu-full \
|
||||
sh -c \
|
||||
"cd /woj/problem/user && make -f $Info_Script compile"
|
40
resource/runner/scripts/problem_judge.sh
Executable file
40
resource/runner/scripts/problem_judge.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
|
||||
. "$WORKSPACE"/scripts/run_timeout.sh
|
||||
. "$WORKSPACE"/scripts/common.sh
|
||||
. "$WORKSPACE"/scripts/problem.sh
|
||||
|
||||
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
|
||||
log_warn "Usage: $0 <problem> <user_dir> <language> <timeout>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_problem_info "$WORKSPACE" "$1" "$3"
|
||||
|
||||
TIMEOUT=${4:-60}
|
||||
for test_num in $(seq "$Info_Num"); do
|
||||
std_file="$WORKSPACE/problem/$1/data/output/$test_num.output"
|
||||
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
|
||||
jdg_file="$WORKSPACE/user/$2/$test_num.judge"
|
||||
|
||||
if [ ! -f "$std_file" ] || [ ! -f "$ans_file" ]; then
|
||||
log_error "Missing test case $test_num"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Judging test case $test_num"
|
||||
|
||||
touch "$jdg_file"
|
||||
|
||||
docker_run \
|
||||
-v "$WORKSPACE"/problem/"$1"/judge:/woj/problem/judge:ro \
|
||||
-v "$WORKSPACE"/problem/"$1"/data:/woj/problem/data:ro \
|
||||
-v "$ans_file":/woj/problem/user/"$test_num".out.usr \
|
||||
-v "$jdg_file":/woj/problem/user/"$test_num".judge \
|
||||
-e TEST_NUM="$test_num" \
|
||||
-e CMP="$Info_Cmp" \
|
||||
woj/ubuntu-full \
|
||||
sh -c \
|
||||
"cd /woj/problem/user && make -f $Info_Script judge"
|
||||
done
|
32
resource/runner/scripts/problem_prebuild.sh
Executable file
32
resource/runner/scripts/problem_prebuild.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
|
||||
. "$WORKSPACE"/scripts/run_timeout.sh
|
||||
. "$WORKSPACE"/scripts/common.sh
|
||||
|
||||
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ]; then
|
||||
log_warn "Usage: $0 <problem> <timeout>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "$WORKSPACE/problem/$1/.mark.prebuild" ]; then
|
||||
log_warn "Problem $1 already prebuilt"
|
||||
log_warn "If you want to re-prebuild the problem, please remove the file $WORKSPACE/problem/$1/.mark.prebuild"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "$WORKSPACE/problem/$1/judge/prebuild.Makefile" ]; then
|
||||
log_warn "Problem $1 does not have prebuild scripts"
|
||||
log_warn "$WORKSPACE/problem/$1/.mark.prebuild"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TIMEOUT=${2:-300}
|
||||
docker_run \
|
||||
-v "$WORKSPACE/problem/$1/data":/woj/problem/data \
|
||||
-v "$WORKSPACE/problem/$1/judge":/woj/problem/judge \
|
||||
-e PREFIX=/woj/problem \
|
||||
woj/ubuntu-full \
|
||||
sh -c "cd /woj/problem/judge && make -f prebuild.Makefile prebuild && touch .mark.prebuild"
|
||||
|
||||
mv "$WORKSPACE/problem/$1/judge/.mark.prebuild" "$WORKSPACE/problem/$1/.mark.prebuild" || exit 1
|
71
resource/runner/scripts/problem_run.sh
Executable file
71
resource/runner/scripts/problem_run.sh
Executable file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
WORKSPACE=$(cd "$(dirname "$0")"/.. && pwd)
|
||||
. "$WORKSPACE"/scripts/run_timeout.sh
|
||||
. "$WORKSPACE"/scripts/common.sh
|
||||
. "$WORKSPACE"/scripts/problem.sh
|
||||
|
||||
if [ "$1" == "" ] || [ ! -d "$WORKSPACE/problem/$1" ] || [ "$2" == "" ] || [ ! -d "$WORKSPACE/user/$2" ] || [ -z "$3" ]; then
|
||||
log_warn "Usage: $0 <problem> <user_dir> <language>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$WORKSPACE/problem/$1/.mark.prebuild" ]; then
|
||||
log_warn "Problem $1 has not been prebuilt"
|
||||
log_warn "Please run 'problem_prebuild.sh $1' first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$WORKSPACE/user/$2/$2.out" ]; then
|
||||
log_warn "User $2 has not been compiled"
|
||||
log_warn "Please run 'problem_compile.sh ...' first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
parse_limits "$WORKSPACE" "$1"
|
||||
|
||||
log_info "Running problem $1 for user $2"
|
||||
log_info "TimeLimit: $Info_Limit_Time"
|
||||
log_info "MemoryLimit: $Info_Limit_Memory"
|
||||
log_info "NProcLimit: $Info_Limit_NProc"
|
||||
|
||||
# launcher will add 2 more seconds
|
||||
# here add 3 more seconds
|
||||
TIMEOUT=$(((LIMIT_TIME + 1000) / 1000 + 3))
|
||||
log_info "Timeout: $TIMEOUT"
|
||||
|
||||
for test_num in $(seq "$Info_Num"); do
|
||||
test_case="$WORKSPACE/problem/$1/data/input/$test_num.input"
|
||||
exe_file="$WORKSPACE/user/$2/$2.out"
|
||||
ans_file="$WORKSPACE/user/$2/$test_num.out.usr"
|
||||
ifo_file="$WORKSPACE/user/$2/$test_num.info"
|
||||
|
||||
if [ ! -f "$test_case" ]; then
|
||||
log_error "Test case $test_num does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Running test case $test_num"
|
||||
rm -f "$ans_file" && touch "$ans_file"
|
||||
rm -f "$ifo_file" && touch "$ifo_file"
|
||||
docker_run \
|
||||
--cpus 1 \
|
||||
--network none \
|
||||
-v "$test_case":/woj/problem/data/input/"$test_num".input:ro \
|
||||
-v "$exe_file":/woj/user/"$2".out:ro \
|
||||
-v "$ans_file":/woj/user/"$test_num".out.usr \
|
||||
-v "$ifo_file":/woj/user/"$test_num".info \
|
||||
woj/ubuntu-run \
|
||||
sh -c \
|
||||
"cd /woj/user && /woj/framework/scripts/woj_launcher \
|
||||
--memory_limit=$Info_Limit_Memory \
|
||||
--nproc_limit=$Info_Limit_NProc \
|
||||
--time_limit=$Info_Limit_Time \
|
||||
--sandbox_path=/woj/framework/scripts/libwoj_sandbox.so \
|
||||
--sandbox_template=$3 \
|
||||
--sandbox_action=nothing \
|
||||
--file_input=/woj/problem/data/input/$test_num.input \
|
||||
--file_output=/woj/user/$test_num.out.usr \
|
||||
--file_info=/woj/user/$test_num.info \
|
||||
--program=/woj/user/$2.out"
|
||||
done
|
16
resource/runner/scripts/run_timeout.sh
Executable file
16
resource/runner/scripts/run_timeout.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. common.sh
|
||||
|
||||
function docker_run() {
|
||||
local timeout=${TIMEOUT:-10}
|
||||
local log_file=${LOG_FILE:-/dev/stderr}
|
||||
log_info "Docker run with timeout $timeout"
|
||||
CONTAINER_NAME=$(uuidgen)
|
||||
(
|
||||
sleep "$timeout"
|
||||
docker kill "$CONTAINER_NAME"
|
||||
) &
|
||||
docker run --rm --name "$CONTAINER_NAME" "$@" > "$log_file" 2>&1
|
||||
pkill -P $$
|
||||
}
|
0
resource/runner/tmp/.gitkeep
Normal file
0
resource/runner/tmp/.gitkeep
Normal file
1
resource/runner/user/.gitignore
vendored
Normal file
1
resource/runner/user/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/test_user
|
Loading…
Reference in New Issue
Block a user