Example #1
0
def grade(reference_solution, student_solution, translate_line, websheet):
    cpp_compiler = config.config_jo["cpp_compiler"]

    unusable_cppflags = []

    # following http://bits.usc.edu/cs103/compile/
    default_cppflags = ["-g",
                        "-Wall", "-Wshadow", "-Wunreachable-code",
                        "-Wconversion",
                        "-Wno-sign-compare", "-Wno-write-strings"]
    if "clang" in cpp_compiler: # good options, but not in g++
        default_cppflags += ["-Wvla", "-Wno-shorten-64-to-32", "-Wno-sign-conversion", "-fsanitize=undefined"]
    else:
      unusable_cppflags = ["-Wno-array-bounds","-Wno-return-stack-address","-Wunreachable-code"]

    websheet.unusable_cppflags = unusable_cppflags

    # create a temp directory
    refdir = config.create_tempdir()
    studir = config.create_tempdir()

    # put slug.cpp
    jail = config.config_jo["java_jail-abspath"]
    refcpp = open(jail + refdir + websheet.slug + ".cpp", "w", encoding="utf-8")
    refcpp.write(reference_solution)
    refcpp.close()
    
    stucpp = open(jail + studir + websheet.slug + ".cpp", "w", encoding="utf-8")
    stucpp.write(student_solution)
    stucpp.close()
    
    suffix = ""
    if websheet.lang == "C++func": suffix = ".o"

    compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)
    
    compile_args = []
    if websheet.lang == "C++func":
      compile_args += ["-c"]      
    compile_args += [websheet.slug + ".cpp", "-o", websheet.slug + suffix]

    # build reference
    if not websheet.example:
      os.chdir(jail + refdir)
      refcompile = execute(compile_list + compile_args, "")
      if (refcompile.stderr != "" or refcompile.returncode != 0
          or not os.path.isfile(jail + refdir + websheet.slug + suffix)):
        return ("Internal Error (Compiling Reference)",
                "cmd:"+pre(" ".join(compile_list))+
                "<br>stdout:"+pre(refcompile.stdout)+
                "<br>stderr:"+pre(refcompile.stderr)+
                "<br>retval:"+pre(str(refcompile.returncode)))

    # build student
    os.chdir(jail + studir)
    stucompile = execute(compile_list + compile_args, "")
      
    result = "<div>Compiling: saving your code as "+tt(websheet.slug+".cpp")
    result += " and calling "+tt(" ".join(["compile"] + compile_args))
    if stucompile.stdout!="":
      result += pre(stucompile.stdout)
    result += "</div>"
    if (stucompile.stderr != "" or stucompile.returncode != 0
        or not os.path.isfile(jail + studir + websheet.slug + suffix)):
      msg = re.sub('(\.cpp:)(\d+)(?!\d)', 
                   lambda m : m.group(1)+translate_line(m.group(2)),
                   stucompile.stderr)
      result += "<div>Did not compile. Error message:"+pre(msg)+"</div>"
      return ("Syntax Error", result)

    if len(websheet.tests)==0:
      return ("Internal Error", "No tests defined!")

    def example_literal(cpptype):
      known = {"int":"0", "double":"0.0", "bool":"false", "char":"'x'", "string":'""', "char*": '(char*)NULL', "char[]": '""'}
      if cpptype in known: return known[cpptype]
      return None

    for test in websheet.tests:
      if websheet.lang =='C++func' and test[0]=="check-function":
        funcname = test[1]
        returntype = test[2]
        if (returntype == "void"):
          global void_functions
          void_functions += [funcname]
        argtypes = test[3]
        literals = [None] * len(argtypes)
        for i in range(len(literals)):
          literals[i] = example_literal(argtypes[i])
          if literals[i] == None:
            return ("Internal Error", tt("need example_literal for " + argtypes[i]))
        tester = student_solution 
        tester += "\n#include <iostream>\n" + returntype + "(*some_unique_identifier)(" + ', '.join(argtypes) + ") = &" + funcname + ";"
        tester += "\n" + " void even_uniquer() { " + funcname + "(" + ', '.join(literals) + ");}"
        tester += "\n" + "int main() {}\n"

        newslug = websheet.slug + "test"
        cpp = open(jail + refdir + newslug + ".cpp", "w")
        cpp.write(tester)
        cpp.close()

        compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)

        compile_list += [newslug + ".cpp", "-o", newslug + suffix]

        os.chdir(jail + refdir)
        refcompile = execute(compile_list, "")

        if (refcompile.stderr != "" or refcompile.returncode != 0
            or not os.path.isfile(jail + refdir + websheet.slug + suffix)):
          text = ("<div><!--"+refcompile.stderr+"-->"+
                  "You must define a function " 
                  + tt(funcname) + 
                  ( " taking no arguments" if len(argtypes)==0 else 
                    (" taking arguments of types " + tt(", ".join(argtypes))))
                  + " and with return type " + tt(returntype) + "</div>")

          return ("Failed Tests",
                  text + "<!--" +
                  "stdout:"+pre(refcompile.stdout)+
                  "<br>stderr:"+pre(refcompile.stderr)+
                  "<br>retval:"+pre(str(refcompile.returncode))
          +"-->"   )
              
        continue # check-function
      
      if websheet.lang=='C++func' and test[0]=="call-function":
        funcname = test[1]
        args = test[2]        
        testline = funcname + "(" + ', '.join(args) + ")"
        testmain = "\n#include <iostream>\nint main(){std::cout << std::showpoint << std::boolalpha;"
        if funcname not in void_functions: testmain += "std::cout << "
        testmain += testline + ";}\n"
        stutester = student_solution + testmain
        reftester = reference_solution + testmain
        newslug = websheet.slug + "test"

        compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)

        compile_list += [newslug + ".cpp", "-o", newslug]

        if not websheet.example:

          cpp = open(jail + refdir + newslug + ".cpp", "w")
