Show More
Commit Description:
add option -A <opt> to box. This options allow more argument to be explicitly passed to the program...
Commit Description:
add option -A <opt> to box. This options allow more argument to be explicitly passed to the program
We have to use this because if the argument we wish to pass to the program is option (in -? format),
box will intepret it as its option and failed accordingly.
be noted that, by the definition of getopt, these options will be put after original argument
(check the code for more info)
References:
File last commit:
Show/Diff file:
Action:
lib/test_request_helper.rb
| 254 lines
| 7.6 KiB
| text/x-ruby
| RubyLexer
|
|
r23 | # | ||
# This part contains various test_request helpers for interfacing | ||||
# with Grader::Engine. There are TestRequestRoomMaker and | ||||
# TestRequestReporter. | ||||
module Grader | ||||
|
r101 | def self.link_or_copy(src, des) | ||
begin | ||||
FileUtils.ln_s(src, des) | ||||
|
r103 | rescue NotImplementedError | ||
|
r101 | FileUtils.cp(src,des) | ||
end | ||||
end | ||||
def self.call_and_log(error_message) | ||||
begin | ||||
yield | ||||
rescue | ||||
msg = "ERROR: #{error_message}" | ||||
raise msg | ||||
end | ||||
end | ||||
|
r23 | # | ||
# A TestRequestRoomMaker is a helper object for Engine | ||||
# - finds grading room: in user_result_dir/(user)/test_request/ ... | ||||
# - prepare problem configuration for grading --- basically it copy | ||||
# all config files, and copy user's input into the testcase | ||||
# directory. First, it finds the template from problem template | ||||
# directory; if it can't find a template, it'll use the template | ||||
# from default template. | ||||
class TestRequestRoomMaker | ||||
def initialize | ||||
@config = Grader::Configuration.get_instance | ||||
end | ||||
def produce_grading_room(test_request) | ||||
grading_room = grading_room_dir(test_request) | ||||
FileUtils.mkdir_p(grading_room) | ||||
|
r55 | |||
# | ||||
# Also copy additional submitted file to this directory as well. | ||||
# The program would see this file only if it is copied | ||||
# to the sandbox directory later. The run script should do it. | ||||
# | ||||
|
r66 | if FileTest.exists?("#{test_request.input_file_name}.files") | ||
|
r101 | FileUtils.cp_r("#{test_request.input_file_name}.files/.", | ||
"#{grading_room}") | ||||
|
r66 | end | ||
|
r55 | |||
|
r23 | grading_room | ||
end | ||||
def find_problem_home(test_request) | ||||
problem_name = test_request.problem_name | ||||
template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name | ||||
raise "Test Request: error template not found" if !File.exists?(template_dir) | ||||
problem_home = problem_home_dir(test_request) | ||||
FileUtils.mkdir_p(problem_home) | ||||
copy_problem_template(template_dir,problem_home) | ||||
link_input_file(test_request,problem_home) | ||||
problem_home | ||||
end | ||||
def save_source(test_request,source_name) | ||||
dir = self.produce_grading_room(test_request) | ||||
submission = test_request.submission | ||||
f = File.open("#{dir}/#{source_name}","w") | ||||
f.write(submission.source) | ||||
f.close | ||||
end | ||||
def clean_up(test_request) | ||||
problem_home = problem_home_dir(test_request) | ||||
remove_data_files(problem_home) | ||||
end | ||||
protected | ||||
def grading_room_dir(test_request) | ||||
problem_name = test_request.problem_name | ||||
user = test_request.user | ||||
|
r55 | grading_room = "#{@config.user_result_dir}" + | ||
|
r23 | "/#{user.login}/test_request" + | ||
"/#{problem_name}/#{test_request.id}" | ||||
|
r55 | grading_room | ||
|
r23 | end | ||
def problem_home_dir(test_request) | ||||
problem_name = test_request.problem_name | ||||
user = test_request.user | ||||
"#{@config.user_result_dir}" + | ||||
"/#{user.login}/test_request/#{problem_name}" | ||||
end | ||||
def copy_problem_template(template_dir,problem_home) | ||||
|
r101 | Grader::call_and_log("Test Request: cannot copy problem template") { | ||
FileUtils.cp_r("#{template_dir}/.","#{problem_home}") | ||||
} | ||||
|
r23 | end | ||
|
r101 | |||
def link_input_file(test_request, problem_home) | ||||
|
r45 | input_fname = "#{test_request.input_file_name}" | ||
if !File.exists?(input_fname) | ||||
raise "Test Request: input file not found." | ||||
end | ||||
input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt" | ||||
if File.exists?(input_fname_problem_home) | ||||
FileUtils.rm([input_fname_problem_home], :force => true) | ||||
end | ||||
|
r101 | Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}") | ||
|
r23 | end | ||
def remove_data_files(problem_home) | ||||
if File.exists?("#{problem_home}/test_cases/1/input-1.txt") | ||||
|
r101 | Grader::call_and_log("Test Request: cannot remove data files") { | ||
FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*") | ||||
} | ||||
|
r23 | end | ||
end | ||||
end | ||||
class TestRequestReporter | ||||
def initialize | ||||
@config = Grader::Configuration.get_instance | ||||
end | ||||
def report(test_request,test_result_dir) | ||||
save_result(test_request,read_result(test_result_dir)) | ||||
end | ||||
def report_error(test_request, msg) | ||||
|
r45 | save_result(test_request, {:running_stat => { | ||
:msg => "#{msg}", | ||||
:running_time => nil, | ||||
:exit_status => "Some error occured. Program did not run", | ||||
:memory_usage => nil | ||||
}}) | ||||
|
r23 | end | ||
protected | ||||
def read_result(test_result_dir) | ||||
# TODO: | ||||
cmp_msg_fname = "#{test_result_dir}/compiler_message" | ||||
cmp_file = File.open(cmp_msg_fname) | ||||
cmp_msg = cmp_file.read | ||||
cmp_file.close | ||||
result_file_name = "#{test_result_dir}/1/result" | ||||
if File.exists?(result_file_name) | ||||
output_file_name = "#{test_result_dir}/1/output.txt" | ||||
|
r112 | results = [] | ||
File.open("#{test_result_dir}/1/result") do |f| | ||||
results = f.readlines | ||||
end | ||||
|
r42 | stat = extract_running_stat(results) | ||
|
r23 | |||
return { | ||||
:output_file_name => output_file_name, | ||||
:running_stat => stat, | ||||
:comment => "", | ||||
:cmp_msg => cmp_msg} | ||||
else | ||||
return { | ||||
|
r41 | :running_stat => nil, | ||
|
r23 | :comment => "Compilation error", | ||
:cmp_msg => cmp_msg} | ||||
end | ||||
end | ||||
|
r42 | def extract_running_stat(results) | ||
running_stat_line = results[-1] | ||||
|
r23 | |||
|
r41 | # extract exit status line | ||
|
r23 | run_stat = "" | ||
if !(/[Cc]orrect/.match(results[0])) | ||||
run_stat = results[0].chomp | ||||
|
r41 | else | ||
run_stat = 'Program exited normally' | ||||
|
r23 | end | ||
|
r41 | # extract running time | ||
|
r42 | if res = /r(.*)u(.*)s/.match(running_stat_line) | ||
|
r23 | seconds = (res[1].to_f + res[2].to_f) | ||
time_stat = "Time used: #{seconds} sec." | ||||
else | ||||
|
r41 | seconds = nil | ||
|
r23 | time_stat = "Time used: n/a sec." | ||
end | ||||
|
r42 | |||
# extract memory usage | ||||
r164 | if res = /s(.*)kbytes/.match(running_stat_line) | |||
|
r42 | memory_used = res[1].to_i | ||
else | ||||
memory_used = -1 | ||||
end | ||||
|
r41 | return { | ||
:msg => "#{run_stat}\n#{time_stat}", | ||||
:running_time => seconds, | ||||
|
r42 | :exit_status => run_stat, | ||
:memory_usage => memory_used | ||||
|
r41 | } | ||
|
r23 | end | ||
def save_result(test_request,result) | ||||
if result[:output_file_name]!=nil | ||||
test_request.output_file_name = link_output_file(test_request, | ||||
result[:output_file_name]) | ||||
end | ||||
test_request.graded_at = Time.now | ||||
test_request.compiler_message = (result[:cmp_msg] or '') | ||||
test_request.grader_comment = (result[:comment] or '') | ||||
|
r41 | if result[:running_stat]!=nil | ||
test_request.running_stat = (result[:running_stat][:msg] or '') | ||||
test_request.running_time = (result[:running_stat][:running_time] or nil) | ||||
|
r42 | test_request.exit_status = result[:running_stat][:exit_status] | ||
test_request.memory_usage = result[:running_stat][:memory_usage] | ||||
|
r41 | else | ||
test_request.running_stat = '' | ||||
end | ||||
|
r23 | test_request.save | ||
end | ||||
protected | ||||
def link_output_file(test_request, fname) | ||||
target_file_name = random_output_file_name(test_request.user, | ||||
test_request.problem) | ||||
FileUtils.mkdir_p(File.dirname(target_file_name)) | ||||
|
r101 | Grader::link_or_copy("#{fname}", "#{target_file_name}") | ||
|
r23 | return target_file_name | ||
end | ||||
def random_output_file_name(user,problem) | ||||
problem_name = TestRequest.name_of(problem) | ||||
begin | ||||
tmpname = "#{@config.test_request_output_base_dir}" + | ||||
"/#{user.login}/#{problem_name}/#{rand(10000)}" | ||||
end while File.exists?(tmpname) | ||||
tmpname | ||||
end | ||||
end | ||||
end | ||||