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

r165:6f663119800b - - 4 files changed: 20 inserted, 3 deleted

@@ -1,166 +1,180
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 require 'fileutils'
3 require 'fileutils'
4
4
5 ##############################
5 ##############################
6 #
6 #
7 # Standard Compile Script
7 # Standard Compile Script
8 #
8 #
9 # Supported compilers:
9 # Supported compilers:
10 # gcc, g++, and fpc.
10 # gcc, g++, and fpc.
11 #
11 #
12 ##############################
12 ##############################
13
13
14 def talk(str='')
14 def talk(str='')
15 if ENV['TALKATIVE']!=nil
15 if ENV['TALKATIVE']!=nil
16 puts str
16 puts str
17 end
17 end
18 if ENV['GRADER_LOGGING']!=nil
18 if ENV['GRADER_LOGGING']!=nil
19 log_fname = ENV['GRADER_LOGGING']
19 log_fname = ENV['GRADER_LOGGING']
20 fp = File.open(log_fname,"a")
20 fp = File.open(log_fname,"a")
21 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
21 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
22 fp.close
22 fp.close
23 end
23 end
24 end
24 end
25
25
26 C_COMPILER = "/usr/bin/gcc"
26 C_COMPILER = "/usr/bin/gcc"
27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
28 PASCAL_COMPILER = "/usr/bin/fpc"
28 PASCAL_COMPILER = "/usr/bin/fpc"
29 JAVA_COMPILER = "/usr/bin/javac"
29 JAVA_COMPILER = "/usr/bin/javac"
30 RUBY_INTERPRETER = "/usr/bin/ruby"
30 RUBY_INTERPRETER = "/usr/bin/ruby"
31 PYTHON_INTERPRETER = "/usr/bin/python"
31 PYTHON_INTERPRETER = "/usr/bin/python"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
33 + PHP_INTERPRETER = "/usr/bin/php"
33
34
34 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
35 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
35 CPLUSPLUS_OPTIONS = "-O2 -s -std=c++11 -static -DCONTEST -lm -Wall"
36 CPLUSPLUS_OPTIONS = "-O2 -s -std=c++11 -static -DCONTEST -lm -Wall"
36 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
37 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
37 JAVA_OPTIONS = ""
38 JAVA_OPTIONS = ""
38 PYTHON_OPTIONS = ""
39 PYTHON_OPTIONS = ""
40 + PHP_OPTIONS = "-l"
39
41
40 # Check for the correct number of arguments. Otherwise, print usage.
42 # Check for the correct number of arguments. Otherwise, print usage.
41 if ARGV.length == 0 or ARGV.length > 4
43 if ARGV.length == 0 or ARGV.length > 4
42 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
44 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
43 puts
45 puts
44 puts "<source-file> is defaulted to \"source\"."
46 puts "<source-file> is defaulted to \"source\"."
45 puts "<output-file> is defaulted to \"a.out\"."
47 puts "<output-file> is defaulted to \"a.out\"."
46 puts "<message-file> is defaulted to \"compiler_message\"."
48 puts "<message-file> is defaulted to \"compiler_message\"."
47 puts
49 puts
48 exit(127)
50 exit(127)
49 end
51 end
50
52
51 PARAMS = {
53 PARAMS = {
52 :source_file => [1,'source'],
54 :source_file => [1,'source'],
53 :output_file => [2,'a.out'],
55 :output_file => [2,'a.out'],
54 :message_file => [3,'compiler_message']
56 :message_file => [3,'compiler_message']
55 }
57 }
56
58
57 params = {}
59 params = {}
58 params[:prog_lang] = ARGV[0]
60 params[:prog_lang] = ARGV[0]
59 PARAMS.each_key do |param_name|
61 PARAMS.each_key do |param_name|
60 index, default = PARAMS[param_name]
62 index, default = PARAMS[param_name]
61 if ARGV.length > index
63 if ARGV.length > index
62 params[param_name] = ARGV[index]
64 params[param_name] = ARGV[index]
63 else
65 else
64 params[param_name] = default
66 params[param_name] = default
65 end
67 end
66 talk "#{param_name}: #{params[param_name]}"
68 talk "#{param_name}: #{params[param_name]}"
67 end
69 end
68
70
69 # Remove any remaining output files or message files.
71 # Remove any remaining output files or message files.
70 if FileTest.exists? params[:output_file]
72 if FileTest.exists? params[:output_file]
71 FileUtils.rm(params[:output_file])
73 FileUtils.rm(params[:output_file])
72 end
74 end
73 if FileTest.exists? params[:message_file]
75 if FileTest.exists? params[:message_file]
74 FileUtils.rm(params[:message_file])
76 FileUtils.rm(params[:message_file])
75 end
77 end
76
78
77 # Check if the source file exists before attempt compiling.
79 # Check if the source file exists before attempt compiling.
78 if !FileTest.exists? params[:source_file]
80 if !FileTest.exists? params[:source_file]
79 talk("ERROR: The source file does not exist!")
81 talk("ERROR: The source file does not exist!")
80 open(params[:message_file],"w") do |f|
82 open(params[:message_file],"w") do |f|
81 f.puts "ERROR: The source file did not exist."
83 f.puts "ERROR: The source file did not exist."
82 end
84 end
83 exit(127)
85 exit(127)
84 end
86 end
85
87
86 if params[:prog_lang]=='cpp'
88 if params[:prog_lang]=='cpp'
87 params[:prog_lang] = 'c++'
89 params[:prog_lang] = 'c++'
88 end
90 end
89
91
90 # Compile.
92 # Compile.
91 case params[:prog_lang]
93 case params[:prog_lang]
92
94
93 when "c"
95 when "c"
94 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
96 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
95 system(command)
97 system(command)
96
98
97 when "c++"
99 when "c++"
98 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
100 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
99 system(command)
101 system(command)
100
102
101 when "pas"
103 when "pas"
102 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
104 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
103 system(command)
105 system(command)
104 FileUtils.mv("output", params[:output_file])
106 FileUtils.mv("output", params[:output_file])
105
107
106 when "java"
108 when "java"
107 #rename the file to the public class name
109 #rename the file to the public class name
108
110
109 #get the class name
111 #get the class name
110 classname = 'DUMMY'
112 classname = 'DUMMY'
111 File.foreach(params[:source_file]) do |line|
113 File.foreach(params[:source_file]) do |line|
112 md = /\s*public\s*class\s*(\w*)/.match(line)
114 md = /\s*public\s*class\s*(\w*)/.match(line)
113 classname=md[1] if md
115 classname=md[1] if md
114 end
116 end
115 system("cp #{params[:source_file]} #{classname}.java")
117 system("cp #{params[:source_file]} #{classname}.java")
116 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
118 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
117 system(command)
119 system(command)
118 if File.exists?(classname + ".class")
120 if File.exists?(classname + ".class")
119 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
121 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
120 end
122 end
121 if classname == 'DUMMY'
123 if classname == 'DUMMY'
122 File.open(params[:message_file],"w") {|file| file.write("Cannot find any public class in the source code\n")}
124 File.open(params[:message_file],"w") {|file| file.write("Cannot find any public class in the source code\n")}
123 end
125 end
124
126
125 when "ruby"
127 when "ruby"
126 command = "#{RUBY_INTERPRETER} -c #{params[:source_file]} 2> #{params[:message_file]}"
128 command = "#{RUBY_INTERPRETER} -c #{params[:source_file]} 2> #{params[:message_file]}"
127 if system(command)
129 if system(command)
128 File.open(params[:output_file],"w") do |out_file|
130 File.open(params[:output_file],"w") do |out_file|
129 out_file.puts "#!#{RUBY_INTERPRETER}"
131 out_file.puts "#!#{RUBY_INTERPRETER}"
130 File.open(params[:source_file],"r").each do |line|
132 File.open(params[:source_file],"r").each do |line|
131 out_file.print line
133 out_file.print line
132 end
134 end
133 end
135 end
134 File.chmod(0755, params[:output_file])
136 File.chmod(0755, params[:output_file])
135 end
137 end
136
138
137 when "python"
139 when "python"
138 command = "#{PYTHON_CHECKER} #{params[:source_file]} > #{params[:message_file]}"
140 command = "#{PYTHON_CHECKER} #{params[:source_file]} > #{params[:message_file]}"
139 if system(command)
141 if system(command)
140 #compile to python bytecode
142 #compile to python bytecode
141 command = "#{PYTHON_INTERPRETER} -m py_compile #{params[:source_file]}"
143 command = "#{PYTHON_INTERPRETER} -m py_compile #{params[:source_file]}"
142 puts "compile: #{command}"
144 puts "compile: #{command}"
143 system(command)
145 system(command)
144 puts "pwd: " + Dir.pwd
146 puts "pwd: " + Dir.pwd
145 Dir.new('.').each {|file| puts file}
147 Dir.new('.').each {|file| puts file}
146 File.open(params[:output_file],"w") do |out_file|
148 File.open(params[:output_file],"w") do |out_file|
147 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
149 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
148 end
150 end
149 File.chmod(0755, params[:output_file])
151 File.chmod(0755, params[:output_file])
150 FileUtils.cp("#{params[:source_file]}c",params[:output_file])
152 FileUtils.cp("#{params[:source_file]}c",params[:output_file])
151 end
153 end
152 -
154 +
155 + when "php"
156 + command = "#{PHP_INTERPRETER} #{PHP_OPTIONS} #{params[:source_file]} 2> #{params[:message_file]}"
157 + if system(command)
158 + File.open(params[:output_file],"w") do |out_file|
159 + out_file.puts "#!#{PHP_INTERPRETER}"
160 + File.open(params[:source_file],"r").each do |line|
161 + out_file.print line
162 + end
163 + end
164 + File.chmod(0755, params[:output_file])
165 + end
166 +
153 else
167 else
154 talk("ERROR: Invalid language specified!")
168 talk("ERROR: Invalid language specified!")
155 open(params[:message_file],"w") do |f|
169 open(params[:message_file],"w") do |f|
156 f.puts "ERROR: Invalid language specified!"
170 f.puts "ERROR: Invalid language specified!"
157 end
171 end
158 exit(127)
172 exit(127)
159 end
173 end
160
174
161 # Report success or failure.
175 # Report success or failure.
162 if FileTest.exists? params[:output_file]
176 if FileTest.exists? params[:output_file]
163 talk "Compilation was successful!"
177 talk "Compilation was successful!"
164 else
178 else
165 talk "ERROR: Something was wrong during the compilation!"
179 talk "ERROR: Something was wrong during the compilation!"
166 end
180 end
@@ -1,131 +1,131
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 CORRECT_MARK = 'P'
3 CORRECT_MARK = 'P'
4 INCORRECT_MARK = '-'
4 INCORRECT_MARK = '-'
5 TIMEOUT_MARK = 'T'
5 TIMEOUT_MARK = 'T'
6 RUN_ERROR_MARK = 'x'
6 RUN_ERROR_MARK = 'x'
7
7
8 def log(str='')
8 def log(str='')
9 if ENV['TALKATIVE']!=nil
9 if ENV['TALKATIVE']!=nil
10 puts str
10 puts str
11 end
11 end
12 if ENV['GRADER_LOGGING']!=nil
12 if ENV['GRADER_LOGGING']!=nil
13 log_fname = ENV['GRADER_LOGGING']
13 log_fname = ENV['GRADER_LOGGING']
14 fp = File.open(log_fname,"a")
14 fp = File.open(log_fname,"a")
15 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
15 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
16 fp.close
16 fp.close
17 end
17 end
18 end
18 end
19
19
20 def char_comment(comment)
20 def char_comment(comment)
21 if comment =~ /[Ii]ncorrect/
21 if comment =~ /[Ii]ncorrect/
22 INCORRECT_MARK
22 INCORRECT_MARK
23 elsif comment =~ /[Cc]orrect/
23 elsif comment =~ /[Cc]orrect/
24 CORRECT_MARK
24 CORRECT_MARK
25 elsif comment =~ /[Tt]ime/
25 elsif comment =~ /[Tt]ime/
26 TIMEOUT_MARK
26 TIMEOUT_MARK
27 elsif res = /^[Cc]omment:(.*)$/.match(comment)
27 elsif res = /^[Cc]omment:(.*)$/.match(comment)
28 res[1]
28 res[1]
29 else
29 else
30 RUN_ERROR_MARK # these are run time errors
30 RUN_ERROR_MARK # these are run time errors
31 end
31 end
32 end
32 end
33
33
34 def extract_time(t)
34 def extract_time(t)
35 - puts "TIME: #{t}"
35 + #puts "TIME: #{t}"
36 if (result=/^(.*)r(.*)u(.*)s(.*)kbytes/.match(t))
36 if (result=/^(.*)r(.*)u(.*)s(.*)kbytes/.match(t))
37 {:real => result[1], :user => result[2], :sys => result[3], :mem => result[4]}
37 {:real => result[1], :user => result[2], :sys => result[3], :mem => result[4]}
38 else
38 else
39 #{:real => 0, :user => 0, :sys => 0}
39 #{:real => 0, :user => 0, :sys => 0}
40 #puts "ERROR READING RUNNING TIME: #{t}"
40 #puts "ERROR READING RUNNING TIME: #{t}"
41 raise "Error reading running time: #{t}"
41 raise "Error reading running time: #{t}"
42 end
42 end
43 end
43 end
44
44
45 problem_home = ENV['PROBLEM_HOME']
45 problem_home = ENV['PROBLEM_HOME']
46 require "#{problem_home}/script/test_dsl.rb"
46 require "#{problem_home}/script/test_dsl.rb"
47 load "#{problem_home}/test_cases/all_tests.cfg"
47 load "#{problem_home}/test_cases/all_tests.cfg"
48 problem = Problem.get_instance
48 problem = Problem.get_instance
49
49
50 if problem.well_formed? == false
50 if problem.well_formed? == false
51 log "The problem specification is not well formed."
51 log "The problem specification is not well formed."
52 exit(127)
52 exit(127)
53 end
53 end
54
54
55 all_score = 0
55 all_score = 0
56 all_comment = ''
56 all_comment = ''
57 peak_memory = -1
57 peak_memory = -1
58 max_runtime = -1
58 max_runtime = -1
59 (1..(problem.runs.length-1)).each do |k|
59 (1..(problem.runs.length-1)).each do |k|
60 log "grade run #{k}"
60 log "grade run #{k}"
61 run = problem.runs[k]
61 run = problem.runs[k]
62 run_score = nil
62 run_score = nil
63 run_comment = ''
63 run_comment = ''
64 run_comment_short = ''
64 run_comment_short = ''
65 run.tests.each do |test_num|
65 run.tests.each do |test_num|
66 result_file_name = "#{test_num}/result"
66 result_file_name = "#{test_num}/result"
67 if not File.exists?(result_file_name)
67 if not File.exists?(result_file_name)
68 run_comment += "result file for test #{test_num} not found\n"
68 run_comment += "result file for test #{test_num} not found\n"
69 run_comment_short += RUN_ERROR_MARK
69 run_comment_short += RUN_ERROR_MARK
70 log "Cannot find the file #{test_num}/result!"
70 log "Cannot find the file #{test_num}/result!"
71 else
71 else
72 result_file = File.new(result_file_name, "r")
72 result_file = File.new(result_file_name, "r")
73 result_file_lines = result_file.readlines
73 result_file_lines = result_file.readlines
74 if result_file_lines.length>=3
74 if result_file_lines.length>=3
75 current_run_score = result_file_lines[1].to_i
75 current_run_score = result_file_lines[1].to_i
76 run_comment += result_file_lines[0]
76 run_comment += result_file_lines[0]
77 run_comment_short += char_comment(result_file_lines[0].chomp)
77 run_comment_short += char_comment(result_file_lines[0].chomp)
78
78
79 #update max runtime & memory
79 #update max runtime & memory
80 run_stat = extract_time result_file_lines[2]
80 run_stat = extract_time result_file_lines[2]
81 peak_memory = [peak_memory,run_stat[:mem].to_i].max
81 peak_memory = [peak_memory,run_stat[:mem].to_i].max
82 max_runtime = [max_runtime,run_stat[:user].to_f + run_stat[:sys].to_f].max
82 max_runtime = [max_runtime,run_stat[:user].to_f + run_stat[:sys].to_f].max
83 else
83 else
84 current_run_score = 0
84 current_run_score = 0
85 run_comment += "result file for test #{test_num} error\n"
85 run_comment += "result file for test #{test_num} error\n"
86 run_comment_short += RUN_ERROR_MARK
86 run_comment_short += RUN_ERROR_MARK
87 log "Error in #{test_num}/result!"
87 log "Error in #{test_num}/result!"
88 end
88 end
89
89
90 # the score of this run should be the minimum of the score for
90 # the score of this run should be the minimum of the score for
91 # each test case
91 # each test case
92 if (run_score==nil) or (run_score>current_run_score)
92 if (run_score==nil) or (run_score>current_run_score)
93 run_score = current_run_score
93 run_score = current_run_score
94 end
94 end
95 result_file.close
95 result_file.close
96 end
96 end
97 end
97 end
98
98
99 run_result_file = File.new("result-#{k}", "w")
99 run_result_file = File.new("result-#{k}", "w")
100 run_result_file.write run_score
100 run_result_file.write run_score
101 run_result_file.write "\n"
101 run_result_file.write "\n"
102 run_result_file.close
102 run_result_file.close
103
103
104 run_comment_file = File.new("comment-#{k}", "w")
104 run_comment_file = File.new("comment-#{k}", "w")
105 run_comment_file.write "#{run_comment}\n"
105 run_comment_file.write "#{run_comment}\n"
106 run_comment_file.close
106 run_comment_file.close
107
107
108 all_score = all_score + run_score
108 all_score = all_score + run_score
109
109
110 # append comment for test run with many test cases
110 # append comment for test run with many test cases
111 if run.tests.length > 1
111 if run.tests.length > 1
112 run_comment_short = '[' + run_comment_short + ']'
112 run_comment_short = '[' + run_comment_short + ']'
113 end
113 end
114 all_comment += run_comment_short
114 all_comment += run_comment_short
115 end
115 end
116
116
117 result_file = File.new("result", "w")
117 result_file = File.new("result", "w")
118 result_file.write all_score
118 result_file.write all_score
119 result_file.write "\n"
119 result_file.write "\n"
120 result_file.close
120 result_file.close
121
121
122 comment_file = File.new("comment", "w")
122 comment_file = File.new("comment", "w")
123 comment_file.write "#{all_comment}\n"
123 comment_file.write "#{all_comment}\n"
124 comment_file.close
124 comment_file.close
125
125
126
126
127 File.open("run_stat","w") do |file|
127 File.open("run_stat","w") do |file|
128 file.puts max_runtime
128 file.puts max_runtime
129 file.puts peak_memory
129 file.puts peak_memory
130 end
130 end
131
131
@@ -1,152 +1,152
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 require 'fileutils'
3 require 'fileutils'
4
4
5 def log(str='')
5 def log(str='')
6 if ENV['TALKATIVE']!=nil
6 if ENV['TALKATIVE']!=nil
7 puts str
7 puts str
8 end
8 end
9 if ENV['GRADER_LOGGING']!=nil
9 if ENV['GRADER_LOGGING']!=nil
10 log_fname = ENV['GRADER_LOGGING']
10 log_fname = ENV['GRADER_LOGGING']
11 fp = File.open(log_fname,"a")
11 fp = File.open(log_fname,"a")
12 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
12 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
13 fp.close
13 fp.close
14 end
14 end
15 end
15 end
16
16
17 problem_home = ENV['PROBLEM_HOME']
17 problem_home = ENV['PROBLEM_HOME']
18
18
19 def execute(command, error_message="")
19 def execute(command, error_message="")
20 if not system(command)
20 if not system(command)
21 msg = "ERROR: #{error_message}"
21 msg = "ERROR: #{error_message}"
22 log msg
22 log msg
23 raise(msg)
23 raise(msg)
24 end
24 end
25 end
25 end
26
26
27 def call_and_log(error_message)
27 def call_and_log(error_message)
28 begin
28 begin
29 yield
29 yield
30 rescue
30 rescue
31 msg = "ERROR: #{error_message}"
31 msg = "ERROR: #{error_message}"
32 log msg
32 log msg
33 raise msg
33 raise msg
34 end
34 end
35 end
35 end
36
36
37 def clear_and_create_empty_dir(dir)
37 def clear_and_create_empty_dir(dir)
38 FileUtils.rm_rf(dir, :secure => true)
38 FileUtils.rm_rf(dir, :secure => true)
39 call_and_log("Cannot make directory #{dir}.") { FileUtils.mkdir(dir) }
39 call_and_log("Cannot make directory #{dir}.") { FileUtils.mkdir(dir) }
40 end
40 end
41
41
42 # ARGV[0] --- language
42 # ARGV[0] --- language
43 # ARGV[1] --- program source file
43 # ARGV[1] --- program source file
44 # ARGV[2] --- test result directory
44 # ARGV[2] --- test result directory
45 # ARGV[3] --- sandbox directory
45 # ARGV[3] --- sandbox directory
46
46
47 if ARGV.length < 2 || ARGV.length > 4
47 if ARGV.length < 2 || ARGV.length > 4
48 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
48 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
49 puts " <sandbox-directory> is defaulted to ./sandbox"
49 puts " <sandbox-directory> is defaulted to ./sandbox"
50 puts " <test-result-directory> is defaulted to ./test-result"
50 puts " <test-result-directory> is defaulted to ./test-result"
51 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."
52 exit(127)
52 exit(127)
53 end
53 end
54
54
55 language = ARGV[0]
55 language = ARGV[0]
56 - if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python"
56 + if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python" && language != "php"
57 log "You specified a language that is not supported: #{language}."
57 log "You specified a language that is not supported: #{language}."
58 exit(127)
58 exit(127)
59 end
59 end
60
60
61 source_file = ARGV[1]
61 source_file = ARGV[1]
62 ENV['SOURCE_NAME'] = source_file
62 ENV['SOURCE_NAME'] = source_file
63 if File.exist?(source_file) == false
63 if File.exist?(source_file) == false
64 log "The source file does not exist."
64 log "The source file does not exist."
65 exit(127)
65 exit(127)
66 end
66 end
67
67
68 log "Making test result and sandbox directories..."
68 log "Making test result and sandbox directories..."
69
69
70 current_dir = FileUtils.pwd
70 current_dir = FileUtils.pwd
71 current_dir.strip!
71 current_dir.strip!
72
72
73 if ARGV.length >= 3
73 if ARGV.length >= 3
74 test_result_dir = ARGV[2]
74 test_result_dir = ARGV[2]
75 else
75 else
76 test_result_dir = "#{current_dir}/test-result"
76 test_result_dir = "#{current_dir}/test-result"
77 end
77 end
78
78
79 log "Test result directory: #{test_result_dir}"
79 log "Test result directory: #{test_result_dir}"
80 clear_and_create_empty_dir(test_result_dir)
80 clear_and_create_empty_dir(test_result_dir)
81
81
82 if ARGV.length >= 4
82 if ARGV.length >= 4
83 sandbox_dir = ARGV[3]
83 sandbox_dir = ARGV[3]
84 else
84 else
85 sandbox_dir = "#{current_dir}/sandbox"
85 sandbox_dir = "#{current_dir}/sandbox"
86 end
86 end
87 log "Sandbox directory: #{sandbox_dir}"
87 log "Sandbox directory: #{sandbox_dir}"
88 clear_and_create_empty_dir(sandbox_dir)
88 clear_and_create_empty_dir(sandbox_dir)
89
89
90 # Compile
90 # Compile
91 log
91 log
92 log "Compiling..."
92 log "Compiling..."
93 call_and_log("Cannot copy the source file to #{sandbox_dir}") {
93 call_and_log("Cannot copy the source file to #{sandbox_dir}") {
94 FileUtils.cp(source_file, sandbox_dir)
94 FileUtils.cp(source_file, sandbox_dir)
95 }
95 }
96 begin
96 begin
97 Dir.chdir sandbox_dir
97 Dir.chdir sandbox_dir
98 rescue
98 rescue
99 log "ERROR: Cannot change directory to #{sandbox_dir}."
99 log "ERROR: Cannot change directory to #{sandbox_dir}."
100 exit(127)
100 exit(127)
101 end
101 end
102 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
102 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
103 compile_message = open("compiler_message").read
103 compile_message = open("compiler_message").read
104 compile_message.strip!
104 compile_message.strip!
105 call_and_log("Cannot move the compiler message to #{test_result_dir}.") {
105 call_and_log("Cannot move the compiler message to #{test_result_dir}.") {
106 FileUtils.mv("compiler_message", test_result_dir)
106 FileUtils.mv("compiler_message", test_result_dir)
107 }
107 }
108 if !FileTest.exist?("a.out")
108 if !FileTest.exist?("a.out")
109 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
109 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
110 exit(127)
110 exit(127)
111 else
111 else
112 call_and_log("Cannot move the compiled program to #{test_result_dir}") {
112 call_and_log("Cannot move the compiled program to #{test_result_dir}") {
113 FileUtils.mv("a.out",test_result_dir)
113 FileUtils.mv("a.out",test_result_dir)
114 if language == "java" then Dir["*.class"].each { |file| FileUtils.mv(file,test_result_dir)} end
114 if language == "java" then Dir["*.class"].each { |file| FileUtils.mv(file,test_result_dir)} end
115 if language == "python" then Dir["*.pyc"].each { |file| FileUtils.mv(file,test_result_dir)} end
115 if language == "python" then Dir["*.pyc"].each { |file| FileUtils.mv(file,test_result_dir)} end
116 }
116 }
117 FileUtils.rm_rf("#{sandbox_dir}/.")
117 FileUtils.rm_rf("#{sandbox_dir}/.")
118 end
118 end
119
119
120 require "#{problem_home}/script/test_dsl.rb"
120 require "#{problem_home}/script/test_dsl.rb"
121 load "#{problem_home}/test_cases/all_tests.cfg"
121 load "#{problem_home}/test_cases/all_tests.cfg"
122 problem = Problem.get_instance
122 problem = Problem.get_instance
123
123
124 if problem.well_formed? == false
124 if problem.well_formed? == false
125 log "The problem specification is not well formed."
125 log "The problem specification is not well formed."
126 exit(127)
126 exit(127)
127 end
127 end
128
128
129 # Doing the testing.
129 # Doing the testing.
130 (1..(problem.num_tests)).each do |test_num|
130 (1..(problem.num_tests)).each do |test_num|
131
131
132 $stdout.print "[#{test_num}]"
132 $stdout.print "[#{test_num}]"
133 $stdout.flush
133 $stdout.flush
134
134
135 log "Test number: #{test_num}"
135 log "Test number: #{test_num}"
136
136
137 call_and_log("Cannot copy the compiled program into #{sandbox_dir}") {
137 call_and_log("Cannot copy the compiled program into #{sandbox_dir}") {
138 FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir, :preserve => true)
138 FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir, :preserve => true)
139 if language == "java" then Dir["#{test_result_dir}/*.class"].each { |file| FileUtils.cp(file,sandbox_dir)} end
139 if language == "java" then Dir["#{test_result_dir}/*.class"].each { |file| FileUtils.cp(file,sandbox_dir)} end
140 if language == "python" then Dir["#{test_result_dir}/*.pyc"].each { |file| FileUtils.cp(file,sandbox_dir)} end
140 if language == "python" then Dir["#{test_result_dir}/*.pyc"].each { |file| FileUtils.cp(file,sandbox_dir)} end
141 }
141 }
142
142
143 begin
143 begin
144 execute("#{problem_home}/script/run #{language} #{test_num} ", "Error occured during execution of the run script")
144 execute("#{problem_home}/script/run #{language} #{test_num} ", "Error occured during execution of the run script")
145 rescue
145 rescue
146 # do nothing
146 # do nothing
147 end
147 end
148
148
149 call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
149 call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
150 FileUtils.mkdir "#{test_result_dir}/#{test_num}"
150 FileUtils.mkdir "#{test_result_dir}/#{test_num}"
151 }
151 }
152 call_and_log("Cannot copy the result file into #{test_result_dir}/#{test_num}") {
152 call_and_log("Cannot copy the result file into #{test_result_dir}/#{test_num}") {
@@ -1,186 +1,189
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 require 'fileutils'
3 require 'fileutils'
4
4
5 def log(str='')
5 def log(str='')
6 if ENV['TALKATIVE']!=nil
6 if ENV['TALKATIVE']!=nil
7 puts str
7 puts str
8 end
8 end
9 if ENV['GRADER_LOGGING']!=nil
9 if ENV['GRADER_LOGGING']!=nil
10 log_fname = ENV['GRADER_LOGGING']
10 log_fname = ENV['GRADER_LOGGING']
11 fp = File.open(log_fname,"a")
11 fp = File.open(log_fname,"a")
12 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
12 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
13 fp.close
13 fp.close
14 end
14 end
15 end
15 end
16
16
17 def extract_time(t)
17 def extract_time(t)
18 # puts "TIME: #{t}"
18 # puts "TIME: #{t}"
19 if (result=/^(.*)r(.*)u(.*)s/.match(t))
19 if (result=/^(.*)r(.*)u(.*)s/.match(t))
20 {:real => result[1], :user => result[2], :sys => result[3]}
20 {:real => result[1], :user => result[2], :sys => result[3]}
21 else
21 else
22 #{:real => 0, :user => 0, :sys => 0}
22 #{:real => 0, :user => 0, :sys => 0}
23 #puts "ERROR READING RUNNING TIME: #{t}"
23 #puts "ERROR READING RUNNING TIME: #{t}"
24 raise "Error reading running time: #{t}"
24 raise "Error reading running time: #{t}"
25 end
25 end
26 end
26 end
27
27
28 def compile_box(source,bin)
28 def compile_box(source,bin)
29 system("g++ #{source} -o #{bin}")
29 system("g++ #{source} -o #{bin}")
30 end
30 end
31
31
32 if ARGV.length < 2 || ARGV.length > 3
32 if ARGV.length < 2 || ARGV.length > 3
33 puts "Usage: run <language> <test-num> [<program-name>]"
33 puts "Usage: run <language> <test-num> [<program-name>]"
34 exit(127)
34 exit(127)
35 end
35 end
36
36
37 language = ARGV[0]
37 language = ARGV[0]
38 test_num = ARGV[1].to_i
38 test_num = ARGV[1].to_i
39 if ARGV.length > 2
39 if ARGV.length > 2
40 program_name = ARGV[2]
40 program_name = ARGV[2]
41 else
41 else
42 program_name = "a.out"
42 program_name = "a.out"
43 end
43 end
44
44
45 problem_home = ENV['PROBLEM_HOME']
45 problem_home = ENV['PROBLEM_HOME']
46 source_name = ENV['SOURCE_NAME']
46 source_name = ENV['SOURCE_NAME']
47 require "#{problem_home}/script/test_dsl.rb"
47 require "#{problem_home}/script/test_dsl.rb"
48 load "#{problem_home}/test_cases/all_tests.cfg"
48 load "#{problem_home}/test_cases/all_tests.cfg"
49 problem = Problem.get_instance
49 problem = Problem.get_instance
50
50
51 sandbox_dir = Dir.getwd
51 sandbox_dir = Dir.getwd
52
52
53 if problem.well_formed? == false
53 if problem.well_formed? == false
54 log "The problem specification is not well formed."
54 log "The problem specification is not well formed."
55 exit(127)
55 exit(127)
56 end
56 end
57
57
58 # Check if the test number is okay.
58 # Check if the test number is okay.
59 if test_num <= 0 || test_num > problem.num_tests
59 if test_num <= 0 || test_num > problem.num_tests
60 log "You have specified a wrong test number."
60 log "You have specified a wrong test number."
61 exit(127)
61 exit(127)
62 end
62 end
63
63
64 #####################################
64 #####################################
65 # Set the relavant file names here. #
65 # Set the relavant file names here. #
66 #####################################
66 #####################################
67
67
68 input_file_name = "#{problem_home}/test_cases/#{test_num}/input-#{test_num}.txt"
68 input_file_name = "#{problem_home}/test_cases/#{test_num}/input-#{test_num}.txt"
69
69
70 #####################################
70 #####################################
71
71
72 time_limit = problem.get_time_limit test_num
72 time_limit = problem.get_time_limit test_num
73 mem_limit = problem.get_mem_limit(test_num) * 1024
73 mem_limit = problem.get_mem_limit(test_num) * 1024
74
74
75 # Copy the input file.
75 # Copy the input file.
76 #`cp #{problem_home}/test_cases/#{test_num}/#{input_file_name} .`
76 #`cp #{problem_home}/test_cases/#{test_num}/#{input_file_name} .`
77
77
78 # check if box is there, if not, compile it!
78 # check if box is there, if not, compile it!
79 if !File.exists?("#{problem_home}/script/box")
79 if !File.exists?("#{problem_home}/script/box")
80 log "WARNING: Compiling box: to increase efficiency, it should be compile manually"
80 log "WARNING: Compiling box: to increase efficiency, it should be compile manually"
81 compile_box("#{problem_home}/script/box.cc",
81 compile_box("#{problem_home}/script/box.cc",
82 "#{problem_home}/script/box")
82 "#{problem_home}/script/box")
83 end
83 end
84
84
85 # Hide PROBLEM_HOME
85 # Hide PROBLEM_HOME
86 ENV['PROBLEM_HOME'] = nil
86 ENV['PROBLEM_HOME'] = nil
87 ENV['SOURCE_NAME'] = nil
87 ENV['SOURCE_NAME'] = nil
88
88
89 # Run the program.
89 # Run the program.
90 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
90 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
91 #
91 #
92
92
93 JAVA_OPTION = "-s set_robust_list -s futex -s clone -s getppid -s clone -s wait4 -p /usr/bin/ -p ./"
93 JAVA_OPTION = "-s set_robust_list -s futex -s clone -s getppid -s clone -s wait4 -p /usr/bin/ -p ./"
94 RUBY_OPTION = "-p /usr/lib64/ -p /lib64/ -p /dev/urandom -p #{sandbox_dir}/#{program_name} -s set_robust_list -s sched_getaffinity -s clock_gettime -s sigaltstack -s pipe2 -s clone -s futex -s openat"
94 RUBY_OPTION = "-p /usr/lib64/ -p /lib64/ -p /dev/urandom -p #{sandbox_dir}/#{program_name} -s set_robust_list -s sched_getaffinity -s clock_gettime -s sigaltstack -s pipe2 -s clone -s futex -s openat"
95 PYTHON_OPTION = "-p /usr/lib64/ -p /lib64/ -p /usr/bin/ -p /usr/local/lib64/ -p /usr/local/lib/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p #{sandbox_dir}/#{source_name} -s set_robust_list -s openat -s recvmsg -s connect -s socket -s sendto -E PYTHONNOUSERSITE=yes"
95 PYTHON_OPTION = "-p /usr/lib64/ -p /lib64/ -p /usr/bin/ -p /usr/local/lib64/ -p /usr/local/lib/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p #{sandbox_dir}/#{source_name} -s set_robust_list -s openat -s recvmsg -s connect -s socket -s sendto -E PYTHONNOUSERSITE=yes"
96 + PHP_OPTION = "-p /usr/lib64/ -p/lib64/ -p /usr/bin/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p /usr/share/ -s setfsuid -s setfsgid -s openat -s set_robust_list -s futex "
96
97
97 case language
98 case language
98 when "java"
99 when "java"
99 # for java, extract the classname
100 # for java, extract the classname
100 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
101 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
101 classname = 'DUMMY'
102 classname = 'DUMMY'
102 File.open(program_name,"r").each do |line|
103 File.open(program_name,"r").each do |line|
103 classname = line
104 classname = line
104 end
105 end
105 #for java, we cannot really check the memory limit...
106 #for java, we cannot really check the memory limit...
106 run_command = "#{problem_home}/script/box -a 3 -f -T -t #{time_limit} #{JAVA_OPTION} -i #{input_file_name} -o output.txt /usr/bin/java #{classname} 2>run_result"
107 run_command = "#{problem_home}/script/box -a 3 -f -T -t #{time_limit} #{JAVA_OPTION} -i #{input_file_name} -o output.txt /usr/bin/java #{classname} 2>run_result"
107 when "ruby"
108 when "ruby"
108 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} #{RUBY_OPTION} -i #{input_file_name} -o output.txt /usr/bin/ruby #{program_name} 2>run_result"
109 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} #{RUBY_OPTION} -i #{input_file_name} -o output.txt /usr/bin/ruby #{program_name} 2>run_result"
109 when "python"
110 when "python"
110 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} #{PYTHON_OPTION} -i #{input_file_name} -o output.txt /usr/bin/python #{program_name} 2>run_result"
111 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} #{PYTHON_OPTION} -i #{input_file_name} -o output.txt /usr/bin/python #{program_name} 2>run_result"
112 + when "php"
113 + run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} #{PHP_OPTION} -i #{input_file_name} -o output.txt /usr/bin/php #{program_name} 2>run_result"
111 else # for c++, pascal, we do the normal checking
114 else # for c++, pascal, we do the normal checking
112 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
115 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
113 end
116 end
114
117
115
118
116 log "Running test #{test_num}..."
119 log "Running test #{test_num}..."
117 log run_command
120 log run_command
118 log
121 log
119 system(run_command)
122 system(run_command)
120
123
121 # Restore PROBLEM_HOME
124 # Restore PROBLEM_HOME
122 ENV['PROBLEM_HOME'] = problem_home
125 ENV['PROBLEM_HOME'] = problem_home
123
126
124 # Create the result file.
127 # Create the result file.
125 result_file = File.new("result", "w")
128 result_file = File.new("result", "w")
126 comment_file = File.new("comment", "w")
129 comment_file = File.new("comment", "w")
127
130
128 # Check if the program actually produced any output.
131 # Check if the program actually produced any output.
129 run_result_file = File.new("run_result", "r")
132 run_result_file = File.new("run_result", "r")
130 run_result = run_result_file.readlines
133 run_result = run_result_file.readlines
131 run_result_file.close
134 run_result_file.close
132
135
133 run_stat = run_result[run_result.length-1]
136 run_stat = run_result[run_result.length-1]
134 running_time = extract_time(run_stat)
137 running_time = extract_time(run_stat)
135
138
136 report = lambda{ |status, points, comment|
139 report = lambda{ |status, points, comment|
137 result_file.write status.strip
140 result_file.write status.strip
138 result_file.write "\n"
141 result_file.write "\n"
139 result_file.write points.to_s.strip
142 result_file.write points.to_s.strip
140 result_file.write "\n"
143 result_file.write "\n"
141 result_file.write run_stat.strip
144 result_file.write run_stat.strip
142 result_file.write "\n"
145 result_file.write "\n"
143 result_file.close
146 result_file.close
144 FileUtils.rm "run_result"
147 FileUtils.rm "run_result"
145 # `rm output.txt` --- keep the output
148 # `rm output.txt` --- keep the output
146
149
147 comment_file.write comment
150 comment_file.write comment
148
151
149 # added for debuggin --- jittat
152 # added for debuggin --- jittat
150 comment_file.write "--run-result--\n"
153 comment_file.write "--run-result--\n"
151 run_result.each do |l|
154 run_result.each do |l|
152 comment_file.write l
155 comment_file.write l
153 end
156 end
154
157
155 comment_file.close
158 comment_file.close
156
159
157 log "Done!"
160 log "Done!"
158 exit(0)
161 exit(0)
159 }
162 }
160
163
161
164
162 if run_result[0][0,2] != "OK"
165 if run_result[0][0,2] != "OK"
163 log "There was a runtime error."
166 log "There was a runtime error."
164 report.call(run_result[0], 0, "No comment.\n")
167 report.call(run_result[0], 0, "No comment.\n")
165 end
168 end
166
169
167 if running_time[:user].to_f > time_limit
170 if running_time[:user].to_f > time_limit
168 log "Time limit exceeded."
171 log "Time limit exceeded."
169 report.call("Time limit exceeded", 0, "No comment.\n")
172 report.call("Time limit exceeded", 0, "No comment.\n")
170 end
173 end
171
174
172 # Run 'check' to evaluate the output.
175 # Run 'check' to evaluate the output.
173 #puts "There was no runtime error. Proceed to checking the output."
176 #puts "There was no runtime error. Proceed to checking the output."
174 check_command = "#{problem_home}/script/check #{language} #{test_num}"
177 check_command = "#{problem_home}/script/check #{language} #{test_num}"
175 log "Checking the output..."
178 log "Checking the output..."
176 log check_command
179 log check_command
177 if not system(check_command)
180 if not system(check_command)
178 log "Problem with check script"
181 log "Problem with check script"
179 report.call("Incorrect",0,"Check script error.\n")
182 report.call("Incorrect",0,"Check script error.\n")
180 exit(127)
183 exit(127)
181 end
184 end
182
185
183 check_file = File.new("check_result", "r")
186 check_file = File.new("check_result", "r")
184 check_file_lines = check_file.readlines
187 check_file_lines = check_file.readlines
185
188
186 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
189 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
You need to be logged in to leave comments. Login now