Description:
removed many 'system' invokations
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r101:65a501bec36b - - 4 files changed: 84 inserted, 41 deleted

@@ -1,14 +1,13
1 require 'fileutils'
1 require 'fileutils'
2 - require 'ftools'
3 require File.join(File.dirname(__FILE__),'dir_init')
2 require File.join(File.dirname(__FILE__),'dir_init')
4
3
5 module Grader
4 module Grader
6
5
7 #
6 #
8 # A grader engine grades a submission, against anything: a test
7 # A grader engine grades a submission, against anything: a test
9 # data, or a user submitted test data. It uses two helpers objects:
8 # data, or a user submitted test data. It uses two helpers objects:
10 # room_maker and reporter.
9 # room_maker and reporter.
11 #
10 #
12 class Engine
11 class Engine
13
12
14 attr_writer :room_maker
13 attr_writer :room_maker
@@ -130,25 +129,25
130 std_script_dir = get_std_script_dir
129 std_script_dir = get_std_script_dir
131
130
132 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
131 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
133
132
134 scripts = Dir[std_script_dir + '/*']
133 scripts = Dir[std_script_dir + '/*']
135
134
136 copied = []
135 copied = []
137
136
138 scripts.each do |s|
137 scripts.each do |s|
139 fname = File.basename(s)
138 fname = File.basename(s)
140 if !FileTest.exist?("#{script_dir}/#{fname}")
139 if !FileTest.exist?("#{script_dir}/#{fname}")
141 copied << fname
140 copied << fname
142 - system("cp #{s} #{script_dir}")
141 + FileUtils.cp(s, "#{script_dir}")
143 end
142 end
144 end
143 end
145
144
146 return copied
145 return copied
147 end
146 end
148
147
149 def copy_log_filename(problem_home)
148 def copy_log_filename(problem_home)
150 return File.join(problem_home, '.scripts_copied')
149 return File.join(problem_home, '.scripts_copied')
151 end
150 end
152
151
153 def save_copy_log(problem_home, log)
152 def save_copy_log(problem_home, log)
154 f = File.new(copy_log_filename(problem_home),"w")
153 f = File.new(copy_log_filename(problem_home),"w")
@@ -165,23 +164,23
165 log << line.strip
164 log << line.strip
166 end
165 end
167 f.close
166 f.close
168 log
167 log
169 end
168 end
170
169
171 def clear_copy_log(problem_home)
170 def clear_copy_log(problem_home)
172 File.delete(copy_log_filename(problem_home))
171 File.delete(copy_log_filename(problem_home))
173 end
172 end
174
173
175 def clear_script(log,problem_home)
174 def clear_script(log,problem_home)
176 log.each do |s|
175 log.each do |s|
177 - system("rm #{problem_home}/script/#{s}")
176 + FileUtils.rm("#{problem_home}/script/#{s}")
178 end
177 end
179 end
178 end
180
179
181 def mkdir_if_does_not_exist(dirname)
180 def mkdir_if_does_not_exist(dirname)
182 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
181 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
183 end
182 end
184
183
185 end
184 end
186
185
187 end
186 end
@@ -1,44 +1,61
1 #
1 #
2 # This part contains various test_request helpers for interfacing
2 # This part contains various test_request helpers for interfacing
3 # with Grader::Engine. There are TestRequestRoomMaker and
3 # with Grader::Engine. There are TestRequestRoomMaker and
4 # TestRequestReporter.
4 # TestRequestReporter.
5
5
6 module Grader
6 module Grader
7
7
8 + def self.link_or_copy(src, des)
9 + begin
10 + FileUtils.ln_s(src, des)
11 + rescue
12 + FileUtils.cp(src,des)
13 + end
14 + end
15 +
16 + def self.call_and_log(error_message)
17 + begin
18 + yield
19 + rescue
20 + msg = "ERROR: #{error_message}"
21 + raise msg
22 + end
23 + end
24 +
8 #
25 #
9 # A TestRequestRoomMaker is a helper object for Engine
26 # A TestRequestRoomMaker is a helper object for Engine
10 # - finds grading room: in user_result_dir/(user)/test_request/ ...
27 # - finds grading room: in user_result_dir/(user)/test_request/ ...
11 # - prepare problem configuration for grading --- basically it copy
28 # - prepare problem configuration for grading --- basically it copy
12 # all config files, and copy user's input into the testcase
29 # all config files, and copy user's input into the testcase
13 # directory. First, it finds the template from problem template
30 # directory. First, it finds the template from problem template
14 # directory; if it can't find a template, it'll use the template
31 # directory; if it can't find a template, it'll use the template
15 # from default template.
32 # from default template.
16 class TestRequestRoomMaker
33 class TestRequestRoomMaker
17 def initialize
34 def initialize
18 @config = Grader::Configuration.get_instance
35 @config = Grader::Configuration.get_instance
19 end
36 end
20
37
21 def produce_grading_room(test_request)
38 def produce_grading_room(test_request)
22 grading_room = grading_room_dir(test_request)
39 grading_room = grading_room_dir(test_request)
23 FileUtils.mkdir_p(grading_room)
40 FileUtils.mkdir_p(grading_room)
24
41
25 #
42 #
26 # Also copy additional submitted file to this directory as well.
43 # Also copy additional submitted file to this directory as well.
27 # The program would see this file only if it is copied
44 # The program would see this file only if it is copied
28 # to the sandbox directory later. The run script should do it.
45 # to the sandbox directory later. The run script should do it.
29 #
46 #
30 if FileTest.exists?("#{test_request.input_file_name}.files")
47 if FileTest.exists?("#{test_request.input_file_name}.files")
31 - cmd = "cp #{test_request.input_file_name}.files/* #{grading_room}"
48 + FileUtils.cp_r("#{test_request.input_file_name}.files/.",
32 - system(cmd)
49 + "#{grading_room}")
33 end
50 end
34
51
35 grading_room
52 grading_room
36 end
53 end
37
54
38 def find_problem_home(test_request)
55 def find_problem_home(test_request)
39 problem_name = test_request.problem_name
56 problem_name = test_request.problem_name
40
57
41 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
58 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
42
59
43 raise "Test Request: error template not found" if !File.exists?(template_dir)
60 raise "Test Request: error template not found" if !File.exists?(template_dir)
44
61
@@ -73,53 +90,48
73 "/#{problem_name}/#{test_request.id}"
90 "/#{problem_name}/#{test_request.id}"
74 grading_room
91 grading_room
75 end
92 end
76
93
77 def problem_home_dir(test_request)
94 def problem_home_dir(test_request)
78 problem_name = test_request.problem_name
95 problem_name = test_request.problem_name
79 user = test_request.user
96 user = test_request.user
80 "#{@config.user_result_dir}" +
97 "#{@config.user_result_dir}" +
81 "/#{user.login}/test_request/#{problem_name}"
98 "/#{user.login}/test_request/#{problem_name}"
82 end
99 end
83
100
84 def copy_problem_template(template_dir,problem_home)
101 def copy_problem_template(template_dir,problem_home)
85 - cmd = "cp -R #{template_dir}/* #{problem_home}"
102 + Grader::call_and_log("Test Request: cannot copy problem template") {
86 - system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
103 + FileUtils.cp_r("#{template_dir}/.","#{problem_home}")
104 + }
87 end
105 end
88 -
106 +
89 - def link_input_file(test_request,problem_home)
107 + def link_input_file(test_request, problem_home)
90 input_fname = "#{test_request.input_file_name}"
108 input_fname = "#{test_request.input_file_name}"
91 if !File.exists?(input_fname)
109 if !File.exists?(input_fname)
92 raise "Test Request: input file not found."
110 raise "Test Request: input file not found."
93 end
111 end
94
112
95 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
113 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
96 if File.exists?(input_fname_problem_home)
114 if File.exists?(input_fname_problem_home)
97 FileUtils.rm([input_fname_problem_home], :force => true)
115 FileUtils.rm([input_fname_problem_home], :force => true)
98 end
116 end
99
117
100 - cmd = "ln -s #{input_fname} #{input_fname_problem_home}"
118 + Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}")
101 - system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
102 end
119 end
103
120
104 def remove_data_files(problem_home)
121 def remove_data_files(problem_home)
105 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
122 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
106 - cmd = "rm #{problem_home}/test_cases/1/*"
123 + Grader::call_and_log("Test Request: cannot remove data files") {
107 - system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
124 + FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*")
108 - end
125 + }
109 - end
110 -
111 - def system_and_raise_when_fail(cmd,msg)
112 - if !system(cmd)
113 - raise msg
114 end
126 end
115 end
127 end
116
128
117 end
129 end
118
130
119 class TestRequestReporter
131 class TestRequestReporter
120 def initialize
132 def initialize
121 @config = Grader::Configuration.get_instance
133 @config = Grader::Configuration.get_instance
122 end
134 end
123
135
124 def report(test_request,test_result_dir)
136 def report(test_request,test_result_dir)
125 save_result(test_request,read_result(test_result_dir))
137 save_result(test_request,read_result(test_result_dir))
@@ -212,28 +224,25
212 test_request.memory_usage = result[:running_stat][:memory_usage]
224 test_request.memory_usage = result[:running_stat][:memory_usage]
213 else
225 else
214 test_request.running_stat = ''
226 test_request.running_stat = ''
215 end
227 end
216 test_request.save
228 test_request.save
217 end
229 end
218
230
219 protected
231 protected
220 def link_output_file(test_request, fname)
232 def link_output_file(test_request, fname)
221 target_file_name = random_output_file_name(test_request.user,
233 target_file_name = random_output_file_name(test_request.user,
222 test_request.problem)
234 test_request.problem)
223 FileUtils.mkdir_p(File.dirname(target_file_name))
235 FileUtils.mkdir_p(File.dirname(target_file_name))
224 - cmd = "ln -s #{fname} #{target_file_name}"
236 + Grader::link_or_copy("#{fname}", "#{target_file_name}")
225 - if !system(cmd)
226 - raise "TestRequestReporter: cannot move output file"
227 - end
228 return target_file_name
237 return target_file_name
229 end
238 end
230
239
231 def random_output_file_name(user,problem)
240 def random_output_file_name(user,problem)
232 problem_name = TestRequest.name_of(problem)
241 problem_name = TestRequest.name_of(problem)
233 begin
242 begin
234 tmpname = "#{@config.test_request_output_base_dir}" +
243 tmpname = "#{@config.test_request_output_base_dir}" +
235 "/#{user.login}/#{problem_name}/#{rand(10000)}"
244 "/#{user.login}/#{problem_name}/#{rand(10000)}"
236 end while File.exists?(tmpname)
245 end while File.exists?(tmpname)
237 tmpname
246 tmpname
238 end
247 end
239
248
@@ -1,36 +1,53
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 + require 'fileutils'
4 +
3 def log(str='')
5 def log(str='')
4 if ENV['TALKATIVE']!=nil
6 if ENV['TALKATIVE']!=nil
5 puts str
7 puts str
6 end
8 end
7 if ENV['GRADER_LOGGING']!=nil
9 if ENV['GRADER_LOGGING']!=nil
8 log_fname = ENV['GRADER_LOGGING']
10 log_fname = ENV['GRADER_LOGGING']
9 fp = File.open(log_fname,"a")
11 fp = File.open(log_fname,"a")
10 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
12 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
11 fp.close
13 fp.close
12 end
14 end
13 end
15 end
14
16
15 problem_home = ENV['PROBLEM_HOME']
17 problem_home = ENV['PROBLEM_HOME']
16
18
17 def execute(command, error_message="")
19 def execute(command, error_message="")
18 if not system(command)
20 if not system(command)
19 msg = "ERROR: #{error_message}"
21 msg = "ERROR: #{error_message}"
20 log msg
22 log msg
21 raise msg
23 raise msg
22 end
24 end
23 end
25 end
24
26
27 + def call_and_log(error_message)
28 + begin
29 + yield
30 + rescue
31 + msg = "ERROR: #{error_message}"
32 + log msg
33 + raise msg
34 + end
35 + end
36 +
37 + def clear_and_create_empty_dir(dir)
38 + FileUtils.rm_rf(dir, :secure => true)
39 + call_and_log("Cannot make directory #{dir}.") { FileUtils.mkdir(dir) }
40 + end
41 +
25 # ARGV[0] --- language
42 # ARGV[0] --- language
26 # ARGV[1] --- program source file
43 # ARGV[1] --- program source file
27 # ARGV[2] --- test result directory
44 # ARGV[2] --- test result directory
28 # ARGV[3] --- sandbox directory
45 # ARGV[3] --- sandbox directory
29
46
30 if ARGV.length < 2 || ARGV.length > 4
47 if ARGV.length < 2 || ARGV.length > 4
31 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
48 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
32 puts " <sandbox-directory> is defaulted to ./sandbox"
49 puts " <sandbox-directory> is defaulted to ./sandbox"
33 puts " <test-result-directory> is defaulted to ./test-result"
50 puts " <test-result-directory> is defaulted to ./test-result"
34 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."
35 exit(127)
52 exit(127)
36 end
53 end
@@ -48,86 +65,103
48 end
65 end
49
66
50 log "Making test result and sandbox directories..."
67 log "Making test result and sandbox directories..."
51
68
52 current_dir = `pwd`
69 current_dir = `pwd`
53 current_dir.strip!
70 current_dir.strip!
54
71
55 if ARGV.length >= 3
72 if ARGV.length >= 3
56 test_result_dir = ARGV[2]
73 test_result_dir = ARGV[2]
57 else
74 else
58 test_result_dir = "#{current_dir}/test-result"
75 test_result_dir = "#{current_dir}/test-result"
59 end
76 end
77 +
60 log "Test result directory: #{test_result_dir}"
78 log "Test result directory: #{test_result_dir}"
61 - system("rm -Rf #{test_result_dir}")
79 + clear_and_create_empty_dir(test_result_dir)
62 - execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
63
80
64 if ARGV.length >= 4
81 if ARGV.length >= 4
65 sandbox_dir = ARGV[3]
82 sandbox_dir = ARGV[3]
66 else
83 else
67 sandbox_dir = "#{current_dir}/sandbox"
84 sandbox_dir = "#{current_dir}/sandbox"
68 end
85 end
69 log "Sandbox directory: #{sandbox_dir}"
86 log "Sandbox directory: #{sandbox_dir}"
70 - system("rm -Rf #{sandbox_dir}")
87 + clear_and_create_empty_dir(sandbox_dir)
71 - execute("mkdir #{sandbox_dir}", "Cannot make directory #{sandbox_dir}")
72
88
73 # Compile
89 # Compile
74 log
90 log
75 log "Compiling..."
91 log "Compiling..."
76 - execute("cp #{source_file} #{sandbox_dir}", "Cannot copy the source file to #{sandbox_dir}")
92 + call_and_log("Cannot copy the source file to #{sandbox_dir}") {
93 + FileUtils.cp(source_file, sandbox_dir)
94 + }
77 begin
95 begin
78 Dir.chdir sandbox_dir
96 Dir.chdir sandbox_dir
79 rescue
97 rescue
80 log "ERROR: Cannot change directory to #{sandbox_dir}."
98 log "ERROR: Cannot change directory to #{sandbox_dir}."
81 exit(127)
99 exit(127)
82 end
100 end
83 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
101 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
84 compile_message = `cat compiler_message`
102 compile_message = `cat compiler_message`
85 compile_message.strip!
103 compile_message.strip!
86 - execute("mv compiler_message #{test_result_dir}", "Cannot move the compiler message to #{test_result_dir}.")
104 + call_and_log("Cannot move the compiler message to #{test_result_dir}.") {
105 + FileUtils.mv("compiler_message", test_result_dir)
106 + }
87 if !FileTest.exist?("a.out")
107 if !FileTest.exist?("a.out")
88 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
108 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
89 exit(127)
109 exit(127)
90 else
110 else
91 - execute("mv a.out #{test_result_dir}", "Cannot move the compiled program to #{test_result_dir}")
111 + call_and_log("Cannot move the compiled program to #{test_result_dir}") {
92 - system("rm -Rf #{sandbox_dir}/*")
112 + FileUtils.mv("a.out",test_result_dir)
113 + }
114 + FileUtils.rm_rf("#{sandbox_dir}/.")
93 end
115 end
94
116
95 require "#{problem_home}/script/test_dsl.rb"
117 require "#{problem_home}/script/test_dsl.rb"
96 load "#{problem_home}/test_cases/all_tests.cfg"
118 load "#{problem_home}/test_cases/all_tests.cfg"
97 problem = Problem.get_instance
119 problem = Problem.get_instance
98
120
99 if problem.well_formed? == false
121 if problem.well_formed? == false
100 log "The problem specification is not well formed."
122 log "The problem specification is not well formed."
101 exit(127)
123 exit(127)
102 end
124 end
103
125
104 # Doing the testing.
126 # Doing the testing.
105 (1..(problem.num_tests)).each do |test_num|
127 (1..(problem.num_tests)).each do |test_num|
106
128
107 $stdout.print "[#{test_num}]"
129 $stdout.print "[#{test_num}]"
108 $stdout.flush
130 $stdout.flush
109
131
110 log "Test number: #{test_num}"
132 log "Test number: #{test_num}"
111 - execute("cp #{test_result_dir}/a.out #{sandbox_dir}", "Cannot copy the compiled program into #{sandbox_dir}")
133 + call_and_log("Cannot copy the compiled program into #{sandbox_dir}") {
134 + FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir)
135 + }
112 begin
136 begin
113 execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
137 execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
114 rescue
138 rescue
115 # do nothing
139 # do nothing
116 end
140 end
117 - execute("mkdir #{test_result_dir}/#{test_num}", "Cannot create directory #{test_result_dir}/#{test_num}")
141 + call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
118 - execute("mv #{sandbox_dir}/result #{test_result_dir}/#{test_num}", "Cannot copy the result file into #{test_result_dir}/#{test_num}")
142 + FileUtils.mkdir "#{test_result_dir}/#{test_num}"
119 - execute("mv #{sandbox_dir}/comment #{test_result_dir}/#{test_num}", "Cannot copy the comment file into #{test_result_dir}/#{test_num}")
143 + }
120 - execute("mv #{sandbox_dir}/output.txt #{test_result_dir}/#{test_num}", "Cannot copy the output file into #{test_result_dir}/#{test_num}")
144 + call_and_log("Cannot copy the result file into #{test_result_dir}/#{test_num}") {
121 - execute("rm -Rf #{sandbox_dir}/*", "Cannot clear #{sandbox_dir}")
145 + FileUtils.mv "#{sandbox_dir}/result", "#{test_result_dir}/#{test_num}"
146 + }
147 + call_and_log("Cannot copy the comment file into #{test_result_dir}/#{test_num}") {
148 + FileUtils.mv "#{sandbox_dir}/comment", "#{test_result_dir}/#{test_num}"
149 + }
150 + call_and_log("Cannot copy the output file into #{test_result_dir}/#{test_num}") {
151 + FileUtils.mv "#{sandbox_dir}/output.txt", "#{test_result_dir}/#{test_num}"
152 + }
153 + call_and_log("Cannot clear #{sandbox_dir}") {
154 + FileUtils.rm_rf(Dir.glob("#{sandbox_dir}/*"), :secure => true)
155 + }
122 end
156 end
123
157
124 $stdout.print "[done]\n"
158 $stdout.print "[done]\n"
125
159
126 # Grade
160 # Grade
127 log
161 log
128 log "Grading..."
162 log "Grading..."
129 begin
163 begin
130 Dir.chdir test_result_dir
164 Dir.chdir test_result_dir
131 rescue
165 rescue
132 log "ERROR: Cannot change directory to #{test_result_dir}."
166 log "ERROR: Cannot change directory to #{test_result_dir}."
133 exit(127)
167 exit(127)
@@ -1,26 +1,27
1 + require 'fileutils'
2 +
1 module GraderEngineHelperMethods
3 module GraderEngineHelperMethods
2
4
3 def clear_sandbox
5 def clear_sandbox
4 config = Grader::Configuration.get_instance
6 config = Grader::Configuration.get_instance
5 - clear_cmd = "rm -rf #{config.test_sandbox_dir}/*"
7 + FileUtils.rm_rf(Dir.glob("#{config.test_sandbox_dir}/*"),
6 - system(clear_cmd)
8 + :secure => true)
7 end
9 end
8
10
9 def init_sandbox
11 def init_sandbox
10 config = Grader::Configuration.get_instance
12 config = Grader::Configuration.get_instance
11 clear_sandbox
13 clear_sandbox
12 FileUtils.mkdir_p config.user_result_dir
14 FileUtils.mkdir_p config.user_result_dir
13 - cp_cmd = "cp -R #{config.test_data_dir}/ev #{config.test_sandbox_dir}"
15 + FileUtils.cp_r("#{config.test_data_dir}/ev", "#{config.test_sandbox_dir}")
14 - system(cp_cmd)
15 end
16 end
16
17
17 def create_submission_from_file(id, user, problem,
18 def create_submission_from_file(id, user, problem,
18 source_fname, language=nil)
19 source_fname, language=nil)
19
20
20 language = stub(Language, :name => 'c', :ext => 'c') if language==nil
21 language = stub(Language, :name => 'c', :ext => 'c') if language==nil
21
22
22 config = Grader::Configuration.get_instance
23 config = Grader::Configuration.get_instance
23 source = File.open(config.test_data_dir + "/" + source_fname).read
24 source = File.open(config.test_data_dir + "/" + source_fname).read
24 stub(Submission,
25 stub(Submission,
25 :id => id, :user => user, :problem => problem,
26 :id => id, :user => user, :problem => problem,
26 :source => source, :language => language)
27 :source => source, :language => language)
You need to be logged in to leave comments. Login now