Description:
merge from algo-bm
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r173:aa6e7ff3942c - - 9 files changed: 124 inserted, 34 deleted

@@ -43,17 +43,28
43 end
43 end
44
44
45 def display_manual
45 def display_manual
46 puts <<USAGE
46 puts <<USAGE
47 Grader.
47 Grader.
48 using: (1) grader
48 using: (1) grader
49 - (2) grader environment [mode]
49 + (2) grader environment [mode] [options]
50 (3) grader stop [all|pids-list]
50 (3) grader stop [all|pids-list]
51 (4) grader --help
51 (4) grader --help
52 (1) call grader with environment = 'exam', mode = 'queue'
52 (1) call grader with environment = 'exam', mode = 'queue'
53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
54 + queue: repeatedly check the task queue and grade any available tasks
55 +
56 + prob: re-grade every user latest submission of the specific problem.
57 + the problem name must be specified by the next argument.
58 +
59 + additional options:
60 +
61 + --all-sub re-grade every submissions instead of just the latest submission of each user.
62 + sub: re-grader the specified submission.
63 + The submission ID to be re-graded must be specified by the next argument.
64 +
54 (3) create stop-file to stop running grader in queue mode
65 (3) create stop-file to stop running grader in queue mode
55 (4) You are here.
66 (4) You are here.
56 USAGE
67 USAGE
57 end
68 end
58
69
59 def process_options_and_stop_file
70 def process_options_and_stop_file
@@ -102,12 +113,14
102 # Process mode and environment option
113 # Process mode and environment option
103 if ARGV.length >= 1
114 if ARGV.length >= 1
104 options[:environment] = ARGV.shift
115 options[:environment] = ARGV.shift
105 if ARGV.length >=1
116 if ARGV.length >=1
106 options[:mode] = ARGV.shift
117 options[:mode] = ARGV.shift
107 end
118 end
119 + else
120 + puts 'no argument specified, using default mode and environment.'
108 end
121 end
109
122
110 options[:dry_run] = (ARGV.delete('--dry') != nil)
123 options[:dry_run] = (ARGV.delete('--dry') != nil)
111 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
124 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
112 puts "Dry run currently works only for 'prob' or 'contest' modes."
125 puts "Dry run currently works only for 'prob' or 'contest' modes."
113 exit(0)
126 exit(0)
@@ -116,12 +129,14
116 options[:report] = (ARGV.delete('--report') != nil)
129 options[:report] = (ARGV.delete('--report') != nil)
117 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
130 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
118 puts "Report currently works only for 'prob' or 'contest' modes."
131 puts "Report currently works only for 'prob' or 'contest' modes."
119 exit(0)
132 exit(0)
120 end
133 end
121
134
135 + options[:all_sub] = (ARGV.delete('--all-sub') != nil)
136 +
122 return options
137 return options
123 end
138 end
124
139
125 class ResultCollector
140 class ResultCollector
126 def initialize
141 def initialize
127 @results = {}
142 @results = {}
@@ -292,13 +307,13
292
307
293 ARGV.each do |prob_name|
308 ARGV.each do |prob_name|
294 prob = Problem.find_by_name(prob_name)
309 prob = Problem.find_by_name(prob_name)
295 if prob==nil
310 if prob==nil
296 puts "cannot find problem: #{prob_name}"
311 puts "cannot find problem: #{prob_name}"
297 else
312 else
298 - runner.grade_problem(prob)
313 + runner.grade_problem(prob,options)
299 end
314 end
300 end
315 end
301
316
302 if options[:report]
317 if options[:report]
303 result_collector.print_report_by_user
318 result_collector.print_report_by_user
304 end
319 end
@@ -375,12 +390,13
375 options = process_options_and_stop_file
390 options = process_options_and_stop_file
376 GRADER_ENV = options[:environment]
391 GRADER_ENV = options[:environment]
377 grader_mode = options[:mode]
392 grader_mode = options[:mode]
378 dry_run = options[:dry_run]
393 dry_run = options[:dry_run]
379
394
380 puts "environment: #{GRADER_ENV}"
395 puts "environment: #{GRADER_ENV}"
396 + puts "grader mode: #{grader_mode}"
381 require File.join(File.dirname(__FILE__),'config/environment')
397 require File.join(File.dirname(__FILE__),'config/environment')
382
398
383 # add grader_mode to config
399 # add grader_mode to config
384 # this is needed because method log needs it. TODO: clean this up
400 # this is needed because method log needs it. TODO: clean this up
385 class << config
401 class << config
386 attr_accessor :grader_mode
402 attr_accessor :grader_mode
@@ -22,22 +22,27
22 @grader_process.report_inactive(task) if @grader_process!=nil
22 @grader_process.report_inactive(task) if @grader_process!=nil
23 end
23 end
24 return task
24 return task
25 end
25 end
26
26
27 def grade_problem(problem, options={})
27 def grade_problem(problem, options={})
28 - users = User.find(:all)
28 + User.find_each do |u|
29 - users.each do |u|
30 puts "user: #{u.login}"
29 puts "user: #{u.login}"
31 if options[:user_conditions]!=nil
30 if options[:user_conditions]!=nil
32 con_proc = options[:user_conditions]
31 con_proc = options[:user_conditions]
33 next if not con_proc.call(u)
32 next if not con_proc.call(u)
34 end
33 end
35 - last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
34 + if options[:all_sub]
36 - if last_sub!=nil
35 + Submission.where(user_id: u.id,problem_id: problem.id).find_each do |sub|
37 - @engine.grade(last_sub)
36 + @engine.grade(sub)
37 + end
38 + else
39 + last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
40 + if last_sub!=nil
41 + @engine.grade(last_sub)
42 + end
38 end
43 end
39 end
44 end
40 end
45 end
41
46
42 def grade_submission(submission)
47 def grade_submission(submission)
43 puts "Submission: #{submission.id} by #{submission.user.full_name}"
48 puts "Submission: #{submission.id} by #{submission.user.full_name}"
@@ -62,13 +62,14
62 cmp_file.close
62 cmp_file.close
63 else
63 else
64 cmp_msg = ""
64 cmp_msg = ""
65 end
65 end
66
66
67 result_fname = "#{test_result_dir}/result"
67 result_fname = "#{test_result_dir}/result"
68 - comment_fname = "#{test_result_dir}/comment"
68 + comment_fname = "#{test_result_dir}/comment"
69 + runstat_fname = "#{test_result_dir}/run_stat"
69 if FileTest.exist?(result_fname)
70 if FileTest.exist?(result_fname)
70 comment = ""
71 comment = ""
71 begin
72 begin
72 result_file = File.open(result_fname)
73 result_file = File.open(result_fname)
73 result = result_file.readline.to_i
74 result = result_file.readline.to_i
74 result_file.close
75 result_file.close
@@ -82,15 +83,28
82 comment += comment_file.readline.chomp
83 comment += comment_file.readline.chomp
83 comment_file.close
84 comment_file.close
84 rescue
85 rescue
85 comment += ""
86 comment += ""
86 end
87 end
87
88
88 - return {:points => result,
89 + begin
89 - :comment => comment,
90 + runstat_file = File.open(runstat_fname)
90 - :cmp_msg => cmp_msg}
91 + max_runtime = runstat_file.readline.to_f
92 + peak_memory = runstat_file.readline.to_i
93 + rescue
94 + max_runtime = -1
95 + peak_memory = -1
96 + end
97 +
98 +
99 + return {points: result,
100 + comment: comment,
101 + cmp_msg: cmp_msg,
102 + max_runtime: max_runtime,
103 + peak_memory: peak_memory
104 + }
91 else
105 else
92 if FileTest.exist?("#{test_result_dir}/a.out")
106 if FileTest.exist?("#{test_result_dir}/a.out")
93 return {:points => 0,
107 return {:points => 0,
94 :comment => 'error during grading',
108 :comment => 'error during grading',
95 :cmp_msg => cmp_msg}
109 :cmp_msg => cmp_msg}
96 else
110 else
@@ -105,12 +119,16
105 problem = submission.problem
119 problem = submission.problem
106 submission.graded_at = Time.now.gmtime
120 submission.graded_at = Time.now.gmtime
107 points = result[:points]
121 points = result[:points]
108 submission.points = points
122 submission.points = points
109 comment = @config.report_comment(result[:comment])
123 comment = @config.report_comment(result[:comment])
110
124
125 + submission.peak_memory = result[:peak_memory]
126 + submission.max_runtime = result[:max_runtime]
127 + submission.effective_code_length =submission.source.length
128 +
111 #
129 #
112 # TODO: FIX THIS MESSAGE
130 # TODO: FIX THIS MESSAGE
113 #
131 #
114 if problem == nil
132 if problem == nil
115 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
133 submission.grader_comment = 'PASSED: ' + comment + '(problem is nil)'
116 elsif points == problem.full_score
134 elsif points == problem.full_score
@@ -195,13 +195,13
195 else
195 else
196 seconds = nil
196 seconds = nil
197 time_stat = "Time used: n/a sec."
197 time_stat = "Time used: n/a sec."
198 end
198 end
199
199
200 # extract memory usage
200 # extract memory usage
201 - if res = /s(.*)m/.match(running_stat_line)
201 + if res = /s(.*)kbytes/.match(running_stat_line)
202 memory_used = res[1].to_i
202 memory_used = res[1].to_i
203 else
203 else
204 memory_used = -1
204 memory_used = -1
205 end
205 end
206
206
207 return {
207 return {
@@ -157,13 +157,13
157 double system_time,
157 double system_time,
158 int mem_usage)
158 int mem_usage)
159 {
159 {
160 //total is user
160 //total is user
161 //wall is wall
161 //wall is wall
162 //
162 //
163 - fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dm\n",
163 + fprintf(stderr,"%.4lfr%.4lfu%.4lfs%dkbytes\n",
164 wall_time, user_time, system_time, mem_usage);
164 wall_time, user_time, system_time, mem_usage);
165 }
165 }
166
166
167 static void
167 static void
168 final_stats(struct rusage *rus)
168 final_stats(struct rusage *rus)
169 {
169 {
@@ -206,13 +206,13
206 }
206 }
207 }
207 }
208 print_running_stat(
208 print_running_stat(
209 (double)wall_ms/1000,
209 (double)wall_ms/1000,
210 (double)total_ms/1000,
210 (double)total_ms/1000,
211 (double)sys_ms/1000,
211 (double)sys_ms/1000,
212 - (mem_peak_kb + 1023) / 1024);
212 + mem_peak_kb);
213 meta_close();
213 meta_close();
214 exit(rc);
214 exit(rc);
215 }
215 }
216
216
217 static void
217 static void
218 flush_line(void)
218 flush_line(void)
@@ -1453,17 +1453,12
1453 if (timeout && total_ms > timeout)
1453 if (timeout && total_ms > timeout)
1454 err("TO: Time limit exceeded");
1454 err("TO: Time limit exceeded");
1455 if (wall_timeout && wall_ms > wall_timeout)
1455 if (wall_timeout && wall_ms > wall_timeout)
1456 err("TO: Time limit exceeded (wall clock)");
1456 err("TO: Time limit exceeded (wall clock)");
1457 flush_line();
1457 flush_line();
1458 fprintf(stderr,"OK\n");
1458 fprintf(stderr,"OK\n");
1459 - print_running_stat(
1460 - (double)wall_ms/1000,
1461 - (double)total_ms/1000,
1462 - (double)sys_ms/1000,
1463 - (mem_peak_kb + 1023) / 1024);
1464 box_exit(0);
1459 box_exit(0);
1465 }
1460 }
1466 if (WIFSIGNALED(stat))
1461 if (WIFSIGNALED(stat))
1467 {
1462 {
1468 box_pid = 0;
1463 box_pid = 0;
1469 meta_printf("exitsig:%d\n", WTERMSIG(stat));
1464 meta_printf("exitsig:%d\n", WTERMSIG(stat));
@@ -27,18 +27,20
27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
28 PASCAL_COMPILER = "/usr/bin/fpc"
28 PASCAL_COMPILER = "/usr/bin/fpc"
29 JAVA_COMPILER = "/usr/bin/javac"
29 JAVA_COMPILER = "/usr/bin/javac"
30 RUBY_INTERPRETER = "/usr/bin/ruby"
30 RUBY_INTERPRETER = "/usr/bin/ruby"
31 PYTHON_INTERPRETER = "/usr/bin/python"
31 PYTHON_INTERPRETER = "/usr/bin/python"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
33 + PHP_INTERPRETER = "/usr/bin/php"
33
34
34 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
35 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
35 - CPLUSPLUS_OPTIONS = "-O2 -s -static -DCONTEST -lm -Wall"
36 + CPLUSPLUS_OPTIONS = "-O2 -s -std=c++11 -static -DCONTEST -lm -Wall"
36 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
37 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
37 JAVA_OPTIONS = ""
38 JAVA_OPTIONS = ""
38 PYTHON_OPTIONS = ""
39 PYTHON_OPTIONS = ""
40 + PHP_OPTIONS = "-l"
39
41
40 # Check for the correct number of arguments. Otherwise, print usage.
42 # Check for the correct number of arguments. Otherwise, print usage.
41 if ARGV.length == 0 or ARGV.length > 4
43 if ARGV.length == 0 or ARGV.length > 4
42 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
44 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
43 puts
45 puts
44 puts "<source-file> is defaulted to \"source\"."
46 puts "<source-file> is defaulted to \"source\"."
@@ -105,17 +107,24
105
107
106 when "java"
108 when "java"
107 #rename the file to the public class name
109 #rename the file to the public class name
108
110
109 #get the class name
111 #get the class name
110 classname = 'DUMMY'
112 classname = 'DUMMY'
113 + source = Array.new
111 File.foreach(params[:source_file]) do |line|
114 File.foreach(params[:source_file]) do |line|
112 md = /\s*public\s*class\s*(\w*)/.match(line)
115 md = /\s*public\s*class\s*(\w*)/.match(line)
113 classname=md[1] if md
116 classname=md[1] if md
117 + source << line unless line =~ /\s*package\s*\w+\s*\;/
114 end
118 end
115 - system("cp #{params[:source_file]} #{classname}.java")
119 + File.open("#{classname}.java","w") do |file|
120 + source.each do |s|
121 + file.puts s
122 + end
123 + end
124 + #system("cp #{params[:source_file]} #{classname}.java")
116 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
125 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
117 system(command)
126 system(command)
118 if File.exists?(classname + ".class")
127 if File.exists?(classname + ".class")
119 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
128 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
120 end
129 end
121 if classname == 'DUMMY'
130 if classname == 'DUMMY'
@@ -144,14 +153,27
144 puts "pwd: " + Dir.pwd
153 puts "pwd: " + Dir.pwd
145 Dir.new('.').each {|file| puts file}
154 Dir.new('.').each {|file| puts file}
146 File.open(params[:output_file],"w") do |out_file|
155 File.open(params[:output_file],"w") do |out_file|
147 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
156 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
148 end
157 end
149 File.chmod(0755, params[:output_file])
158 File.chmod(0755, params[:output_file])
159 + FileUtils.cp("#{params[:source_file]}c",params[:output_file])
150 end
160 end
151 -
161 +
162 + when "php"
163 + command = "#{PHP_INTERPRETER} #{PHP_OPTIONS} #{params[:source_file]} 2> #{params[:message_file]}"
164 + if system(command)
165 + File.open(params[:output_file],"w") do |out_file|
166 + out_file.puts "#!#{PHP_INTERPRETER}"
167 + File.open(params[:source_file],"r").each do |line|
168 + out_file.print line
169 + end
170 + end
171 + File.chmod(0755, params[:output_file])
172 + end
173 +
152 else
174 else
153 talk("ERROR: Invalid language specified!")
175 talk("ERROR: Invalid language specified!")
154 open(params[:message_file],"w") do |f|
176 open(params[:message_file],"w") do |f|
155 f.puts "ERROR: Invalid language specified!"
177 f.puts "ERROR: Invalid language specified!"
156 end
178 end
157 exit(127)
179 exit(127)
@@ -28,24 +28,37
28 res[1]
28 res[1]
29 else
29 else
30 RUN_ERROR_MARK # these are run time errors
30 RUN_ERROR_MARK # these are run time errors
31 end
31 end
32 end
32 end
33
33
34 + def extract_time(t)
35 + #puts "TIME: #{t}"
36 + if (result=/^(.*)r(.*)u(.*)s(.*)kbytes/.match(t))
37 + {:real => result[1], :user => result[2], :sys => result[3], :mem => result[4]}
38 + else
39 + #{:real => 0, :user => 0, :sys => 0}
40 + #puts "ERROR READING RUNNING TIME: #{t}"
41 + raise "Error reading running time: #{t}"
42 + end
43 + end
44 +
34 problem_home = ENV['PROBLEM_HOME']
45 problem_home = ENV['PROBLEM_HOME']
35 require "#{problem_home}/script/test_dsl.rb"
46 require "#{problem_home}/script/test_dsl.rb"
36 load "#{problem_home}/test_cases/all_tests.cfg"
47 load "#{problem_home}/test_cases/all_tests.cfg"
37 problem = Problem.get_instance
48 problem = Problem.get_instance
38
49
39 if problem.well_formed? == false
50 if problem.well_formed? == false
40 log "The problem specification is not well formed."
51 log "The problem specification is not well formed."
41 exit(127)
52 exit(127)
42 end
53 end
43
54
44 all_score = 0
55 all_score = 0
45 all_comment = ''
56 all_comment = ''
57 + peak_memory = -1
58 + max_runtime = -1
46 (1..(problem.runs.length-1)).each do |k|
59 (1..(problem.runs.length-1)).each do |k|
47 log "grade run #{k}"
60 log "grade run #{k}"
48 run = problem.runs[k]
61 run = problem.runs[k]
49 run_score = nil
62 run_score = nil
50 run_comment = ''
63 run_comment = ''
51 run_comment_short = ''
64 run_comment_short = ''
@@ -55,16 +68,21
55 run_comment += "result file for test #{test_num} not found\n"
68 run_comment += "result file for test #{test_num} not found\n"
56 run_comment_short += RUN_ERROR_MARK
69 run_comment_short += RUN_ERROR_MARK
57 log "Cannot find the file #{test_num}/result!"
70 log "Cannot find the file #{test_num}/result!"
58 else
71 else
59 result_file = File.new(result_file_name, "r")
72 result_file = File.new(result_file_name, "r")
60 result_file_lines = result_file.readlines
73 result_file_lines = result_file.readlines
61 - if result_file_lines.length>=2
74 + if result_file_lines.length>=3
62 current_run_score = result_file_lines[1].to_i
75 current_run_score = result_file_lines[1].to_i
63 run_comment += result_file_lines[0]
76 run_comment += result_file_lines[0]
64 run_comment_short += char_comment(result_file_lines[0].chomp)
77 run_comment_short += char_comment(result_file_lines[0].chomp)
78 +
79 + #update max runtime & memory
80 + run_stat = extract_time result_file_lines[2]
81 + peak_memory = [peak_memory,run_stat[:mem].to_i].max
82 + max_runtime = [max_runtime,run_stat[:user].to_f + run_stat[:sys].to_f].max
65 else
83 else
66 current_run_score = 0
84 current_run_score = 0
67 run_comment += "result file for test #{test_num} error\n"
85 run_comment += "result file for test #{test_num} error\n"
68 run_comment_short += RUN_ERROR_MARK
86 run_comment_short += RUN_ERROR_MARK
69 log "Error in #{test_num}/result!"
87 log "Error in #{test_num}/result!"
70 end
88 end
@@ -102,7 +120,14
102 result_file.close
120 result_file.close
103
121
104 comment_file = File.new("comment", "w")
122 comment_file = File.new("comment", "w")
105 comment_file.write "#{all_comment}\n"
123 comment_file.write "#{all_comment}\n"
106 comment_file.close
124 comment_file.close
107
125
108 - log "score = #{all_score} comment = #{all_comment}"
126 +
127 + File.open("run_stat","w") do |file|
128 + file.puts max_runtime
129 + file.puts peak_memory
130 + end
131 +
132 + log "score = #{all_score}\ncomment = #{all_comment}"
133 + log "max_runtime = #{max_runtime}\npeak_memory = #{peak_memory}"
@@ -50,18 +50,19
50 puts " <test-result-directory> is defaulted to ./test-result"
50 puts " <test-result-directory> is defaulted to ./test-result"
51 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
51 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
52 exit(127)
52 exit(127)
53 end
53 end
54
54
55 language = ARGV[0]
55 language = ARGV[0]
56 - if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python"
56 + if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python" && language != "php"
57 log "You specified a language that is not supported: #{language}."
57 log "You specified a language that is not supported: #{language}."
58 exit(127)
58 exit(127)
59 end
59 end
60
60
61 source_file = ARGV[1]
61 source_file = ARGV[1]
62 + ENV['SOURCE_NAME'] = source_file
62 if File.exist?(source_file) == false
63 if File.exist?(source_file) == false
63 log "The source file does not exist."
64 log "The source file does not exist."
64 exit(127)
65 exit(127)
65 end
66 end
66
67
67 log "Making test result and sandbox directories..."
68 log "Making test result and sandbox directories..."
@@ -137,13 +138,13
137 FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir, :preserve => true)
138 FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir, :preserve => true)
138 if language == "java" then Dir["#{test_result_dir}/*.class"].each { |file| FileUtils.cp(file,sandbox_dir)} end
139 if language == "java" then Dir["#{test_result_dir}/*.class"].each { |file| FileUtils.cp(file,sandbox_dir)} end
139 if language == "python" then Dir["#{test_result_dir}/*.pyc"].each { |file| FileUtils.cp(file,sandbox_dir)} end
140 if language == "python" then Dir["#{test_result_dir}/*.pyc"].each { |file| FileUtils.cp(file,sandbox_dir)} end
140 }
141 }
141
142
142 begin
143 begin
143 - execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
144 + execute("#{problem_home}/script/run #{language} #{test_num} ", "Error occured during execution of the run script")
144 rescue
145 rescue
145 # do nothing
146 # do nothing
146 end
147 end
147
148
148 call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
149 call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
149 FileUtils.mkdir "#{test_result_dir}/#{test_num}"
150 FileUtils.mkdir "#{test_result_dir}/#{test_num}"
@@ -40,16 +40,19
40 program_name = ARGV[2]
40 program_name = ARGV[2]
41 else
41 else
42 program_name = "a.out"
42 program_name = "a.out"
43 end
43 end
44
44
45 problem_home = ENV['PROBLEM_HOME']
45 problem_home = ENV['PROBLEM_HOME']
46 + source_name = ENV['SOURCE_NAME']
46 require "#{problem_home}/script/test_dsl.rb"
47 require "#{problem_home}/script/test_dsl.rb"
47 load "#{problem_home}/test_cases/all_tests.cfg"
48 load "#{problem_home}/test_cases/all_tests.cfg"
48 problem = Problem.get_instance
49 problem = Problem.get_instance
49
50
51 + sandbox_dir = Dir.getwd
52 +
50 if problem.well_formed? == false
53 if problem.well_formed? == false
51 log "The problem specification is not well formed."
54 log "The problem specification is not well formed."
52 exit(127)
55 exit(127)
53 end
56 end
54
57
55 # Check if the test number is okay.
58 # Check if the test number is okay.
@@ -78,43 +81,47
78 compile_box("#{problem_home}/script/box.cc",
81 compile_box("#{problem_home}/script/box.cc",
79 "#{problem_home}/script/box")
82 "#{problem_home}/script/box")
80 end
83 end
81
84
82 # Hide PROBLEM_HOME
85 # Hide PROBLEM_HOME
83 ENV['PROBLEM_HOME'] = nil
86 ENV['PROBLEM_HOME'] = nil
87 + ENV['SOURCE_NAME'] = nil
84
88
85 # Run the program.
89 # Run the program.
86 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
90 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
87 #
91 #
88
92
89 -
93 + JAVA_OPTION = "-s set_robust_list -s futex -s clone -s getppid -s clone -s wait4 -p /usr/bin/ -p ./"
90 -
94 + RUBY_OPTION = "-p /usr/lib64/ -p /usr/local/lib64/ -p /usr/local/lib/ -p /lib64/ -p /dev/urandom -p #{sandbox_dir}/#{program_name} -p #{sandbox_dir}/ -s set_robust_list -s sched_getaffinity -s clock_gettime -s sigaltstack -s pipe2 -s clone -s futex -s openat -s pipe"
95 + PYTHON_OPTION = "-p /usr/lib64/ -p /usr/local/lib64/ -p /usr/local/lib/ -p /usr/bin/ -p /lib64/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p #{sandbox_dir}/#{source_name} -s set_robust_list -s openat -s recvmsg -s connect -s socket -s sendto -s futex -E PYTHONNOUSERSITE=yes"
96 + PHP_OPTION = "-p /usr/lib64/ -p/lib64/ -p /usr/bin/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p /usr/share/ -s setfsuid -s setfsgid -s openat -s set_robust_list -s futex -s clone -s socket -s connect"
91
97
92 case language
98 case language
93 when "java"
99 when "java"
94 -
95 # for java, extract the classname
100 # for java, extract the classname
96 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
101 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
97 classname = 'DUMMY'
102 classname = 'DUMMY'
98 File.open(program_name,"r").each do |line|
103 File.open(program_name,"r").each do |line|
99 classname = line
104 classname = line
100 end
105 end
101 - run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s clone -s wait4 -p /usr/bin/ -p ./ -i #{input_file_name} -o output.txt /usr/bin/java #{classname} 2>run_result"
106 + #for java, we cannot really check the memory limit...
107 + run_command = "#{problem_home}/script/box -a 3 -f -T -t #{time_limit} #{JAVA_OPTION} -i #{input_file_name} -o output.txt /usr/bin/java #{classname} 2>run_result"
102 when "ruby"
108 when "ruby"
103 - run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s wait4 -s clone -s set_robust_list -s futex -s sigaltstack -p /dev/urandom -p ./ -p /home/dae/.rvm/rubies/ruby-1.9.2-p320/ -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
109 + run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{mem_limit} #{RUBY_OPTION} -i #{input_file_name} -o output.txt /usr/bin/ruby #{program_name} 2>run_result"
104 when "python"
110 when "python"
105 - #this code just run without any checking
111 + run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{mem_limit} #{PYTHON_OPTION} -i #{input_file_name} -o output.txt /usr/bin/python #{program_name} 2>run_result"
106 - run_command = "#{problem_home}/script/box -T -t #{time_limit} -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
112 + when "php"
113 + run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} #{PHP_OPTION} -i #{input_file_name} -o output.txt /usr/bin/php #{program_name} 2>run_result"
107 else # for c++, pascal, we do the normal checking
114 else # for c++, pascal, we do the normal checking
108 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
115 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
109 end
116 end
110
117
111
118
112 log "Running test #{test_num}..."
119 log "Running test #{test_num}..."
113 log run_command
120 log run_command
114 - log
121 + log
115 system(run_command)
122 system(run_command)
116
123
117 # Restore PROBLEM_HOME
124 # Restore PROBLEM_HOME
118 ENV['PROBLEM_HOME'] = problem_home
125 ENV['PROBLEM_HOME'] = problem_home
119
126
120 # Create the result file.
127 # Create the result file.
@@ -151,12 +158,13
151 comment_file.close
158 comment_file.close
152
159
153 log "Done!"
160 log "Done!"
154 exit(0)
161 exit(0)
155 }
162 }
156
163
164 +
157 if run_result[0][0,2] != "OK"
165 if run_result[0][0,2] != "OK"
158 log "There was a runtime error."
166 log "There was a runtime error."
159 report.call(run_result[0], 0, "No comment.\n")
167 report.call(run_result[0], 0, "No comment.\n")
160 end
168 end
161
169
162 if running_time[:user].to_f > time_limit
170 if running_time[:user].to_f > time_limit
You need to be logged in to leave comments. Login now