#        print(reftester)
          cpp.write(reftester)
          cpp.close()
          os.chdir(jail + refdir)
          refcompile = execute(compile_list, "")

          if (refcompile.stderr != "" or refcompile.returncode != 0
              or not os.path.isfile(jail + refdir + newslug)):
            return ("Internal Error: Reference Type Check Failed",
                    "<!--" +
                    "stdout:"+pre(refcompile.stdout)+
                    "<br>stderr:"+pre(refcompile.stderr)+
                    "<br>retval:"+pre(str(refcompile.returncode))
                    +"-->"   )

        cpp = open(jail + studir + newslug + ".cpp", "w")
        cpp.write(stutester)
        cpp.close()
        os.chdir(jail + studir)
        stucompile = execute(compile_list, "")

        if (stucompile.stderr != "" or stucompile.returncode != 0
            or not os.path.isfile(jail + refdir + newslug)):
          return ("Internal Error: Type Check Failed",
                  "<!--" +
                  "stdout:"+pre(stucompile.stdout)+
                  "<br>stderr:"+pre(stucompile.stderr)+
                  "<br>retval:"+pre(str(stucompile.returncode))
          +"-->"   )
         # call-function
        if funcname in void_functions:
          result += "<div>Calling " + tt(testline) + "&hellip;</div>"
        else:
          result += "<div>Printing the result of calling " + tt(testline) + "&hellip;</div>"

        exename = newslug
        stdin = ""
        args = []

      if websheet.lang=='C++': # normal test, calling main
        stdin = ""
        args = []
        if 'stdin' in test:
          stdin = test['stdin']
        if 'args' in test:
          args = test['args']

        cmd = websheet.slug
        if len(args) > 0: cmd += " " + " ".join(args)
        result += "<div>Running " + tt("./" + cmd)

        if len(stdin) > 0: 
          result += " on input " + pre(stdin)
        else:
          result += "&hellip;"
        result += "</div>"

        exename = websheet.slug
      
      cfg = config.config_jo

      cmd = [cfg["safeexec-executable-abspath"]]
      cmd += ["--chroot_dir", cfg["java_jail-abspath"]]
      cmd += ["--exec_dir", "/" + refdir]
      cmd += ["--clock", "1"]
      cmd += ["--mem", "40000"]
      cmd += ["--exec", exename]
      cmd += args

      if not websheet.example:
        runref = execute(cmd, stdin)

        if runref.returncode != 0 or not runref.stderr.startswith("OK"):
          result += "<div>Reference solution crashed!"
          result += "<br>stdout:"+pre(runref.stdout)
          result += "stderr:"+pre(runref.stderr)
          result += "val:"+pre(str(runref.returncode))
          result += "</div>"
          return ("Internal Error", result)

      cmd = [cfg["safeexec-executable-abspath"]]
      cmd += ["--chroot_dir", cfg["java_jail-abspath"]]
      cmd += ["--exec_dir", "/" + studir]
      cmd += ["--clock", "1"]
      cmd += ["--mem", "40000"]
      cmd += ["--exec", exename]
      cmd += args

      runstu = execute(cmd, stdin, flag_badchars = True)
      if websheet.slug == "ascii_table":
          # this is the unique exercise where a corrcet solution uses a badchar
          runstu.stdout = runstu.stdout.replace("\\u007f", chr(127))
      if runstu.returncode != 0 or not runstu.stderr.startswith("OK"):
        result += "<div>Crashed! "
        errmsg = runstu.stderr
        if "elapsed time:" in errmsg:
          errmsg = errmsg[:errmsg.index("elapsed time:")]
        errmsg = errmsg.replace("Command terminated by signal (8: SIGFPE)",
                                "Floating point exception")
        errmsg = errmsg.replace("Command terminated by signal (11: SIGSEGV)",
                                "Segmentation fault (core dumped)")
        if errmsg != "":
          result += "Error messages:" + pre(errmsg)
        if runstu.stdout != "":
          result += "Produced this output:"+pre(runstu.stdout)
