mirror of
https://github.com/QingdaoU/Judger.git
synced 2024-12-29 00:11:41 +00:00
初步完成Python binding
增加单元测试基础
This commit is contained in:
parent
0ec206bb4b
commit
69713edb78
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,10 +1,6 @@
|
||||
.idea/
|
||||
build/
|
||||
a.out
|
||||
limit
|
||||
runner
|
||||
main
|
||||
demo
|
||||
.DS_Store
|
||||
judger.log
|
||||
*.log
|
||||
*.swp
|
||||
*.so
|
13
.travis.yml
Normal file
13
.travis.yml
Normal file
@ -0,0 +1,13 @@
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
sudo: required
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install libseccomp-dev cmake
|
||||
install:
|
||||
- mkdir build && cd build
|
||||
- cmake .. && make && make install
|
||||
- cd ../bindings/Python && python setup.py install
|
||||
script:
|
||||
- cd tests && sudo python test.py
|
@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 2.5)
|
||||
project(judger C)
|
||||
|
||||
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output)
|
||||
|
||||
set(BASE_CMAKE_C_FLAGS "-Wall -Werror -O3 -std=c99")
|
||||
set(CMAKE_C_FLAGS "${BASE_CMAKE_C_FLAGS}")
|
||||
@ -23,7 +22,4 @@ foreach(lang_rule_path ${RULE_SOURCE})
|
||||
target_link_libraries("rule_${lang_name}" seccomp)
|
||||
endforeach(lang_rule_path src/rules)
|
||||
|
||||
|
||||
# make tests
|
||||
add_executable(run_test test/main.c ${SOURCE})
|
||||
target_link_libraries(run_test pthread dl seccomp)
|
||||
install(DIRECTORY output/ DESTINATION /usr/lib/judger)
|
96
bindings/Python/_judger.c
Normal file
96
bindings/Python/_judger.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <python2.7/Python.h>
|
||||
#include "../../src/runner.h"
|
||||
|
||||
|
||||
#define RaiseValueError(msg) {PyErr_SetString(PyExc_ValueError, msg); return NULL;}
|
||||
|
||||
|
||||
static PyObject *judger_run(PyObject *self, PyObject *args, PyObject *kwargs) {
|
||||
struct config _config;
|
||||
struct result _result = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
PyObject *args_list = NULL, *env_list = NULL, *args_iter = NULL, *env_iter = NULL, *next = NULL;
|
||||
|
||||
int count = 0;
|
||||
|
||||
static char *kwargs_list[] = {"max_cpu_time", "max_real_time", "max_memory",
|
||||
"max_process_number", "max_output_size",
|
||||
"exe_path", "input_path", "output_path",
|
||||
"error_path", "args", "env", "log_path",
|
||||
"seccomp_rule_so_path", "uid", "gid", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iililssssOOssii", kwargs_list,
|
||||
&(_config.max_cpu_time), &(_config.max_real_time), &(_config.max_memory),
|
||||
&(_config.max_process_number), &(_config.max_output_size),
|
||||
&(_config.exe_path), &(_config.input_path), &(_config.output_path),
|
||||
&(_config.error_path), &args_list, &env_list, &(_config.log_path),
|
||||
&(_config.seccomp_rule_so_path), &(_config.uid), &(_config.gid))) {
|
||||
RaiseValueError("Invalid args and kwargs");
|
||||
}
|
||||
|
||||
if (!PyList_Check(args_list)) {
|
||||
RaiseValueError("args must be a list");
|
||||
}
|
||||
|
||||
_config.args[count++] = _config.exe_path;
|
||||
args_iter = PyObject_GetIter(args_list);
|
||||
while (1) {
|
||||
next = PyIter_Next((args_iter));
|
||||
if (!next) {
|
||||
break;
|
||||
}
|
||||
if (!PyString_Check(next)) {
|
||||
RaiseValueError("arg in args must be a string");
|
||||
}
|
||||
_config.args[count] = PyString_AsString(next);
|
||||
count++;
|
||||
}
|
||||
|
||||
_config.args[count] = NULL;
|
||||
|
||||
count = 0;
|
||||
if (!PyList_Check(env_list)) {
|
||||
RaiseValueError("env must be a list");
|
||||
}
|
||||
env_iter = PyObject_GetIter(env_list);
|
||||
while (1) {
|
||||
next = PyIter_Next(env_iter);
|
||||
if (!next) {
|
||||
break;
|
||||
}
|
||||
if (!PyString_Check(next) && !PyUnicode_Check(next)) {
|
||||
RaiseValueError("env item must be a string");
|
||||
}
|
||||
_config.env[count] = PyString_AsString(next);
|
||||
count++;
|
||||
}
|
||||
_config.env[count] = NULL;
|
||||
|
||||
void *handler = dlopen("/usr/lib/judger/lib/libjudger.so", RTLD_LAZY);
|
||||
int (*judger_run)(struct config *, struct result *);
|
||||
|
||||
if (!handler) {
|
||||
RaiseValueError("dlopen error")
|
||||
}
|
||||
judger_run = dlsym(handler, "run");
|
||||
judger_run(&_config, &_result);
|
||||
|
||||
return Py_BuildValue("{s:l, s:i, s:i, s:i, s:i, s:i}",
|
||||
"cpu_time", _result.cpu_time, "memory", _result.memory, "real_time", _result.real_time,
|
||||
"signal", _result.signal, "exit_code", _result.exit_code, "error", _result.error);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef judger_methods[] = {
|
||||
{"run", (PyCFunction) judger_run, METH_KEYWORDS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
PyMODINIT_FUNC init_judger(void) {
|
||||
Py_InitModule3("_judger", judger_methods, NULL);
|
||||
}
|
7
bindings/Python/setup.py
Normal file
7
bindings/Python/setup.py
Normal file
@ -0,0 +1,7 @@
|
||||
# coding=utf-8
|
||||
import platform
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup(name='_judger',
|
||||
version='1.0',
|
||||
ext_modules=[Extension('_judger', sources=['_judger.c'], libraries=["dl"])])
|
@ -1,8 +0,0 @@
|
||||
#include <seccomp.h>
|
||||
|
||||
#include "../../runner.h"
|
||||
|
||||
|
||||
int load_seccomp(void *dl_handler) {
|
||||
return 0;
|
||||
}
|
30
test/main.c
30
test/main.c
@ -1,30 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include "../src/runner.h"
|
||||
|
||||
int main() {
|
||||
runner_config config;
|
||||
config.max_cpu_time = 100;
|
||||
config.max_real_time = 100;
|
||||
config.max_memory = 1024 * 1024 * 1024;
|
||||
config.max_process_number = 1024;
|
||||
config.max_output_size = 1024 * 1024 * 64;
|
||||
config.log_path = "log.log";
|
||||
config.seccomp_rule_so_path = NULL;//"/home/virusdefender/ClionProjects/Judger/output/lib/librule_c_cpp.so";
|
||||
config.input_path = "/dev/null";
|
||||
config.output_path = "output.txt";
|
||||
config.error_path = "error.txt";
|
||||
config.exe_path = "/bin/ls";
|
||||
|
||||
config.args[0] = "/bin/ls";
|
||||
config.args[1] = "/dev";
|
||||
config.args[2] = NULL;
|
||||
|
||||
config.env[0] = "PATH=test";
|
||||
config.env[1] = NULL;
|
||||
|
||||
runner_result result;
|
||||
run(&config, &result);
|
||||
|
||||
printf("cpu time:%d\nreal time:%d\nmemory:%ld\nsignal:%d\nexit code:%d\nerror:%d", result.cpu_time, result.real_time, result.memory, result.signal, result.exit_code, result.error);
|
||||
return 0;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/* This is a really minimal testing framework for C.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* test_cond("Check if 1 == 1", 1==1)
|
||||
* test_cond("Check if 5 > 10", 5 > 10)
|
||||
* test_report()
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010-2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef JDGER_TESTHELP_H
|
||||
#define JDGER_TESTHELP_H
|
||||
|
||||
int __failed_tests = 0;
|
||||
int __test_num = 0;
|
||||
#define test_cond(descr,_c) do { \
|
||||
__test_num++; printf("%d - %s: ", __test_num, descr); \
|
||||
if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
|
||||
} while(0);
|
||||
#define test_report() do { \
|
||||
printf("%d tests, %d passed, %d failed\n", __test_num, \
|
||||
__test_num-__failed_tests, __failed_tests); \
|
||||
if (__failed_tests) { \
|
||||
printf("=== WARNING === We have failed tests here...\n"); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#endif
|
3
tests/test.py
Normal file
3
tests/test.py
Normal file
@ -0,0 +1,3 @@
|
||||
# coding=utf-8
|
||||
|
||||
print "todo"
|
Loading…
Reference in New Issue
Block a user