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

r230:791a8b27f2e4 - - 3 files changed: 16 inserted, 5 deleted

@@ -1,188 +1,196
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/python3"
31 PYTHON_INTERPRETER = "/usr/bin/python3"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
32 PYTHON_CHECKER = "/usr/bin/pyflakes"
33 PHP_INTERPRETER = "/usr/bin/php"
33 PHP_INTERPRETER = "/usr/bin/php"
34 + HASKELL_COMPILER = "/usr/bin/ghc"
34
35
35 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
36 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
36 CPLUSPLUS_OPTIONS = "-O2 -s -std=c++11 -static -DCONTEST -lm -Wall"
37 CPLUSPLUS_OPTIONS = "-O2 -s -std=c++11 -static -DCONTEST -lm -Wall"
37 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
38 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
38 JAVA_OPTIONS = ""
39 JAVA_OPTIONS = ""
39 PYTHON_OPTIONS = ""
40 PYTHON_OPTIONS = ""
40 PHP_OPTIONS = "-l"
41 PHP_OPTIONS = "-l"
42 + HASKELL_OPTIONS = ""
41
43
42 # Check for the correct number of arguments. Otherwise, print usage.
44 # Check for the correct number of arguments. Otherwise, print usage.
43 if ARGV.length == 0 or ARGV.length > 4
45 if ARGV.length == 0 or ARGV.length > 4
44 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
46 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
45 puts
47 puts
46 puts "<source-file> is defaulted to \"source\"."
48 puts "<source-file> is defaulted to \"source\"."
47 puts "<output-file> is defaulted to \"a.out\"."
49 puts "<output-file> is defaulted to \"a.out\"."
48 puts "<message-file> is defaulted to \"compiler_message\"."
50 puts "<message-file> is defaulted to \"compiler_message\"."
49 puts
51 puts
50 exit(127)
52 exit(127)
51 end
53 end
52
54
53 PARAMS = {
55 PARAMS = {
54 :source_file => [1,'source'],
56 :source_file => [1,'source'],
55 :output_file => [2,'a.out'],
57 :output_file => [2,'a.out'],
56 :message_file => [3,'compiler_message']
58 :message_file => [3,'compiler_message']
57 }
59 }
58
60
59 params = {}
61 params = {}
60 params[:prog_lang] = ARGV[0]
62 params[:prog_lang] = ARGV[0]
61 PARAMS.each_key do |param_name|
63 PARAMS.each_key do |param_name|
62 index, default = PARAMS[param_name]
64 index, default = PARAMS[param_name]
63 if ARGV.length > index
65 if ARGV.length > index
64 params[param_name] = ARGV[index]
66 params[param_name] = ARGV[index]
65 else
67 else
66 params[param_name] = default
68 params[param_name] = default
67 end
69 end
68 talk "#{param_name}: #{params[param_name]}"
70 talk "#{param_name}: #{params[param_name]}"
69 end
71 end
70
72
71 # Remove any remaining output files or message files.
73 # Remove any remaining output files or message files.
72 if FileTest.exists? params[:output_file]
74 if FileTest.exists? params[:output_file]
73 FileUtils.rm(params[:output_file])
75 FileUtils.rm(params[:output_file])
74 end
76 end
75 if FileTest.exists? params[:message_file]
77 if FileTest.exists? params[:message_file]
76 FileUtils.rm(params[:message_file])
78 FileUtils.rm(params[:message_file])
77 end
79 end
78
80
79 # Check if the source file exists before attempt compiling.
81 # Check if the source file exists before attempt compiling.
80 if !FileTest.exists? params[:source_file]
82 if !FileTest.exists? params[:source_file]
81 talk("ERROR: The source file does not exist!")
83 talk("ERROR: The source file does not exist!")
82 open(params[:message_file],"w") do |f|
84 open(params[:message_file],"w") do |f|
83 f.puts "ERROR: The source file did not exist."
85 f.puts "ERROR: The source file did not exist."
84 end
86 end
85 exit(127)
87 exit(127)
86 end
88 end
87
89
88 if params[:prog_lang]=='cpp'
90 if params[:prog_lang]=='cpp'
89 params[:prog_lang] = 'c++'
91 params[:prog_lang] = 'c++'
90 end
92 end
91
93
92 # Compile.
94 # Compile.
93 case params[:prog_lang]
95 case params[:prog_lang]
94
96
95 when "c"
97 when "c"
96 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS}"
98 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS}"
97 system(command, err: params[:message_file])
99 system(command, err: params[:message_file])
98
100
99 when "c++"
101 when "c++"
100 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS}"
102 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS}"
101 system(command, err: params[:message_file])
103 system(command, err: params[:message_file])
102
104
103 when "pas"
105 when "pas"
104 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS}"
106 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS}"
105 system(command,out: params[:message_file])
107 system(command,out: params[:message_file])
106 FileUtils.mv("output", params[:output_file])
108 FileUtils.mv("output", params[:output_file])
107
109
108 when "java"
110 when "java"
109 #rename the file to the public class name
111 #rename the file to the public class name
110
112
111 #get the class name
113 #get the class name
112 classname = 'DUMMY'
114 classname = 'DUMMY'
113 source = Array.new
115 source = Array.new
114 File.foreach(params[:source_file],'r:UTF-8') do |line|
116 File.foreach(params[:source_file],'r:UTF-8') do |line|
115 line.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
117 line.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
116 md = /\s*public\s*class\s*(\w*)/.match(line)
118 md = /\s*public\s*class\s*(\w*)/.match(line)
117 classname=md[1] if md
119 classname=md[1] if md
118 source << line unless line =~ /\s*package\s*\w+\s*\;/
120 source << line unless line =~ /\s*package\s*\w+\s*\;/
119 end
121 end
120 File.open("#{classname}.java","w") do |file|
122 File.open("#{classname}.java","w") do |file|
121 source.each do |s|
123 source.each do |s|
122 file.puts s
124 file.puts s
123 end
125 end
124 end
126 end
125 #system("cp #{params[:source_file]} #{classname}.java")
127 #system("cp #{params[:source_file]} #{classname}.java")
126 command = "#{JAVA_COMPILER} -encoding utf8 #{classname}.java"
128 command = "#{JAVA_COMPILER} -encoding utf8 #{classname}.java"
127 system(command, err: params[:message_file])
129 system(command, err: params[:message_file])
128 if File.exists?(classname + ".class")
130 if File.exists?(classname + ".class")
129 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
131 File.open(params[:output_file],"w") {|file| file.write("#{classname}")}
130 end
132 end
131 if classname == 'DUMMY'
133 if classname == 'DUMMY'
132 File.open(params[:message_file],"w") {|file| file.write("Cannot find any public class in the source code\n")}
134 File.open(params[:message_file],"w") {|file| file.write("Cannot find any public class in the source code\n")}
133 end
135 end
134
136
135 when "ruby"
137 when "ruby"
136 command = "#{RUBY_INTERPRETER} -c #{params[:source_file]}"
138 command = "#{RUBY_INTERPRETER} -c #{params[:source_file]}"
137 if system(command, err: params[:message_file])
139 if system(command, err: params[:message_file])
138 File.open(params[:output_file],"w") do |out_file|
140 File.open(params[:output_file],"w") do |out_file|
139 out_file.puts "#!#{RUBY_INTERPRETER}"
141 out_file.puts "#!#{RUBY_INTERPRETER}"
140 File.open(params[:source_file],"r").each do |line|
142 File.open(params[:source_file],"r").each do |line|
141 out_file.print line
143 out_file.print line
142 end
144 end
143 end
145 end
144 File.chmod(0755, params[:output_file])
146 File.chmod(0755, params[:output_file])
145 end
147 end
146
148
147 when "python"
149 when "python"
148 - command = "#{PYTHON_CHECKER} #{params[:source_file]}"
150 + #command = "#{PYTHON_CHECKER} #{params[:source_file]}"
149 - if system(command, out: params[:message_file])
151 + #if system(command, out: params[:message_file])
150 #compile to python bytecode
152 #compile to python bytecode
151 command = "#{PYTHON_INTERPRETER} -c \"import py_compile; py_compile.compile('#{params[:source_file]}','#{params[:source_file]}c');\""
153 command = "#{PYTHON_INTERPRETER} -c \"import py_compile; py_compile.compile('#{params[:source_file]}','#{params[:source_file]}c');\""
152 puts "compile: #{command}"
154 puts "compile: #{command}"
153 - system(command)
155 + system(command, err: params[:message_file])
156 + if FileTest.exists?("#{params[:source_file]}c")
154 puts "pwd: " + Dir.pwd
157 puts "pwd: " + Dir.pwd
155 Dir.new('.').each {|file| puts file}
158 Dir.new('.').each {|file| puts file}
156 File.open(params[:output_file],"w") do |out_file|
159 File.open(params[:output_file],"w") do |out_file|
157 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
160 out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
158 end
161 end
159 File.chmod(0755, params[:output_file])
162 File.chmod(0755, params[:output_file])
160 FileUtils.cp("#{params[:source_file]}c",params[:output_file])
163 FileUtils.cp("#{params[:source_file]}c",params[:output_file])
161 end
164 end
165 + #end
162
166
163 when "php"
167 when "php"
164 command = "#{PHP_INTERPRETER} #{PHP_OPTIONS} #{params[:source_file]}"
168 command = "#{PHP_INTERPRETER} #{PHP_OPTIONS} #{params[:source_file]}"
165 if system(command, err: params[:message_file])
169 if system(command, err: params[:message_file])
166 File.open(params[:output_file],"w") do |out_file|
170 File.open(params[:output_file],"w") do |out_file|
167 out_file.puts "#!#{PHP_INTERPRETER}"
171 out_file.puts "#!#{PHP_INTERPRETER}"
168 File.open(params[:source_file],"r").each do |line|
172 File.open(params[:source_file],"r").each do |line|
169 out_file.print line
173 out_file.print line
170 end
174 end
171 end
175 end
172 File.chmod(0755, params[:output_file])
176 File.chmod(0755, params[:output_file])
173 end
177 end
174
178
179 + when "haskell"
180 + command = "#{HASKELL_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{HASKELL_OPTIONS}"
181 + system(command, err: params[:message_file])
182 +
175 else
183 else
176 talk("ERROR: Invalid language specified!")
184 talk("ERROR: Invalid language specified!")
177 open(params[:message_file],"w") do |f|
185 open(params[:message_file],"w") do |f|
178 f.puts "ERROR: Invalid language specified!"
186 f.puts "ERROR: Invalid language specified!"
179 end
187 end
180 exit(127)
188 exit(127)
181 end
189 end
182
190
183 # Report success or failure.
191 # Report success or failure.
184 if FileTest.exists? params[:output_file]
192 if FileTest.exists? params[:output_file]
185 talk "Compilation was successful!"
193 talk "Compilation was successful!"
186 else
194 else
187 talk "ERROR: Something was wrong during the compilation!"
195 talk "ERROR: Something was wrong during the compilation!"
188 end
196 end
@@ -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" && language != "php"
56 + if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python" && language != "php" && language != "haskell"
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,189 +1,192
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 /usr/local/lib64/ -p /usr/local/lib/ -p /lib64/ -p /dev/urandom -p #{sandbox_dir}/#{program_name} -p #{sandbox_dir}/ -s set_robust_list -s sched_getaffinity -s clock_gettime -s sigaltstack -s pipe2 -s clone -s futex -s openat -s pipe"
94 RUBY_OPTION = "-p /usr/lib64/ -p /usr/local/lib64/ -p /usr/local/lib/ -p /lib64/ -p /dev/urandom -p #{sandbox_dir}/#{program_name} -p #{sandbox_dir}/ -s set_robust_list -s sched_getaffinity -s clock_gettime -s sigaltstack -s pipe2 -s clone -s futex -s openat -s pipe"
95 - PYTHON_OPTION = "-p /usr/lib64/ -p /usr/local/lib64/ -p /usr/local/lib/ -p /usr/bin/ -p /lib64/ -p /dev/urandom -p /usr/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p #{sandbox_dir}/#{source_name} -p /proc/mounts -s statfs -s set_robust_list -s openat -s recvmsg -s connect -s socket -s sendto -s futex -s sigaltstack -E PYTHONNOUSERSITE=yes"
95 + PYTHON_OPTION = "-p /usr/lib64/ -p /usr/local/lib64/ -p /usr/local/lib/ -p /usr/bin/ -p /lib64/ -p /dev/urandom -p /usr/ -p #{sandbox_dir}/#{program_name} -p ./#{program_name} -p #{sandbox_dir}/#{source_name} -p /proc/sys/crypto/fips_enabled -p /proc/self/status -p /proc/mounts -p /var/lib/dpkg/status -s statfs -s set_robust_list -s openat -s sysinfo -s recvmsg -s connect -s socket -s sendto -s futex -s sigaltstack -s getrandom -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 -s clone -s socket -s connect"
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 -s clone -s socket -s connect"
97 + HASKELL_OPTION = "-s set_robust_list -s clock_gettime -s sysinfo -s timer_create -s timer_settime -s futex -s timer_delete"
97
98
98 case language
99 case language
99 when "java"
100 when "java"
100 # for java, extract the classname
101 # for java, extract the classname
101 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
102 # wne have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
102 classname = 'DUMMY'
103 classname = 'DUMMY'
103 File.open(program_name,"r").each do |line|
104 File.open(program_name,"r").each do |line|
104 classname = line
105 classname = line
105 end
106 end
106 #for java, we cannot really check the memory limit...
107 #for java, we cannot really check the memory limit...
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 -A -Xmx#{mem_limit}k -A #{classname} "
108 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 -A -Xmx#{mem_limit}k -A #{classname} "
108 when "ruby"
109 when "ruby"
109 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{mem_limit} #{RUBY_OPTION} -i #{input_file_name} -o output.txt /usr/bin/ruby #{program_name} "
110 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{mem_limit} #{RUBY_OPTION} -i #{input_file_name} -o output.txt /usr/bin/ruby #{program_name} "
110 when "python"
111 when "python"
111 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{[128 * 1024,mem_limit].max} #{PYTHON_OPTION} -i #{input_file_name} -o output.txt /usr/bin/python3 #{program_name} "
112 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{[128 * 1024,mem_limit].max} #{PYTHON_OPTION} -i #{input_file_name} -o output.txt /usr/bin/python3 #{program_name} "
113 + when "haskell"
114 + run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{[512 * 1024,mem_limit].max} #{HASKELL_OPTION} -i #{input_file_name} -o output.txt #{program_name} "
112 when "php"
115 when "php"
113 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{[128 * 1024,mem_limit].max} #{PHP_OPTION} -i #{input_file_name} -o output.txt /usr/bin/php -A -d -A memory_limit=#{mem_limit}k -A #{program_name} "
116 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit*=2} -m #{[128 * 1024,mem_limit].max} #{PHP_OPTION} -i #{input_file_name} -o output.txt /usr/bin/php -A -d -A memory_limit=#{mem_limit}k -A #{program_name} "
114 else # for c++, pascal, we do the normal checking
117 else # for c++, pascal, we do the normal checking
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} "
118 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} "
116 end
119 end
117
120
118
121
119 log "Running test #{test_num}..."
122 log "Running test #{test_num}..."
120 log run_command
123 log run_command
121 log
124 log
122 system(run_command,err: 'run_result')
125 system(run_command,err: 'run_result')
123
126
124 # Restore PROBLEM_HOME
127 # Restore PROBLEM_HOME
125 ENV['PROBLEM_HOME'] = problem_home
128 ENV['PROBLEM_HOME'] = problem_home
126
129
127 # Create the result file.
130 # Create the result file.
128 result_file = File.new("result", "w")
131 result_file = File.new("result", "w")
129 comment_file = File.new("comment", "w")
132 comment_file = File.new("comment", "w")
130
133
131 # Check if the program actually produced any output.
134 # Check if the program actually produced any output.
132 run_result_file = File.new("run_result", "r")
135 run_result_file = File.new("run_result", "r")
133 run_result = run_result_file.readlines
136 run_result = run_result_file.readlines
134 run_result_file.close
137 run_result_file.close
135
138
136 run_stat = run_result[run_result.length-1]
139 run_stat = run_result[run_result.length-1]
137 running_time = extract_time(run_stat)
140 running_time = extract_time(run_stat)
138
141
139 report = lambda{ |status, points, comment|
142 report = lambda{ |status, points, comment|
140 result_file.write status.strip
143 result_file.write status.strip
141 result_file.write "\n"
144 result_file.write "\n"
142 result_file.write points.to_s.strip
145 result_file.write points.to_s.strip
143 result_file.write "\n"
146 result_file.write "\n"
144 result_file.write run_stat.strip
147 result_file.write run_stat.strip
145 result_file.write "\n"
148 result_file.write "\n"
146 result_file.close
149 result_file.close
147 FileUtils.rm "run_result"
150 FileUtils.rm "run_result"
148 # `rm output.txt` --- keep the output
151 # `rm output.txt` --- keep the output
149
152
150 comment_file.write comment
153 comment_file.write comment
151
154
152 # added for debuggin --- jittat
155 # added for debuggin --- jittat
153 comment_file.write "--run-result--\n"
156 comment_file.write "--run-result--\n"
154 run_result.each do |l|
157 run_result.each do |l|
155 comment_file.write l
158 comment_file.write l
156 end
159 end
157
160
158 comment_file.close
161 comment_file.close
159
162
160 log "Done!"
163 log "Done!"
161 exit(0)
164 exit(0)
162 }
165 }
163
166
164
167
165 if run_result[0][0,2] != "OK"
168 if run_result[0][0,2] != "OK"
166 log "There was a runtime error."
169 log "There was a runtime error."
167 report.call(run_result[0], 0, "No comment.\n")
170 report.call(run_result[0], 0, "No comment.\n")
168 end
171 end
169
172
170 if running_time[:user].to_f > time_limit
173 if running_time[:user].to_f > time_limit
171 log "Time limit exceeded."
174 log "Time limit exceeded."
172 report.call("Time limit exceeded", 0, "No comment.\n")
175 report.call("Time limit exceeded", 0, "No comment.\n")
173 end
176 end
174
177
175 # Run 'check' to evaluate the output.
178 # Run 'check' to evaluate the output.
176 #puts "There was no runtime error. Proceed to checking the output."
179 #puts "There was no runtime error. Proceed to checking the output."
177 check_command = "#{problem_home}/script/check #{language} #{test_num}"
180 check_command = "#{problem_home}/script/check #{language} #{test_num}"
178 log "Checking the output..."
181 log "Checking the output..."
179 log check_command
182 log check_command
180 if not system(check_command)
183 if not system(check_command)
181 log "Problem with check script"
184 log "Problem with check script"
182 report.call("Incorrect",0,"Check script error.\n")
185 report.call("Incorrect",0,"Check script error.\n")
183 exit(127)
186 exit(127)
184 end
187 end
185
188
186 check_file = File.new("check_result", "r")
189 check_file = File.new("check_result", "r")
187 check_file_lines = check_file.readlines
190 check_file_lines = check_file.readlines
188
191
189 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
192 report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
You need to be logged in to leave comments. Login now