#        result += "Return code:"+pre(str(runstu.returncode))
        result += "</div>"
        return ("Sandbox Limit", result)
      
      if websheet.example:
        result += "<div>Printed this output:"
        result += pre(runstu.stdout) + "</div>"
        continue

      stucanon = re.sub(' +$', '', runstu.stdout, flags=re.MULTILINE)
      refcanon = re.sub(' +$', '', runref.stdout, flags=re.MULTILINE)

      if (stucanon == refcanon 
          or stucanon == refcanon + "\n" and not refcanon.endswith("\n")):
        result += "<div>Passed! Printed this correct output:"
        result += pre(runstu.stdout, True) + "</div>"
      elif stucanon == refcanon + "\n":
        result += "<div>Failed! Printed this output:"
        result += pre(runstu.stdout, True)
        result += "which is almost correct but <i>you printed an extra newline at the end</i>.</div>"
        return ("Failed Tests", result)
      elif refcanon == stucanon + "\n":
        result += "<div>Failed! Printed this output:"
        result += pre(runstu.stdout, True)
        result += "which is almost correct but <i>you are missing a newline at the end</i>.</div>"
        return ("Failed Tests", result)
      else:
        result += "<div>Failed! Printed this incorrect output:"
        result += pre(runstu.stdout, True)
        result += "Expected this correct output instead:"
        result += pre(runref.stdout, True) + "</div>"
        return ("Failed Tests", result)

    if websheet.example:
      return ("Example", result)
    else:
      result += "<div>Passed all tests!</div>"
      return ("Passed", result)
