mirror of
https://github.com/QingdaoU/Judger.git
synced 2024-12-29 08:21:41 +00:00
Merge pull request #28 from slimeoj/nodejs
judger nodejs binding initialize 🎉
This commit is contained in:
commit
e828f1ea4c
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,3 +7,5 @@ build/
|
|||||||
__pycache__
|
__pycache__
|
||||||
*.pyc
|
*.pyc
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
.ycm_extra_conf.py
|
||||||
|
node_modules/
|
||||||
|
9
bindings/NodeJS/binding.gyp
Normal file
9
bindings/NodeJS/binding.gyp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"target_name": "judger",
|
||||||
|
'cflags_cc!': [ '-std=c++11','-O2' ],
|
||||||
|
"sources": [ "judger.cc"],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
234
bindings/NodeJS/judger.cc
Normal file
234
bindings/NodeJS/judger.cc
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
#include "node.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace demo {
|
||||||
|
|
||||||
|
using v8::FunctionCallbackInfo;
|
||||||
|
using v8::Isolate;
|
||||||
|
using v8::JSON;
|
||||||
|
using v8::Local;
|
||||||
|
using v8::Int32;
|
||||||
|
using v8::Array;
|
||||||
|
using v8::Integer;
|
||||||
|
using v8::Uint32;
|
||||||
|
using v8::Number;
|
||||||
|
using v8::Object;
|
||||||
|
using v8::String;
|
||||||
|
using v8::Value;
|
||||||
|
using v8::MaybeLocal;
|
||||||
|
using v8::Exception;
|
||||||
|
using v8::Context;
|
||||||
|
|
||||||
|
/* 转成数字 */
|
||||||
|
bool ToNumber(Isolate * isolate,Local<Value> &args,char * key,std::string &str){
|
||||||
|
Local<Context> context= isolate->GetCurrentContext();
|
||||||
|
Local<Value> val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||||
|
if(val->IsNullOrUndefined())
|
||||||
|
return true;
|
||||||
|
else if( val->IsNumber()){
|
||||||
|
Local<Integer> num = val->ToInteger(context).ToLocalChecked();
|
||||||
|
str+=" --";
|
||||||
|
str+=std::string(key);
|
||||||
|
str+="=";
|
||||||
|
str+=std::to_string(num->Value());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!")));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char * _ToCharPTR(Local<Value> &val,Local<Context> &context,char * str_content){
|
||||||
|
String::Utf8Value str_val( val->ToString(context).ToLocalChecked());
|
||||||
|
strcpy(str_content,*str_val);
|
||||||
|
return str_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 转成字符串 */
|
||||||
|
bool ToCStr(Isolate * isolate,Local<Value> &args,char * key,std::string &str){
|
||||||
|
|
||||||
|
char str_content[255]={0};
|
||||||
|
Local<Context> context= isolate->GetCurrentContext();
|
||||||
|
Local<Value> val;
|
||||||
|
if(args->IsObject())
|
||||||
|
val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||||
|
else
|
||||||
|
val = args;
|
||||||
|
if(val->IsNullOrUndefined())
|
||||||
|
return true;
|
||||||
|
else if(val->IsString()){
|
||||||
|
_ToCharPTR(val,context,str_content);
|
||||||
|
str+=" --";
|
||||||
|
str+=std::string(key);
|
||||||
|
str+="=";
|
||||||
|
str+=std::string(str_content);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char ret[100];
|
||||||
|
sprintf(ret,"typeof %s must be String!",key);
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,ret)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数:
|
||||||
|
* {
|
||||||
|
* max_cpu_time
|
||||||
|
* max_real_time
|
||||||
|
* max_memory
|
||||||
|
* memory_limit_check_only ??
|
||||||
|
* max_stack
|
||||||
|
* max_process
|
||||||
|
* max_output_size
|
||||||
|
* exe_path
|
||||||
|
* input_path
|
||||||
|
* output_path
|
||||||
|
* error_path
|
||||||
|
* args:[]
|
||||||
|
* env:[]
|
||||||
|
* }
|
||||||
|
* 返回值
|
||||||
|
* {
|
||||||
|
* cpu_time
|
||||||
|
* real_time
|
||||||
|
* memory
|
||||||
|
* signal
|
||||||
|
* exit_code
|
||||||
|
* result
|
||||||
|
* error:
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Method(const FunctionCallbackInfo<Value>& args)
|
||||||
|
{
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context= isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
std::string _args = "/usr/lib/judger/libjudger.so";
|
||||||
|
|
||||||
|
if( !args[0]->IsObject()){
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<Value> argument = args[0];
|
||||||
|
|
||||||
|
std::string int_vars[] = { "max_cpu_time","max_real_time","max_memory","memory_limit_check_only","max_stack","max_process_number","max_output_size","uid","gid"};
|
||||||
|
std::string str_vars[] = { "input_path","output_path","error_path","exe_path","log_path","seccomp_rule_name"};
|
||||||
|
|
||||||
|
for( auto var :int_vars){
|
||||||
|
if( ! ToNumber(isolate,argument,(char *)var.c_str(),_args))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto var : str_vars){
|
||||||
|
if( !ToCStr(isolate,argument,(char *)var.c_str(),_args))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* args */
|
||||||
|
Local<Value> margs= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"args")).ToLocalChecked();
|
||||||
|
if( margs->IsNullOrUndefined()){
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if( margs->IsArray()){
|
||||||
|
Local<Array> args = margs.As<Array>();
|
||||||
|
int len = args->Length();
|
||||||
|
int i;
|
||||||
|
for(i=0;i<len;i++){
|
||||||
|
Local<Value> in = args->Get(i);
|
||||||
|
if( !ToCStr(isolate,in,(char *)"args",_args))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //not array
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"args must be a list")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<Value> menv= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"env")).ToLocalChecked();
|
||||||
|
if( menv->IsNullOrUndefined()){
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if( margs->IsArray()){
|
||||||
|
Local<Array> env = menv.As<Array>();
|
||||||
|
int len = env->Length();
|
||||||
|
int i;
|
||||||
|
for(i=0;i<len;i++){
|
||||||
|
Local<Value> in = env->Get(i);
|
||||||
|
if(!ToCStr(isolate,in,(char *)"env",_args))
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //not array
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"env must be a list")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char buf[255];
|
||||||
|
FILE *_result_f;
|
||||||
|
std::string result;
|
||||||
|
if(( _result_f = popen(_args.c_str(),"r"))==NULL)
|
||||||
|
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"run /usr/lib/judger/libjudger.so failed!")));
|
||||||
|
while(fgets(buf,sizeof(buf),_result_f)){
|
||||||
|
result += std::string(buf);
|
||||||
|
}
|
||||||
|
pclose(_result_f);
|
||||||
|
|
||||||
|
const char *pr = result.c_str();
|
||||||
|
int len = strlen(pr);
|
||||||
|
for(len--;len>=0;len--){
|
||||||
|
if( pr[len] == '{')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len)
|
||||||
|
printf("%*.*s",len,len,pr); //输出 程序的输出
|
||||||
|
|
||||||
|
MaybeLocal<Value> mres = JSON::Parse(isolate,String::NewFromUtf8(isolate,pr+len));
|
||||||
|
args.GetReturnValue().Set(mres.ToLocalChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(Local<Object> exports)
|
||||||
|
{
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
|
NODE_SET_METHOD(exports, "run", Method);
|
||||||
|
exports->Set( String::NewFromUtf8(isolate,"UNLIMITED"),Integer::New(isolate, -1));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"VERSION"),Integer::New(isolate, 0x020101));
|
||||||
|
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_SUCCESS"),Integer::New(isolate, 0));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_WRONG_ANSWER"),Integer::New(isolate, -1));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_CPU_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 1));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_REAL_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 2));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_MEMORY_LIMIT_EXCEEDED"),Integer::New(isolate, 3));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_RUNTIME_ERROR"),Integer::New(isolate, 4));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"RESULT_SYSTEM_ERROR"),Integer::New(isolate, 5));
|
||||||
|
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_INVALID_CONFIG"),Integer::New(isolate, -1));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_FORK_FAILED"),Integer::New(isolate, -2));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_PTHREAD_FAILED"),Integer::New(isolate, -3));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_WAIT_FAILED"),Integer::New(isolate, -4));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_ROOT_REQUIRED"),Integer::New(isolate, -5));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_LOAD_SECCOMP_FAILED"),Integer::New(isolate, -6));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_SETRLIMIT_FAILED"),Integer::New(isolate, -7));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_DUP2_FAILED"),Integer::New(isolate, -8));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_SETUID_FAILED"),Integer::New(isolate, -9));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_EXECVE_FAILED"),Integer::New(isolate, -10));
|
||||||
|
exports->Set(String::NewFromUtf8(isolate,"ERROR_SPJ_ERROR"),Integer::New(isolate, -11));
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_MODULE(addon, init)
|
||||||
|
|
||||||
|
}
|
16
bindings/NodeJS/package.json
Normal file
16
bindings/NodeJS/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "judger",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "judger for online system",
|
||||||
|
"main": "./build/Release/judger.node",
|
||||||
|
"scripts": {
|
||||||
|
"build": "node-gyp rebuild",
|
||||||
|
"test": "sudo ./node_modules/.bin/mocha -t 5000 ../../tests/Nodejs_and_core"
|
||||||
|
},
|
||||||
|
"author": "virusdefender,rainboy",
|
||||||
|
"license": "GPL",
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "^6.1.4",
|
||||||
|
"node-gyp": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
15
bindings/NodeJS/readme.md
Normal file
15
bindings/NodeJS/readme.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
## 安装
|
||||||
|
|
||||||
|
先安装`judger`,然后
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 已知bug
|
||||||
|
|
||||||
|
#### bug_1
|
||||||
|
|
||||||
|
`freopen("data.out","w",stdout)`,不能产生"data.out",这个应该是judger代码的锅,:cry:
|
71
tests/Nodejs_and_core/base.js
Normal file
71
tests/Nodejs_and_core/base.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
const fs = require("fs")
|
||||||
|
const path = require("path")
|
||||||
|
const execSync = require("child_process").execSync
|
||||||
|
|
||||||
|
var out_base_path = '/tmp/judge'
|
||||||
|
var compile_base_path = ""
|
||||||
|
var compile_c = function(name){
|
||||||
|
out_path =path.join(out_base_path,'main')
|
||||||
|
execSync(`gcc -o ${out_path} ${path.join(this.compile_base_path,name)}`)
|
||||||
|
return out_path
|
||||||
|
}
|
||||||
|
|
||||||
|
var compile_cpp = function(name){
|
||||||
|
out_path =path.join(out_base_path,'main')
|
||||||
|
execSync(`g++ -o ${out_path} ${path.join(this.compile_base_path,name)}`)
|
||||||
|
return out_path
|
||||||
|
}
|
||||||
|
|
||||||
|
var make_input = content =>{
|
||||||
|
fs.writeFileSync('/tmp/judge/input',content,{'encoding':'utf-8'})
|
||||||
|
return '/tmp/judge/input'
|
||||||
|
}
|
||||||
|
|
||||||
|
var read_input = read_path => {
|
||||||
|
return fs.readFileSync(read_path,{'encoding':'utf-8'})
|
||||||
|
}
|
||||||
|
|
||||||
|
var output_path = ()=>{
|
||||||
|
return '/tmp/judge/output'
|
||||||
|
}
|
||||||
|
|
||||||
|
var error_path = ()=>{
|
||||||
|
return '/tmp/judge/error'
|
||||||
|
}
|
||||||
|
|
||||||
|
var mkdir = _path => {
|
||||||
|
execSync(`mkdir -p ${_path}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rmdir = _path => {
|
||||||
|
execSync(`rm -r ${_path}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseconfig = ()=>{
|
||||||
|
return {
|
||||||
|
max_cpu_time:1000,
|
||||||
|
max_real_time:8000,
|
||||||
|
max_memory:128*1024*1024,
|
||||||
|
max_stack:128*1024*1024,
|
||||||
|
max_process_number:8,
|
||||||
|
max_output_size:128*1024*1024,
|
||||||
|
exe_path:"/dev/null",
|
||||||
|
input_path:"/dev/null",
|
||||||
|
output_path:"/dev/null",
|
||||||
|
error_path:"/dev/null",
|
||||||
|
args:[],
|
||||||
|
env:[],
|
||||||
|
log_path:"/dev/null",
|
||||||
|
seccomp_rule_name:null,
|
||||||
|
gid:0,
|
||||||
|
uid:0,
|
||||||
|
info:false,
|
||||||
|
debug:false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
compile_c,compile_cpp,make_input,read_input,mkdir,rmdir,baseconfig,compile_base_path,
|
||||||
|
output_path,
|
||||||
|
error_path
|
||||||
|
}
|
245
tests/Nodejs_and_core/test_integration.js
Normal file
245
tests/Nodejs_and_core/test_integration.js
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
const assert = require("assert")
|
||||||
|
const path = require("path")
|
||||||
|
var judger = require("../../bindings/NodeJS")
|
||||||
|
var base = require('./base.js')
|
||||||
|
var signal = require("os").constants.signals
|
||||||
|
|
||||||
|
|
||||||
|
var compile_base_path = base.compile_base_path = path.join(__dirname,"../test_src","integration")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
describe('#常用测试',function(){
|
||||||
|
|
||||||
|
|
||||||
|
before( ()=>{
|
||||||
|
//mkdir /tmp/judge
|
||||||
|
base.mkdir('/tmp/judge')
|
||||||
|
})
|
||||||
|
after( ()=>{
|
||||||
|
base.rmdir('/tmp/judge')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('args must be a list 1',()=>{
|
||||||
|
assert.throws(()=>judger.run({args:{},output_path:"/dev/null"}),/args must be a list$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('args must be a list 2',()=>{
|
||||||
|
assert.throws(()=>judger.run({args:"1234",output_path:"/dev/null"}),/args must be a list$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test_env_must_be_list',()=>{
|
||||||
|
assert.throws(()=>judger.run({env:"1234",output_path:"/dev/null"}),/env must be a list$/)
|
||||||
|
})
|
||||||
|
it('test_seccomp_rule_can_be_none',()=>{
|
||||||
|
let ret = judger.run({ output_path:"/dev/null",exe_path:"/bin/ls",args:["/"],env:["a=b"] })
|
||||||
|
assert.strictEqual(ret.result,0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test normal.c',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("normal.c")
|
||||||
|
config["input_path"] = base.make_input("judger_test")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
let ret = judger.run(config)
|
||||||
|
let output = "judger_test\nHello world"
|
||||||
|
let content = base.read_input( base.output_path())
|
||||||
|
assert.strictEqual(content,output)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test math.c' ,()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("math.c")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
let ret = judger.run(config)
|
||||||
|
assert.strictEqual(ret.result,judger.RESULT_SUCCESS)
|
||||||
|
let content = base.read_input( base.output_path())
|
||||||
|
assert.strictEqual(content,"abs 1024")
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test_args',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("args.c")
|
||||||
|
config["args"] = ["test", "hehe", "000"]
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
|
||||||
|
let result = judger.run(config)
|
||||||
|
let output = "argv[0]: /tmp/judge/main\nargv[1]: test\nargv[2]: hehe\nargv[3]: 000\n"
|
||||||
|
assert.strictEqual(result.result, judger.RESULT_SUCCESS)
|
||||||
|
assert.strictEqual(output, base.read_input(config["output_path"]))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test env',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("env.c")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
config["env"] = ["env=judger_test","test=judger"]
|
||||||
|
let result = judger.run(config)
|
||||||
|
let output = "judger_test\njudger\n"
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
assert.strictEqual(output, base.read_input(config["output_path"]))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test real time',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("sleep.c")
|
||||||
|
config["max_real_time"] = 3
|
||||||
|
let result = judger.run(config)
|
||||||
|
//assert.strictEqual(result["result"], judger.RESULT_REAL_TIME_LIMIT_EXCEEDED)
|
||||||
|
assert.strictEqual(result["signal"], signal.SIGKILL)
|
||||||
|
assert.ok(result["real_time"] >= config["max_real_time"])
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test cpu time',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("while1.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED)
|
||||||
|
assert.strictEqual(result["signal"], signal.SIGKILL)
|
||||||
|
assert.ok(result["cpu_time"] >= config["max_cpu_time"])
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test memory1',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["max_memory"] = 64 * 1024 * 1024
|
||||||
|
config["exe_path"] = base.compile_c("memory1.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
//# malloc succeeded
|
||||||
|
assert.ok(result["memory"] > 80 * 1024 * 1024)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_MEMORY_LIMIT_EXCEEDED)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test memory2',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["max_memory"] = 64 * 1024 * 1024
|
||||||
|
config["exe_path"] = base.compile_c("memory2.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
//# malloc failed, return 1
|
||||||
|
assert.strictEqual(result["exit_code"], 1)
|
||||||
|
//# malloc failed, so it should use a little memory
|
||||||
|
assert.ok(result["memory"] < 12 * 1024 * 1024)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('test memory3',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["max_memory"] = 512 * 1024 * 1024
|
||||||
|
config["exe_path"] = base.compile_c("memory3.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
assert.ok(result["memory"] >= 102400000 * 4)
|
||||||
|
})
|
||||||
|
it('test re1',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("re1.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
//# re1.c return 25
|
||||||
|
assert.strictEqual(result["exit_code"], 25)
|
||||||
|
|
||||||
|
})
|
||||||
|
it('test re2',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("re2.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR)
|
||||||
|
assert.strictEqual(result["signal"], signal.SIGSEGV)
|
||||||
|
})
|
||||||
|
it('test child proc cpu time limit',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
|
||||||
|
config["exe_path"] = base.compile_c("child_proc_cpu_time_limit.c")
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED)
|
||||||
|
|
||||||
|
})
|
||||||
|
it('test child proc real time limit',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("child_proc_real_time_limit.c")
|
||||||
|
config["max_real_time"] = 3
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_REAL_TIME_LIMIT_EXCEEDED)
|
||||||
|
assert.strictEqual(result["signal"], signal.SIGKILL)
|
||||||
|
})
|
||||||
|
it('test stdout and stderr',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("stdout_stderr.c")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
let output = "stderr\n+++++++++++++++\n--------------\nstdout\n"
|
||||||
|
assert.strictEqual(output, base.read_input(config["output_path"]))
|
||||||
|
})
|
||||||
|
it('test uid and gid',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("uid_gid.c")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
config["uid"] = 65534
|
||||||
|
config["gid"] = 65534
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
output = "uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)\nuid 65534\ngid 65534\n"
|
||||||
|
assert.strictEqual(output, base.read_input(config["output_path"]))
|
||||||
|
|
||||||
|
})
|
||||||
|
it('test gcc random',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["max_memory"] = judger.UNLIMITED
|
||||||
|
config["exe_path"] = "/usr/bin/gcc"
|
||||||
|
config["args"] = [path.join(compile_base_path,'gcc_random.c'),
|
||||||
|
"-o", '/tmp/judge/gcc_random']
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.ok(result["real_time"] >= 2000)
|
||||||
|
|
||||||
|
})
|
||||||
|
it('test cpp meta',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = "/usr/bin/g++"
|
||||||
|
config["max_memory"] = 1024 * 1024 * 1024
|
||||||
|
config["args"] = [path.join(compile_base_path,'cpp_meta.cpp'),
|
||||||
|
"-o",'/tmp/judge/cpp_meta']
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED)
|
||||||
|
assert.ok(result["cpu_time"] > 1500)
|
||||||
|
assert.ok(result["real_time"] >= 2000)
|
||||||
|
})
|
||||||
|
it('test output size',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_c("output_size.c")
|
||||||
|
config["output_path"] = base.output_path()
|
||||||
|
config["max_output_size"] = 1000 * 10
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR)
|
||||||
|
assert.ok(base.read_input("/tmp/judge/fsize_test").length <= 1000*10)
|
||||||
|
})
|
||||||
|
it('test stack size',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["max_memory"] = 256 * 1024 * 1024
|
||||||
|
config["exe_path"] = base.compile_c("stack.c")
|
||||||
|
config["max_stack"] = 16 * 1024 * 1024
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR)
|
||||||
|
|
||||||
|
config["max_stack"] = 128 * 1024 * 1024
|
||||||
|
result= judger.run(config).result
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
assert.strictEqual("big stack", base.read_input(config["output_path"]))
|
||||||
|
|
||||||
|
})
|
||||||
|
it('test writev',()=>{
|
||||||
|
let config = base.baseconfig()
|
||||||
|
config["exe_path"] = base.compile_cpp("writev.cpp")
|
||||||
|
config["seccomp_rule_name"] = "c_cpp"
|
||||||
|
config["input_path"] = base.make_input("111" * 10000 + "\n")
|
||||||
|
config["output_path"] = config["error_path"] = base.output_path()
|
||||||
|
|
||||||
|
let result= judger.run(config)
|
||||||
|
assert.strictEqual(result["result"], judger.RESULT_SUCCESS)
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user