Description:
[grader] extracted test_request info into new stat columns git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@163 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r41:d4e37450ddbc - - 3 files changed: 39 inserted, 9 deleted

@@ -11,180 +11,196
11 # - prepare problem configuration for grading --- basically it copy
11 # - prepare problem configuration for grading --- basically it copy
12 # all config files, and copy user's input into the testcase
12 # all config files, and copy user's input into the testcase
13 # directory. First, it finds the template from problem template
13 # directory. First, it finds the template from problem template
14 # directory; if it can't find a template, it'll use the template
14 # directory; if it can't find a template, it'll use the template
15 # from default template.
15 # from default template.
16 class TestRequestRoomMaker
16 class TestRequestRoomMaker
17 def initialize
17 def initialize
18 @config = Grader::Configuration.get_instance
18 @config = Grader::Configuration.get_instance
19 end
19 end
20
20
21 def produce_grading_room(test_request)
21 def produce_grading_room(test_request)
22 grading_room = grading_room_dir(test_request)
22 grading_room = grading_room_dir(test_request)
23 FileUtils.mkdir_p(grading_room)
23 FileUtils.mkdir_p(grading_room)
24 grading_room
24 grading_room
25 end
25 end
26
26
27 def find_problem_home(test_request)
27 def find_problem_home(test_request)
28 problem_name = test_request.problem_name
28 problem_name = test_request.problem_name
29
29
30 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
30 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
31
31
32 raise "Test Request: error template not found" if !File.exists?(template_dir)
32 raise "Test Request: error template not found" if !File.exists?(template_dir)
33
33
34 problem_home = problem_home_dir(test_request)
34 problem_home = problem_home_dir(test_request)
35 FileUtils.mkdir_p(problem_home)
35 FileUtils.mkdir_p(problem_home)
36
36
37 copy_problem_template(template_dir,problem_home)
37 copy_problem_template(template_dir,problem_home)
38 link_input_file(test_request,problem_home)
38 link_input_file(test_request,problem_home)
39
39
40 problem_home
40 problem_home
41 end
41 end
42
42
43 def save_source(test_request,source_name)
43 def save_source(test_request,source_name)
44 dir = self.produce_grading_room(test_request)
44 dir = self.produce_grading_room(test_request)
45 submission = test_request.submission
45 submission = test_request.submission
46 f = File.open("#{dir}/#{source_name}","w")
46 f = File.open("#{dir}/#{source_name}","w")
47 f.write(submission.source)
47 f.write(submission.source)
48 f.close
48 f.close
49 end
49 end
50
50
51 def clean_up(test_request)
51 def clean_up(test_request)
52 problem_home = problem_home_dir(test_request)
52 problem_home = problem_home_dir(test_request)
53 remove_data_files(problem_home)
53 remove_data_files(problem_home)
54 end
54 end
55
55
56 protected
56 protected
57 def grading_room_dir(test_request)
57 def grading_room_dir(test_request)
58 problem_name = test_request.problem_name
58 problem_name = test_request.problem_name
59 user = test_request.user
59 user = test_request.user
60 "#{@config.user_result_dir}" +
60 "#{@config.user_result_dir}" +
61 "/#{user.login}/test_request" +
61 "/#{user.login}/test_request" +
62 "/#{problem_name}/#{test_request.id}"
62 "/#{problem_name}/#{test_request.id}"
63 end
63 end
64
64
65 def problem_home_dir(test_request)
65 def problem_home_dir(test_request)
66 problem_name = test_request.problem_name
66 problem_name = test_request.problem_name
67 user = test_request.user
67 user = test_request.user
68 "#{@config.user_result_dir}" +
68 "#{@config.user_result_dir}" +
69 "/#{user.login}/test_request/#{problem_name}"
69 "/#{user.login}/test_request/#{problem_name}"
70 end
70 end
71
71
72 def copy_problem_template(template_dir,problem_home)
72 def copy_problem_template(template_dir,problem_home)
73 cmd = "cp -R #{template_dir}/* #{problem_home}"
73 cmd = "cp -R #{template_dir}/* #{problem_home}"
74 system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
74 system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
75 end
75 end
76
76
77 def link_input_file(test_request,problem_home)
77 def link_input_file(test_request,problem_home)
78 cmd = "ln -s #{test_request.input_file_name} #{problem_home}/test_cases/1/input-1.txt"
78 cmd = "ln -s #{test_request.input_file_name} #{problem_home}/test_cases/1/input-1.txt"
79 system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
79 system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
80 end
80 end
81
81
82 def remove_data_files(problem_home)
82 def remove_data_files(problem_home)
83 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
83 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
84 cmd = "rm #{problem_home}/test_cases/1/*"
84 cmd = "rm #{problem_home}/test_cases/1/*"
85 system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
85 system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
86 end
86 end
87 end
87 end
88
88
89 def system_and_raise_when_fail(cmd,msg)
89 def system_and_raise_when_fail(cmd,msg)
90 if !system(cmd)
90 if !system(cmd)
91 raise msg
91 raise msg
92 end
92 end
93 end
93 end
94
94
95 end
95 end
96
96
97 class TestRequestReporter
97 class TestRequestReporter
98 def initialize
98 def initialize
99 @config = Grader::Configuration.get_instance
99 @config = Grader::Configuration.get_instance
100 end
100 end
101
101
102 def report(test_request,test_result_dir)
102 def report(test_request,test_result_dir)
103 save_result(test_request,read_result(test_result_dir))
103 save_result(test_request,read_result(test_result_dir))
104 end
104 end
105
105
106 def report_error(test_request, msg)
106 def report_error(test_request, msg)
107 - save_result(test_request, {:running_stat => "#{msg}"})
107 + save_result(test_request, {:running_stat => {:msg => "#{msg}"}})
108 end
108 end
109
109
110 protected
110 protected
111 def read_result(test_result_dir)
111 def read_result(test_result_dir)
112 # TODO:
112 # TODO:
113 cmp_msg_fname = "#{test_result_dir}/compiler_message"
113 cmp_msg_fname = "#{test_result_dir}/compiler_message"
114 cmp_file = File.open(cmp_msg_fname)
114 cmp_file = File.open(cmp_msg_fname)
115 cmp_msg = cmp_file.read
115 cmp_msg = cmp_file.read
116 cmp_file.close
116 cmp_file.close
117
117
118 result_file_name = "#{test_result_dir}/1/result"
118 result_file_name = "#{test_result_dir}/1/result"
119
119
120 if File.exists?(result_file_name)
120 if File.exists?(result_file_name)
121 output_file_name = "#{test_result_dir}/1/output.txt"
121 output_file_name = "#{test_result_dir}/1/output.txt"
122 results = File.open("#{test_result_dir}/1/result").readlines
122 results = File.open("#{test_result_dir}/1/result").readlines
123 stat = format_running_stat(results)
123 stat = format_running_stat(results)
124
124
125 return {
125 return {
126 :output_file_name => output_file_name,
126 :output_file_name => output_file_name,
127 :running_stat => stat,
127 :running_stat => stat,
128 :comment => "",
128 :comment => "",
129 :cmp_msg => cmp_msg}
129 :cmp_msg => cmp_msg}
130 else
130 else
131 return {
131 return {
132 - :running_stat => "",
132 + :running_stat => nil,
133 :comment => "Compilation error",
133 :comment => "Compilation error",
134 :cmp_msg => cmp_msg}
134 :cmp_msg => cmp_msg}
135 end
135 end
136 end
136 end
137
137
138 def format_running_stat(results)
138 def format_running_stat(results)
139 running_time_line = results[-1]
139 running_time_line = results[-1]
140
140
141 + # extract exit status line
141 run_stat = ""
142 run_stat = ""
142 if !(/[Cc]orrect/.match(results[0]))
143 if !(/[Cc]orrect/.match(results[0]))
143 run_stat = results[0].chomp
144 run_stat = results[0].chomp
145 + else
146 + run_stat = 'Program exited normally'
144 end
147 end
145
148
149 + # extract running time
146 if res = /r(.*)u(.*)s/.match(running_time_line)
150 if res = /r(.*)u(.*)s/.match(running_time_line)
147 seconds = (res[1].to_f + res[2].to_f)
151 seconds = (res[1].to_f + res[2].to_f)
148 time_stat = "Time used: #{seconds} sec."
152 time_stat = "Time used: #{seconds} sec."
149 else
153 else
154 + seconds = nil
150 time_stat = "Time used: n/a sec."
155 time_stat = "Time used: n/a sec."
151 end
156 end
152 - return "#{run_stat}\n#{time_stat}"
157 + return {
158 + :msg => "#{run_stat}\n#{time_stat}",
159 + :running_time => seconds,
160 + :exit_status => run_stat
161 + }
153 end
162 end
154
163
155 def save_result(test_request,result)
164 def save_result(test_request,result)
156 if result[:output_file_name]!=nil
165 if result[:output_file_name]!=nil
157 test_request.output_file_name = link_output_file(test_request,
166 test_request.output_file_name = link_output_file(test_request,
158 result[:output_file_name])
167 result[:output_file_name])
159 end
168 end
160 test_request.graded_at = Time.now
169 test_request.graded_at = Time.now
161 test_request.compiler_message = (result[:cmp_msg] or '')
170 test_request.compiler_message = (result[:cmp_msg] or '')
162 test_request.grader_comment = (result[:comment] or '')
171 test_request.grader_comment = (result[:comment] or '')
163 - test_request.running_stat = (result[:running_stat] or '')
172 + if result[:running_stat]!=nil
173 + test_request.running_stat = (result[:running_stat][:msg] or '')
174 + test_request.running_time = (result[:running_stat][:running_time] or nil)
175 + test_request.exit_status = (result[:running_stat][:exit_status])
176 + test_request.memory_usage = nil # should be added later
177 + else
178 + test_request.running_stat = ''
179 + end
164 test_request.save
180 test_request.save
165 end
181 end
166
182
167 protected
183 protected
168 def link_output_file(test_request, fname)
184 def link_output_file(test_request, fname)
169 target_file_name = random_output_file_name(test_request.user,
185 target_file_name = random_output_file_name(test_request.user,
170 test_request.problem)
186 test_request.problem)
171 FileUtils.mkdir_p(File.dirname(target_file_name))
187 FileUtils.mkdir_p(File.dirname(target_file_name))
172 cmd = "ln -s #{fname} #{target_file_name}"
188 cmd = "ln -s #{fname} #{target_file_name}"
173 if !system(cmd)
189 if !system(cmd)
174 raise "TestRequestReporter: cannot move output file"
190 raise "TestRequestReporter: cannot move output file"
175 end
191 end
176 return target_file_name
192 return target_file_name
177 end
193 end
178
194
179 def random_output_file_name(user,problem)
195 def random_output_file_name(user,problem)
180 problem_name = TestRequest.name_of(problem)
196 problem_name = TestRequest.name_of(problem)
181 begin
197 begin
182 tmpname = "#{@config.test_request_output_base_dir}" +
198 tmpname = "#{@config.test_request_output_base_dir}" +
183 "/#{user.login}/#{problem_name}/#{rand(10000)}"
199 "/#{user.login}/#{problem_name}/#{rand(10000)}"
184 end while File.exists?(tmpname)
200 end while File.exists?(tmpname)
185 tmpname
201 tmpname
186 end
202 end
187
203
188 end
204 end
189
205
190 end
206 end
@@ -1,21 +1,23
1 #include <stdio.h>
1 #include <stdio.h>
2 #include <stdlib.h>
2 #include <stdlib.h>
3 + #include <unistd.h>
3
4
4 int main()
5 int main()
5 {
6 {
6 int a,b;
7 int a,b;
7
8
8 int c=0;
9 int c=0;
9
10
10 scanf("%d %d",&a,&b);
11 scanf("%d %d",&a,&b);
11 printf("%d\n",a+b);
12 printf("%d\n",a+b);
12
13
13 - for(a=0; a<2; a++) {
14 + sleep(1);
14 - while(c<1550000000) {
15 +
15 - c++;
16 + c = 0;
16 - b+=c;
17 + while(c<1000000000) {
17 - }
18 + c++;
19 + b+=c;
18 }
20 }
19 exit(0);
21 exit(0);
20 }
22 }
21
23
@@ -79,202 +79,214
79 :and_report => {
79 :and_report => {
80 :score => 10,
80 :score => 10,
81 :comment => /FAILED: [^P]P/})
81 :comment => /FAILED: [^P]P/})
82 end
82 end
83
83
84 it "should score test runs correctly when submission fails in some test case" do
84 it "should score test runs correctly when submission fails in some test case" do
85 grader_should(:grade => "add_fail_test_case_1.c",
85 grader_should(:grade => "add_fail_test_case_1.c",
86 :on => @problem_test_normal,
86 :on => @problem_test_normal,
87 :and_report => {
87 :and_report => {
88 :score => 105,
88 :score => 105,
89 :comment => /^FAILED:/})
89 :comment => /^FAILED:/})
90 end
90 end
91
91
92 it "should fail submission with non-zero exit status" do
92 it "should fail submission with non-zero exit status" do
93 grader_should(:grade => "add_nonzero_exit_status.c",
93 grader_should(:grade => "add_nonzero_exit_status.c",
94 :on => @problem_test_normal,
94 :on => @problem_test_normal,
95 :and_report => {
95 :and_report => {
96 :score => 0,
96 :score => 0,
97 :comment => /^FAILED:/})
97 :comment => /^FAILED:/})
98 end
98 end
99
99
100 it "should not allow malicious submission to see PROBLEM_HOME" do
100 it "should not allow malicious submission to see PROBLEM_HOME" do
101 problem_test_yesno = stub(Problem,
101 problem_test_yesno = stub(Problem,
102 :id => 1, :name => 'test_yesno',
102 :id => 1, :name => 'test_yesno',
103 :full_score => 10)
103 :full_score => 10)
104 grader_should(:grade => "yesno_access_problem_home.c",
104 grader_should(:grade => "yesno_access_problem_home.c",
105 :on => problem_test_yesno,
105 :on => problem_test_yesno,
106 :and_report => {
106 :and_report => {
107 :score => 0,
107 :score => 0,
108 :comment => /^FAILED:/})
108 :comment => /^FAILED:/})
109 end
109 end
110
110
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 => /^FAILED:/})
119 :comment => /^FAILED:/})
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(Grader::TestRequestRoomMaker.new,
160 Grader::TestRequestReporter.new)
160 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,
176 + :exit_status= => nil,
177 + :memory_usage= => nil,
175 :save => nil})
178 :save => nil})
176 end
179 end
177
180
178 it "should run test request and produce output file" do
181 it "should run test request and produce output file" do
179 problem = stub(Problem,
182 problem = stub(Problem,
180 :id => 1, :name => 'test_normal')
183 :id => 1, :name => 'test_normal')
181 grader_should(:grade => 'test1_correct.c',
184 grader_should(:grade => 'test1_correct.c',
182 :on => problem,
185 :on => problem,
183 :with => 'in1.txt',
186 :with => 'in1.txt',
184 :and_report => {
187 :and_report => {
185 :graded_at= => nil,
188 :graded_at= => nil,
186 :compiler_message= => '',
189 :compiler_message= => '',
187 :grader_comment= => '',
190 :grader_comment= => '',
188 :running_stat= => /0.0 sec./,
191 :running_stat= => /0.0 sec./,
189 :output_file_name= => lambda { |fname|
192 :output_file_name= => lambda { |fname|
190 File.exists?(fname).should be_true
193 File.exists?(fname).should be_true
191 },
194 },
195 + :running_time= => nil,
196 + :exit_status= => nil,
197 + :memory_usage= => nil,
192 :save => nil})
198 :save => nil})
193 end
199 end
194
200
195 it "should clean up problem directory after running test request" do
201 it "should clean up problem directory after running test request" do
196 problem = stub(Problem,
202 problem = stub(Problem,
197 :id => 1, :name => 'test_normal')
203 :id => 1, :name => 'test_normal')
198 grader_should(:grade => 'test1_correct.c',
204 grader_should(:grade => 'test1_correct.c',
199 :on => problem,
205 :on => problem,
200 :with => 'in1.txt',
206 :with => 'in1.txt',
201 :and_report => {
207 :and_report => {
202 :graded_at= => nil,
208 :graded_at= => nil,
203 :compiler_message= => '',
209 :compiler_message= => '',
204 :grader_comment= => '',
210 :grader_comment= => '',
205 :running_stat= => nil,
211 :running_stat= => nil,
206 :output_file_name= => nil,
212 :output_file_name= => nil,
213 + :running_time= => nil,
214 + :exit_status= => nil,
215 + :memory_usage= => nil,
207 :save => nil})
216 :save => nil})
208 File.exists?(@config.user_result_dir + "/test_request/test_normal/test_cases/1/input-1.txt").should be_false
217 File.exists?(@config.user_result_dir + "/test_request/test_normal/test_cases/1/input-1.txt").should be_false
209 end
218 end
210
219
211 it "should compile test request with error and report compilation error" do
220 it "should compile test request with error and report compilation error" do
212 problem = stub(Problem,
221 problem = stub(Problem,
213 :id => 1, :name => 'test_normal')
222 :id => 1, :name => 'test_normal')
214 grader_should(:grade => 'test1_compile_error.c',
223 grader_should(:grade => 'test1_compile_error.c',
215 :on => problem,
224 :on => problem,
216 :with => 'in1.txt',
225 :with => 'in1.txt',
217 :and_report => {
226 :and_report => {
218 :graded_at= => nil,
227 :graded_at= => nil,
219 :compiler_message= => /.+/,
228 :compiler_message= => /.+/,
220 :grader_comment= => /[Cc]ompil.*error/,
229 :grader_comment= => /[Cc]ompil.*error/,
221 :running_stat= => '',
230 :running_stat= => '',
222 :save => nil})
231 :save => nil})
223 end
232 end
224
233
225 it "should report exit status" do
234 it "should report exit status" do
226 problem = stub(Problem,
235 problem = stub(Problem,
227 :id => 1, :name => 'test_normal')
236 :id => 1, :name => 'test_normal')
228 grader_should(:grade => 'add_nonzero_exit_status.c',
237 grader_should(:grade => 'add_nonzero_exit_status.c',
229 :on => problem,
238 :on => problem,
230 :with => 'in1.txt',
239 :with => 'in1.txt',
231 :and_report => {
240 :and_report => {
232 :graded_at= => nil,
241 :graded_at= => nil,
233 :compiler_message= => '',
242 :compiler_message= => '',
234 :grader_comment= => '',
243 :grader_comment= => '',
235 :running_stat= => /[Ee]xit.*status.*10.*0\.0 sec/m,
244 :running_stat= => /[Ee]xit.*status.*10.*0\.0 sec/m,
236 :output_file_name= => lambda { |fname|
245 :output_file_name= => lambda { |fname|
237 File.exists?(fname).should be_true
246 File.exists?(fname).should be_true
238 },
247 },
248 + :running_time= => nil,
249 + :exit_status= => /10/,
250 + :memory_usage= => nil,
239 :save => nil})
251 :save => nil})
240 end
252 end
241
253
242 protected
254 protected
243 def grader_should(args)
255 def grader_should(args)
244 @user1 = stub(User,
256 @user1 = stub(User,
245 :id => 1, :login => 'user1')
257 :id => 1, :login => 'user1')
246
258
247 problem = args[:on]
259 problem = args[:on]
248 input_file = @config.test_request_input_base_dir + "/" + args[:with]
260 input_file = @config.test_request_input_base_dir + "/" + args[:with]
249
261
250 submission =
262 submission =
251 create_submission_from_file(1, @user1, args[:on], args[:grade])
263 create_submission_from_file(1, @user1, args[:on], args[:grade])
252
264
253 test_request = stub(TestRequest,
265 test_request = stub(TestRequest,
254 :id => 1,
266 :id => 1,
255 :user => @user1,
267 :user => @user1,
256 :problem => problem,
268 :problem => problem,
257 :submission => submission,
269 :submission => submission,
258 :input_file_name => input_file,
270 :input_file_name => input_file,
259 :language => submission.language,
271 :language => submission.language,
260 :problem_name => problem.name)
272 :problem_name => problem.name)
261
273
262 expectations = args[:and_report]
274 expectations = args[:and_report]
263
275
264 expectations.each do |key,val|
276 expectations.each do |key,val|
265 if val==nil
277 if val==nil
266 test_request.should_receive(key)
278 test_request.should_receive(key)
267 elsif val.class == Proc
279 elsif val.class == Proc
268 test_request.should_receive(key) { |fname|
280 test_request.should_receive(key) { |fname|
269 val.call(fname)
281 val.call(fname)
270 }
282 }
271 else
283 else
272 test_request.should_receive(key).with(val)
284 test_request.should_receive(key).with(val)
273 end
285 end
274 end
286 end
275
287
276 @engine.grade(test_request)
288 @engine.grade(test_request)
277 end
289 end
278
290
279 end
291 end
280
292
You need to be logged in to leave comments. Login now