Example #2
0
def grade(reference_solution, student_solution, translate_line, websheet):
    jail = cfg["java_jail-abspath"]
    # build reference
    if not websheet.example:
        refdir = config.create_tempdir()
        refcompile = compile( jail, refdir, websheet.slug, reference_solution )
        if refcompile.error: return refcompile.error

    # build student
    studir = config.create_tempdir()
    stucompile = compile( jail, studir, websheet.slug, student_solution, 'student', translate_line )
    
    # result = output to user/student
    result = "<div>Compiling: saving your code as "+tt(websheet.slug+".cs")
    result += " and calling "+tt(" ".join(["compile"] ))
    if stucompile.stdout!="":
      result += pre(stucompile.stdout)
    result += "</div>"

    if stucompile.error:
        result += "<div>Did not compile. Error message:"+pre(': '.join(stucompile.error))+"</div>"
        return ("Syntax Error", result)

    # RUN TESTS
    if len(websheet.tests)==0:
      return ("Internal Error", "No tests defined!")

    #~ def example_literal(cpptype):
      #~ known = {"int":"0", "double":"0.0", "bool":"false", "char":"'x'", "string":'""', "char*": '(char*)NULL', "char[]": '""'}
      #~ if cpptype in known: return known[cpptype]
      #~ return None

    for test in websheet.tests:
    #~ for test in json.loads(websheet.tests):

        if websheet.lang=='C#': # normal test, calling main

            stdin = test.get('stdin', "")
            args = test.get('args', [])
            title = test.get('title', "")
            hidden = test.get('hidden', False)

            cmd = websheet.slug
            cmd =  " ".join([cmd] + args)

            if title: 
                result += 'Title: "%s" '%title
            result += "<div>Running " + tt("./" + cmd)
            if hidden and stdin:   
                result += " with hidden input "
            elif stdin:  result += " on input " + pre(stdin)
            else:      result += "&hellip;"
            result += "</div>"


        # RUN REFERENCE
        if not websheet.example:
            os.chdir(jail + refdir)      

            runref = run( websheet.slug, tag='reference', stdin=stdin)

            if runref.error:
                return ("Internal Error", runref.error)

        # RUN STUDENT
        os.chdir(jail + studir)      
        runstu = run( websheet.slug, tag='student', stdin=stdin)
        
        if runstu.error:
            return ("Sandbox Limit", runstu.error)
      
  
        # TODO
        if websheet.example:
            result += "<div>Printed this output:"
            result += pre(runstu.stdout) + "</div>"
            continue

        stucanon = re.sub(' +$', '', runstu.stdout, flags=re.MULTILINE)
        refcanon = re.sub(' +$', '', runref.stdout, flags=re.MULTILINE)

        if (stucanon == refcanon 
          or stucanon == refcanon + "\n" and not refcanon.endswith("\n")):
            result += "<div>Passed! Printed correct output:"
            result += pre(runstu.stdout, True) + "</div>"
        elif stucanon == refcanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you printed an extra newline at the end</i>.</div>"
            return ("Failed Tests", result)
        elif refcanon == stucanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you are missing a newline at the end</i>.</div>"
            return ("Failed Tests", result)
        else:
            result += "<div>Failed!"
            if not hidden: 
                result += " Printed this incorrect output:"
                result += pre(runstu.stdout, True)
                result += "Expected this correct output instead:"
                result += pre(runref.stdout, True) 
            result += "</div>"
            return ("Failed Tests", result)

    if websheet.example:
      return ("Example", result)
    else:
      result += "<div>Passed all tests!</div>"
      return ("Passed", result)
Example #3
0
def grade(reference_solution, student_solution, translate_line, websheet):
    jail = cfg["java_jail-abspath"]
    # build reference
    if not websheet.example:
        refdir = config.create_tempdir()
        refcompile = compile(jail, refdir, websheet.slug, reference_solution)
        if refcompile.error: return refcompile.error

    # build student
    studir = config.create_tempdir()
    stucompile = compile(jail, studir, websheet.slug, student_solution,
                         'student', translate_line)

    # result = output to user/student
    result = "<div>Compiling: saving your code as " + tt(websheet.slug + ".cs")
    result += " and calling " + tt(" ".join(["compile"]))
    if stucompile.stdout != "":
        result += pre(stucompile.stdout)
    result += "</div>"

    if stucompile.error:
        result += "<div>Did not compile. Error message:" + pre(': '.join(
            stucompile.error)) + "</div>"
        return ("Syntax Error", result)

    # RUN TESTS
    if len(websheet.tests) == 0:
        return ("Internal Error", "No tests defined!")

    #~ def example_literal(cpptype):
    #~ known = {"int":"0", "double":"0.0", "bool":"false", "char":"'x'", "string":'""', "char*": '(char*)NULL', "char[]": '""'}
    #~ if cpptype in known: return known[cpptype]
    #~ return None

    for test in websheet.tests:
        #~ for test in json.loads(websheet.tests):

        if websheet.lang == 'C#':  # normal test, calling main

            stdin = test.get('stdin', "")
            args = test.get('args', [])
            title = test.get('title', "")
            hidden = test.get('hidden', False)

            cmd = websheet.slug
            cmd = " ".join([cmd] + args)

            if title:
                result += 'Title: "%s" ' % title
            result += "<div>Running " + tt("./" + cmd)
            if hidden and stdin:
                result += " with hidden input "
            elif stdin:
                result += " on input " + pre(stdin)
            else:
                result += "&hellip;"
            result += "</div>"

        # RUN REFERENCE
        if not websheet.example:
            os.chdir(jail + refdir)

            runref = run(websheet.slug, tag='reference', stdin=stdin)

            if runref.error:
                return ("Internal Error", runref.error)

        # RUN STUDENT
        os.chdir(jail + studir)
        runstu = run(websheet.slug, tag='student', stdin=stdin)

        if runstu.error:
            return ("Sandbox Limit", runstu.error)

        # TODO
        if websheet.example:
            result += "<div>Printed this output:"
            result += pre(runstu.stdout) + "</div>"
            continue

        stucanon = re.sub(' +$', '', runstu.stdout, flags=re.MULTILINE)
        refcanon = re.sub(' +$', '', runref.stdout, flags=re.MULTILINE)

        if (stucanon == refcanon or stucanon == refcanon + "\n"
                and not refcanon.endswith("\n")):
            result += "<div>Passed! Printed correct output:"
            result += pre(runstu.stdout, True) + "</div>"
        elif stucanon == refcanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you printed an extra newline at the end</i>.</div>"
            return ("Failed Tests", result)
        elif refcanon == stucanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you are missing a newline at the end</i>.</div>"
            return ("Failed Tests", result)
        else:
            result += "<div>Failed!"
            if not hidden:
                result += " Printed this incorrect output:"
                result += pre(runstu.stdout, True)
                result += "Expected this correct output instead:"
                result += pre(runref.stdout, True)
            result += "</div>"
            return ("Failed Tests", result)

    if websheet.example:
        return ("Example", result)
    else:
        result += "<div>Passed all tests!</div>"
        return ("Passed", result)
