# -*- coding: utf-8 -*-
# $Id: Java.py 1634 2013-04-12 15:36:36Z amelung $
#
# Copyright (c) 2007-2011 Otto-von-Guericke-Universität Magdeburg
#
# This file is part of ECSpooler.
import logging
# local imports
# The packages that the model and student solution will be put in
# The name of the wrapper class that performs the semantic check
# load Java function to do a simple test
try:
except IOError:
# load Java function to do a test which allows permutation of list elems
#try:
# permTest = file('permTest.java', 'r').read()
#except IOError:
# permTest = ''
WRAPPER_TEMPLATE = \
'''
public class %s
{
private static Object isArray(Object o)
{
if (o.getClass().isArray())
{
java.util.LinkedList<Object> list = new java.util.LinkedList<Object>();
for (int i = 0; i < java.lang.reflect.Array.getLength(o); i++)
{
list.add(java.lang.reflect.Array.get(o, i));
}
return list;
}
return o;
}
${helpFunctions}
${testFunction}
public static void main(String[] argv)
{
Object exp = ${model_testData};
Object rec = ${student_testData};
exp = isArray(exp);
rec = isArray(rec);
Boolean eql = new Boolean(test(exp, rec));
System.out.println("isEqual=" + eql.toString()
+ ";;expected=" + exp.toString()
+ ";;received=" + rec.toString());
}
}
''' % (CLASS_SEMANTIC_CHECK)
# input schema
'modelSolution',
'is a Java class which implements methods ' +
'to resolve the given assignment.',
),
'helpFunctions',
'can be used, e.g., to calculate values for testing ' +
'or as a parameter in a test call.',
),
'testData',
#accessor = # must return a list; default is one element per line
'just a Java method call with appropriate parameters, ' +
'e.g., new MyTest().(3, 2, 5).' +
'The Java class name and metod names are normally ' +
'given in the assignment directives.' +
'Each test call must be written in a single line.',
),
))
# testSchema
'simple',
),
# TestEnvironment(
# 'permutation',
# label = 'Permutation',
# description = 'Test with permutations',
# test = permTest,
# semantic = WRAPPER_TEMPLATE,
# lineNumberOffset = 2,
# compiler = config.COMPILER,
# interpreter = config.INTERPRETER,
# ),
))
# The regular expression to extract the name of the *public* class
# from a piece of source.
#
# The grammar at <http://cobase-www.cs.ucla.edu/pub/javacc/java1.4.jj>
# says this:
#
# void ClassDeclaration() :
# {}
# {
# ( "abstract" | "final" | "public" | "strictfp")*
# UnmodifiedClassDeclaration()
# }
#
# void UnmodifiedClassDeclaration() :
# {}
# {
# "class" <IDENTIFIER> [ "extends" Name() ]
# [ "implements" NameList() ]
# ClassBody()
# }
CLASS_NAME_RE = re.compile(r'^\s*(?:public\s+(?:(?:abstract|final|public|strictfp)\s+)*)+\s*class\s+(?P<name>[a-zA-Z_]\w*)', re.MULTILINE)
def non_null_str(s):
"""
"""
"""
A simple backend for testing Java programs by comparing
student and model solution on a given set of test data.
"""
"""
This constructor is needed to reset the logging environment.
"""
"""
Extract the class name from the source code snippet [src]
"""
assert m is not None, \
'Name of the public class could not be ' \
return m.group('name')
# -- check syntax ---------------------------------------------------------
"""
Replace module name in students' submission.
@see: ProgrammingBackend._preProcessCheckSyntax
@return: modified source code and new module name
"""
"""
@see: AbtractSimpleBackend._postProcessCheckSyntax
"""
# search for path, filename and line numbers
# result is something like [('Tutor1.java:7', '7'), ('Tutor1.java:7', '7')]
# replace each filename and line number
1)
return message
# -- check semantics ------------------------------------------------------
"""
Pre process student's submissions and semantic check wrapper code.
Override this method if you need to reformat the wrapper code or
the student's submission.
"""
"""
Runs sematic test on a Java program.
Remember: Before we can run the wrapper code we have to compile it!!
@return: a BackendResult object with result code and value
"""
# test for available test specs
msg = 'No test specification selected.'
# test for defined repeat fields in the schema definition
assert repeatFields, 'No RepeatField found.'
# test for available test data
msg = 'No test data defined.'
# get model solution and student's submission
assert non_null_str(model), \
"Semantic check requires valid 'model solution' (%s)" % \
assert non_null_str(submission), \
"Semantic check requires valid 'student solution' (%s)" % \
# define return values
# run selected test specifications
if not solved: break
# compile the solutions
compiled = {}
try:
# replace module name in the solution
# write 'solution' to a file
# compile the solution
except AssertionError, err:
msg = 'Internal error during semantic check: %s: %s' % \
#student = compiled['student']
# get the interpreter
# 4.1. set wrapper source
# 4.2. get values for all other input fields from schema which are
# available in the job data
# 4.3 set test function
# 4.3.1 replace class names
# 4.4. run with all test data
for t in testdata:
# and now add repeatable data values
tStudent = None
('student', NS_STUDENT)):
# substitute the class name in the test data with
# the actual, package-qualified class name
t)
if k == 'student':
# We use this for error reports. It is like
# the test data that we actually use, but
# without the package qualifier. After all,
# the package is something we add and seeing
# that in the error report might confuse the
# student.
compiled['studentClass'],
t)
# substitute the respective test data placeholder
# with the test data we just fixed up
# remove all remaining placeholders
# compile and execute wrapper
try:
# write module for wrapper
# compile the wrapper
'Error in wrapper code for semantic check: %s' % result
# run the wrapper
except Exception, e:
msg = 'Internal error during semantic check: %s: %s' % \
# an error occured
result = "\nYour submission failed. Test " \
"case was: '%s' (%s)" \
"\n\n Received result: %s"\
# has the students' solution passed this tests?
else:
# TODO: i18n
feedback = "\nYour submission failed. Test " \
"case was: '%s' (%s)" \
feedback += '\n\n Expected result: %s\n ' \
'Received result: %s' \
break # means: end testing right now
# end inner for loop
#end out for loop
if solved:
# TODO: i18n
feedback = '\nYour submission passed all tests.'
# -- some testing -------------------------------------------------------------
import socket
if __name__ == "__main__":
"""
"""
try:
except AttributeError, aerr:
print('os.fork not defined - skipping.')
cpid = 0
if cpid == 0:
'port': 5060,
'auth': {'username':'demo', 'password':'foobar'}
})
else:
print 'pid=', cpid