#! /usr/bin/env python # $Id: test_statemachine.py 7400 2012-05-01 08:34:41Z grubert $ # Author: David Goodger # Copyright: This module has been placed in the public domain. """ Test module for statemachine.py. """ import unittest import sys import re from DocutilsTestSupport import statemachine # python 2.3 if not hasattr(unittest.TestCase, "assertTrue"): # HACK? this changes TestCase, fixes the problem for tests executing afterwards. # this tests break if run alone unittest.TestCase.assertTrue = unittest.TestCase.assertTrue debug = False testtext = statemachine.string2lines("""\ First paragraph. - This is a bullet list. First list item. Second line of first para. Second para. block quote - Second list item. Example:: a literal block Last paragraph.""") expected = ('StateMachine1 text1 blank1 bullet1 known_indent1 ' 'StateMachine2 text2 text2 blank2 text2 blank2 indent2 ' 'StateMachine3 text3 blank3 finished3 finished2 ' 'bullet1 known_indent1 ' 'StateMachine2 text2 blank2 literalblock2(4) finished2 ' 'text1 finished1').split() para1 = testtext[:2] item1 = [line[2:] for line in testtext[2:9]] item2 = [line[2:] for line in testtext[9:-1]] lbindent = 6 literalblock = [line[lbindent:] for line in testtext[11:-1]] para2 = testtext[-1] class MockState(statemachine.StateWS): patterns = {'bullet': re.compile(r'- '), 'text': ''} initial_transitions = ['bullet', ['text']] levelholder = [0] def bof(self, context): self.levelholder[0] += 1 self.level = self.levelholder[0] if self.debug: print('StateMachine%s' % self.level, file=sys.stderr) return [], ['StateMachine%s' % self.level] def blank(self, match, context, next_state): result = ['blank%s' % self.level] if self.debug: print('blank%s' % self.level, file=sys.stderr) if context and context[-1] and context[-1][-2:] == '::': result.extend(self.literalblock()) return [], None, result def indent(self, match, context, next_state): if self.debug: print('indent%s' % self.level, file=sys.stderr) context, next_state, result = statemachine.StateWS.indent( self, match, context, next_state) return context, next_state, ['indent%s' % self.level] + result def known_indent(self, match, context, next_state): if self.debug: print('known_indent%s' % self.level, file=sys.stderr) context, next_state, result = statemachine.StateWS.known_indent( self, match, context, next_state) return context, next_state, ['known_indent%s' % self.level] + result def bullet(self, match, context, next_state): if self.debug: print('bullet%s' % self.level, file=sys.stderr) context, next_state, result \ = self.known_indent(match, context, next_state) return [], next_state, ['bullet%s' % self.level] + result def text(self, match, context, next_state): if self.debug: print('text%s' % self.level, file=sys.stderr) return [match.string], next_state, ['text%s' % self.level] def literalblock(self): indented, indent, offset, good = self.state_machine.get_indented() if self.debug: print('literalblock%s(%s)' % (self.level, indent), file=sys.stderr) return ['literalblock%s(%s)' % (self.level, indent)] def eof(self, context): self.levelholder[0] -= 1 if self.debug: print('finished%s' % self.level, file=sys.stderr) return ['finished%s' % self.level] class EmptySMTests(unittest.TestCase): def setUp(self): self.sm = statemachine.StateMachine( state_classes=[], initial_state='State') self.sm.debug = debug def test_add_state(self): self.sm.add_state(statemachine.State) self.assertTrue(len(self.sm.states) == 1) self.assertRaises(statemachine.DuplicateStateError, self.sm.add_state, statemachine.State) self.sm.add_state(statemachine.StateWS) self.assertTrue(len(self.sm.states) == 2) def test_add_states(self): self.sm.add_states((statemachine.State, statemachine.StateWS)) self.assertEqual(len(self.sm.states), 2) def test_get_state(self): self.assertRaises(statemachine.UnknownStateError, self.sm.get_state) self.sm.add_states((statemachine.State, statemachine.StateWS)) self.assertRaises(statemachine.UnknownStateError, self.sm.get_state, 'unknownState') self.assertTrue(isinstance(self.sm.get_state('State'), statemachine.State)) self.assertTrue(isinstance(self.sm.get_state('StateWS'), statemachine.State)) self.assertEqual(self.sm.current_state, 'StateWS') class EmptySMWSTests(EmptySMTests): def setUp(self): self.sm = statemachine.StateMachineWS( state_classes=[], initial_state='State') self.sm.debug = debug class SMWSTests(unittest.TestCase): def setUp(self): self.sm = statemachine.StateMachineWS([MockState], 'MockState', debug=debug) self.sm.debug = debug self.sm.states['MockState'].levelholder[0] = 0 def tearDown(self): self.sm.unlink() def test___init__(self): self.assertEqual(list(self.sm.states.keys()), ['MockState']) self.assertEqual(len(self.sm.states['MockState'].transitions), 4) def test_get_indented(self): self.sm.input_lines = statemachine.StringList(testtext) self.sm.line_offset = -1 self.sm.next_line(3) indented, offset, good = self.sm.get_known_indented(2) self.assertEqual(indented, item1) self.assertEqual(offset, len(para1)) self.assertTrue(good) self.sm.next_line() indented, offset, good = self.sm.get_known_indented(2) self.assertEqual(indented, item2) self.assertEqual(offset, len(para1) + len(item1)) self.assertTrue(good) self.sm.previous_line(3) if self.sm.debug: print('\ntest_get_indented: self.sm.line:\n', self.sm.line) indented, indent, offset, good = self.sm.get_indented() if self.sm.debug: print('\ntest_get_indented: indented:\n', indented) self.assertEqual(indent, lbindent) self.assertEqual(indented, literalblock) self.assertEqual(offset, (len(para1) + len(item1) + len(item2) - len(literalblock))) self.assertTrue(good) def test_get_text_block(self): self.sm.input_lines = statemachine.StringList(testtext) self.sm.line_offset = -1 self.sm.next_line() textblock = self.sm.get_text_block() self.assertEqual(textblock, testtext[:1]) self.sm.next_line(2) textblock = self.sm.get_text_block() self.assertEqual(textblock, testtext[2:4]) def test_get_text_block_flush_left(self): self.sm.input_lines = statemachine.StringList(testtext) self.sm.line_offset = -1 self.sm.next_line() textblock = self.sm.get_text_block(flush_left=1) self.assertEqual(textblock, testtext[:1]) self.sm.next_line(2) self.assertRaises(statemachine.UnexpectedIndentationError, self.sm.get_text_block, flush_left=1) def test_run(self): self.assertEqual(self.sm.run(testtext), expected) class EmptyClass: pass class EmptyStateTests(unittest.TestCase): def setUp(self): self.state = statemachine.State(EmptyClass(), debug=debug) self.state.patterns = {'nop': 'dummy', 'nop2': 'dummy', 'nop3': 'dummy', 'bogus': 'dummy'} self.state.nop2 = self.state.nop3 = self.state.nop def test_add_transitions(self): self.assertEqual(len(self.state.transitions), 0) self.state.add_transitions(['None'], {'None': None}) self.assertEqual(len(self.state.transitions), 1) self.assertRaises(statemachine.UnknownTransitionError, self.state.add_transitions, ['bogus'], {}) self.assertRaises(statemachine.DuplicateTransitionError, self.state.add_transitions, ['None'], {'None': None}) def test_add_transition(self): self.assertEqual(len(self.state.transitions), 0) self.state.add_transition('None', None) self.assertEqual(len(self.state.transitions), 1) self.assertRaises(statemachine.DuplicateTransitionError, self.state.add_transition, 'None', None) def test_remove_transition(self): self.assertEqual(len(self.state.transitions), 0) self.state.add_transition('None', None) self.assertEqual(len(self.state.transitions), 1) self.state.remove_transition('None') self.assertEqual(len(self.state.transitions), 0) self.assertRaises(statemachine.UnknownTransitionError, self.state.remove_transition, 'None') def test_make_transition(self): dummy = re.compile('dummy') self.assertEqual(self.state.make_transition('nop', 'bogus'), (dummy, self.state.nop, 'bogus')) self.assertEqual(self.state.make_transition('nop'), (dummy, self.state.nop, self.state.__class__.__name__)) self.assertRaises(statemachine.TransitionPatternNotFound, self.state.make_transition, 'None') self.assertRaises(statemachine.TransitionMethodNotFound, self.state.make_transition, 'bogus') def test_make_transitions(self): dummy = re.compile('dummy') self.assertEqual(self.state.make_transitions(('nop', ['nop2'], ('nop3', 'bogus'))), (['nop', 'nop2', 'nop3'], {'nop': (dummy, self.state.nop, self.state.__class__.__name__), 'nop2': (dummy, self.state.nop2, self.state.__class__.__name__), 'nop3': (dummy, self.state.nop3, 'bogus')})) class MiscTests(unittest.TestCase): s2l_string = "hello\tthere\thow are\tyou?\n\tI'm fine\tthanks.\n" s2l_expected = ['hello there how are you?', " I'm fine thanks."] def test_string2lines(self): self.assertEqual(statemachine.string2lines(self.s2l_string), self.s2l_expected) if __name__ == '__main__': unittest.main()