diff options
Diffstat (limited to 'testapp')
-rwxr-xr-x | testapp/code_server.py | 166 | ||||
-rw-r--r-- | testapp/exam/forms.py | 1 | ||||
-rw-r--r-- | testapp/exam/models.py | 1 | ||||
-rw-r--r-- | testapp/exam/views.py | 2 | ||||
-rw-r--r-- | testapp/exam/xmlrpc_clients.py | 1 | ||||
-rw-r--r-- | testapp/java_files/main_array_sum.java | 36 | ||||
-rw-r--r-- | testapp/java_files/main_fact.java | 29 | ||||
-rw-r--r-- | testapp/java_files/main_great.java | 39 | ||||
-rw-r--r-- | testapp/java_files/main_hello_name.java | 29 | ||||
-rw-r--r-- | testapp/java_files/main_palindrome.java | 29 | ||||
-rw-r--r-- | testapp/java_files/main_square.java | 32 | ||||
-rw-r--r-- | testapp/test_server.py | 115 |
12 files changed, 463 insertions, 17 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. """ diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index 1b60a71..8506de2 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -18,6 +18,7 @@ QUESTION_TYPE_CHOICES = ( ("mcq", "MCQ"), ("C", "C Language"), ("C++", "C++ Language"), + ("java", "Java Language"), ) UNAME_CHARS = letters + "._" + digits diff --git a/testapp/exam/models.py b/testapp/exam/models.py index fac01ec..5d6e2cf 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -20,6 +20,7 @@ QUESTION_TYPE_CHOICES = ( ("mcq", "MultipleChoice"), ("C", "C Language"), ("C++", "C++ Language"), + ("java", "Java Language"), ) ################################################################################ diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 4c47004..dd11346 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -963,7 +963,7 @@ def user_data(request, username): """Render user data.""" current_user = request.user - if not current_user.is_authenticated() or not is_moderator(user): + if not current_user.is_authenticated() or not is_moderator(current_user): raise Http404('You are not allowed to view this page!') data = get_user_data(username) diff --git a/testapp/exam/xmlrpc_clients.py b/testapp/exam/xmlrpc_clients.py index b846212..cc21e62 100644 --- a/testapp/exam/xmlrpc_clients.py +++ b/testapp/exam/xmlrpc_clients.py @@ -25,6 +25,7 @@ class CodeServerProxy(object): "bash": 'run_bash_code', "C": "run_c_code", "C++": "run_cplus_code", + "java": "run_java_code", } def run_code(self, answer, test_code, user_dir, language): diff --git a/testapp/java_files/main_array_sum.java b/testapp/java_files/main_array_sum.java new file mode 100644 index 0000000..5eae299 --- /dev/null +++ b/testapp/java_files/main_array_sum.java @@ -0,0 +1,36 @@ +class main_array_sum +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + int result; + Test t = new Test(); + int x[] = {0,0,0,0,0}; + result = t.array_sum(x); + System.out.println("Input submitted to the function: {0,0,0,0,0}"); + check(0, result); + int a[] = {1,2,3,4,5}; + result = t.array_sum(a); + System.out.println("Input submitted to the function: {1,2,3,4,5}"); + check(15, result); + int b[] = {1,2,3,0,0}; + result = t.array_sum(b); + System.out.println("Input submitted to the function: {1,2,3,0,0}"); + check(6, result); + int c[] = {1,1,1,1,1}; + result = t.array_sum(c); + System.out.println("Input submitted to the function: {1,1,1,1,1}"); + check(5, result); + } +} diff --git a/testapp/java_files/main_fact.java b/testapp/java_files/main_fact.java new file mode 100644 index 0000000..325dab6 --- /dev/null +++ b/testapp/java_files/main_fact.java @@ -0,0 +1,29 @@ +class main_fact +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result; + result = t.factorial(0); + System.out.println("Input submitted to the function: 0"); + check(1, result); + result = t.factorial(3); + System.out.println("Input submitted to the function: 3"); + check(6, result); + result = t.factorial(4); + System.out.println("Input submitted to the function: 4"); + check(24, result); + } +} diff --git a/testapp/java_files/main_great.java b/testapp/java_files/main_great.java new file mode 100644 index 0000000..4bfcb1f --- /dev/null +++ b/testapp/java_files/main_great.java @@ -0,0 +1,39 @@ +class main_great +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result; + result = t.greatest(1, 3, 4); + System.out.println("Input submitted to the function: 1, 3, 4"); + check(4, result); + result = t.greatest(5, 10, 3); + System.out.println("Input submitted to the function: 5, 10, 3"); + check(10, result); + result = t.greatest(6, 1, 4); + System.out.println("Input submitted to the function: 6, 1, 4"); + check(6, result); + result = t.greatest(6, 11, 14); + System.out.println("Input submitted to the function: 6, 11, 14"); + check(14, result); + result = t.greatest(3, 31, 4); + System.out.println("Input submitted to the function: 3, 31, 4"); + check(31, result); + result = t.greatest(26, 13, 3); + System.out.println("Input submitted to the function: 26, 13, 3"); + check(26, result); + + } +} diff --git a/testapp/java_files/main_hello_name.java b/testapp/java_files/main_hello_name.java new file mode 100644 index 0000000..84bb282 --- /dev/null +++ b/testapp/java_files/main_hello_name.java @@ -0,0 +1,29 @@ +class main_hello_name +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + String result; + result = t.hello_name("Raj"); + System.out.println("Input submitted to the function: 'Raj'"); + check("hello Raj", result); + result = t.hello_name("Pratham"); + System.out.println("Input submitted to the function: 'Pratham'"); + check("hello Pratham", result); + result = t.hello_name("Ram"); + System.out.println("Input submitted to the function: 'Ram'"); + check("hello Ram", result); + } +} diff --git a/testapp/java_files/main_palindrome.java b/testapp/java_files/main_palindrome.java new file mode 100644 index 0000000..bd463e5 --- /dev/null +++ b/testapp/java_files/main_palindrome.java @@ -0,0 +1,29 @@ +class main_palindrome +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct\n:Output expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + boolean result; + result= t.palindrome(123); + System.out.println("Input submitted to the function: 123"); + check(false, result); + result = t.palindrome(151); + System.out.println("Input submitted to the function: 151"); + check(true, result); + result = t.palindrome(23432); + System.out.println("Input submitted to the function: 23432"); + check(true, result); + } +} diff --git a/testapp/java_files/main_square.java b/testapp/java_files/main_square.java new file mode 100644 index 0000000..5cb8c35 --- /dev/null +++ b/testapp/java_files/main_square.java @@ -0,0 +1,32 @@ +class main_square +{ + public static <E> void check(E expect, E result) + { + if(result.equals(expect)) + { + System.out.println("Correct:\nOutput expected "+expect+" and got "+result); + } + else + { + System.out.println("Incorrect:\nOutput expected "+expect+" but got "+result); + System.exit(1); + } + } + public static void main(String arg[]) + { + Test t = new Test(); + int result, input, output; + input = 0; output = 0; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + input = 5; output = 25; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + input = 6; output = 36; + result = t.square_num(input); + System.out.println("Input submitted to the function: "+input); + check(output, result); + } +} diff --git a/testapp/test_server.py b/testapp/test_server.py index 924a6c5..2a17739 100644 --- a/testapp/test_server.py +++ b/testapp/test_server.py @@ -16,6 +16,7 @@ def check_result(result, check='correct answer'): assert result[0], result[1] assert check in result[1].lower(), result[1] + def test_python(): """Test if server runs Python code as expected.""" src = 'while True: pass' @@ -43,14 +44,16 @@ def test_c(): int ad(int a, int b) {return a+b;} """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C") check_result(result, 'error') src = """ int add(int a, int b) {return a+b} """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C") check_result(result, 'compilation error') src = """ @@ -58,14 +61,16 @@ def test_c(): {while(1>0){} return a+b;} """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C") check_result(result, 'more than') src = """ int add(int a, int b) {return a+b;} """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C") check_result(result, 'correct answer') src = """ @@ -73,7 +78,8 @@ def test_c(): int add(int a, int b) {printf("All Correct");} """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C") check_result(result, 'incorrect') @@ -85,8 +91,9 @@ def test_cpp(): return a+b } """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C++") - check_result(result, 'compilation error') + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C++") + check_result(result, 'error') src = """ int add(int a, int b) @@ -94,7 +101,8 @@ def test_cpp(): return a+b; } """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C++") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C++") check_result(result, 'correct answer') src = """ @@ -103,7 +111,8 @@ def test_cpp(): return a+b; } """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C++") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C++") check_result(result, 'error') src = """ @@ -114,9 +123,92 @@ def test_cpp(): return a+b; } """ - result = code_server.run_code(src, 'c_cpp_files/main.cpp', '/tmp', language="C++") + result = code_server.run_code(src, 'c_cpp_files/main.cpp', + '/tmp', language="C++") check_result(result, 'more than') + +def test_java(): + """Test if server runs java code as expected.""" + src = """ + class Test + { + int square_num(int a) + { + return a*a; + } + } + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'correct answer') + + src = """ + class Test + { + int square_num(int a) + { + return b*b; + } + } + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'error') + + src = """ + class Test + { + int square_nu(int a) + { + return a*a; + } + } + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'error') + + src = """ + class Test + { + int square_num(int a) + { + while(0==0) + {} + } + } + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'more than') + + src = """ + class Test + { + int square_num(int a) + { + return a+b + } + } + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'error') + + src = """ + class Test + { + int square_num(int a) + { + return a+b + + """ + result = code_server.run_code(src, 'java_files/main_square.java', + '/tmp', language="java") + check_result(result, 'error') + + def test_bash(): """Test if server runs Bash code as expected.""" src = """ @@ -132,7 +224,7 @@ def test_bash(): [[ $# -eq 2 ]] && echo $(( $1 - $2 )) && exit $(( $1 - $2 )) """ result = code_server.run_code(src, - 'docs/sample.sh\ndocs/sample.args', '/tmp', language="bash") + 'docs/sample.sh\ndocs/sample.args', '/tmp', language="bash") check_result(result, 'error') src = """\ @@ -164,3 +256,4 @@ if __name__ == '__main__': test_bash() test_c() test_cpp() + test_java() |