Description:
translates test_request input/output file paths for remote grading test_request
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r117:cc3e1102f8c6 - - 5 files changed: 36 inserted, 3 deleted

@@ -1,20 +1,23
1 #
1 #
2 # See documentation in lib/configuration.rb
2 # See documentation in lib/configuration.rb
3 #
3 #
4 Grader::Initializer.run do |config|
4 Grader::Initializer.run do |config|
5
5
6 config.problems_dir = GRADER_ROOT + "/../ev-exam"
6 config.problems_dir = GRADER_ROOT + "/../ev-exam"
7 config.user_result_dir = GRADER_ROOT + "/../result"
7 config.user_result_dir = GRADER_ROOT + "/../result"
8
8
9 config.talkative = true
9 config.talkative = true
10 config.logging = true
10 config.logging = true
11 config.log_dir = GRADER_ROOT + "/../log"
11 config.log_dir = GRADER_ROOT + "/../log"
12
12
13 config.report_grader = true
13 config.report_grader = true
14
14
15 config.test_request_input_base_dir = RAILS_ROOT + "/data/test_request/input"
15 config.test_request_input_base_dir = RAILS_ROOT + "/data/test_request/input"
16 config.test_request_output_base_dir = RAILS_ROOT + "/data/test_request/output"
16 config.test_request_output_base_dir = RAILS_ROOT + "/data/test_request/output"
17 config.test_request_problem_templates_dir = config.problems_dir + "/test_request"
17 config.test_request_problem_templates_dir = config.problems_dir + "/test_request"
18
18
19 + # change this if you want the path on the output to be translated
20 + config.test_request_org_output_base_dir = config.test_request_output_base_dir
21 +
19 config.comment_report_style = :short
22 config.comment_report_style = :short
20 end
23 end
@@ -1,19 +1,22
1 #
1 #
2 # See documentation in lib/configuration.rb
2 # See documentation in lib/configuration.rb
3 #
3 #
4 Grader::Initializer.run do |config|
4 Grader::Initializer.run do |config|
5 config.problems_dir = GRADER_ROOT + "/../ev"
5 config.problems_dir = GRADER_ROOT + "/../ev"
6 config.user_result_dir = GRADER_ROOT + "/../result"
6 config.user_result_dir = GRADER_ROOT + "/../result"
7
7
8 config.talkative = true
8 config.talkative = true
9 config.logging = true
9 config.logging = true
10 config.log_dir = GRADER_ROOT + "/../log"
10 config.log_dir = GRADER_ROOT + "/../log"
11
11
12 config.report_grader = true
12 config.report_grader = true
13
13
14 config.test_request_input_base_dir = RAILS_ROOT + "/data/test_request/input"
14 config.test_request_input_base_dir = RAILS_ROOT + "/data/test_request/input"
15 config.test_request_output_base_dir = RAILS_ROOT + "/data/test_request/output"
15 config.test_request_output_base_dir = RAILS_ROOT + "/data/test_request/output"
16 config.test_request_problem_templates_dir = config.problems_dir + "/test_request"
16 config.test_request_problem_templates_dir = config.problems_dir + "/test_request"
17 +
18 + # change this if you want the path on the output to be translated
19 + config.test_request_org_output_base_dir = config.test_request_output_base_dir
17
20
18 config.comment_report_style = :full
21 config.comment_report_style = :full
19 end
22 end
@@ -1,29 +1,32
1 #
1 #
2 # See documentation in lib/configuration.rb
2 # See documentation in lib/configuration.rb
3 #
3 #
4 Grader::Initializer.run do |config|
4 Grader::Initializer.run do |config|
5 config.problems_dir = GRADER_ROOT + "/test/sandbox/ev"
5 config.problems_dir = GRADER_ROOT + "/test/sandbox/ev"
6 config.user_result_dir = GRADER_ROOT + "/test/sandbox/result"
6 config.user_result_dir = GRADER_ROOT + "/test/sandbox/result"
7
7
8 config.talkative = false
8 config.talkative = false
9
9
10 config.report_grader = false
10 config.report_grader = false
11
11
12 config.rails_env = 'test'
12 config.rails_env = 'test'
13
13
14 config.comment_report_style = :full
14 config.comment_report_style = :full
15
15
16 config.test_request_input_base_dir = GRADER_ROOT + "/test/data/test_request/input"
16 config.test_request_input_base_dir = GRADER_ROOT + "/test/data/test_request/input"
17 config.test_request_output_base_dir = GRADER_ROOT + "/test/sandbox/test_request/output"
17 config.test_request_output_base_dir = GRADER_ROOT + "/test/sandbox/test_request/output"
18 config.test_request_problem_templates_dir = GRADER_ROOT + "/test/data/test_request/problems"
18 config.test_request_problem_templates_dir = GRADER_ROOT + "/test/data/test_request/problems"
19
19
20 + # change this if you want the path on the output to be translated
21 + config.test_request_org_output_base_dir = config.test_request_output_base_dir
22 +
20 #
23 #
21 # These options are for testing
24 # These options are for testing
22 #
25 #
23 class << config
26 class << config
24 attr_accessor :test_data_dir, :test_sandbox_dir
27 attr_accessor :test_data_dir, :test_sandbox_dir
25 end
28 end
26
29
27 config.test_data_dir = GRADER_ROOT + "/test/data"
30 config.test_data_dir = GRADER_ROOT + "/test/data"
28 config.test_sandbox_dir = GRADER_ROOT + "/test/sandbox"
31 config.test_sandbox_dir = GRADER_ROOT + "/test/sandbox"
29 end
32 end
@@ -12,48 +12,52
12 # execution results for submission [x] of user [u] in directory
12 # execution results for submission [x] of user [u] in directory
13 # user_result_dir/[u]/[x]
13 # user_result_dir/[u]/[x]
14 attr_accessor :problems_dir
14 attr_accessor :problems_dir
15 attr_accessor :user_result_dir
15 attr_accessor :user_result_dir
16
16
17 # If report_grader=true, the grader would add a row in model
17 # If report_grader=true, the grader would add a row in model
18 # GraderProcess. It would report itself with grader_hostname and
18 # GraderProcess. It would report itself with grader_hostname and
19 # process id.
19 # process id.
20 attr_accessor :report_grader
20 attr_accessor :report_grader
21 attr_accessor :grader_hostname
21 attr_accessor :grader_hostname
22
22
23 # If talkative=true, grader would report status to console. If
23 # If talkative=true, grader would report status to console. If
24 # logging=true, grader would report status to a log file located
24 # logging=true, grader would report status to a log file located
25 # in log_dir, in a file name mode.options.pid. TODO: defined
25 # in log_dir, in a file name mode.options.pid. TODO: defined
26 # log file naming.
26 # log file naming.
27 attr_accessor :talkative
27 attr_accessor :talkative
28 attr_accessor :logging
28 attr_accessor :logging
29 attr_accessor :log_dir
29 attr_accessor :log_dir
30
30
31 # These are directories related to the test interface.
31 # These are directories related to the test interface.
32 attr_accessor :test_request_input_base_dir
32 attr_accessor :test_request_input_base_dir
33 attr_accessor :test_request_output_base_dir
33 attr_accessor :test_request_output_base_dir
34 attr_accessor :test_request_problem_templates_dir
34 attr_accessor :test_request_problem_templates_dir
35
35
36 + # this is for linking output from test request
37 + # TODO: find a cleaner way to do this.
38 + attr_accessor :test_request_org_output_base_dir
39 +
36 # Comment received from the grading script will be filtered
40 # Comment received from the grading script will be filtered
37 # through Configuration#report_comment. How this method behave
41 # through Configuration#report_comment. How this method behave
38 # depends on this option; right now only two formats, :short and
42 # depends on this option; right now only two formats, :short and
39 # :long
43 # :long
40 attr_accessor :comment_report_style
44 attr_accessor :comment_report_style
41
45
42 def report_comment(comment)
46 def report_comment(comment)
43 case comment_report_style
47 case comment_report_style
44 when :short
48 when :short
45 if comment.chomp =~ /^[\[\]P]+$/ # all P's
49 if comment.chomp =~ /^[\[\]P]+$/ # all P's
46 'passed'
50 'passed'
47 elsif comment.chomp =~ /[Cc]ompil.*[Ee]rror/
51 elsif comment.chomp =~ /[Cc]ompil.*[Ee]rror/
48 'compilation error'
52 'compilation error'
49 else
53 else
50 'failed'
54 'failed'
51 end
55 end
52
56
53 when :full
57 when :full
54 comment.chomp
58 comment.chomp
55 end
59 end
56 end
60 end
57
61
58 # Codes for singleton
62 # Codes for singleton
59 private_class_method :new
63 private_class_method :new
@@ -1,31 +1,37
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.translate_filepath(filename, marker, new_base_path)
9 + p = filename.index(marker)
10 + end_path = filename[(p+marker.length)..-1]
11 + return new_base_path + end_path
12 + end
13 +
8 def self.link_or_copy(src, des)
14 def self.link_or_copy(src, des)
9 begin
15 begin
10 FileUtils.ln_s(src, des)
16 FileUtils.ln_s(src, des)
11 rescue NotImplementedError
17 rescue NotImplementedError
12 FileUtils.cp(src,des)
18 FileUtils.cp(src,des)
13 end
19 end
14 end
20 end
15
21
16 def self.call_and_log(error_message)
22 def self.call_and_log(error_message)
17 begin
23 begin
18 yield
24 yield
19 rescue
25 rescue
20 msg = "ERROR: #{error_message}"
26 msg = "ERROR: #{error_message}"
21 raise msg
27 raise msg
22 end
28 end
23 end
29 end
24
30
25 #
31 #
26 # A TestRequestRoomMaker is a helper object for Engine
32 # A TestRequestRoomMaker is a helper object for Engine
27 # - finds grading room: in user_result_dir/(user)/test_request/ ...
33 # - finds grading room: in user_result_dir/(user)/test_request/ ...
28 # - prepare problem configuration for grading --- basically it copy
34 # - prepare problem configuration for grading --- basically it copy
29 # all config files, and copy user's input into the testcase
35 # all config files, and copy user's input into the testcase
30 # directory. First, it finds the template from problem template
36 # directory. First, it finds the template from problem template
31 # directory; if it can't find a template, it'll use the template
37 # directory; if it can't find a template, it'll use the template
@@ -83,50 +89,57
83
89
84 protected
90 protected
85 def grading_room_dir(test_request)
91 def grading_room_dir(test_request)
86 problem_name = test_request.problem_name
92 problem_name = test_request.problem_name
87 user = test_request.user
93 user = test_request.user
88 grading_room = "#{@config.user_result_dir}" +
94 grading_room = "#{@config.user_result_dir}" +
89 "/#{user.login}/test_request" +
95 "/#{user.login}/test_request" +
90 "/#{problem_name}/#{test_request.id}"
96 "/#{problem_name}/#{test_request.id}"
91 grading_room
97 grading_room
92 end
98 end
93
99
94 def problem_home_dir(test_request)
100 def problem_home_dir(test_request)
95 problem_name = test_request.problem_name
101 problem_name = test_request.problem_name
96 user = test_request.user
102 user = test_request.user
97 "#{@config.user_result_dir}" +
103 "#{@config.user_result_dir}" +
98 "/#{user.login}/test_request/#{problem_name}"
104 "/#{user.login}/test_request/#{problem_name}"
99 end
105 end
100
106
101 def copy_problem_template(template_dir,problem_home)
107 def copy_problem_template(template_dir,problem_home)
102 Grader::call_and_log("Test Request: cannot copy problem template") {
108 Grader::call_and_log("Test Request: cannot copy problem template") {
103 FileUtils.cp_r("#{template_dir}/.","#{problem_home}")
109 FileUtils.cp_r("#{template_dir}/.","#{problem_home}")
104 }
110 }
105 end
111 end
106
112
113 + def translate_input_filename(filename)
114 + return Grader::translate_filepath(filename,
115 + 'input',
116 + @config.test_request_input_base_dir)
117 + end
118 +
107 def link_input_file(test_request, problem_home)
119 def link_input_file(test_request, problem_home)
108 - input_fname = "#{test_request.input_file_name}"
120 + input_fname = translate_input_filename(test_request.input_file_name)
121 +
109 if !File.exists?(input_fname)
122 if !File.exists?(input_fname)
110 raise "Test Request: input file not found."
123 raise "Test Request: input file not found."
111 end
124 end
112
125
113 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
126 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
114 if File.exists?(input_fname_problem_home)
127 if File.exists?(input_fname_problem_home)
115 FileUtils.rm([input_fname_problem_home], :force => true)
128 FileUtils.rm([input_fname_problem_home], :force => true)
116 end
129 end
117
130
118 Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}")
131 Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}")
119 end
132 end
120
133
121 def remove_data_files(problem_home)
134 def remove_data_files(problem_home)
122 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
135 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
123 Grader::call_and_log("Test Request: cannot remove data files") {
136 Grader::call_and_log("Test Request: cannot remove data files") {
124 FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*")
137 FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*")
125 }
138 }
126 end
139 end
127 end
140 end
128
141
129 end
142 end
130
143
131 class TestRequestReporter
144 class TestRequestReporter
132 def initialize
145 def initialize
@@ -193,62 +206,69
193 seconds = (res[1].to_f + res[2].to_f)
206 seconds = (res[1].to_f + res[2].to_f)
194 time_stat = "Time used: #{seconds} sec."
207 time_stat = "Time used: #{seconds} sec."
195 else
208 else
196 seconds = nil
209 seconds = nil
197 time_stat = "Time used: n/a sec."
210 time_stat = "Time used: n/a sec."
198 end
211 end
199
212
200 # extract memory usage
213 # extract memory usage
201 if res = /s(.*)m/.match(running_stat_line)
214 if res = /s(.*)m/.match(running_stat_line)
202 memory_used = res[1].to_i
215 memory_used = res[1].to_i
203 else
216 else
204 memory_used = -1
217 memory_used = -1
205 end
218 end
206
219
207 return {
220 return {
208 :msg => "#{run_stat}\n#{time_stat}",
221 :msg => "#{run_stat}\n#{time_stat}",
209 :running_time => seconds,
222 :running_time => seconds,
210 :exit_status => run_stat,
223 :exit_status => run_stat,
211 :memory_usage => memory_used
224 :memory_usage => memory_used
212 }
225 }
213 end
226 end
214
227
215 def save_result(test_request,result)
228 def save_result(test_request,result)
216 if result[:output_file_name]!=nil
229 if result[:output_file_name]!=nil
217 - test_request.output_file_name = link_output_file(test_request,
230 + org_filename = link_output_file(test_request,
218 - result[:output_file_name])
231 + result[:output_file_name])
232 + test_request.output_file_name = translate_output_filename(org_filename)
219 end
233 end
220 test_request.graded_at = Time.now
234 test_request.graded_at = Time.now
221 test_request.compiler_message = (result[:cmp_msg] or '')
235 test_request.compiler_message = (result[:cmp_msg] or '')
222 test_request.grader_comment = (result[:comment] or '')
236 test_request.grader_comment = (result[:comment] or '')
223 if result[:running_stat]!=nil
237 if result[:running_stat]!=nil
224 test_request.running_stat = (result[:running_stat][:msg] or '')
238 test_request.running_stat = (result[:running_stat][:msg] or '')
225 test_request.running_time = (result[:running_stat][:running_time] or nil)
239 test_request.running_time = (result[:running_stat][:running_time] or nil)
226 test_request.exit_status = result[:running_stat][:exit_status]
240 test_request.exit_status = result[:running_stat][:exit_status]
227 test_request.memory_usage = result[:running_stat][:memory_usage]
241 test_request.memory_usage = result[:running_stat][:memory_usage]
228 else
242 else
229 test_request.running_stat = ''
243 test_request.running_stat = ''
230 end
244 end
231 test_request.save
245 test_request.save
232 end
246 end
233
247
234 protected
248 protected
249 + def translate_output_filename(filename)
250 + return Grader::translate_filepath(filename,
251 + 'output',
252 + @config.test_request_org_output_base_dir)
253 + end
254 +
235 def link_output_file(test_request, fname)
255 def link_output_file(test_request, fname)
236 target_file_name = random_output_file_name(test_request.user,
256 target_file_name = random_output_file_name(test_request.user,
237 test_request.problem)
257 test_request.problem)
238 FileUtils.mkdir_p(File.dirname(target_file_name))
258 FileUtils.mkdir_p(File.dirname(target_file_name))
239 Grader::link_or_copy("#{fname}", "#{target_file_name}")
259 Grader::link_or_copy("#{fname}", "#{target_file_name}")
240 return target_file_name
260 return target_file_name
241 end
261 end
242
262
243 def random_output_file_name(user,problem)
263 def random_output_file_name(user,problem)
244 problem_name = TestRequest.name_of(problem)
264 problem_name = TestRequest.name_of(problem)
245 begin
265 begin
246 tmpname = "#{@config.test_request_output_base_dir}" +
266 tmpname = "#{@config.test_request_output_base_dir}" +
247 "/#{user.login}/#{problem_name}/#{rand(10000)}"
267 "/#{user.login}/#{problem_name}/#{rand(10000)}"
248 end while File.exists?(tmpname)
268 end while File.exists?(tmpname)
249 tmpname
269 tmpname
250 end
270 end
251
271
252 end
272 end
253
273
254 end
274 end
You need to be logged in to leave comments. Login now