Example #4
0
def grade(reference_solution, student_solution, translate_line, websheet):
    cpp_compiler = config.config_jo["cpp_compiler"]

    unusable_cppflags = []

    # following http://bits.usc.edu/cs103/compile/
    default_cppflags = [
        "-g", "-Wall", "-Wshadow", "-Wunreachable-code", "-Wconversion",
        "-Wno-sign-compare", "-Wno-write-strings"
    ]
    if "clang" in cpp_compiler:  # good options, but not in g++
        default_cppflags += [
            "-Wvla", "-Wno-shorten-64-to-32", "-Wno-sign-conversion",
            "-fsanitize=undefined"
        ]
    else:
        unusable_cppflags = [
            "-Wno-array-bounds", "-Wno-return-stack-address",
            "-Wunreachable-code"
        ]

    websheet.unusable_cppflags = unusable_cppflags

    # create a temp directory
    refdir = config.create_tempdir()
    studir = config.create_tempdir()

    # put slug.cpp
    jail = config.config_jo["java_jail-abspath"]
    refcpp = open(jail + refdir + websheet.slug + ".cpp",
                  "w",
                  encoding="utf-8")
    refcpp.write(reference_solution)
    refcpp.close()

    stucpp = open(jail + studir + websheet.slug + ".cpp",
                  "w",
                  encoding="utf-8")
    stucpp.write(student_solution)
    stucpp.close()

    suffix = ""
    if websheet.lang == "C++func": suffix = ".o"

    compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)

    compile_args = []
    if websheet.lang == "C++func":
        compile_args += ["-c"]
    compile_args += [websheet.slug + ".cpp", "-o", websheet.slug + suffix]

    # build reference
    if not websheet.example:
        os.chdir(jail + refdir)
        refcompile = execute(compile_list + compile_args, "")
        if (refcompile.stderr != "" or refcompile.returncode != 0
                or not os.path.isfile(jail + refdir + websheet.slug + suffix)):
            return ("Internal Error (Compiling Reference)",
                    "cmd:" + pre(" ".join(compile_list)) + "<br>stdout:" +
                    pre(refcompile.stdout) + "<br>stderr:" +
                    pre(refcompile.stderr) + "<br>retval:" +
                    pre(str(refcompile.returncode)))

    # build student
    os.chdir(jail + studir)
    stucompile = execute(compile_list + compile_args, "")

    result = "<div>Compiling: saving your code as " + tt(websheet.slug +
                                                         ".cpp")
    result += " and calling " + tt(" ".join(["compile"] + compile_args))
    if stucompile.stdout != "":
        result += pre(stucompile.stdout)
    result += "</div>"
    if (stucompile.stderr != "" or stucompile.returncode != 0
            or not os.path.isfile(jail + studir + websheet.slug + suffix)):
        msg = re.sub('(\.cpp:)(\d+)(?!\d)',
                     lambda m: m.group(1) + translate_line(m.group(2)),
                     stucompile.stderr)
        result += "<div>Did not compile. Error message:" + pre(msg) + "</div>"
        return ("Syntax Error", result)

    if len(websheet.tests) == 0:
        return ("Internal Error", "No tests defined!")

    def example_literal(cpptype):
        known = {
            "int": "0",
            "double": "0.0",
            "bool": "false",
            "char": "'x'",
            "string": '""',
            "char*": '(char*)NULL',
            "char[]": '""'
        }
        if cpptype in known: return known[cpptype]
        return None

    for test in websheet.tests:
        if websheet.lang == 'C++func' and test[0] == "check-function":
            funcname = test[1]
            returntype = test[2]
            if (returntype == "void"):
                global void_functions
                void_functions += [funcname]
            argtypes = test[3]
            literals = [None] * len(argtypes)
            for i in range(len(literals)):
                literals[i] = example_literal(argtypes[i])
                if literals[i] == None:
                    return ("Internal Error",
                            tt("need example_literal for " + argtypes[i]))
            tester = student_solution
            tester += "\n#include <iostream>\n" + returntype + "(*some_unique_identifier)(" + ', '.join(
                argtypes) + ") = &" + funcname + ";"
            tester += "\n" + " void even_uniquer() { " + funcname + "(" + ', '.join(
                literals) + ");}"
            tester += "\n" + "int main() {}\n"

            newslug = websheet.slug + "test"
            cpp = open(jail + refdir + newslug + ".cpp", "w")
            cpp.write(tester)
            cpp.close()

            compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)

            compile_list += [newslug + ".cpp", "-o", newslug + suffix]

            os.chdir(jail + refdir)
            refcompile = execute(compile_list, "")

            if (refcompile.stderr != "" or refcompile.returncode != 0
                    or not os.path.isfile(jail + refdir + websheet.slug +
                                          suffix)):
                text = ("<div><!--" + refcompile.stderr + "-->" +
                        "You must define a function " + tt(funcname) +
                        (" taking no arguments" if len(argtypes) == 0 else
                         (" taking arguments of types " +
                          tt(", ".join(argtypes)))) +
                        " and with return type " + tt(returntype) + "</div>")

                return ("Failed Tests", text + "<!--" + "stdout:" +
                        pre(refcompile.stdout) + "<br>stderr:" +
                        pre(refcompile.stderr) + "<br>retval:" +
                        pre(str(refcompile.returncode)) + "-->")

            continue  # check-function

        if websheet.lang == 'C++func' and test[0] == "call-function":
            funcname = test[1]
            args = test[2]
            testline = funcname + "(" + ', '.join(args) + ")"
            testmain = "\n#include <iostream>\nint main(){std::cout << std::showpoint << std::boolalpha;"
            if funcname not in void_functions: testmain += "std::cout << "
            testmain += testline + ";}\n"
            stutester = student_solution + testmain
            reftester = reference_solution + testmain
            newslug = websheet.slug + "test"

            compile_list = [cpp_compiler] + websheet.cppflags(default_cppflags)

            compile_list += [newslug + ".cpp", "-o", newslug]

            if not websheet.example:

                cpp = open(jail + refdir + newslug + ".cpp", "w")
                #        print(reftester)
                cpp.write(reftester)
                cpp.close()
                os.chdir(jail + refdir)
                refcompile = execute(compile_list, "")

                if (refcompile.stderr != "" or refcompile.returncode != 0
                        or not os.path.isfile(jail + refdir + newslug)):
                    return ("Internal Error: Reference Type Check Failed",
                            "<!--" + "stdout:" + pre(refcompile.stdout) +
                            "<br>stderr:" + pre(refcompile.stderr) +
                            "<br>retval:" + pre(str(refcompile.returncode)) +
                            "-->")

            cpp = open(jail + studir + newslug + ".cpp", "w")
            cpp.write(stutester)
            cpp.close()
            os.chdir(jail + studir)
            stucompile = execute(compile_list, "")

            if (stucompile.stderr != "" or stucompile.returncode != 0
                    or not os.path.isfile(jail + refdir + newslug)):
                return ("Internal Error: Type Check Failed", "<!--" +
                        "stdout:" + pre(stucompile.stdout) + "<br>stderr:" +
                        pre(stucompile.stderr) + "<br>retval:" +
                        pre(str(stucompile.returncode)) + "-->")
            # call-function
            if funcname in void_functions:
                result += "<div>Calling " + tt(testline) + "&hellip;</div>"
            else:
                result += "<div>Printing the result of calling " + tt(
                    testline) + "&hellip;</div>"

            exename = newslug
            stdin = ""
            args = []

        if websheet.lang == 'C++':  # normal test, calling main
            stdin = ""
            args = []
            if 'stdin' in test:
                stdin = test['stdin']
            if 'args' in test:
                args = test['args']

            cmd = websheet.slug
            if len(args) > 0: cmd += " " + " ".join(args)
            result += "<div>Running " + tt("./" + cmd)

            if len(stdin) > 0:
                result += " on input " + pre(stdin)
            else:
                result += "&hellip;"
            result += "</div>"

            exename = websheet.slug

        cfg = config.config_jo

        cmd = [cfg["safeexec-executable-abspath"]]
        cmd += ["--chroot_dir", cfg["java_jail-abspath"]]
        cmd += ["--exec_dir", "/" + refdir]
        cmd += ["--clock", "1"]
        cmd += ["--mem", "40000"]
        cmd += ["--exec", exename]
        cmd += args

        if not websheet.example:
            runref = execute(cmd, stdin)

            if runref.returncode != 0 or not runref.stderr.startswith("OK"):
                result += "<div>Reference solution crashed!"
                result += "<br>stdout:" + pre(runref.stdout)
                result += "stderr:" + pre(runref.stderr)
                result += "val:" + pre(str(runref.returncode))
                result += "</div>"
                return ("Internal Error", result)

        cmd = [cfg["safeexec-executable-abspath"]]
        cmd += ["--chroot_dir", cfg["java_jail-abspath"]]
        cmd += ["--exec_dir", "/" + studir]
        cmd += ["--clock", "1"]
        cmd += ["--mem", "40000"]
        cmd += ["--exec", exename]
        cmd += args

        runstu = execute(cmd, stdin, flag_badchars=True)
        if websheet.slug == "ascii_table":
            # this is the unique exercise where a corrcet solution uses a badchar
            runstu.stdout = runstu.stdout.replace("\\u007f", chr(127))
        if runstu.returncode != 0 or not runstu.stderr.startswith("OK"):
            result += "<div>Crashed! "
            errmsg = runstu.stderr
            if "elapsed time:" in errmsg:
                errmsg = errmsg[:errmsg.index("elapsed time:")]
            errmsg = errmsg.replace("Command terminated by signal (8: SIGFPE)",
                                    "Floating point exception")
            errmsg = errmsg.replace(
                "Command terminated by signal (11: SIGSEGV)",
                "Segmentation fault (core dumped)")
            if errmsg != "":
                result += "Error messages:" + pre(errmsg)
            if runstu.stdout != "":
                result += "Produced this output:" + pre(runstu.stdout)
