assembly program
Homework2/64bitAdd/64bitAdd.s
Homework2/64bitAdd/Makefile
sfile = 64bitAdd.s exe = 64bitAdd.out 64bitAdd.out: 64bitAdd.o ld -melf_i386 -o $(exe) 64bitAdd.o 64bitAdd.o: $(sfile) as --32 --gstabs -o 64bitAdd.o $(sfile) clean: rm -fr $(exe) 64bitAdd.o
Homework2/64bitAdd/result.py
class Result(object): """ a wrapper to contain the results of a test @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ def __init__(self, testName, correct, timeTaken): """ @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ self.testName = testName self.correct = correct self.timeTaken = timeTaken #end init def __repr__(self): if type(self.timeTaken) == str: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {!s}' else: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {:.3f}' s = format_str.format(self.testName, self.correct, self.timeTaken) return s def __str__(self): return self.__repr__()
Homework2/64bitAdd/Solutions/0-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = -2 (gdb) $2 = -1 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/1-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 5820913 (gdb) $2 = -4 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/2-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 24 (gdb) $2 = 24 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/3-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 562447 (gdb) $2 = -94625 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/4-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 6 (gdb) $2 = 4 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/5-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 154 (gdb) $2 = 126 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/6-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = -59 (gdb) $2 = -16 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/7-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = -4 (gdb) $2 = -3 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/8-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 1438 (gdb) $2 = 120 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/Solutions/9-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out...done. (gdb) Breakpoint 1 at 0x8048074: file 64bitAdd.s, line 26. (gdb) Breakpoint 2 at 0x8048090: file 64bitAdd.s, line 39. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/64bitAdd/64bitAdd.out Breakpoint 1, _start () at 64bitAdd.s:26 26 movl num1_lower32, %eax (gdb) (gdb) (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at 64bitAdd.s:39 39 addl %eax, %eax (gdb) $1 = 313331120 (gdb) $2 = 220011470 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/64bitAdd/tester.py
#this is the base class for tester objects import sys import subprocess import logging import os from time import clock from result import Result studentLogger = logging.getLogger('errorLogger.progressLogger.studentLogger') studentLogger.setLevel(logging.INFO) h = logging.StreamHandler() h.setLevel(logging.INFO) studentLogger.addHandler(h) class Tester(object): """ Tester abstract class representing a testing interface """ __name__ = 'Tester' #the name of this class INPUT_STDIN = 1 #input is expected to come via standard input INPUT_CMDLINE = 2 #input is expected to comve via the command line OUTPUT_STDOUT = 3 #output of executable will be to the standard output OUTPUT_FILE = 4 #exectuables output will be a file _PROGRAM_COMPLETED = 5 #the program completed the test _PROGRAM_CRASHED = 6 #the program crashed during a test _PROGRAM_TIMED_OUT = 7 #the program timed out during a test def str2InputType(typename): """converts the string name of the input type to the internal type @typename: the name of the type. either stdin cmdline """ if(typename.lower() == 'stdin'): return Tester.INPUT_STDIN elif(typename.lower() == 'cmdline'): return Tester.INPUT_CMDLINE else: raise ValueError('Unknown input type ' + typename) def str2OutputType(typename): """converts the string name of the output type to the internal type @typename: the name of the type. either stdout file """ if(typename.lower() == 'stdout'): return Tester.OUTPUT_STDOUT elif(typename.lower() == 'file'): return Tester.OUTPUT_FILE else: raise ValueError('Unknown input type ' + typename) def __init__(self, executable, usingCmdArgs, usingStdin, outputType, inDir, solDir, scratchDir, maxRunTime = 5, cmdArgs = None, lines2skip = 0): """ @executable: the name of the exectuable to be run @usingCmdArgs: Are command line arguments being used? @usingStdin: Will there be input from the standard input? @outputType: how are outputs generated: Either OUTPUT_STDOUT: for when the solution is sent to standard out or OUTPUT_FILE: for when the solution is sent to a file @inDir: the name of the directory containing the inputs to be used for testing the naming convention for the tests contained within is testname-test.filetype @solDir: the name of the directory containing the solutions the naming convention for the solutions contained within is testname-sol.filetype @scratchDir: directory to write scratch files in @maxRunTime: the maximum number of seconds to run the program or None to allow the program to run until completion (if it does not terminate the program will hang) @cmdArgs: a list of additional command line arguments to the executable @lines2skip: number of lines of output program and solution file to skip """ self.executable = executable self.usingCmdArgs = usingCmdArgs self.usingStdin = usingStdin self.outputType = outputType self.inDir = inDir self.solDir = solDir self.scratchDir = scratchDir self.maxRunTime = maxRunTime self.lines2skip = lines2skip if cmdArgs == None: self.cmdArgs = [] else: self.cmdArgs = cmdArgs.copy() self.testFiles = [self.inDir + os.sep + test for test in os.listdir(inDir) if not test.startswith('.')] #get the tests in the test directory self.testFiles.sort() #make the tests sorted if(scratchDir == None): self.userOut = None else: self.userOut = scratchDir + os.sep + 'userOut.txt' #file to temporarily store the use's output self.startTime = 0 #when did the test begin running self.endTime = 0 #when did the test end running self.results = [] #the results of the testing def _runOne(self, inFileName, outFileName = None): """run self.executable using the inputs contained in inFileName @inFileName: the name of the file containing the inputs @outFileName: the name of the file to write the program's stdout to if the solution is contained in the stdout @returns: the success status of running the program """ #determine how to pass input file infile = None #the input file to be used additionalArgs = [] with open(inFileName) as infile: if(self.usingCmdArgs): #using command line arguments num_args = int(infile.readline()) #the first line contains the number of command line arguments for i in range(num_args): #read the command arguments in additionalArgs.append(infile.readline().strip()) #remaining lines in the file are considerd input to be given #via standard input #determine how outputs will be generated outfile = None if(self.outputType == Tester.OUTPUT_STDOUT): #outputting to stdout outfile = open(outFileName,'w') #open a file to hold the results elif(self.outputType == Tester.OUTPUT_FILE): #outputting to a file raise NotImplementedError #nothing we can really do as of now else: raise NotImplementedError #this clears out python's buffer so that the program run through subprocess #actually gets input. Another fix if this stops working is to open the file in unbuffered mode #http://stackoverflow.com/questions/22417010/subprocess-popen-stdin-read-file infile.seek(infile.tell()) studentLogger.info('Preparing to test %s on %s', self.executable, os.path.basename(inFileName)) #start the clocks self.endTime = clock() self.startTime = clock() #run the program with subprocess.Popen([self.executable] + self.cmdArgs + additionalArgs, stdin = infile, stdout = outfile, stderr = subprocess.PIPE, universal_newlines = True) as program: try: program.wait(timeout = self.maxRunTime) #wait for the program to finish self.endTime = clock() #program completed err = '\t'.join(program.stderr.readlines()) #always have to read the pipes if(program.returncode != 0): studentLogger.warning('%s %s crashed for the following reasons:\n\t%s\n', self.executable, ' '.join(self.cmdArgs), err) return Tester._PROGRAM_CRASHED else: return Tester._PROGRAM_COMPLETED except subprocess.TimeoutExpired: studentLogger.warning('%s %s timed out', ' '.join(self.cmdArgs), self.executable) program.kill() return Tester._PROGRAM_TIMED_OUT #end _runOne def testOne(self, inFile, solFile): """ run the executable using inFile as the inputs and checking the output against solFile @inFile: the name of the file containing the inputs @solFile: the name of the file containg the solution @returns: a Result """ progStatus = self._runOne(inFile, self.userOut)#run the program testName = os.path.basename(inFile) #the name of the test if(progStatus == Tester._PROGRAM_CRASHED): return Result(testName, False, 'Crashed') elif(progStatus == Tester._PROGRAM_TIMED_OUT): return Result(testName, False, 'Timed Out') else: #program completed successfully if(self.outputType == Tester.OUTPUT_STDOUT): with open(self.userOut) as answer: (correct, out, sol) = self._checkSolution(answer, solFile) if(correct): studentLogger.info('%s %s passed test %s', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile)) else: first_diff = '' i = 0 for (i,(o,s)) in enumerate(zip(out,sol)): if o != s: first_diff = 'First mismatch at word %d\nout = %s but sol = %s' % (i,o,s) #print(first_diff) break studentLogger.info('%s %s failed test %s. Program output: %s \n Solution: %s \n%s\n\n', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile), out, sol, first_diff) return Result(testName, correct, self.endTime - self.startTime ) else: #haven't done anything where solutions are contained in files raise NotImplementedError #end testOne def generateSolutions(self): """generates all the solutions""" for test in self.testFiles: outfileName = test.replace('-test', '-sol') outfileName = self.solDir + os.sep + os.path.basename(outfileName) self._runOne(test,outfileName) #end generateSolutions def testAll(self): """ Test all the tests @returns: a list of triples of the form (testName, correct, time taken) correct is True if the answer is correct and False if it is wrong time taken is expressed in seconds. See Result """ self.results = [] #clear old results if any exist for test in self.testFiles: #get the name of the file containing the solution to this test sol = test.replace('-test', '-sol') #replace test with sol sol = self.solDir + os.sep + os.path.basename(sol) #prepend solution directory name and remove test directory path self.results.append(self.testOne(test, sol)) try: os.remove(self.userOut) except FileNotFoundError: pass #end testAll def getResults(self): """get the results of the testing""" return self.results.copy() #end getResults def getNumTests(self): """get the number of tests that are to be preformed""" return len(self.testFiles) #end getNumTests def getNumCorrect(self): """ get the number of answers that were correct should only be called after testAll is run @returns: the number of tests that were correct """ numCorrect = 0 for res in self.results: if(res.correct == True): numCorrect += 1 return numCorrect #end getNumCorrect def getPercentCorrect(self): """get the precentage of right answers should only be called after testAll is run @returns: the percentage of tests that were correct """ numCorrect = self.getNumCorrect() numTests = float(self.getNumTests()) return numCorrect / numTests #end getPercentCorrect def getMissedTests(self): """ get a list of the test names that were missed should only be called after testAll is run @returns: a list of the test names that were missed """ return [res.testName for res in self.results if not res.correct] #end getMissedTests def getPassedTests(self): """ get a list of the test names that were passed correctly should only be called after testAll is run @returns: a list of the test names that were passed correctly """ return [res.testName for res in self.results if res.correct] #getPassedTests def getTestNames(self): """ get the names of the tests to be run can be called before testAll is run @returns: a list containg the test names """ return [test.rsplit(os.sep, 1)[-1] for test in self.testFiles] def _checkSolution(self, progOut, solutionFileName): """ checkSolution @progOut: the opened file containing the student's answer @solutionFileName: the name of the file containg the solution @returns a tuple containing (correct, program out, solution) """ progOut.flush() #make sure the file is up to date progOut.seek(0) #go back to the begining of the file try: sol = [] with open(solutionFileName, 'r') as solFil: #open the solution file for (_1,_2,_3) in zip(range(self.lines2skip), progOut, solFil): #somehow placin zip as the first argument fixes a bug pass #skip the leading lines of input sol = [] #the solution for line in solFil: #make it so that white space does not matter sol += line.strip().split() out = [] # the programs output for line in progOut: #make it so that white space will not be an issue out += line.strip().split() if(out != sol):#output does not match solution return (False, out, sol) return (True, out, sol) #if everything is correct and all lines in the solution file are used the student got it right except UnicodeDecodeError: return (False, 'NonUnicode Character. This means your print statement is printing something crazy.', sol) # end _checkSolution #end class Tester if __name__ =='__main__': python = sys.executable t = Tester('gdb', False, True, Tester.OUTPUT_STDOUT, 'Tests', 'Solutions', '.', cmdArgs = ['-q', '64bitAdd.out'], lines2skip = 11) t.testAll() for res in t.getResults(): print(res)
Homework2/64bitAdd/Tests/0-test.txt
break _start break done run set ((int*)&num1)[0] = -1 set ((int*)&num1)[1] = -1 set ((int*)&num2)[0] = -1 set ((int*)&num2)[1] = -1 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/1-test.txt
break _start break done run set ((int*)&num1)[0] = -3 set ((int*)&num1)[1] = 1035789 set ((int*)&num2)[0] = -1 set ((int*)&num2)[1] = 4785124 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/2-test.txt
break _start break done run set ((int*)&num1)[0] = 12 set ((int*)&num1)[1] = 12 set ((int*)&num2)[0] = 12 set ((int*)&num2)[1] = 12 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/3-test.txt
break _start break done run set ((int*)&num1)[0] = -45867 set ((int*)&num1)[1] = 562437 set ((int*)&num2)[0] = -48758 set ((int*)&num2)[1] = 10 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/4-test.txt
break _start break done run set ((int*)&num1)[0] = 1 set ((int*)&num1)[1] = 2 set ((int*)&num2)[0] = 3 set ((int*)&num2)[1] = 4 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/5-test.txt
break _start break done run set ((int*)&num1)[0] = 27 set ((int*)&num1)[1] = 54 set ((int*)&num2)[0] = 99 set ((int*)&num2)[1] = 100 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/6-test.txt
break _start break done run set ((int*)&num1)[0] = -10 set ((int*)&num1)[1] = -56 set ((int*)&num2)[0] = -7 set ((int*)&num2)[1] = -3 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/7-test.txt
break _start break done run set ((int*)&num1)[0] = -2 set ((int*)&num1)[1] = -2 set ((int*)&num2)[0] = -2 set ((int*)&num2)[1] = -2 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/8-test.txt
break _start break done run set ((int*)&num1)[0] = 78 set ((int*)&num1)[1] = 101 set ((int*)&num2)[0] = 42 set ((int*)&num2)[1] = 1337 continue print $eax print $edx kill quit y
Homework2/64bitAdd/Tests/9-test.txt
break _start break done run set ((int*)&num1)[0] = 3216231 set ((int*)&num1)[1] = 78435889 set ((int*)&num2)[0] = 216795239 set ((int*)&num2)[1] = 234895231 continue print $eax print $edx kill quit y
Homework2/div/div.c
Homework2/div/result.py
class Result(object): """ a wrapper to contain the results of a test @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ def __init__(self, testName, correct, timeTaken): """ @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ self.testName = testName self.correct = correct self.timeTaken = timeTaken #end init def __repr__(self): if type(self.timeTaken) == str: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {!s}' else: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {:.3f}' s = format_str.format(self.testName, self.correct, self.timeTaken) return s def __str__(self): return self.__repr__()
Homework2/div/Solutions/0-sol.txt
0 / 172561 = 0 R 0
Homework2/div/Solutions/1-sol.txt
64 / 4 = 16 R 0
Homework2/div/Solutions/2-sol.txt
27 / 1 = 27 R 0
Homework2/div/Solutions/3-sol.txt
100 / 17 = 5 R 15
Homework2/div/Solutions/4-sol.txt
7 / 3 = 2 R 1
Homework2/div/Solutions/5-sol.txt
4294967295 / 113 = 38008560 R 15
Homework2/div/Solutions/6-sol.txt
50 / 125 = 0 R 50
Homework2/div/Solutions/7-sol.txt
9 / 9 = 1 R 0
Homework2/div/Solutions/8-sol.txt
74088 / 42 = 1764 R 0
Homework2/div/Solutions/9-sol.txt
3 / 7 = 0 R 3
Homework2/div/tester.py
#this is the base class for tester objects import sys import subprocess import logging import os from time import clock from result import Result studentLogger = logging.getLogger('errorLogger.progressLogger.studentLogger') studentLogger.setLevel(logging.INFO) h = logging.StreamHandler() h.setLevel(logging.INFO) studentLogger.addHandler(h) class Tester(object): """ Tester abstract class representing a testing interface """ __name__ = 'Tester' #the name of this class INPUT_STDIN = 1 #input is expected to come via standard input INPUT_CMDLINE = 2 #input is expected to comve via the command line OUTPUT_STDOUT = 3 #output of executable will be to the standard output OUTPUT_FILE = 4 #exectuables output will be a file _PROGRAM_COMPLETED = 5 #the program completed the test _PROGRAM_CRASHED = 6 #the program crashed during a test _PROGRAM_TIMED_OUT = 7 #the program timed out during a test def str2InputType(typename): """converts the string name of the input type to the internal type @typename: the name of the type. either stdin cmdline """ if(typename.lower() == 'stdin'): return Tester.INPUT_STDIN elif(typename.lower() == 'cmdline'): return Tester.INPUT_CMDLINE else: raise ValueError('Unknown input type ' + typename) def str2OutputType(typename): """converts the string name of the output type to the internal type @typename: the name of the type. either stdout file """ if(typename.lower() == 'stdout'): return Tester.OUTPUT_STDOUT elif(typename.lower() == 'file'): return Tester.OUTPUT_FILE else: raise ValueError('Unknown input type ' + typename) def __init__(self, executable, usingCmdArgs, usingStdin, outputType, inDir, solDir, scratchDir, maxRunTime = 5, cmdArgs = None, lines2skip = 0): """ @executable: the name of the exectuable to be run @usingCmdArgs: Are command line arguments being used? @usingStdin: Will there be input from the standard input? @outputType: how are outputs generated: Either OUTPUT_STDOUT: for when the solution is sent to standard out or OUTPUT_FILE: for when the solution is sent to a file @inDir: the name of the directory containing the inputs to be used for testing the naming convention for the tests contained within is testname-test.filetype @solDir: the name of the directory containing the solutions the naming convention for the solutions contained within is testname-sol.filetype @scratchDir: directory to write scratch files in @maxRunTime: the maximum number of seconds to run the program or None to allow the program to run until completion (if it does not terminate the program will hang) @cmdArgs: a list of additional command line arguments to the executable @lines2skip: number of lines of output program and solution file to skip """ self.executable = executable self.usingCmdArgs = usingCmdArgs self.usingStdin = usingStdin self.outputType = outputType self.inDir = inDir self.solDir = solDir self.scratchDir = scratchDir self.maxRunTime = maxRunTime self.lines2skip = lines2skip if cmdArgs == None: self.cmdArgs = [] else: self.cmdArgs = cmdArgs.copy() self.testFiles = [self.inDir + os.sep + test for test in os.listdir(inDir) if not test.startswith('.')] #get the tests in the test directory self.testFiles.sort() #make the tests sorted if(scratchDir == None): self.userOut = None else: self.userOut = scratchDir + os.sep + 'userOut.txt' #file to temporarily store the use's output self.startTime = 0 #when did the test begin running self.endTime = 0 #when did the test end running self.results = [] #the results of the testing def _runOne(self, inFileName, outFileName = None): """run self.executable using the inputs contained in inFileName @inFileName: the name of the file containing the inputs @outFileName: the name of the file to write the program's stdout to if the solution is contained in the stdout @returns: the success status of running the program """ #determine how to pass input file infile = None #the input file to be used additionalArgs = [] with open(inFileName) as infile: if(self.usingCmdArgs): #using command line arguments num_args = int(infile.readline()) #the first line contains the number of command line arguments for i in range(num_args): #read the command arguments in additionalArgs.append(infile.readline().strip()) #remaining lines in the file are considerd input to be given #via standard input #determine how outputs will be generated outfile = None if(self.outputType == Tester.OUTPUT_STDOUT): #outputting to stdout outfile = open(outFileName,'w') #open a file to hold the results elif(self.outputType == Tester.OUTPUT_FILE): #outputting to a file raise NotImplementedError #nothing we can really do as of now else: raise NotImplementedError #this clears out python's buffer so that the program run through subprocess #actually gets input. Another fix if this stops working is to open the file in unbuffered mode #http://stackoverflow.com/questions/22417010/subprocess-popen-stdin-read-file infile.seek(infile.tell()) studentLogger.info('Preparing to test %s on %s', self.executable, os.path.basename(inFileName)) #start the clocks self.endTime = clock() self.startTime = clock() #run the program with subprocess.Popen([self.executable] + self.cmdArgs + additionalArgs, stdin = infile, stdout = outfile, stderr = subprocess.PIPE, universal_newlines = True) as program: try: program.wait(timeout = self.maxRunTime) #wait for the program to finish self.endTime = clock() #program completed err = '\t'.join(program.stderr.readlines()) #always have to read the pipes if(program.returncode != 0): studentLogger.warning('%s %s crashed for the following reasons:\n\t%s\n', self.executable, ' '.join(self.cmdArgs), err) return Tester._PROGRAM_CRASHED else: return Tester._PROGRAM_COMPLETED except subprocess.TimeoutExpired: studentLogger.warning('%s %s timed out', ' '.join(self.cmdArgs), self.executable) program.kill() return Tester._PROGRAM_TIMED_OUT #end _runOne def testOne(self, inFile, solFile): """ run the executable using inFile as the inputs and checking the output against solFile @inFile: the name of the file containing the inputs @solFile: the name of the file containg the solution @returns: a Result """ progStatus = self._runOne(inFile, self.userOut)#run the program testName = os.path.basename(inFile) #the name of the test if(progStatus == Tester._PROGRAM_CRASHED): return Result(testName, False, 'Crashed') elif(progStatus == Tester._PROGRAM_TIMED_OUT): return Result(testName, False, 'Timed Out') else: #program completed successfully if(self.outputType == Tester.OUTPUT_STDOUT): with open(self.userOut) as answer: (correct, out, sol) = self._checkSolution(answer, solFile) if(correct): studentLogger.info('%s %s passed test %s', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile)) else: first_diff = '' i = 0 for (i,(o,s)) in enumerate(zip(out,sol)): if o != s: first_diff = 'First mismatch at word %d\nout = %s but sol = %s' % (i,o,s) #print(first_diff) break studentLogger.info('%s %s failed test %s. Program output: %s \n Solution: %s \n%s\n\n', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile), out, sol, first_diff) return Result(testName, correct, self.endTime - self.startTime ) else: #haven't done anything where solutions are contained in files raise NotImplementedError #end testOne def generateSolutions(self): """generates all the solutions""" for test in self.testFiles: outfileName = test.replace('-test', '-sol') outfileName = self.solDir + os.sep + os.path.basename(outfileName) self._runOne(test,outfileName) #end generateSolutions def testAll(self): """ Test all the tests @returns: a list of triples of the form (testName, correct, time taken) correct is True if the answer is correct and False if it is wrong time taken is expressed in seconds. See Result """ self.results = [] #clear old results if any exist for test in self.testFiles: #get the name of the file containing the solution to this test sol = test.replace('-test', '-sol') #replace test with sol sol = self.solDir + os.sep + os.path.basename(sol) #prepend solution directory name and remove test directory path self.results.append(self.testOne(test, sol)) try: os.remove(self.userOut) except FileNotFoundError: pass #end testAll def getResults(self): """get the results of the testing""" return self.results.copy() #end getResults def getNumTests(self): """get the number of tests that are to be preformed""" return len(self.testFiles) #end getNumTests def getNumCorrect(self): """ get the number of answers that were correct should only be called after testAll is run @returns: the number of tests that were correct """ numCorrect = 0 for res in self.results: if(res.correct == True): numCorrect += 1 return numCorrect #end getNumCorrect def getPercentCorrect(self): """get the precentage of right answers should only be called after testAll is run @returns: the percentage of tests that were correct """ numCorrect = self.getNumCorrect() numTests = float(self.getNumTests()) return numCorrect / numTests #end getPercentCorrect def getMissedTests(self): """ get a list of the test names that were missed should only be called after testAll is run @returns: a list of the test names that were missed """ return [res.testName for res in self.results if not res.correct] #end getMissedTests def getPassedTests(self): """ get a list of the test names that were passed correctly should only be called after testAll is run @returns: a list of the test names that were passed correctly """ return [res.testName for res in self.results if res.correct] #getPassedTests def getTestNames(self): """ get the names of the tests to be run can be called before testAll is run @returns: a list containg the test names """ return [test.rsplit(os.sep, 1)[-1] for test in self.testFiles] def _checkSolution(self, progOut, solutionFileName): """ checkSolution @progOut: the opened file containing the student's answer @solutionFileName: the name of the file containg the solution @returns a tuple containing (correct, program out, solution) """ progOut.flush() #make sure the file is up to date progOut.seek(0) #go back to the begining of the file try: sol = [] with open(solutionFileName, 'r') as solFil: #open the solution file for (_1,_2,_3) in zip(range(self.lines2skip), progOut, solFil): #somehow placin zip as the first argument fixes a bug pass #skip the leading lines of input sol = [] #the solution for line in solFil: #make it so that white space does not matter sol += line.strip().split() out = [] # the programs output for line in progOut: #make it so that white space will not be an issue out += line.strip().split() if(out != sol):#output does not match solution return (False, out, sol) return (True, out, sol) #if everything is correct and all lines in the solution file are used the student got it right except UnicodeDecodeError: return (False, 'NonUnicode Character. This means your print statement is printing something crazy.', sol) # end _checkSolution #end class Tester if __name__ =='__main__': python = sys.executable t = Tester('./div.out', True, False, Tester.OUTPUT_STDOUT, 'Tests', 'Solutions', '.') t.testAll() for res in t.getResults(): print(res)
Homework2/div/Tests/0-test.txt
2 0 172561
Homework2/div/Tests/1-test.txt
2 64 4
Homework2/div/Tests/2-test.txt
2 27 1
Homework2/div/Tests/3-test.txt
2 100 17
Homework2/div/Tests/4-test.txt
2 7 3
Homework2/div/Tests/5-test.txt
2 4294967295 113
Homework2/div/Tests/6-test.txt
2 50 125
Homework2/div/Tests/7-test.txt
2 9 9
Homework2/div/Tests/8-test.txt
2 74088 42
Homework2/div/Tests/9-test.txt
2 3 7
Homework2/divAssembly/divAssembly.s
Homework2/divAssembly/Makefile
sfile = divAssembly.s exe = divAssembly.out divAssembly.out: divAssembly.o ld -melf_i386 -o $(exe) divAssembly.o divAssembly.o: $(sfile) as --32 --gstabs -o divAssembly.o $(sfile) clean: rm -fr $(exe) divAssembly.o
Homework2/divAssembly/result.py
class Result(object): """ a wrapper to contain the results of a test @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ def __init__(self, testName, correct, timeTaken): """ @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ self.testName = testName self.correct = correct self.timeTaken = timeTaken #end init def __repr__(self): if type(self.timeTaken) == str: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {!s}' else: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {:.3f}' s = format_str.format(self.testName, self.correct, self.timeTaken) return s def __str__(self): return self.__repr__()
Homework2/divAssembly/Solutions/0-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 0 (gdb) $2 = 0 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/1-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 16 (gdb) $2 = 0 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/2-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 27 (gdb) $2 = 0 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/3-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 5 (gdb) $2 = 15 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/4-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 2 (gdb) $2 = 1 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/5-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 38008560 (gdb) $2 = 15 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/6-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 0 (gdb) $2 = 50 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/7-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 1 (gdb) $2 = 0 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/8-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 1121 (gdb) $2 = 6 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/Solutions/9-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out...done. (gdb) Breakpoint 1 at 0x80480ff: file divAssembly.s, line 199. (gdb) Breakpoint 2 at 0x8048128: file divAssembly.s, line 214. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/divAssembly/divAssembly.out Breakpoint 1, _start () at divAssembly.s:199 199 push $remainder (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at divAssembly.s:214 214 movl %eax, %eax (gdb) $1 = 0 (gdb) $2 = 3 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/divAssembly/tester.py
#this is the base class for tester objects import sys import subprocess import logging import os from time import clock from result import Result studentLogger = logging.getLogger('errorLogger.progressLogger.studentLogger') studentLogger.setLevel(logging.INFO) h = logging.StreamHandler() h.setLevel(logging.INFO) studentLogger.addHandler(h) class Tester(object): """ Tester abstract class representing a testing interface """ __name__ = 'Tester' #the name of this class INPUT_STDIN = 1 #input is expected to come via standard input INPUT_CMDLINE = 2 #input is expected to comve via the command line OUTPUT_STDOUT = 3 #output of executable will be to the standard output OUTPUT_FILE = 4 #exectuables output will be a file _PROGRAM_COMPLETED = 5 #the program completed the test _PROGRAM_CRASHED = 6 #the program crashed during a test _PROGRAM_TIMED_OUT = 7 #the program timed out during a test def str2InputType(typename): """converts the string name of the input type to the internal type @typename: the name of the type. either stdin cmdline """ if(typename.lower() == 'stdin'): return Tester.INPUT_STDIN elif(typename.lower() == 'cmdline'): return Tester.INPUT_CMDLINE else: raise ValueError('Unknown input type ' + typename) def str2OutputType(typename): """converts the string name of the output type to the internal type @typename: the name of the type. either stdout file """ if(typename.lower() == 'stdout'): return Tester.OUTPUT_STDOUT elif(typename.lower() == 'file'): return Tester.OUTPUT_FILE else: raise ValueError('Unknown input type ' + typename) def __init__(self, executable, usingCmdArgs, usingStdin, outputType, inDir, solDir, scratchDir, maxRunTime = 5, cmdArgs = None, lines2skip = 0): """ @executable: the name of the exectuable to be run @usingCmdArgs: Are command line arguments being used? @usingStdin: Will there be input from the standard input? @outputType: how are outputs generated: Either OUTPUT_STDOUT: for when the solution is sent to standard out or OUTPUT_FILE: for when the solution is sent to a file @inDir: the name of the directory containing the inputs to be used for testing the naming convention for the tests contained within is testname-test.filetype @solDir: the name of the directory containing the solutions the naming convention for the solutions contained within is testname-sol.filetype @scratchDir: directory to write scratch files in @maxRunTime: the maximum number of seconds to run the program or None to allow the program to run until completion (if it does not terminate the program will hang) @cmdArgs: a list of additional command line arguments to the executable @lines2skip: number of lines of output program and solution file to skip """ self.executable = executable self.usingCmdArgs = usingCmdArgs self.usingStdin = usingStdin self.outputType = outputType self.inDir = inDir self.solDir = solDir self.scratchDir = scratchDir self.maxRunTime = maxRunTime self.lines2skip = lines2skip if cmdArgs == None: self.cmdArgs = [] else: self.cmdArgs = cmdArgs.copy() self.testFiles = [self.inDir + os.sep + test for test in os.listdir(inDir) if not test.startswith('.')] #get the tests in the test directory self.testFiles.sort() #make the tests sorted if(scratchDir == None): self.userOut = None else: self.userOut = scratchDir + os.sep + 'userOut.txt' #file to temporarily store the use's output self.startTime = 0 #when did the test begin running self.endTime = 0 #when did the test end running self.results = [] #the results of the testing def _runOne(self, inFileName, outFileName = None): """run self.executable using the inputs contained in inFileName @inFileName: the name of the file containing the inputs @outFileName: the name of the file to write the program's stdout to if the solution is contained in the stdout @returns: the success status of running the program """ #determine how to pass input file infile = None #the input file to be used additionalArgs = [] with open(inFileName) as infile: if(self.usingCmdArgs): #using command line arguments num_args = int(infile.readline()) #the first line contains the number of command line arguments for i in range(num_args): #read the command arguments in additionalArgs.append(infile.readline().strip()) #remaining lines in the file are considerd input to be given #via standard input #determine how outputs will be generated outfile = None if(self.outputType == Tester.OUTPUT_STDOUT): #outputting to stdout outfile = open(outFileName,'w') #open a file to hold the results elif(self.outputType == Tester.OUTPUT_FILE): #outputting to a file raise NotImplementedError #nothing we can really do as of now else: raise NotImplementedError #this clears out python's buffer so that the program run through subprocess #actually gets input. Another fix if this stops working is to open the file in unbuffered mode #http://stackoverflow.com/questions/22417010/subprocess-popen-stdin-read-file infile.seek(infile.tell()) studentLogger.info('Preparing to test %s on %s', self.executable, os.path.basename(inFileName)) #start the clocks self.endTime = clock() self.startTime = clock() #run the program with subprocess.Popen([self.executable] + self.cmdArgs + additionalArgs, stdin = infile, stdout = outfile, stderr = subprocess.PIPE, universal_newlines = True) as program: try: program.wait(timeout = self.maxRunTime) #wait for the program to finish self.endTime = clock() #program completed err = '\t'.join(program.stderr.readlines()) #always have to read the pipes if(program.returncode != 0): studentLogger.warning('%s %s crashed for the following reasons:\n\t%s\n', self.executable, ' '.join(self.cmdArgs), err) return Tester._PROGRAM_CRASHED else: return Tester._PROGRAM_COMPLETED except subprocess.TimeoutExpired: studentLogger.warning('%s %s timed out', ' '.join(self.cmdArgs), self.executable) program.kill() return Tester._PROGRAM_TIMED_OUT #end _runOne def testOne(self, inFile, solFile): """ run the executable using inFile as the inputs and checking the output against solFile @inFile: the name of the file containing the inputs @solFile: the name of the file containg the solution @returns: a Result """ progStatus = self._runOne(inFile, self.userOut)#run the program testName = os.path.basename(inFile) #the name of the test if(progStatus == Tester._PROGRAM_CRASHED): return Result(testName, False, 'Crashed') elif(progStatus == Tester._PROGRAM_TIMED_OUT): return Result(testName, False, 'Timed Out') else: #program completed successfully if(self.outputType == Tester.OUTPUT_STDOUT): with open(self.userOut) as answer: (correct, out, sol) = self._checkSolution(answer, solFile) if(correct): studentLogger.info('%s %s passed test %s', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile)) else: first_diff = '' i = 0 for (i,(o,s)) in enumerate(zip(out,sol)): if o != s: first_diff = 'First mismatch at word %d\nout = %s but sol = %s' % (i,o,s) #print(first_diff) break studentLogger.info('%s %s failed test %s. Program output: %s \n Solution: %s \n%s\n\n', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile), out, sol, first_diff) return Result(testName, correct, self.endTime - self.startTime ) else: #haven't done anything where solutions are contained in files raise NotImplementedError #end testOne def generateSolutions(self): """generates all the solutions""" for test in self.testFiles: outfileName = test.replace('-test', '-sol') outfileName = self.solDir + os.sep + os.path.basename(outfileName) self._runOne(test,outfileName) #end generateSolutions def testAll(self): """ Test all the tests @returns: a list of triples of the form (testName, correct, time taken) correct is True if the answer is correct and False if it is wrong time taken is expressed in seconds. See Result """ self.results = [] #clear old results if any exist for test in self.testFiles: #get the name of the file containing the solution to this test sol = test.replace('-test', '-sol') #replace test with sol sol = self.solDir + os.sep + os.path.basename(sol) #prepend solution directory name and remove test directory path self.results.append(self.testOne(test, sol)) try: os.remove(self.userOut) except FileNotFoundError: pass #end testAll def getResults(self): """get the results of the testing""" return self.results.copy() #end getResults def getNumTests(self): """get the number of tests that are to be preformed""" return len(self.testFiles) #end getNumTests def getNumCorrect(self): """ get the number of answers that were correct should only be called after testAll is run @returns: the number of tests that were correct """ numCorrect = 0 for res in self.results: if(res.correct == True): numCorrect += 1 return numCorrect #end getNumCorrect def getPercentCorrect(self): """get the precentage of right answers should only be called after testAll is run @returns: the percentage of tests that were correct """ numCorrect = self.getNumCorrect() numTests = float(self.getNumTests()) return numCorrect / numTests #end getPercentCorrect def getMissedTests(self): """ get a list of the test names that were missed should only be called after testAll is run @returns: a list of the test names that were missed """ return [res.testName for res in self.results if not res.correct] #end getMissedTests def getPassedTests(self): """ get a list of the test names that were passed correctly should only be called after testAll is run @returns: a list of the test names that were passed correctly """ return [res.testName for res in self.results if res.correct] #getPassedTests def getTestNames(self): """ get the names of the tests to be run can be called before testAll is run @returns: a list containg the test names """ return [test.rsplit(os.sep, 1)[-1] for test in self.testFiles] def _checkSolution(self, progOut, solutionFileName): """ checkSolution @progOut: the opened file containing the student's answer @solutionFileName: the name of the file containg the solution @returns a tuple containing (correct, program out, solution) """ progOut.flush() #make sure the file is up to date progOut.seek(0) #go back to the begining of the file try: sol = [] with open(solutionFileName, 'r') as solFil: #open the solution file for (_1,_2,_3) in zip(range(self.lines2skip), progOut, solFil): #somehow placin zip as the first argument fixes a bug pass #skip the leading lines of input sol = [] #the solution for line in solFil: #make it so that white space does not matter sol += line.strip().split() out = [] # the programs output for line in progOut: #make it so that white space will not be an issue out += line.strip().split() if(out != sol):#output does not match solution return (False, out, sol) return (True, out, sol) #if everything is correct and all lines in the solution file are used the student got it right except UnicodeDecodeError: return (False, 'NonUnicode Character. This means your print statement is printing something crazy.', sol) # end _checkSolution #end class Tester if __name__ =='__main__': python = sys.executable t = Tester('gdb', False, True, Tester.OUTPUT_STDOUT, 'Tests', 'Solutions', '.', cmdArgs = ['-q', 'divAssembly.out'], lines2skip = 11) t.testAll() for res in t.getResults(): print(res)
Homework2/divAssembly/Tests/0-test.txt
break _start break done run set dividend = 0 set divisor = 172561 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/1-test.txt
break _start break done run set dividend = 64 set divisor = 4 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/2-test.txt
break _start break done run set dividend = 27 set divisor = 1 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/3-test.txt
break _start break done run set dividend = 100 set divisor = 17 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/4-test.txt
break _start break done run set dividend = 7 set divisor = 3 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/5-test.txt
break _start break done run set dividend = 4294967295 set divisor = 113 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/6-test.txt
break _start break done run set dividend = 50 set divisor = 125 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/7-test.txt
break _start break done run set dividend = 9 set divisor = 9 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/8-test.txt
break _start break done run set dividend = 47088 set divisor = 42 continue print $eax print $edx kill quit y
Homework2/divAssembly/Tests/9-test.txt
break _start break done run set dividend = 3 set divisor = 7 continue print $eax print $edx kill quit y
Homework2/editDist/editDist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> int editDist(char* word1, char* word2); int min(int a, int b); void swap(int** a, int** b); int min(int a, int b){ return a < b ? a:b; } void swap(int** a, int** b){ int* temp = *a; *a = *b; *b = temp; } int editDist(char* word1, char* word2){ int word1_len = strlen(word1); int word2_len = strlen(word2); int* oldDist = (int*)malloc((word2_len + 1) * sizeof(int)); int* curDist = (int*)malloc((word2_len + 1) * sizeof(int)); int i,j,dist; //intialize distances to length of the substrings for(i = 0; i < word2_len + 1; i++){ oldDist[i] = i; curDist[i] = i; } for(i = 1; i < word1_len + 1; i++){ curDist[0] = i; for(j = 1; j < word2_len + 1; j++){ if(word1[i-1] == word2[j-1]){ curDist[j] = oldDist[j - 1]; }//the characters in the words are the same else{ curDist[j] = min(min(oldDist[j], //deletion curDist[j-1]), //insertion oldDist[j-1]) + 1; //subtitution } }//for each character in the second word swap(&oldDist, &curDist); }//for each character in the first word dist = oldDist[word2_len];//using oldDist instead of curDist because of the last swap free(oldDist); free(curDist); return dist; } int main(int argc, char** argv){ if(argc < 3){ printf("Usage: %s word1 word 2\n", argv[0]); exit(1); } printf("The distance between %s and %s is %d.\n", argv[1], argv[2], editDist(argv[1], argv[2])); return 0; }
Homework2/editDist/editDist.s
Homework2/editDist/Makefile
sfile = editDist.s exe = editDist.out editDist.out: editDist.o ld -melf_i386 -o $(exe) editDist.o editDist.o: $(sfile) as --32 --gstabs -o editDist.o $(sfile) clean: rm -fr $(exe) editDist.o
Homework2/editDist/result.py
class Result(object): """ a wrapper to contain the results of a test @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ def __init__(self, testName, correct, timeTaken): """ @testName: the name of the test run @correct: True if the output of matched the solution; False otherwise @timeTaken is either the number of seconds it took the program to run 'Timed Out' if the program took too long to complete 'Crashed' if the program encountered some fatal error """ self.testName = testName self.correct = correct self.timeTaken = timeTaken #end init def __repr__(self): if type(self.timeTaken) == str: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {!s}' else: format_str = 'Test: {!s} | Correct: {!s} | Time Taken: {:.3f}' s = format_str.format(self.testName, self.correct, self.timeTaken) return s def __str__(self): return self.__repr__()
Homework2/editDist/Solutions/0-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 3 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/1-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 1 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/2-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 13 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/3-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 4 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/4-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 0 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/5-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 8 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/6-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 11 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/7-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 17 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/8-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 12 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/Solutions/9-sol.txt
Reading symbols from /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out...done. (gdb) Breakpoint 1 at 0x80480b8: file editDist.s, line 82. (gdb) Breakpoint 2 at 0x8048130: file editDist.s, line 121. (gdb) Starting program: /home/matthew/Dropbox/ECS/50/Homework/Homework2/editDist/editDist.out Breakpoint 1, _start () at editDist.s:82 82 call init_oldDist #initialize oldDist (gdb) (gdb) (gdb) Continuing. Breakpoint 2, done () at editDist.s:121 121 done: movl %eax, %eax #this line doesn't do anything (gdb) $1 = 20 (gdb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] (gdb)
Homework2/editDist/tester.py
#this is the base class for tester objects import sys import subprocess import logging import os from time import clock from result import Result studentLogger = logging.getLogger('errorLogger.progressLogger.studentLogger') studentLogger.setLevel(logging.INFO) h = logging.StreamHandler() h.setLevel(logging.INFO) studentLogger.addHandler(h) class Tester(object): """ Tester abstract class representing a testing interface """ __name__ = 'Tester' #the name of this class INPUT_STDIN = 1 #input is expected to come via standard input INPUT_CMDLINE = 2 #input is expected to comve via the command line OUTPUT_STDOUT = 3 #output of executable will be to the standard output OUTPUT_FILE = 4 #exectuables output will be a file _PROGRAM_COMPLETED = 5 #the program completed the test _PROGRAM_CRASHED = 6 #the program crashed during a test _PROGRAM_TIMED_OUT = 7 #the program timed out during a test def str2InputType(typename): """converts the string name of the input type to the internal type @typename: the name of the type. either stdin cmdline """ if(typename.lower() == 'stdin'): return Tester.INPUT_STDIN elif(typename.lower() == 'cmdline'): return Tester.INPUT_CMDLINE else: raise ValueError('Unknown input type ' + typename) def str2OutputType(typename): """converts the string name of the output type to the internal type @typename: the name of the type. either stdout file """ if(typename.lower() == 'stdout'): return Tester.OUTPUT_STDOUT elif(typename.lower() == 'file'): return Tester.OUTPUT_FILE else: raise ValueError('Unknown input type ' + typename) def __init__(self, executable, usingCmdArgs, usingStdin, outputType, inDir, solDir, scratchDir, maxRunTime = 5, cmdArgs = None, lines2skip = 0): """ @executable: the name of the exectuable to be run @usingCmdArgs: Are command line arguments being used? @usingStdin: Will there be input from the standard input? @outputType: how are outputs generated: Either OUTPUT_STDOUT: for when the solution is sent to standard out or OUTPUT_FILE: for when the solution is sent to a file @inDir: the name of the directory containing the inputs to be used for testing the naming convention for the tests contained within is testname-test.filetype @solDir: the name of the directory containing the solutions the naming convention for the solutions contained within is testname-sol.filetype @scratchDir: directory to write scratch files in @maxRunTime: the maximum number of seconds to run the program or None to allow the program to run until completion (if it does not terminate the program will hang) @cmdArgs: a list of additional command line arguments to the executable @lines2skip: number of lines of output program and solution file to skip """ self.executable = executable self.usingCmdArgs = usingCmdArgs self.usingStdin = usingStdin self.outputType = outputType self.inDir = inDir self.solDir = solDir self.scratchDir = scratchDir self.maxRunTime = maxRunTime self.lines2skip = lines2skip if cmdArgs == None: self.cmdArgs = [] else: self.cmdArgs = cmdArgs.copy() self.testFiles = [self.inDir + os.sep + test for test in os.listdir(inDir) if not test.startswith('.')] #get the tests in the test directory self.testFiles.sort() #make the tests sorted if(scratchDir == None): self.userOut = None else: self.userOut = scratchDir + os.sep + 'userOut.txt' #file to temporarily store the use's output self.startTime = 0 #when did the test begin running self.endTime = 0 #when did the test end running self.results = [] #the results of the testing def _runOne(self, inFileName, outFileName = None): """run self.executable using the inputs contained in inFileName @inFileName: the name of the file containing the inputs @outFileName: the name of the file to write the program's stdout to if the solution is contained in the stdout @returns: the success status of running the program """ #determine how to pass input file infile = None #the input file to be used additionalArgs = [] with open(inFileName) as infile: if(self.usingCmdArgs): #using command line arguments num_args = int(infile.readline()) #the first line contains the number of command line arguments for i in range(num_args): #read the command arguments in additionalArgs.append(infile.readline().strip()) #remaining lines in the file are considerd input to be given #via standard input #determine how outputs will be generated outfile = None if(self.outputType == Tester.OUTPUT_STDOUT): #outputting to stdout outfile = open(outFileName,'w') #open a file to hold the results elif(self.outputType == Tester.OUTPUT_FILE): #outputting to a file raise NotImplementedError #nothing we can really do as of now else: raise NotImplementedError #this clears out python's buffer so that the program run through subprocess #actually gets input. Another fix if this stops working is to open the file in unbuffered mode #http://stackoverflow.com/questions/22417010/subprocess-popen-stdin-read-file infile.seek(infile.tell()) studentLogger.info('Preparing to test %s on %s', self.executable, os.path.basename(inFileName)) #start the clocks self.endTime = clock() self.startTime = clock() #run the program with subprocess.Popen([self.executable] + self.cmdArgs + additionalArgs, stdin = infile, stdout = outfile, stderr = subprocess.PIPE, universal_newlines = True) as program: try: program.wait(timeout = self.maxRunTime) #wait for the program to finish self.endTime = clock() #program completed err = '\t'.join(program.stderr.readlines()) #always have to read the pipes if(program.returncode != 0): studentLogger.warning('%s %s crashed for the following reasons:\n\t%s\n', self.executable, ' '.join(self.cmdArgs), err) return Tester._PROGRAM_CRASHED else: return Tester._PROGRAM_COMPLETED except subprocess.TimeoutExpired: studentLogger.warning('%s %s timed out', ' '.join(self.cmdArgs), self.executable) program.kill() return Tester._PROGRAM_TIMED_OUT #end _runOne def testOne(self, inFile, solFile): """ run the executable using inFile as the inputs and checking the output against solFile @inFile: the name of the file containing the inputs @solFile: the name of the file containg the solution @returns: a Result """ progStatus = self._runOne(inFile, self.userOut)#run the program testName = os.path.basename(inFile) #the name of the test if(progStatus == Tester._PROGRAM_CRASHED): return Result(testName, False, 'Crashed') elif(progStatus == Tester._PROGRAM_TIMED_OUT): return Result(testName, False, 'Timed Out') else: #program completed successfully if(self.outputType == Tester.OUTPUT_STDOUT): with open(self.userOut) as answer: (correct, out, sol) = self._checkSolution(answer, solFile) if(correct): studentLogger.info('%s %s passed test %s', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile)) else: first_diff = '' i = 0 for (i,(o,s)) in enumerate(zip(out,sol)): if o != s: first_diff = 'First mismatch at word %d\nout = %s but sol = %s' % (i,o,s) #print(first_diff) break studentLogger.info('%s %s failed test %s. Program output: %s \n Solution: %s \n%s\n\n', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile), out, sol, first_diff) return Result(testName, correct, self.endTime - self.startTime ) else: #haven't done anything where solutions are contained in files raise NotImplementedError #end testOne def generateSolutions(self): """generates all the solutions""" for test in self.testFiles: outfileName = test.replace('-test', '-sol') outfileName = self.solDir + os.sep + os.path.basename(outfileName) self._runOne(test,outfileName) #end generateSolutions def testAll(self): """ Test all the tests @returns: a list of triples of the form (testName, correct, time taken) correct is True if the answer is correct and False if it is wrong time taken is expressed in seconds. See Result """ self.results = [] #clear old results if any exist for test in self.testFiles: #get the name of the file containing the solution to this test sol = test.replace('-test', '-sol') #replace test with sol sol = self.solDir + os.sep + os.path.basename(sol) #prepend solution directory name and remove test directory path self.results.append(self.testOne(test, sol)) try: os.remove(self.userOut) except FileNotFoundError: pass #end testAll def getResults(self): """get the results of the testing""" return self.results.copy() #end getResults def getNumTests(self): """get the number of tests that are to be preformed""" return len(self.testFiles) #end getNumTests def getNumCorrect(self): """ get the number of answers that were correct should only be called after testAll is run @returns: the number of tests that were correct """ numCorrect = 0 for res in self.results: if(res.correct == True): numCorrect += 1 return numCorrect #end getNumCorrect def getPercentCorrect(self): """get the precentage of right answers should only be called after testAll is run @returns: the percentage of tests that were correct """ numCorrect = self.getNumCorrect() numTests = float(self.getNumTests()) return numCorrect / numTests #end getPercentCorrect def getMissedTests(self): """ get a list of the test names that were missed should only be called after testAll is run @returns: a list of the test names that were missed """ return [res.testName for res in self.results if not res.correct] #end getMissedTests def getPassedTests(self): """ get a list of the test names that were passed correctly should only be called after testAll is run @returns: a list of the test names that were passed correctly """ return [res.testName for res in self.results if res.correct] #getPassedTests def getTestNames(self): """ get the names of the tests to be run can be called before testAll is run @returns: a list containg the test names """ return [test.rsplit(os.sep, 1)[-1] for test in self.testFiles] def _checkSolution(self, progOut, solutionFileName): """ checkSolution @progOut: the opened file containing the student's answer @solutionFileName: the name of the file containg the solution @returns a tuple containing (correct, program out, solution) """ progOut.flush() #make sure the file is up to date progOut.seek(0) #go back to the begining of the file try: sol = [] with open(solutionFileName, 'r') as solFil: #open the solution file for (_1,_2,_3) in zip(range(self.lines2skip), progOut, solFil): #somehow placin zip as the first argument fixes a bug pass #skip the leading lines of input sol = [] #the solution for line in solFil: #make it so that white space does not matter sol += line.strip().split() out = [] # the programs output for line in progOut: #make it so that white space will not be an issue out += line.strip().split() if(out != sol):#output does not match solution return (False, out, sol) return (True, out, sol) #if everything is correct and all lines in the solution file are used the student got it right except UnicodeDecodeError: return (False, 'NonUnicode Character. This means your print statement is printing something crazy.', sol) # end _checkSolution #end class Tester if __name__ =='__main__': python = sys.executable t = Tester('gdb', False, True, Tester.OUTPUT_STDOUT, 'Tests', 'Solutions', '.', cmdArgs = ['-q', 'editDist.out'], lines2skip = 11) t.testAll() for res in t.getResults(): print(res)
Homework2/editDist/tester.py~
#this is the base class for tester objects import sys import subprocess import logging import os from time import clock from result import Result studentLogger = logging.getLogger('errorLogger.progressLogger.studentLogger') studentLogger.setLevel(logging.INFO) h = logging.StreamHandler() h.setLevel(logging.INFO) studentLogger.addHandler(h) class Tester(object): """ Tester abstract class representing a testing interface """ __name__ = 'Tester' #the name of this class INPUT_STDIN = 1 #input is expected to come via standard input INPUT_CMDLINE = 2 #input is expected to comve via the command line OUTPUT_STDOUT = 3 #output of executable will be to the standard output OUTPUT_FILE = 4 #exectuables output will be a file _PROGRAM_COMPLETED = 5 #the program completed the test _PROGRAM_CRASHED = 6 #the program crashed during a test _PROGRAM_TIMED_OUT = 7 #the program timed out during a test def str2InputType(typename): """converts the string name of the input type to the internal type @typename: the name of the type. either stdin cmdline """ if(typename.lower() == 'stdin'): return Tester.INPUT_STDIN elif(typename.lower() == 'cmdline'): return Tester.INPUT_CMDLINE else: raise ValueError('Unknown input type ' + typename) def str2OutputType(typename): """converts the string name of the output type to the internal type @typename: the name of the type. either stdout file """ if(typename.lower() == 'stdout'): return Tester.OUTPUT_STDOUT elif(typename.lower() == 'file'): return Tester.OUTPUT_FILE else: raise ValueError('Unknown input type ' + typename) def __init__(self, executable, usingCmdArgs, usingStdin, outputType, inDir, solDir, scratchDir, maxRunTime = 5, cmdArgs = None, lines2skip = 0): """ @executable: the name of the exectuable to be run @usingCmdArgs: Are command line arguments being used? @usingStdin: Will there be input from the standard input? @outputType: how are outputs generated: Either OUTPUT_STDOUT: for when the solution is sent to standard out or OUTPUT_FILE: for when the solution is sent to a file @inDir: the name of the directory containing the inputs to be used for testing the naming convention for the tests contained within is testname-test.filetype @solDir: the name of the directory containing the solutions the naming convention for the solutions contained within is testname-sol.filetype @scratchDir: directory to write scratch files in @maxRunTime: the maximum number of seconds to run the program or None to allow the program to run until completion (if it does not terminate the program will hang) @cmdArgs: a list of additional command line arguments to the executable @lines2skip: number of lines of output program and solution file to skip """ self.executable = executable self.usingCmdArgs = usingCmdArgs self.usingStdin = usingStdin self.outputType = outputType self.inDir = inDir self.solDir = solDir self.scratchDir = scratchDir self.maxRunTime = maxRunTime self.lines2skip = lines2skip if cmdArgs == None: self.cmdArgs = [] else: self.cmdArgs = cmdArgs.copy() self.testFiles = [self.inDir + os.sep + test for test in os.listdir(inDir) if not test.startswith('.')] #get the tests in the test directory self.testFiles.sort() #make the tests sorted if(scratchDir == None): self.userOut = None else: self.userOut = scratchDir + os.sep + 'userOut.txt' #file to temporarily store the use's output self.startTime = 0 #when did the test begin running self.endTime = 0 #when did the test end running self.results = [] #the results of the testing def _runOne(self, inFileName, outFileName = None): """run self.executable using the inputs contained in inFileName @inFileName: the name of the file containing the inputs @outFileName: the name of the file to write the program's stdout to if the solution is contained in the stdout @returns: the success status of running the program """ #determine how to pass input file infile = None #the input file to be used additionalArgs = [] with open(inFileName) as infile: if(self.usingCmdArgs): #using command line arguments num_args = int(infile.readline()) #the first line contains the number of command line arguments for i in range(num_args): #read the command arguments in additionalArgs.append(infile.readline().strip()) #remaining lines in the file are considerd input to be given #via standard input #determine how outputs will be generated outfile = None if(self.outputType == Tester.OUTPUT_STDOUT): #outputting to stdout outfile = open(outFileName,'w') #open a file to hold the results elif(self.outputType == Tester.OUTPUT_FILE): #outputting to a file raise NotImplementedError #nothing we can really do as of now else: raise NotImplementedError #this clears out python's buffer so that the program run through subprocess #actually gets input. Another fix if this stops working is to open the file in unbuffered mode #http://stackoverflow.com/questions/22417010/subprocess-popen-stdin-read-file infile.seek(infile.tell()) studentLogger.info('Preparing to test %s on %s', self.executable, os.path.basename(inFileName)) #start the clocks self.endTime = clock() self.startTime = clock() #run the program with subprocess.Popen([self.executable] + self.cmdArgs + additionalArgs, stdin = infile, stdout = outfile, stderr = subprocess.PIPE, universal_newlines = True) as program: try: program.wait(timeout = self.maxRunTime) #wait for the program to finish self.endTime = clock() #program completed err = '\t'.join(program.stderr.readlines()) #always have to read the pipes if(program.returncode != 0): studentLogger.warning('%s %s crashed for the following reasons:\n\t%s\n', self.executable, ' '.join(self.cmdArgs), err) return Tester._PROGRAM_CRASHED else: return Tester._PROGRAM_COMPLETED except subprocess.TimeoutExpired: studentLogger.warning('%s %s timed out', ' '.join(self.cmdArgs), self.executable) program.kill() return Tester._PROGRAM_TIMED_OUT #end _runOne def testOne(self, inFile, solFile): """ run the executable using inFile as the inputs and checking the output against solFile @inFile: the name of the file containing the inputs @solFile: the name of the file containg the solution @returns: a Result """ progStatus = self._runOne(inFile, self.userOut)#run the program testName = os.path.basename(inFile) #the name of the test if(progStatus == Tester._PROGRAM_CRASHED): return Result(testName, False, 'Crashed') elif(progStatus == Tester._PROGRAM_TIMED_OUT): return Result(testName, False, 'Timed Out') else: #program completed successfully if(self.outputType == Tester.OUTPUT_STDOUT): with open(self.userOut) as answer: (correct, out, sol) = self._checkSolution(answer, solFile) if(correct): studentLogger.info('%s %s passed test %s', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile)) else: first_diff = '' i = 0 for (i,(o,s)) in enumerate(zip(out,sol)): if o != s: first_diff = 'First mismatch at word %d\nout = %s but sol = %s' % (i,o,s) #print(first_diff) break studentLogger.info('%s %s failed test %s. Program output: %s \n Solution: %s \n%s\n\n', self.executable, ' '.join(self.cmdArgs), os.path.basename(inFile), out, sol, first_diff) return Result(testName, correct, self.endTime - self.startTime ) else: #haven't done anything where solutions are contained in files raise NotImplementedError #end testOne def generateSolutions(self): """generates all the solutions""" for test in self.testFiles: outfileName = test.replace('-test', '-sol') outfileName = self.solDir + os.sep + os.path.basename(outfileName) self._runOne(test,outfileName) #end generateSolutions def testAll(self): """ Test all the tests @returns: a list of triples of the form (testName, correct, time taken) correct is True if the answer is correct and False if it is wrong time taken is expressed in seconds. See Result """ self.results = [] #clear old results if any exist for test in self.testFiles: #get the name of the file containing the solution to this test sol = test.replace('-test', '-sol') #replace test with sol sol = self.solDir + os.sep + os.path.basename(sol) #prepend solution directory name and remove test directory path self.results.append(self.testOne(test, sol)) try: os.remove(self.userOut) except FileNotFoundError: pass #end testAll def getResults(self): """get the results of the testing""" return self.results.copy() #end getResults def getNumTests(self): """get the number of tests that are to be preformed""" return len(self.testFiles) #end getNumTests def getNumCorrect(self): """ get the number of answers that were correct should only be called after testAll is run @returns: the number of tests that were correct """ numCorrect = 0 for res in self.results: if(res.correct == True): numCorrect += 1 return numCorrect #end getNumCorrect def getPercentCorrect(self): """get the precentage of right answers should only be called after testAll is run @returns: the percentage of tests that were correct """ numCorrect = self.getNumCorrect() numTests = float(self.getNumTests()) return numCorrect / numTests #end getPercentCorrect def getMissedTests(self): """ get a list of the test names that were missed should only be called after testAll is run @returns: a list of the test names that were missed """ return [res.testName for res in self.results if not res.correct] #end getMissedTests def getPassedTests(self): """ get a list of the test names that were passed correctly should only be called after testAll is run @returns: a list of the test names that were passed correctly """ return [res.testName for res in self.results if res.correct] #getPassedTests def getTestNames(self): """ get the names of the tests to be run can be called before testAll is run @returns: a list containg the test names """ return [test.rsplit(os.sep, 1)[-1] for test in self.testFiles] def _checkSolution(self, progOut, solutionFileName): """ checkSolution @progOut: the opened file containing the student's answer @solutionFileName: the name of the file containg the solution @returns a tuple containing (correct, program out, solution) """ progOut.flush() #make sure the file is up to date progOut.seek(0) #go back to the begining of the file try: sol = [] with open(solutionFileName, 'r') as solFil: #open the solution file for (_1,_2,_3) in zip(range(self.lines2skip), progOut, solFil): #somehow placin zip as the first argument fixes a bug pass #skip the leading lines of input sol = [] #the solution for line in solFil: #make it so that white space does not matter sol += line.strip().split() out = [] # the programs output for line in progOut: #make it so that white space will not be an issue out += line.strip().split() if(out != sol):#output does not match solution return (False, out, sol) return (True, out, sol) #if everything is correct and all lines in the solution file are used the student got it right except UnicodeDecodeError: return (False, 'NonUnicode Character. This means your print statement is printing something crazy.', sol) # end _checkSolution #end class Tester if __name__ =='__main__': python = sys.executable t = Tester('gdb', False, True, Tester.OUTPUT_STDOUT, 'Tests', 'Solutions', '.', cmdArgs = ['-q', 'editDist.out'], lines2skip = 10) t.testAll() for res in t.getResults(): print(res)
Homework2/editDist/Tests/0-test.txt
break _start break done run set {char[8]}&string1 = "sitting" set {char[7]}&string2 = "kitten" continue print $eax kill quit y
Homework2/editDist/Tests/1-test.txt
break _start break done run set {char[9]}&string1 = "cat" set {char[9]}&string2 = "bat" continue print $eax kill quit y
Homework2/editDist/Tests/2-test.txt
break _start break done run set {char[12]}&string1 = "FUS-ROH-DAH" set {char[15]}&string2 = "BOB'S MY UNCLE" continue print $eax kill quit y
Homework2/editDist/Tests/3-test.txt
break _start break done run set {char[9]}&string1 = "escaltor" set {char[9]}&string2 = "elevator" continue print $eax kill quit y
Homework2/editDist/Tests/4-test.txt
break _start break done run set {char[1]}&string1 = "" set {char[1]}&string2 = "" continue print $eax kill quit y
Homework2/editDist/Tests/5-test.txt
break _start break done run set {char[11]}&string1 = "Dig deeper" set {char[12]}&string2 = "Weep harder" continue print $eax kill quit y
Homework2/editDist/Tests/6-test.txt
break _start break done run set {char[20]}&string1 = "Use your eagle eyes" set {char[18]}&string2 = "I have lazer eyes" continue print $eax kill quit y
Homework2/editDist/Tests/7-test.txt
break _start break done run set {char[22]}&string1 = "Slow Slow Tango Close" set {char[17]}&string2 = "Quick Quick Slow" continue print $eax kill quit y
Homework2/editDist/Tests/8-test.txt
break _start break done run set {char[21]}&string1 = "3 lefts make a right" set {char[28]}&string2 = "2 wrongs don't make a right" continue print $eax kill quit y
Homework2/editDist/Tests/9-test.txt
break _start break done run set {char[23]}&string1 = "You made it to end" set {char[27]}&string2 = "This is only the beginning" continue print $eax kill quit y
Homework2/Homework2.pdf
Due: Smartsite Wed., 4/29, 11:55 p.m. Names of Files to Submit: 64bitAdd.s, editDist.s , div.c, divAssembly.s, ReadMe.txt
• If you are working in a group ALL members must submit the assignment • All programs should compile with no warnings when compiled with the -Wall option • All prompts for input and all output must match my prompts/output. We use a program to grade
your work and tiny differences can cause your work to be marked as a 0. ◦ The best way to avoid being deducted points is to copy the prompt/unchanging portion of
the outputs into your code. Make sure to get the spaces as well. • You must also submit a file called ReadMe.txt. Include the names of all partners and any
trouble you had on the assignment • An example ReadMe.txt has been included with this assignment • The input in the examples has been underlined to help you figure out what is input and what is
output • Submit your work on Smartsite by uploading each file separately. Do not upload any folders or
compressed files such as .rar, .tar, .targz, .zip etc. • If you have any questions please post them to Piazza
1. (Time 15 min)Write an assembly program called 64bitAdd.s that adds two 64 bit numbers together. 1. The first number will be referenced by the label num1 and the second number will be
referenced by the label num2. 2. The upper 32 bits of the sum should be placed in EDX and the lower 32 bits in EAX. 3. AFTER the last line of code that you wish to be executed in your program please place the
label done. 4. I have included a Makefile for you that will compile your program. 5. IT IS OF VITAL IMPORTANCE THAT YOU NAME YOUR LABELS AS
SPECIFIED AND MAKE THE APPROPRIATE AMOUNT OF SPACE FOR EACH VARIABLE! I will be using gdb to test your code and if your labels do not match then the tests will fail. You must also make sure to include the done label AFTER the last line of code you want executed in your program so that I know where to set break points.
6. The following table shows how the numbers will be laid out in memory. num1: Upper 32 bits of num1 Lower 32 bits of num1
num2: Upper 32 bits of num2 Lower 32 bits of num2
2. (Time 2 hours) Write an assembly program called editDist.s that calculates the edit distance between 2 strings. An explanation of what edit distance is can be found here while accompanying pseudo code can be found here. 1. The label for the first string should be string1 and the label for the second string should be
string2. 2. The edit distance between string1 and string2 should be placed in EAX. 3. For each string please allocate space for 100 bytes.
1. While you must allocate space for 100 bytes in your final submission you will likely find it easier to work with the .string directive for testing and debugging.
4. AFTER the last line of code that you wish to be executed in your program please place the label done.
5. I have included a C implementation of the edit distance program. I highly recommend translating this solution into assembly as it will make your life much easier.
6. I have included a Makefile that will compile your program. Your program must be able to be compiled by this Makefile when you submit it
7. IT IS OF VITAL IMPORTANCE THAT YOU NAME YOUR LABELS AS SPECIFIED AND MAKE THE APPROPRIATE AMOUNT OF SPACE FOR EACH VARIABLE! I will be using gdb to test your code and if your labels do not match then the tests will fail. You must also make sure to include the done label AFTER the last line of code you want executed in your program so that I know where to set break points.
3. Write a C program called div.c that implements division on two unsigned integers. 1. Name your executable div.out 2. You cannot use division in your solution 3. Arguments should be accepted from the command line
1. The first argument is the dividend 2. The second argument is divisor
4. Your program should display the quotient and remainder after doing the division 5. Your program must complete in O(1) time
1. This is possible because an integer is 32 bits long and so the loop that does the division should not take longer than 32 iterations.
2. Because of this restriction the following solution is not acceptable as it does not meet the O requirements
void bad_div(unsigned int dividend, unsigned int divisor, unsigned int* quotient, unsigned int *remainder){ *quotient = 0;
while(dividend >= divisor){ (*quotient)++; dividend -= divisor; }
*remainder = dividend;
} 3. In order to meet the O requirements you will have to division in base 2 as you would by
hand. See these 2 articles for some examples: Dr. Math and Exploring Binary 1. Hint: use bitwise operators 2. The one step that they leave out and one that you normally skip when doing division
by hand is checking to see how many times the divisor goes into the dividend for the numbers that contain fewer digits than the divisor. 1. For example: 30 / 15 2. First we should check how many times does 15 go into 3. The answer is 0. 3. Then we check how many times does 15 go into 30, which is 2. 4. So our answer would be 02 R 0
4. Examples: 1. ./div.out 10 5
10 / 5 = 2 R 0 2. ./div.out 100 17
100 / 17 = 5 R 15 3.
4. Translate your C program from problem 3 into an assembly program called divAssembly.s. 1. The label for the dividend is dividend
1. 4 bytes of space should be made for the dividend 2. The label for the divisor is divisor
1. 4 bytes of space should be made for the divisor 3. Place the quotient in EAX 4. Place the remainder in EDX 5. AFTER the last line of code that you wish to be executed in your program please place the
label done. 6. IT IS OF VITAL IMPORTANCE THAT YOU NAME YOUR LABELS AS
SPECIFIED AND MAKE THE APPROPRIATE AMOUNT OF SPACE FOR EACH VARIABLE! I will be using gdb to test your code and if your labels do not match then the tests will fail. You must also make sure to include the done label AFTER the last line of code you want executed in your program so that I know where to set break points.