Description:
added grading report
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r92:274af5f15b1f - - 4 files changed: 95 inserted, 21 deleted

@@ -11,229 +11,287
11 def check_stopfile
11 def check_stopfile
12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 end
14 end
15
15
16 def clear_stopfile
16 def clear_stopfile
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 end
19 end
20 end
20 end
21
21
22 def config
22 def config
23 Grader::Configuration.get_instance
23 Grader::Configuration.get_instance
24 end
24 end
25
25
26 def log_file_name
26 def log_file_name
27 if !File.exists?(config.log_dir)
27 if !File.exists?(config.log_dir)
28 raise "Log directory does not exist: #{config.log_dir}"
28 raise "Log directory does not exist: #{config.log_dir}"
29 end
29 end
30 config.log_dir +
30 config.log_dir +
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 end
32 end
33
33
34 def log(str)
34 def log(str)
35 if config.talkative
35 if config.talkative
36 puts str
36 puts str
37 end
37 end
38 if config.logging
38 if config.logging
39 fp = File.open(log_file_name,"a")
39 fp = File.open(log_file_name,"a")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 fp.close
41 fp.close
42 end
42 end
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]
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', 'prob', 'test_request'
53 (2) possible modes are: 'queue', 'prob', 'test_request'
54 (3) create stop-file to stop running grader in queue mode
54 (3) create stop-file to stop running grader in queue mode
55 (4) You are here.
55 (4) You are here.
56 USAGE
56 USAGE
57 end
57 end
58
58
59 - #########################################
60 - # main program
61 - #########################################
62 -
63 - # Reading environment and options.
64 -
65 def process_options_and_stop_file
59 def process_options_and_stop_file
66 # The list of options are:
60 # The list of options are:
67 # - stop [all|process ids]
61 # - stop [all|process ids]
68 # -
62 # -
69
63
70 # Process 'help' option
64 # Process 'help' option
71 if (ARGV.length==1) and (/help/.match(ARGV[0]))
65 if (ARGV.length==1) and (/help/.match(ARGV[0]))
72 display_manual
66 display_manual
73 exit(0)
67 exit(0)
74 end
68 end
75
69
76 # Process 'stop' option.
70 # Process 'stop' option.
77 if (ARGV.length >= 1) and (ARGV[0]=='stop')
71 if (ARGV.length >= 1) and (ARGV[0]=='stop')
78 if ARGV.length==1
72 if ARGV.length==1
79 puts "you should specify pid-list or 'all'"
73 puts "you should specify pid-list or 'all'"
80 display_manual
74 display_manual
81 elsif (ARGV.length==2) and (ARGV[1]=='all')
75 elsif (ARGV.length==2) and (ARGV[1]=='all')
82 stop_grader(:all)
76 stop_grader(:all)
83 puts "A global stop file ('stop.all') created."
77 puts "A global stop file ('stop.all') created."
84 puts "You should remove it manually later."
78 puts "You should remove it manually later."
85 else
79 else
86 (1..ARGV.length-1).each do |i|
80 (1..ARGV.length-1).each do |i|
87 stop_grader(ARGV[i])
81 stop_grader(ARGV[i])
88 end
82 end
89 puts "stop file(s) created"
83 puts "stop file(s) created"
90 end
84 end
91 exit(0)
85 exit(0)
92 end
86 end
93
87
94 # Check stop file.
88 # Check stop file.
95 if check_stopfile
89 if check_stopfile
96 puts "Stop file exists. Terminated."
90 puts "Stop file exists. Terminated."
97 clear_stopfile
91 clear_stopfile
98 exit(0)
92 exit(0)
99 end
93 end
100
94
101 #default options
95 #default options
102 options = {
96 options = {
103 :mode => 'queue',
97 :mode => 'queue',
104 :environment => 'exam',
98 :environment => 'exam',
105 :dry_run => false,
99 :dry_run => false,
106 }
100 }
107
101
108 # Process mode and environment option
102 # Process mode and environment option
109 if ARGV.length >= 1
103 if ARGV.length >= 1
110 options[:environment] = ARGV.shift
104 options[:environment] = ARGV.shift
111 if ARGV.length >=1
105 if ARGV.length >=1
112 options[:mode] = ARGV.shift
106 options[:mode] = ARGV.shift
113 end
107 end
114 end
108 end
115
109
116 options[:dry_run] = (ARGV.delete('--dry') != nil)
110 options[:dry_run] = (ARGV.delete('--dry') != nil)
117 if options[:dry_run] and (not options[:mode] == 'prob')
111 if options[:dry_run] and (not options[:mode] == 'prob')
118 - puts "Dry run currently works for 'prob' mode."
112 + puts "Dry run currently works only for 'prob' mode."
113 + exit(0)
114 + end
115 +
116 + options[:report] = (ARGV.delete('--report') != nil)
117 + if options[:report] and (not options[:mode] == 'prob')
118 + puts "Report currently works only for 'prob' mode."
119 exit(0)
119 exit(0)
120 end
120 end
121
121
122 return options
122 return options
123 end
123 end
124
124
125 - # ======= Main ========
125 + class ResultCollector
126 + def initialize
127 + @results = {}
128 + @problems = {}
129 + @users = {}
130 + end
131 +
132 + def save(user, problem, grading_result)
133 + if not @problems.has_key? problem.id
134 + @problems[problem.id] = problem
135 + end
136 + if not @users.has_key? user.id
137 + @users[user.id] = user
138 + end
139 + @results[[user.id, problem.id]] = grading_result
140 + end
141 +
142 + def print_report_by_user
143 + puts "---------------------"
144 + puts " REPORT"
145 + puts "---------------------"
146 +
147 + print "login"
148 + @problems.each_value do |problem|
149 + print ",#{problem.name}"
150 + end
151 + print "\n"
152 +
153 + @users.each_value do |user|
154 + print "#{user.login}"
155 + @problems.each_value do |problem|
156 + if @results.has_key? [user.id, problem.id]
157 + print ",#{@results[[user.id,problem.id]][:points]}"
158 + else
159 + print ","
160 + end
161 + end
162 + print "\n"
163 + end
164 + end
165 + end
166 +
167 + #########################################
168 + # main program
169 + #########################################
170 +
126 options = process_options_and_stop_file
171 options = process_options_and_stop_file
127 GRADER_ENV = options[:environment]
172 GRADER_ENV = options[:environment]
128 grader_mode = options[:mode]
173 grader_mode = options[:mode]
129 dry_run = options[:dry_run]
174 dry_run = options[:dry_run]
130
175
131 puts "environment: #{GRADER_ENV}"
176 puts "environment: #{GRADER_ENV}"
132 require File.join(File.dirname(__FILE__),'config/environment')
177 require File.join(File.dirname(__FILE__),'config/environment')
133
178
134 # add grader_mode to config
179 # add grader_mode to config
135 # this is needed because method log needs it. TODO: clean this up
180 # this is needed because method log needs it. TODO: clean this up
136 class << config
181 class << config
137 attr_accessor :grader_mode
182 attr_accessor :grader_mode
138 end
183 end
139 config.grader_mode = grader_mode
184 config.grader_mode = grader_mode
140
185
141 # reading rails environment
186 # reading rails environment
142 log 'Reading rails environment'
187 log 'Reading rails environment'
143
188
144 RAILS_ENV = config.rails_env
189 RAILS_ENV = config.rails_env
145 require RAILS_ROOT + '/config/environment'
190 require RAILS_ROOT + '/config/environment'
146
191
147 # register grader process
192 # register grader process
148 if config.report_grader
193 if config.report_grader
149 grader_proc = GraderProcess.register(config.grader_hostname,
194 grader_proc = GraderProcess.register(config.grader_hostname,
150 Process.pid,
195 Process.pid,
151 grader_mode)
196 grader_mode)
152 else
197 else
153 grader_proc = nil
198 grader_proc = nil
154 end
199 end
155
200
156 #set loggin environment
201 #set loggin environment
157 ENV['GRADER_LOGGING'] = log_file_name
202 ENV['GRADER_LOGGING'] = log_file_name
158
203
159 # register exit handler to report inactive, and terminated
204 # register exit handler to report inactive, and terminated
160 at_exit do
205 at_exit do
161 if grader_proc!=nil
206 if grader_proc!=nil
162 grader_proc.report_inactive
207 grader_proc.report_inactive
163 grader_proc.terminate
208 grader_proc.terminate
164 end
209 end
165 end
210 end
166
211
167 #
212 #
168 # MAIN LOOP
213 # MAIN LOOP
169 #
214 #
170
215
171 case grader_mode
216 case grader_mode
172 when "queue", "test_request"
217 when "queue", "test_request"
173 log "Grader: #{grader_mode}"
218 log "Grader: #{grader_mode}"
174 if grader_mode=="queue"
219 if grader_mode=="queue"
175 engine = Grader::Engine.new
220 engine = Grader::Engine.new
176 else
221 else
177 - engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
222 + engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
178 - Grader::TestRequestReporter.new)
223 + :reporter => Grader::TestRequestReporter.new)
179 end
224 end
180
225
181 runner = Grader::Runner.new(engine, grader_proc)
226 runner = Grader::Runner.new(engine, grader_proc)
182 while true
227 while true
183
228
184 if check_stopfile # created by calling grader stop
229 if check_stopfile # created by calling grader stop
185 clear_stopfile
230 clear_stopfile
186 log "stopped (with stop file)"
231 log "stopped (with stop file)"
187 break
232 break
188 end
233 end
189
234
190 if grader_mode=="queue"
235 if grader_mode=="queue"
191 task = runner.grade_oldest_task
236 task = runner.grade_oldest_task
192 else
237 else
193 task = runner.grade_oldest_test_request
238 task = runner.grade_oldest_test_request
194 end
239 end
195 if task==nil
240 if task==nil
196 sleep(1)
241 sleep(1)
197 end
242 end
198 end
243 end
199
244
200 when "prob"
245 when "prob"
201 - engine = Grader::Engine.new(nil, Grader::SubmissionReporter.new(dry_run))
246 + if options[:report]
247 + result_collector = ResultCollector.new
248 + else
249 + result_collector = nil
250 + end
251 +
252 + engine = (Grader::Engine.
253 + new(:reporter =>
254 + Grader::SubmissionReporter.new(:dry_run => dry_run,
255 + :result_collector => result_collector)))
202 runner = Grader::Runner.new(engine, grader_proc)
256 runner = Grader::Runner.new(engine, grader_proc)
203 -
257 +
204 grader_proc.report_active if grader_proc!=nil
258 grader_proc.report_active if grader_proc!=nil
205 -
259 +
206 ARGV.each do |prob_name|
260 ARGV.each do |prob_name|
207 prob = Problem.find_by_name(prob_name)
261 prob = Problem.find_by_name(prob_name)
208 if prob==nil
262 if prob==nil
209 puts "cannot find problem: #{prob_name}"
263 puts "cannot find problem: #{prob_name}"
210 else
264 else
211 runner.grade_problem(prob)
265 runner.grade_problem(prob)
212 end
266 end
213 end
267 end
214
268
269 + if options[:report]
270 + result_collector.print_report_by_user
271 + end
272 +
215 when "sub"
273 when "sub"
216 engine = Grader::Engine.new
274 engine = Grader::Engine.new
217 runner = Grader::Runner.new(engine, grader_proc)
275 runner = Grader::Runner.new(engine, grader_proc)
218
276
219 grader_proc.report_active if grader_proc!=nil
277 grader_proc.report_active if grader_proc!=nil
220
278
221 ARGV.each do |sub_id|
279 ARGV.each do |sub_id|
222 puts "Grading #{sub_id}"
280 puts "Grading #{sub_id}"
223 begin
281 begin
224 submission = Submission.find(sub_id.to_i)
282 submission = Submission.find(sub_id.to_i)
225 rescue ActiveRecord::RecordNotFound
283 rescue ActiveRecord::RecordNotFound
226 puts "Record not found"
284 puts "Record not found"
227 submission = nil
285 submission = nil
228 end
286 end
229
287
230 if submission!=nil
288 if submission!=nil
231 runner.grade_submission(submission)
289 runner.grade_submission(submission)
232 end
290 end
233 end
291 end
234
292
235 else
293 else
236 display_manual
294 display_manual
237 exit(0)
295 exit(0)
238 end
296 end
239
297
@@ -1,69 +1,77
1 require 'fileutils'
1 require 'fileutils'
2 require 'ftools'
2 require 'ftools'
3 require File.join(File.dirname(__FILE__),'dir_init')
3 require File.join(File.dirname(__FILE__),'dir_init')
4
4
5 module Grader
5 module Grader
6
6
7 #
7 #
8 # A grader engine grades a submission, against anything: a test
8 # A grader engine grades a submission, against anything: a test
9 # data, or a user submitted test data. It uses two helpers objects:
9 # data, or a user submitted test data. It uses two helpers objects:
10 # room_maker and reporter.
10 # room_maker and reporter.
11 #
11 #
12 class Engine
12 class Engine
13
13
14 attr_writer :room_maker
14 attr_writer :room_maker
15 attr_writer :reporter
15 attr_writer :reporter
16
16
17 - def initialize(room_maker=nil, reporter=nil)
17 + def initialize(options={})
18 + # default options
19 + if not options.include? :room_maker
20 + options[:room_maker] = Grader::SubmissionRoomMaker.new
21 + end
22 + if not options.include? :reporter
23 + options[:reporter] = Grader::SubmissionReporter.new
24 + end
25 +
18 @config = Grader::Configuration.get_instance
26 @config = Grader::Configuration.get_instance
19
27
20 - @room_maker = room_maker || Grader::SubmissionRoomMaker.new
28 + @room_maker = options[:room_maker]
21 - @reporter = reporter || Grader::SubmissionReporter.new
29 + @reporter = options[:reporter]
22 end
30 end
23
31
24 # takes a submission, asks room_maker to produce grading directories,
32 # takes a submission, asks room_maker to produce grading directories,
25 # calls grader scripts, and asks reporter to save the result
33 # calls grader scripts, and asks reporter to save the result
26 def grade(submission)
34 def grade(submission)
27 current_dir = `pwd`.chomp
35 current_dir = `pwd`.chomp
28
36
29 user = submission.user
37 user = submission.user
30 problem = submission.problem
38 problem = submission.problem
31
39
32 # TODO: will have to create real exception for this
40 # TODO: will have to create real exception for this
33 if user==nil or problem == nil
41 if user==nil or problem == nil
34 @reporter.report_error(submission,"Grading error: problem with submission")
42 @reporter.report_error(submission,"Grading error: problem with submission")
35 #raise "engine: user or problem is nil"
43 #raise "engine: user or problem is nil"
36 end
44 end
37
45
38 # TODO: this is another hack so that output only task can be judged
46 # TODO: this is another hack so that output only task can be judged
39 if submission.language!=nil
47 if submission.language!=nil
40 language = submission.language.name
48 language = submission.language.name
41 lang_ext = submission.language.ext
49 lang_ext = submission.language.ext
42 else
50 else
43 language = 'c'
51 language = 'c'
44 lang_ext = 'c'
52 lang_ext = 'c'
45 end
53 end
46
54
47 # FIX THIS
55 # FIX THIS
48 talk 'some hack on language'
56 talk 'some hack on language'
49 if language == 'cpp'
57 if language == 'cpp'
50 language = 'c++'
58 language = 'c++'
51 end
59 end
52
60
53 # COMMENT: should it be only source.ext?
61 # COMMENT: should it be only source.ext?
54 if problem!=nil
62 if problem!=nil
55 source_name = "#{problem.name}.#{lang_ext}"
63 source_name = "#{problem.name}.#{lang_ext}"
56 else
64 else
57 source_name = "source.#{lang_ext}"
65 source_name = "source.#{lang_ext}"
58 end
66 end
59
67
60 begin
68 begin
61 grading_dir = @room_maker.produce_grading_room(submission)
69 grading_dir = @room_maker.produce_grading_room(submission)
62 @room_maker.save_source(submission,source_name)
70 @room_maker.save_source(submission,source_name)
63 problem_home = @room_maker.find_problem_home(submission)
71 problem_home = @room_maker.find_problem_home(submission)
64
72
65 # puts "GRADING DIR: #{grading_dir}"
73 # puts "GRADING DIR: #{grading_dir}"
66 # puts "PROBLEM DIR: #{problem_home}"
74 # puts "PROBLEM DIR: #{problem_home}"
67
75
68 if !FileTest.exist?(problem_home)
76 if !FileTest.exist?(problem_home)
69 raise "No test data."
77 raise "No test data."
@@ -1,89 +1,97
1 module Grader
1 module Grader
2
2
3 class SubmissionRoomMaker
3 class SubmissionRoomMaker
4 def initialize
4 def initialize
5 @config = Grader::Configuration.get_instance
5 @config = Grader::Configuration.get_instance
6 end
6 end
7
7
8 def produce_grading_room(submission)
8 def produce_grading_room(submission)
9 user = submission.user
9 user = submission.user
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(dry_run=false)
35 + def initialize(options={})
36 + options = {:dry_run => false, :result_collector => nil}.merge(options)
36 @config = Grader::Configuration.get_instance
37 @config = Grader::Configuration.get_instance
37 - @dry_run = dry_run
38 + @dry_run = options[:dry_run]
39 + @result_collector = options[:result_collector]
38 end
40 end
39
41
40 def report(sub,test_result_dir)
42 def report(sub,test_result_dir)
41 - save_result(sub,read_result(test_result_dir))
43 + result = read_result(test_result_dir)
44 + if @result_collector
45 + @result_collector.save(sub.user,
46 + sub.problem,
47 + result)
48 + end
49 + save_result(sub,result)
42 end
50 end
43
51
44 def report_error(sub,msg)
52 def report_error(sub,msg)
45 save_result(sub,{:points => 0,
53 save_result(sub,{:points => 0,
46 :comment => "Grading error: #{msg}" })
54 :comment => "Grading error: #{msg}" })
47 end
55 end
48
56
49 protected
57 protected
50 def read_result(test_result_dir)
58 def read_result(test_result_dir)
51 cmp_msg_fname = "#{test_result_dir}/compiler_message"
59 cmp_msg_fname = "#{test_result_dir}/compiler_message"
52 if FileTest.exist?(cmp_msg_fname)
60 if FileTest.exist?(cmp_msg_fname)
53 cmp_file = File.open(cmp_msg_fname)
61 cmp_file = File.open(cmp_msg_fname)
54 cmp_msg = cmp_file.read
62 cmp_msg = cmp_file.read
55 cmp_file.close
63 cmp_file.close
56 else
64 else
57 cmp_msg = ""
65 cmp_msg = ""
58 end
66 end
59
67
60 result_fname = "#{test_result_dir}/result"
68 result_fname = "#{test_result_dir}/result"
61 comment_fname = "#{test_result_dir}/comment"
69 comment_fname = "#{test_result_dir}/comment"
62 if FileTest.exist?(result_fname)
70 if FileTest.exist?(result_fname)
63 comment = ""
71 comment = ""
64 begin
72 begin
65 result_file = File.open(result_fname)
73 result_file = File.open(result_fname)
66 result = result_file.readline.to_i
74 result = result_file.readline.to_i
67 result_file.close
75 result_file.close
68 rescue
76 rescue
69 result = 0
77 result = 0
70 comment = "error reading result file."
78 comment = "error reading result file."
71 end
79 end
72
80
73 begin
81 begin
74 comment_file = File.open(comment_fname)
82 comment_file = File.open(comment_fname)
75 comment += comment_file.readline.chomp
83 comment += comment_file.readline.chomp
76 comment_file.close
84 comment_file.close
77 rescue
85 rescue
78 comment += ""
86 comment += ""
79 end
87 end
80
88
81 return {:points => result,
89 return {:points => result,
82 :comment => comment,
90 :comment => comment,
83 :cmp_msg => cmp_msg}
91 :cmp_msg => cmp_msg}
84 else
92 else
85 if FileTest.exist?("#{test_result_dir}/a.out")
93 if FileTest.exist?("#{test_result_dir}/a.out")
86 return {:points => 0,
94 return {:points => 0,
87 :comment => 'error during grading',
95 :comment => 'error during grading',
88 :cmp_msg => cmp_msg}
96 :cmp_msg => cmp_msg}
89 else
97 else
@@ -111,98 +111,98
111 it "should not allow malicious submission to open files" do
111 it "should not allow malicious submission to open files" do
112 problem_test_yesno = stub(Problem,
112 problem_test_yesno = stub(Problem,
113 :id => 1, :name => 'test_yesno',
113 :id => 1, :name => 'test_yesno',
114 :full_score => 10)
114 :full_score => 10)
115 grader_should(:grade => "yesno_open_file.c",
115 grader_should(:grade => "yesno_open_file.c",
116 :on => problem_test_yesno,
116 :on => problem_test_yesno,
117 :and_report => {
117 :and_report => {
118 :score => 0,
118 :score => 0,
119 :comment => /(-|x)/})
119 :comment => /(-|x)/})
120 end
120 end
121
121
122 def grader_should(args)
122 def grader_should(args)
123 @user1 = stub(User,
123 @user1 = stub(User,
124 :id => 1, :login => 'user1')
124 :id => 1, :login => 'user1')
125 submission =
125 submission =
126 create_submission_from_file(1, @user1, args[:on], args[:grade])
126 create_submission_from_file(1, @user1, args[:on], args[:grade])
127 submission.should_receive(:graded_at=)
127 submission.should_receive(:graded_at=)
128
128
129 expected_score = args[:and_report][:score]
129 expected_score = args[:and_report][:score]
130 expected_comment = args[:and_report][:comment]
130 expected_comment = args[:and_report][:comment]
131 if args[:and_report][:compiler_message]!=nil
131 if args[:and_report][:compiler_message]!=nil
132 expected_compiler_message = args[:and_report][:compiler_message]
132 expected_compiler_message = args[:and_report][:compiler_message]
133 else
133 else
134 expected_compiler_message = ''
134 expected_compiler_message = ''
135 end
135 end
136
136
137 submission.should_receive(:points=).with(expected_score)
137 submission.should_receive(:points=).with(expected_score)
138 submission.should_receive(:grader_comment=).with(expected_comment)
138 submission.should_receive(:grader_comment=).with(expected_comment)
139 submission.should_receive(:compiler_message=).with(expected_compiler_message)
139 submission.should_receive(:compiler_message=).with(expected_compiler_message)
140 submission.should_receive(:save)
140 submission.should_receive(:save)
141
141
142 @engine.grade(submission)
142 @engine.grade(submission)
143 end
143 end
144
144
145 protected
145 protected
146
146
147 def create_normal_submission_mock_from_file(source_fname)
147 def create_normal_submission_mock_from_file(source_fname)
148 create_submission_from_file(1, @user_user1, @problem_test_normal, source_fname)
148 create_submission_from_file(1, @user_user1, @problem_test_normal, source_fname)
149 end
149 end
150
150
151 end
151 end
152
152
153 describe "A grader engine, when grading test requests" do
153 describe "A grader engine, when grading test requests" do
154
154
155 include GraderEngineHelperMethods
155 include GraderEngineHelperMethods
156
156
157 before(:each) do
157 before(:each) do
158 @config = Grader::Configuration.get_instance
158 @config = Grader::Configuration.get_instance
159 - @engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
159 + @engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
160 - Grader::TestRequestReporter.new)
160 + :reporter => Grader::TestRequestReporter.new)
161 init_sandbox
161 init_sandbox
162 end
162 end
163
163
164 it "should report error if there is no problem template" do
164 it "should report error if there is no problem template" do
165 problem = stub(Problem,
165 problem = stub(Problem,
166 :id => 1, :name => 'nothing')
166 :id => 1, :name => 'nothing')
167 grader_should(:grade => 'test1_correct.c',
167 grader_should(:grade => 'test1_correct.c',
168 :on => problem,
168 :on => problem,
169 :with => 'in1.txt',
169 :with => 'in1.txt',
170 :and_report => {
170 :and_report => {
171 :graded_at= => nil,
171 :graded_at= => nil,
172 :compiler_message= => '',
172 :compiler_message= => '',
173 :grader_comment= => '',
173 :grader_comment= => '',
174 :running_stat= => /template not found/,
174 :running_stat= => /template not found/,
175 :running_time= => nil,
175 :running_time= => nil,
176 :exit_status= => nil,
176 :exit_status= => nil,
177 :memory_usage= => nil,
177 :memory_usage= => nil,
178 :save => nil})
178 :save => nil})
179 end
179 end
180
180
181 it "should run test request and produce output file" do
181 it "should run test request and produce output file" do
182 problem = stub(Problem,
182 problem = stub(Problem,
183 :id => 1, :name => 'test_normal')
183 :id => 1, :name => 'test_normal')
184 grader_should(:grade => 'test1_correct.c',
184 grader_should(:grade => 'test1_correct.c',
185 :on => problem,
185 :on => problem,
186 :with => 'in1.txt',
186 :with => 'in1.txt',
187 :and_report => {
187 :and_report => {
188 :graded_at= => nil,
188 :graded_at= => nil,
189 :compiler_message= => '',
189 :compiler_message= => '',
190 :grader_comment= => '',
190 :grader_comment= => '',
191 :running_stat= => /0.0\d* sec./,
191 :running_stat= => /0.0\d* sec./,
192 :output_file_name= => lambda { |fname|
192 :output_file_name= => lambda { |fname|
193 File.exists?(fname).should be_true
193 File.exists?(fname).should be_true
194 },
194 },
195 :running_time= => nil,
195 :running_time= => nil,
196 :exit_status= => nil,
196 :exit_status= => nil,
197 :memory_usage= => nil,
197 :memory_usage= => nil,
198 :save => nil})
198 :save => nil})
199 end
199 end
200
200
201 it "should clean up problem directory after running test request" do
201 it "should clean up problem directory after running test request" do
202 problem = stub(Problem,
202 problem = stub(Problem,
203 :id => 1, :name => 'test_normal')
203 :id => 1, :name => 'test_normal')
204 grader_should(:grade => 'test1_correct.c',
204 grader_should(:grade => 'test1_correct.c',
205 :on => problem,
205 :on => problem,
206 :with => 'in1.txt',
206 :with => 'in1.txt',
207 :and_report => {
207 :and_report => {
208 :graded_at= => nil,
208 :graded_at= => nil,
You need to be logged in to leave comments. Login now