#        result += "Return code:"+pre(str(runstu.returncode))
            result += "</div>"
            return ("Sandbox Limit", result)

        if websheet.example:
            result += "<div>Printed this output:"
            result += pre(runstu.stdout) + "</div>"
            continue

        stucanon = re.sub(' +$', '', runstu.stdout, flags=re.MULTILINE)
        refcanon = re.sub(' +$', '', runref.stdout, flags=re.MULTILINE)

        if (stucanon == refcanon or stucanon == refcanon + "\n"
                and not refcanon.endswith("\n")):
            result += "<div>Passed! Printed this correct output:"
            result += pre(runstu.stdout, True) + "</div>"
        elif stucanon == refcanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you printed an extra newline at the end</i>.</div>"
            return ("Failed Tests", result)
        elif refcanon == stucanon + "\n":
            result += "<div>Failed! Printed this output:"
            result += pre(runstu.stdout, True)
            result += "which is almost correct but <i>you are missing a newline at the end</i>.</div>"
            return ("Failed Tests", result)
        else:
            result += "<div>Failed! Printed this incorrect output:"
            result += pre(runstu.stdout, True)
            result += "Expected this correct output instead:"
            result += pre(runref.stdout, True) + "</div>"
            return ("Failed Tests", result)

    if websheet.example:
        return ("Example", result)
    else:
        result += "<div>Passed all tests!</div>"
        return ("Passed", result)