def testToggleDebugOn(self): "It must be possible to toggle debugging on" c = Calculator() # Double-check it starts out off (don't rely on above test). self.assertFalse(c._debug) c.toggleDebug() self.assertTrue(c._debug)
def testStackLengthOne(self): "Calling on a stack with only one item must result in a StackError" c = Calculator() c.execute('4') error = r"^Cannot run 'cmd' \(stack has only 1 item\)$" self.assertRaisesRegex(StackError, error, c.findStringAndArgs, 'cmd', strToModifiers('r'), None)
def testNoImplicitConversion(self): """An int without suffixes should not be implicitly converted to EngNumber""" c = Calculator() c.execute('2000') (result, ) = c.stack self.assertNotIsInstance(result, EngNumber)
def testInput(self): """A value suffixed by a unit should be recognized as engineering notation.""" c = Calculator() c.execute('2k') (result, ) = c.stack self.assertEqual(EngNumber('2k'), result)
def testBatch(self): "It must be possible to read from a file using the batch method" infp = StringIO('3\n4\n+\np\n') outfp = StringIO() c = Calculator(outfp=outfp) c.batch(infp) self.assertEqual('7\n', outfp.getvalue())
def testAddOneArg(self): "Adding must give an error if there is only one thing on the stack" err = StringIO() c = Calculator(errfp=err) c.execute('3 +') self.assertEqual( 'Not enough args on stack! (+ needs 2 args, stack has 1 item)\n', err.getvalue())
def testStarModifierReversed(self): """ Calling store on a stack with three items and a * modifier and the reverse modifier must result in the variable being set as expected. """ c = Calculator() c.execute('4 5 6 "a" store:r* a') self.assertEqual([[4, 5, 6]], c.stack)
def testStackWithThreeItemsReversed(self): """ Calling store on a stack with three items and a numeric modifier and the reverse modifier must result in the variable being set as expected. """ c = Calculator() c.execute('4 5 "a" store:r2 a') self.assertEqual([[4, 5]], c.stack)
def testStackWithTwoItemsPreservingStack(self): """ Calling store on a stack with two items and asking for the stack to be preserved must work as expected. """ c = Calculator() c.execute('"a" 4 store:=') self.assertEqual(['a', 4], c.stack)
def testCountConflictsWithAllModifier(self): "If :* and a count is given, it's an error if they don't agree" errfp = StringIO() c = Calculator(errfp=errfp) self.assertFalse(c.execute('4 5 6 list:*5')) error = ('* modifier conflicts with explicit count 5 ' '(stack has 3 items)\n') self.assertEqual(error, errfp.getvalue())
def testReverseWithStackTooSmall(self): "It's an error if an attempt is made to reverse too many things" errfp = StringIO() c = Calculator(errfp=errfp) self.assertFalse(c.execute('4 5 6 reverse:10')) error = ("Could not run special command 'reverse': Cannot reverse 10 " "items (stack length is 3)\n") self.assertEqual(error, errfp.getvalue())
def testStackLengthOne(self): "Calling on a stack with only one item must return None, None" errfp = StringIO() c = Calculator(errfp=errfp) c.execute('4') error = r"^Cannot run 'cmd' \(stack has only 1 item\)$" self.assertRaisesRegex(StackError, error, c.findCallableAndArgs, 'cmd', Modifiers(), None)
def testReduceWithCount(self): "Reduce must work correctly when given a count" c = Calculator() c.execute('4') c.execute('5') c.execute('6') c.execute('+ :!') c.execute('reduce :2r') self.assertEqual([4, 11], c.stack)
def testStackWithTwoItems(self): """ Calling store on a stack with two items must result in the variable being set as expected. """ c = Calculator() c.execute('"a" 4 store a') (result, ) = c.stack self.assertEqual(4, result)
def testItemgetter(self): "itemgetter must work correctly" c = Calculator(splitLines=False) c.execute('1') c.execute('itemgetter') c.execute('[[1, 2, 3], [4, 5, 6]]') c.execute('map :i') (result, ) = c.stack self.assertEqual([2, 5], result)
def testApplyVariables(self): "apply must work correctly when Variable instances are on the stack" c = Calculator() c.execute('a=4 b=5') c.execute('+ :!') c.execute('a :!') c.execute('b :!') c.execute('apply') (result, ) = c.stack self.assertEqual(9, result)
def testReduceAl(self): "Reduce must work correctly when told to operate on the whole stack" c = Calculator() c.execute('5') c.execute('6') c.execute('7') c.execute('+ :!') c.execute('reduce :*r') (result, ) = c.stack self.assertEqual(18, result)
def testREPL(self): "It must be possible to read input in REPL form" infp = StringIO('3\n4\n+\np\n') outfp = StringIO() c = Calculator(outfp=outfp) stdin = sys.stdin sys.stdin = infp c.repl('prompt') sys.stdin = stdin self.assertEqual('7\n', outfp.getvalue())
def testAllStack(self): "Calling on all the stack must return correctly" c = Calculator() c.execute('4') c.execute('5') c.execute('6') c.execute("'string'") string, args = c.findStringAndArgs('cmd', strToModifiers('*r'), None) self.assertEqual('string', string) self.assertEqual([4, 5, 6], args)
def testAllStack(self): "Calling on all the stack must return correctly" c = Calculator() c.execute('4') c.execute('5') c.execute('6') c.execute('log10 :!') func, args = c.findCallableAndArgs('cmd', strToModifiers('*r'), None) self.assertIs(math.log10, func) self.assertEqual([4, 5, 6], args)
def testWithCount(self): "map must work as expected when given a count" c = Calculator() c.execute('str :!') c.execute('1 2 3') c.execute('map :3i') self.assertEqual(['1', '2', '3'], c.stack)
def testApplyWithCount(self): "apply must work correctly when given a count" c = Calculator() c.execute('+ :!') c.execute('3 5') c.execute('apply :2') (result, ) = c.stack self.assertEqual(8, result)
def testApplyNoCount(self): "apply must work correctly when not given a count" c = Calculator() c.execute('abs :!') c.execute('-1') c.execute('apply') (result, ) = c.stack self.assertEqual(1, result)
def testDef(self): "Use def to make a new function." c = Calculator(splitLines=False) c.execute('def celcius(f): return (f - 32) / 1.8') c.execute('212') c.execute('celcius') (result, ) = c.stack self.assertEqual(100, result)
def testMap(self): "Call map with args reversed from their normal order" c = Calculator() c.execute('[1,2,3]') c.execute('str :!') c.execute('map :ir') (result, ) = c.stack self.assertEqual(['1', '2', '3'], result)
def testIterateGenerator(self): "The :i (iterate) modifier must work as expected on a map generator" c = Calculator() c.execute('str :!') c.execute('[1,2,3]') c.execute('map :i') (result, ) = c.stack self.assertEqual(['1', '2', '3'], result)
def testEmptyStack(self): "Calling on an empty stack must return None, None" c = Calculator() error = r"^Cannot run 'cmd' \(stack has only 0 items\)$" self.assertRaisesRegex(StackError, error, c.findCallableAndArgs, 'cmd', Modifiers(), None)
def testImplicitConversion(self): """Arithmetic involving an EngNumber and an int should return an EngNumber""" c = Calculator() c.execute('2k') c.execute('2000') c.execute('+') (result, ) = c.stack self.assertEqual(EngNumber('4k'), result)
def testPopWhenAVariableCalledPopExists(self): """pop must put a value on the stack when there is a varible of that name""" c = Calculator() c.execute('pop=4') c.execute('6') c.execute('5') c.execute('pop') self.assertEqual([6, 5, 4], c.stack)
def testReduceWithCount(self): "Reduce must work correctly when given a count" c = Calculator() c.execute('+ :!') c.execute('5') c.execute('6') c.execute('reduce :2') (result, ) = c.stack self.assertEqual(11, result)