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