Update TODO

This commit is contained in:
MeiK 2020-05-21 15:05:28 +08:00
parent 353236a154
commit d3ed13ea13
6 changed files with 100 additions and 31 deletions

View File

@ -1 +1,6 @@
# river
# river
## TODO
- 资源限制
- 资源占用过多的错误

View File

@ -21,7 +21,7 @@ pub enum Error {
TemplateRenderError(RenderError),
LanguageConfigError(String),
CreateTempDirError(io::Error),
CloseTempDirError(io::Error),
// CloseTempDirError(io::Error),
CopyFileError(io::Error),
OsStringToStringError(OsString),
ForkError(Option<i32>),

View File

@ -36,6 +36,7 @@ fn main() {
match process::run(&judge_config) {
Ok(_) => {}
Err(err) => {
// TODO: SE
eprintln!("{}", err);
return;
}

View File

@ -134,11 +134,18 @@ pub fn run(judge_config: &JudgeConfig) -> Result<()> {
};
}
// TODO: 处理 CE 与 RE编译期间程序运行出错为 CE运行期间出错为 RE
let _ = compile(judge_config, to_dir)?;
let compile_status = compile(judge_config, to_dir)?;
if !compile_status.exited {
// TODO: CE
}
for test_case in &judge_config.tests {
let exit_status = run_one(judge_config, test_case, to_dir)?;
let output_file_path = to_dir.join(&test_case.output_file);
let answer_file_path = from_dir.join(&test_case.answer_file);
if !exit_status.exited {
// TODO: RE
}
let res = TestCaseResult::standard(&output_file_path, &answer_file_path, exit_status);
println!("{:?}", res);
match fs::remove_file(output_file_path) {
@ -151,10 +158,11 @@ pub fn run(judge_config: &JudgeConfig) -> Result<()> {
}
};
}
match pwd.close() {
Ok(_) => {}
Err(err) => return Err(Error::CloseTempDirError(err)),
};
println!("{:?}", pwd);
// match pwd.close() {
// Ok(_) => {}
// Err(err) => return Err(Error::CloseTempDirError(err)),
// };
Ok(())
}
@ -200,9 +208,26 @@ pub fn wait(pid: i32) -> Result<ExitStatus> {
Ok(elapsed) => elapsed.as_millis(),
Err(err) => return Err(Error::SystemTimeError(err)),
};
let signal = unsafe {
if libc::WIFSIGNALED(status) {
libc::WTERMSIG(status)
} else if libc::WIFSTOPPED(status) {
libc::WSTOPSIG(status)
} else {
0
}
};
let exited = unsafe { libc::WIFEXITED(status) };
if exited {
status = unsafe { libc::WEXITSTATUS(status) };
}
let coredump = unsafe { libc::WCOREDUMP(status) };
Ok(ExitStatus {
rusage,
status,
signal,
exited,
coredump,
time_used,
real_time_used,
memory_used,
@ -267,15 +292,14 @@ pub fn run_one(
panic!("How dare you!");
} else if pid > 0 {
// 父进程
let exit_status = wait(pid)?;
return Ok(exit_status);
return Ok(wait(pid)?);
} else {
// 异常
return Err(Error::ForkError(io::Error::last_os_error().raw_os_error()));
}
}
pub fn compile(judge_config: &JudgeConfig, workdir: &Path) -> Result<()> {
pub fn compile(judge_config: &JudgeConfig, workdir: &Path) -> Result<ExitStatus> {
let pid;
unsafe {
pid = libc::fork();
@ -292,9 +316,8 @@ pub fn compile(judge_config: &JudgeConfig, workdir: &Path) -> Result<()> {
}
panic!("How dare you!");
} else if pid > 0 {
let _ = wait(pid)?;
return Ok(wait(pid)?);
} else {
return Err(Error::ForkError(io::Error::last_os_error().raw_os_error()));
}
Ok(())
}

View File

@ -6,15 +6,12 @@ use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::path::Path;
#[derive(Debug, Copy, Clone)]
pub struct ResourceUsed {
pub time_used: i64,
pub memory_used: i64,
}
pub struct ExitStatus {
pub rusage: libc::rusage,
pub status: i32,
pub signal: i32,
pub exited: bool,
pub coredump: bool,
pub time_used: i64,
pub real_time_used: u128,
pub memory_used: i64,
@ -22,11 +19,11 @@ pub struct ExitStatus {
#[derive(Debug, Clone)]
pub enum TestCaseResult {
Accepted(ResourceUsed),
CompileError(ResourceUsed, String),
WrongAnswer(ResourceUsed),
RuntimeError(ResourceUsed, String),
SystemError(ResourceUsed, String),
Accepted,
CompileError(String),
WrongAnswer,
RuntimeError(String),
SystemError(String),
}
impl fmt::Display for TestCaseResult {
@ -45,10 +42,9 @@ impl TestCaseResult {
println!("time used:\t{}", exit_status.time_used);
println!("real time used:\t{}", exit_status.real_time_used);
println!("memory used:\t{}", exit_status.rusage.ru_maxrss);
let used = ResourceUsed {
time_used: exit_status.time_used,
memory_used: exit_status.rusage.ru_maxrss,
};
println!("status:\t{}", exit_status.status);
println!("signal:\t{}", exit_status.signal);
println!("exited:\t{}", exit_status.exited);
let output_filename = match output_file.as_ref().to_str() {
Some(val) => val,
@ -108,13 +104,13 @@ impl TestCaseResult {
break;
}
if output_buffer.trim_end() != answer_buffer.trim_end() {
return Ok(TestCaseResult::WrongAnswer(used));
return Ok(TestCaseResult::WrongAnswer);
}
}
// 末尾的空白字符不影响结果
while output_bytes != 0 {
if output_buffer.trim() != "" {
return Ok(TestCaseResult::WrongAnswer(used));
return Ok(TestCaseResult::WrongAnswer);
}
output_bytes = match output_reader.read_line(&mut output_buffer) {
Ok(val) => val,
@ -128,7 +124,7 @@ impl TestCaseResult {
}
while answer_bytes != 0 {
if answer_buffer.trim() != "" {
return Ok(TestCaseResult::WrongAnswer(used));
return Ok(TestCaseResult::WrongAnswer);
}
answer_bytes = match answer_reader.read_line(&mut answer_buffer) {
Ok(val) => val,
@ -141,6 +137,6 @@ impl TestCaseResult {
};
}
Ok(TestCaseResult::Accepted(used))
Ok(TestCaseResult::Accepted)
}
}

44
tests/response.json Normal file
View File

@ -0,0 +1,44 @@
{
"compile": {
"time": 120,
"memory": 4096,
"status": 0,
"signal": 0,
"exited": true,
"output": "main.c: In function main: \nmain.c:5:5: warning: ignoring return value of scanf, declared with attribute warn_unused_result [-Wunused-result] \n scanf(\"%d %d\", &a, &b);"
},
"tests": [
{
"time": 0,
"memory": 1576,
"status": 0,
"signal": 0,
"exited": true,
"result": "Accepted"
},
{
"time": 0,
"memory": 1576,
"status": 0,
"signal": 0,
"exited": true,
"result": "WrongAnswer"
},
{
"time": 0,
"memory": 1576,
"status": 0,
"signal": 0,
"exited": true,
"result": "Accepted"
},
{
"time": 0,
"memory": 1576,
"status": 139,
"signal": 11,
"exited": false,
"result": "RuntimeError"
}
]
}