diff options
author | prathamesh | 2013-07-03 16:49:29 +0530 |
---|---|---|
committer | prathamesh | 2013-07-03 16:49:29 +0530 |
commit | b522a1ba1c1edff7648c6c7d69fa2867a08b4100 (patch) | |
tree | 26df2b155c4db789dabd53f309057ac0aaca5f04 /testapp/code_server.py | |
parent | 781842c523ccf11b85e0be06e884b2cd585f3cb9 (diff) | |
download | online_test-b522a1ba1c1edff7648c6c7d69fa2867a08b4100.tar.gz online_test-b522a1ba1c1edff7648c6c7d69fa2867a08b4100.tar.bz2 online_test-b522a1ba1c1edff7648c6c7d69fa2867a08b4100.zip |
merged java
Diffstat (limited to 'testapp/code_server.py')
-rwxr-xr-x | testapp/code_server.py | 166 |
1 files changed, 161 insertions, 5 deletions
diff --git a/testapp/code_server.py b/testapp/code_server.py index a3513b7..8b3f8f1 100755 --- a/testapp/code_server.py +++ b/testapp/code_server.py @@ -353,7 +353,7 @@ class CodeServer(object): return success, err def _compile_command(self, cmd, *args, **kw): - """Compiles C/C++ code and returns errors if any. + """Compiles C/C++/java code and returns errors if any. Run a command in a subprocess while blocking, the process is killed if it takes more than 2 seconds to run. Return the Popen object, the stderr. @@ -370,6 +370,7 @@ class CodeServer(object): raise return proc_compile, err + def _check_c_cpp_code(self, ref_code_path, submit_code_path): """ Function validates student code using instructor code as reference.The first argument ref_code_path, is the path to @@ -399,11 +400,11 @@ class CodeServer(object): output_path = os.getcwd() + '/output' compile_command = "g++ %s -c -o %s" % (submit_code_path, output_path) ret = self._compile_command(compile_command) - proc, inst_stderr = ret + proc, stdnt_stderr = ret # Only if compilation is successful, the program is executed # And tested with testcases - if inst_stderr == '': + if stdnt_stderr == '': executable = os.getcwd() + '/executable' compile_main = "g++ %s %s -o %s" % (ref_code_path, output_path, executable) @@ -432,14 +433,14 @@ class CodeServer(object): else: err = "Compilation Error:" try: - error_lines = inst_stderr.splitlines() + error_lines = stdnt_stderr.splitlines() for e in error_lines: if ':' in e: err = err + "\n" + e.split(":", 1)[1] else: err = err + "\n" + e except: - err = err + "\n" + inst_stderr + err = err + "\n" + stdnt_stderr return success, err def run_cplus_code(self, answer, test_code, in_dir=None): @@ -504,6 +505,161 @@ class CodeServer(object): return success, err + def run_java_code(self, answer, test_code, in_dir=None): + """Tests given java code (`answer`) with the `test_code` supplied. + + The testcode is a path to the reference code. + The reference code will call the function submitted by the student. + The reference code will check for the expected output. + + If the path's start with a "/" then we assume they are absolute paths. + If not, we assume they are relative paths w.r.t. the location of this + code_server script. + + If the optional `in_dir` keyword argument is supplied it changes the + directory to that directory (it does not change it back to the original + when done). + + Returns + ------- + + A tuple: (success, error message). + + """ + if in_dir is not None and isdir(in_dir): + os.chdir(in_dir) + + # The file extension must be .java + # The class name and file name must be same in java + submit_f = open('Test.java', 'w') + submit_f.write(answer.lstrip()) + submit_f.close() + submit_path = abspath(submit_f.name) + + ref_path = test_code.strip() + if not ref_path.startswith('/'): + ref_path = join(MY_DIR, ref_path) + + # Add a new signal handler for the execution of this code. + old_handler = signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(SERVER_TIMEOUT) + + # Do whatever testing needed. + success = False + try: + success, err = self._check_java_code(ref_path, submit_path) + except TimeoutException: + err = self.timeout_msg + except: + type, value = sys.exc_info()[:2] + err = "Error: {0}".format(repr(value)) + finally: + # Set back any original signal handler. + signal.signal(signal.SIGALRM, old_handler) + + # Delete the created file. + os.remove(submit_path) + + # Cancel the signal if any, see signal.alarm documentation. + signal.alarm(0) + + # Put us back into the server pool queue since we are free now. + self.queue.put(self.port) + + return success, err + + def _check_java_code(self, ref_code_path, submit_code_path): + """ Function validates student code using instructor code as + reference.The first argument ref_code_path, is the path to + instructor code, it is assumed to have executable permission. + The second argument submit_code_path, is the path to the student + code, it is assumed to have executable permission. + + Returns + -------- + + returns (True, "Correct answer") : If the student function returns + expected output when called by reference code. + + returns (False, error_msg): If the student function fails to return + expected output when called by reference code. + + Returns (False, error_msg): If mandatory arguments are not files or + if the required permissions are not given to the file(s). + + """ + if not isfile(ref_code_path): + return False, "No file at %s" % ref_code_path + if not isfile(submit_code_path): + return False, 'No file at %s' % submit_code_path + + success = False + compile_command = "javac %s" % (submit_code_path) + ret = self._compile_command(compile_command) + proc, stdnt_stderr = ret + stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) + + # Only if compilation is successful, the program is executed + # And tested with testcases + if stdnt_stderr == '': + student_directory = os.getcwd() + '/' + student_file_name = "Test" + compile_main = "javac %s -classpath %s -d %s" % (ref_code_path, + student_directory, + student_directory) + ret = self._compile_command(compile_main) + proc, main_err = ret + main_err = self._remove_null_substitute_char(main_err) + + if main_err == '': + main_file_name = (ref_code_path.split('/')[-1]).split('.')[0] + run_command = "java -cp %s %s" % (student_directory, + main_file_name) + ret = self._run_command(run_command, + stdin=None, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc, stdout, stderr = ret + if proc.returncode == 0: + success, err = True, "Correct answer" + else: + err = stdout + "\n" + stderr + success = False + os.remove("%s%s.class" % (student_directory, main_file_name)) + else: + err = "Error:\n" + try: + error_lines = main_err.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + main_err + os.remove("%s%s.class" % (student_directory, student_file_name)) + else: + err = "Compilation Error:\n" + try: + error_lines = stdnt_stderr.splitlines() + for e in error_lines: + if ':' in e: + err = err + "\n" + e.split(":", 1)[1] + else: + err = err + "\n" + e + except: + err = err + "\n" + stdnt_stderr + return success, err + + def _remove_null_substitute_char(self, string): + """Returns a string without any null and substitute characters""" + stripped = "" + for c in string: + if ord(c) is not 26 and ord(c) is not 0: + stripped = stripped + c + return ''.join(stripped) + def run(self): """Run XMLRPC server, serving our methods. """ |