Show More
Commit Description:
[grader] import script now support raw with testruns...
Commit Description:
[grader] import script now support raw with testruns git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@267 6386c4cd-e34a-4fa8-8920-d93eb39b512e
File last commit:
Show/Diff file:
Action:
lib/test_request_helper.rb | 240 lines | 7.4 KiB | text/x-ruby | RubyLexer |
#
# This part contains various test_request helpers for interfacing
# with Grader::Engine. There are TestRequestRoomMaker and
# TestRequestReporter.
module Grader
#
# 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)
#
# 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.
#
cmd = "cp #{test_request.input_file_name}.files/* #{grading_room}"
system(cmd)
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
grading_room = "#{@config.user_result_dir}" +
"/#{user.login}/test_request" +
"/#{problem_name}/#{test_request.id}"
grading_room
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)
cmd = "cp -R #{template_dir}/* #{problem_home}"
system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
end
def link_input_file(test_request,problem_home)
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
cmd = "ln -s #{input_fname} #{input_fname_problem_home}"
system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
end
def remove_data_files(problem_home)
if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
cmd = "rm #{problem_home}/test_cases/1/*"
system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
end
end
def system_and_raise_when_fail(cmd,msg)
if !system(cmd)
raise msg
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)
save_result(test_request, {:running_stat => {
:msg => "#{msg}",
:running_time => nil,
:exit_status => "Some error occured. Program did not run",
:memory_usage => nil
}})
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"
results = File.open("#{test_result_dir}/1/result").readlines
stat = extract_running_stat(results)
return {
:output_file_name => output_file_name,
:running_stat => stat,
:comment => "",
:cmp_msg => cmp_msg}
else
return {
:running_stat => nil,
:comment => "Compilation error",
:cmp_msg => cmp_msg}
end
end
def extract_running_stat(results)
running_stat_line = results[-1]
# extract exit status line
run_stat = ""
if !(/[Cc]orrect/.match(results[0]))
run_stat = results[0].chomp
else
run_stat = 'Program exited normally'
end
# extract running time
if res = /r(.*)u(.*)s/.match(running_stat_line)
seconds = (res[1].to_f + res[2].to_f)
time_stat = "Time used: #{seconds} sec."
else
seconds = nil
time_stat = "Time used: n/a sec."
end
# extract memory usage
if res = /s(.*)m/.match(running_stat_line)
memory_used = res[1].to_i
else
memory_used = -1
end
return {
:msg => "#{run_stat}\n#{time_stat}",
:running_time => seconds,
:exit_status => run_stat,
:memory_usage => memory_used
}
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 '')
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)
test_request.exit_status = result[:running_stat][:exit_status]
test_request.memory_usage = result[:running_stat][:memory_usage]
else
test_request.running_stat = ''
end
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))
cmd = "ln -s #{fname} #{target_file_name}"
if !system(cmd)
raise "TestRequestReporter: cannot move output file"
end
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