Description:
[grader] report error when the check script crashed (i.e., when the result file is not found, while the compilation is okay) git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@117 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r30:8c0d78da1958 - - 4 files changed: 38 inserted, 19 deleted

@@ -10,86 +10,102
10 problem = submission.problem
10 problem = submission.problem
11 grading_room = "#{@config.user_result_dir}/" +
11 grading_room = "#{@config.user_result_dir}/" +
12 "#{user.login}/#{problem.name}/#{submission.id}"
12 "#{user.login}/#{problem.name}/#{submission.id}"
13
13
14 FileUtils.mkdir_p(grading_room)
14 FileUtils.mkdir_p(grading_room)
15 grading_room
15 grading_room
16 end
16 end
17
17
18 def find_problem_home(submission)
18 def find_problem_home(submission)
19 problem = submission.problem
19 problem = submission.problem
20 "#{@config.problems_dir}/#{problem.name}"
20 "#{@config.problems_dir}/#{problem.name}"
21 end
21 end
22
22
23 def save_source(submission,source_name)
23 def save_source(submission,source_name)
24 dir = self.produce_grading_room(submission)
24 dir = self.produce_grading_room(submission)
25 f = File.open("#{dir}/#{source_name}","w")
25 f = File.open("#{dir}/#{source_name}","w")
26 f.write(submission.source)
26 f.write(submission.source)
27 f.close
27 f.close
28 end
28 end
29
29
30 def clean_up(submission)
30 def clean_up(submission)
31 end
31 end
32 end
32 end
33
33
34 class SubmissionReporter
34 class SubmissionReporter
35 def initialize
35 def initialize
36 @config = Grader::Configuration.get_instance
36 @config = Grader::Configuration.get_instance
37 end
37 end
38
38
39 def report(sub,test_result_dir)
39 def report(sub,test_result_dir)
40 save_result(sub,read_result(test_result_dir))
40 save_result(sub,read_result(test_result_dir))
41 end
41 end
42
42
43 def report_error(sub,msg)
43 def report_error(sub,msg)
44 save_result(sub,{:points => 0,
44 save_result(sub,{:points => 0,
45 :comment => "Grading error: #{msg}" })
45 :comment => "Grading error: #{msg}" })
46 end
46 end
47
47
48 protected
48 protected
49 def read_result(test_result_dir)
49 def read_result(test_result_dir)
50 cmp_msg_fname = "#{test_result_dir}/compiler_message"
50 cmp_msg_fname = "#{test_result_dir}/compiler_message"
51 cmp_file = File.open(cmp_msg_fname)
51 cmp_file = File.open(cmp_msg_fname)
52 cmp_msg = cmp_file.read
52 cmp_msg = cmp_file.read
53 cmp_file.close
53 cmp_file.close
54
54
55 result_fname = "#{test_result_dir}/result"
55 result_fname = "#{test_result_dir}/result"
56 comment_fname = "#{test_result_dir}/comment"
56 comment_fname = "#{test_result_dir}/comment"
57 if FileTest.exist?(result_fname)
57 if FileTest.exist?(result_fname)
58 - result_file = File.open(result_fname)
58 + comment = ""
59 - result = result_file.readline.to_i
59 + begin
60 - result_file.close
60 + result_file = File.open(result_fname)
61 -
61 + result = result_file.readline.to_i
62 - comment_file = File.open(comment_fname)
62 + result_file.close
63 - comment = comment_file.readline.chomp
63 + rescue
64 - comment_file.close
64 + result = 0
65 -
65 + comment = "error reading result file."
66 + end
67 +
68 + begin
69 + comment_file = File.open(comment_fname)
70 + comment += comment_file.readline.chomp
71 + comment_file.close
72 + rescue
73 + comment += ""
74 + end
75 +
66 return {:points => result,
76 return {:points => result,
67 :comment => comment,
77 :comment => comment,
68 :cmp_msg => cmp_msg}
78 :cmp_msg => cmp_msg}
69 else
79 else
70 - return {:points => 0,
80 + if FileTest.exist?("#{test_result_dir}/a.out")
71 - :comment => 'compile error',
81 + return {:points => 0,
72 - :cmp_msg => cmp_msg}
82 + :comment => 'error during grading',
83 + :cmp_msg => cmp_msg}
84 + else
85 + return {:points => 0,
86 + :comment => 'compile error',
87 + :cmp_msg => cmp_msg}
88 + end
73 end
89 end
74 end
90 end
75
91
76 def save_result(submission,result)
92 def save_result(submission,result)
77 problem = submission.problem
93 problem = submission.problem
78 submission.graded_at = Time.now
94 submission.graded_at = Time.now
79 points = result[:points]
95 points = result[:points]
80 submission.points = points
96 submission.points = points
81 comment = @config.report_comment(result[:comment])
97 comment = @config.report_comment(result[:comment])
82 if problem == nil
98 if problem == nil
83 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
99 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
84 elsif points == problem.full_score
100 elsif points == problem.full_score
85 submission.grader_comment = 'PASSED: ' + comment
101 submission.grader_comment = 'PASSED: ' + comment
86 else
102 else
87 submission.grader_comment = 'FAILED: ' + comment
103 submission.grader_comment = 'FAILED: ' + comment
88 end
104 end
89 submission.compiler_message = result[:cmp_msg] or ''
105 submission.compiler_message = result[:cmp_msg] or ''
90 submission.save
106 submission.save
91 end
107 end
92
108
93 end
109 end
94
110
95 end
111 end
@@ -1,80 +1,81
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 def log(str='')
3 def log(str='')
4 if ENV['TALKATIVE']!=nil
4 if ENV['TALKATIVE']!=nil
5 puts str
5 puts str
6 end
6 end
7 if ENV['GRADER_LOGGING']!=nil
7 if ENV['GRADER_LOGGING']!=nil
8 log_fname = ENV['GRADER_LOGGING']
8 log_fname = ENV['GRADER_LOGGING']
9 fp = File.open(log_fname,"a")
9 fp = File.open(log_fname,"a")
10 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
10 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
11 fp.close
11 fp.close
12 end
12 end
13 end
13 end
14
14
15 def char_comment(comment)
15 def char_comment(comment)
16 if comment =~ /[iI]ncorrect/
16 if comment =~ /[iI]ncorrect/
17 '-'
17 '-'
18 elsif comment =~ /[Cc]orrect/
18 elsif comment =~ /[Cc]orrect/
19 'P'
19 'P'
20 elsif comment =~ /[Tt]ime/
20 elsif comment =~ /[Tt]ime/
21 'T'
21 'T'
22 else
22 else
23 'x' # these are run time errors
23 'x' # these are run time errors
24 end
24 end
25 end
25 end
26
26
27 problem_home = ENV['PROBLEM_HOME']
27 problem_home = ENV['PROBLEM_HOME']
28 require "#{problem_home}/script/test_dsl.rb"
28 require "#{problem_home}/script/test_dsl.rb"
29 load "#{problem_home}/test_cases/all_tests.cfg"
29 load "#{problem_home}/test_cases/all_tests.cfg"
30 problem = Problem.get_instance
30 problem = Problem.get_instance
31
31
32 if problem.well_formed? == false
32 if problem.well_formed? == false
33 log "The problem specification is not well formed."
33 log "The problem specification is not well formed."
34 exit(127)
34 exit(127)
35 end
35 end
36
36
37 all_score = 0
37 all_score = 0
38 all_comment = ''
38 all_comment = ''
39 (1..(problem.runs.length-1)).each do |k|
39 (1..(problem.runs.length-1)).each do |k|
40 log "grade run #{k}"
40 log "grade run #{k}"
41 run = problem.runs[k]
41 run = problem.runs[k]
42 run_score = 0
42 run_score = 0
43 run_comment = ''
43 run_comment = ''
44 run_comment_short = ''
44 run_comment_short = ''
45 run.tests.each do |test_num|
45 run.tests.each do |test_num|
46 result_file_name = "#{test_num}/result"
46 result_file_name = "#{test_num}/result"
47 if not File.exists?(result_file_name)
47 if not File.exists?(result_file_name)
48 + run_comment += "result file for test #{test_num} not found\n"
49 + run_comment_short += 'x'
48 log "Cannot find the file #{test_num}/result!"
50 log "Cannot find the file #{test_num}/result!"
49 - exit(127)
51 + else
52 + result_file = File.new(result_file_name, "r")
53 + result_file_lines = result_file.readlines
54 + run_score = run_score + result_file_lines[1].to_i
55 + run_comment += result_file_lines[0]
56 + run_comment_short += char_comment(result_file_lines[0])
57 + result_file.close
50 end
58 end
51 -
52 - result_file = File.new(result_file_name, "r")
53 - result_file_lines = result_file.readlines
54 - run_score = run_score + result_file_lines[1].to_i
55 - run_comment += result_file_lines[0]
56 - run_comment_short += char_comment(result_file_lines[0])
57 - result_file.close
58 end
59 end
59
60
60 run_result_file = File.new("result-#{k}", "w")
61 run_result_file = File.new("result-#{k}", "w")
61 run_result_file.write run_score
62 run_result_file.write run_score
62 run_result_file.write "\n"
63 run_result_file.write "\n"
63 run_result_file.close
64 run_result_file.close
64
65
65 run_comment_file = File.new("comment-#{k}", "w")
66 run_comment_file = File.new("comment-#{k}", "w")
66 run_comment_file.write "#{run_comment}\n"
67 run_comment_file.write "#{run_comment}\n"
67 run_comment_file.close
68 run_comment_file.close
68
69
69 all_score = all_score + run_score
70 all_score = all_score + run_score
70 all_comment += run_comment_short
71 all_comment += run_comment_short
71 end
72 end
72
73
73 result_file = File.new("result", "w")
74 result_file = File.new("result", "w")
74 result_file.write all_score
75 result_file.write all_score
75 result_file.write "\n"
76 result_file.write "\n"
76 result_file.close
77 result_file.close
77
78
78 comment_file = File.new("comment", "w")
79 comment_file = File.new("comment", "w")
79 comment_file.write "#{all_comment}\n"
80 comment_file.write "#{all_comment}\n"
80 comment_file.close
81 comment_file.close
@@ -1,66 +1,67
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 def log(str='')
3 def log(str='')
4 if ENV['TALKATIVE']!=nil
4 if ENV['TALKATIVE']!=nil
5 puts str
5 puts str
6 end
6 end
7 if ENV['GRADER_LOGGING']!=nil
7 if ENV['GRADER_LOGGING']!=nil
8 log_fname = ENV['GRADER_LOGGING']
8 log_fname = ENV['GRADER_LOGGING']
9 fp = File.open(log_fname,"a")
9 fp = File.open(log_fname,"a")
10 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
10 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
11 fp.close
11 fp.close
12 end
12 end
13 end
13 end
14
14
15 problem_home = ENV['PROBLEM_HOME']
15 problem_home = ENV['PROBLEM_HOME']
16
16
17 def execute(command, error_message="")
17 def execute(command, error_message="")
18 if not system(command)
18 if not system(command)
19 + log "ERROR: #{error_message}"
19 puts "ERROR: #{error_message}"
20 puts "ERROR: #{error_message}"
20 exit(127)
21 exit(127)
21 end
22 end
22 end
23 end
23
24
24 # ARGV[0] --- language
25 # ARGV[0] --- language
25 # ARGV[1] --- program source file
26 # ARGV[1] --- program source file
26 # ARGV[2] --- test result directory
27 # ARGV[2] --- test result directory
27 # ARGV[3] --- sandbox directory
28 # ARGV[3] --- sandbox directory
28
29
29 if ARGV.length < 2 || ARGV.length > 4
30 if ARGV.length < 2 || ARGV.length > 4
30 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
31 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
31 puts " <sandbox-directory> is defaulted to ./sandbox"
32 puts " <sandbox-directory> is defaulted to ./sandbox"
32 puts " <test-result-directory> is defaulted to ./test-result"
33 puts " <test-result-directory> is defaulted to ./test-result"
33 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
34 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
34 exit(127)
35 exit(127)
35 end
36 end
36
37
37 language = ARGV[0]
38 language = ARGV[0]
38 if language != "c" && language != "c++" && language != "pascal"
39 if language != "c" && language != "c++" && language != "pascal"
39 log "You specified a language that is not supported."
40 log "You specified a language that is not supported."
40 exit(127)
41 exit(127)
41 end
42 end
42
43
43 source_file = ARGV[1]
44 source_file = ARGV[1]
44 if File.exist?(source_file) == false
45 if File.exist?(source_file) == false
45 log "The source file does not exist."
46 log "The source file does not exist."
46 exit(127)
47 exit(127)
47 end
48 end
48
49
49 log "Making test result and sandbox directories..."
50 log "Making test result and sandbox directories..."
50
51
51 current_dir = `pwd`
52 current_dir = `pwd`
52 current_dir.strip!
53 current_dir.strip!
53
54
54 if ARGV.length >= 3
55 if ARGV.length >= 3
55 test_result_dir = ARGV[2]
56 test_result_dir = ARGV[2]
56 else
57 else
57 test_result_dir = "#{current_dir}/test-result"
58 test_result_dir = "#{current_dir}/test-result"
58 end
59 end
59 log "Test result directory: #{test_result_dir}"
60 log "Test result directory: #{test_result_dir}"
60 system("rm -Rf #{test_result_dir}")
61 system("rm -Rf #{test_result_dir}")
61 execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
62 execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
62
63
63 if ARGV.length >= 4
64 if ARGV.length >= 4
64 sandbox_dir = ARGV[3]
65 sandbox_dir = ARGV[3]
65 else
66 else
66 sandbox_dir = "#{current_dir}/sandbox"
67 sandbox_dir = "#{current_dir}/sandbox"
@@ -87,55 +87,56
87 result_file = File.new("result", "w")
87 result_file = File.new("result", "w")
88 comment_file = File.new("comment", "w")
88 comment_file = File.new("comment", "w")
89
89
90 # Check if the program actually produced any output.
90 # Check if the program actually produced any output.
91 run_result_file = File.new("run_result", "r")
91 run_result_file = File.new("run_result", "r")
92 run_result = run_result_file.readlines
92 run_result = run_result_file.readlines
93 run_result_file.close
93 run_result_file.close
94 time_elapsed = run_result[run_result.length-1]
94 time_elapsed = run_result[run_result.length-1]
95 running_time = extract_time(time_elapsed)
95 running_time = extract_time(time_elapsed)
96
96
97 report = lambda{ |status, points, comment|
97 report = lambda{ |status, points, comment|
98 result_file.write status.strip
98 result_file.write status.strip
99 result_file.write "\n"
99 result_file.write "\n"
100 result_file.write points.to_s.strip
100 result_file.write points.to_s.strip
101 result_file.write "\n"
101 result_file.write "\n"
102 result_file.write time_elapsed.strip
102 result_file.write time_elapsed.strip
103 result_file.write "\n"
103 result_file.write "\n"
104 result_file.close
104 result_file.close
105 `rm run_result`
105 `rm run_result`
106 # `rm output.txt` --- keep the output
106 # `rm output.txt` --- keep the output
107
107
108 comment_file.write comment
108 comment_file.write comment
109 comment_file.write "--run-result--\n"
109 comment_file.write "--run-result--\n"
110 run_result.each do |l|
110 run_result.each do |l|
111 comment_file.write l
111 comment_file.write l
112 end
112 end
113 comment_file.close
113 comment_file.close
114
114
115 log "Done!"
115 log "Done!"
116 exit(0)
116 exit(0)
117 }
117 }
118
118
119 if run_result[0][0,2] != "OK"
119 if run_result[0][0,2] != "OK"
120 log "There was a runtime error."
120 log "There was a runtime error."
121 report.call(run_result[0], 0, "No comment.\n")
121 report.call(run_result[0], 0, "No comment.\n")
122 end
122 end
123
123
124 if running_time[:user].to_f + running_time[:sys].to_f > time_limit
124 if running_time[:user].to_f + running_time[:sys].to_f > time_limit
125 log "Time limit exceeded."
125 log "Time limit exceeded."
126 report.call("Time limit exceeded", 0, "No comment.\n")
126 report.call("Time limit exceeded", 0, "No comment.\n")
127 end
127 end
128
128
129 # Run 'check' to evaluate the output.
129 # Run 'check' to evaluate the output.
130 #puts "There was no runtime error. Proceed to checking the output."
130 #puts "There was no runtime error. Proceed to checking the output."
131 check_command = "#{problem_home}/script/check #{language} #{test_num}"
131 check_command = "#{problem_home}/script/check #{language} #{test_num}"
132 log "Checking the output..."
132 log "Checking the output..."
133 log check_command
133 log check_command
134 if not system(check_command)
134 if not system(check_command)
135 + log "Problem with check script"
135 exit(127)
136 exit(127)
136 end
137 end
137
138
138 check_file = File.new("check_result", "r")
139 check_file = File.new("check_result", "r")
139 check_file_lines = check_file.readlines
140 check_file_lines = check_file.readlines
140
141
141 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
142 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
You need to be logged in to leave comments. Login now