You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
10 KiB
282 lines
10 KiB
7 years ago
|
#! /usr/bin/env python
|
||
|
|
||
|
# $Id: test_statemachine.py 7463 2012-06-22 19:49:51Z milde $
|
||
|
# Author: David Goodger <goodger@python.org>
|
||
|
# 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
|
||
|
|
||
|
|
||
|
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 >>sys.stderr, 'StateMachine%s' % self.level
|
||
|
return [], ['StateMachine%s' % self.level]
|
||
|
|
||
|
def blank(self, match, context, next_state):
|
||
|
result = ['blank%s' % self.level]
|
||
|
if self.debug: print >>sys.stderr, 'blank%s' % self.level
|
||
|
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 >>sys.stderr, 'indent%s' % self.level
|
||
|
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 >>sys.stderr, 'known_indent%s' % self.level
|
||
|
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 >>sys.stderr, 'bullet%s' % self.level
|
||
|
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 >>sys.stderr, 'text%s' % self.level
|
||
|
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 >>sys.stderr, 'literalblock%s(%s)' % (self.level,
|
||
|
indent)
|
||
|
return ['literalblock%s(%s)' % (self.level, indent)]
|
||
|
|
||
|
def eof(self, context):
|
||
|
self.levelholder[0] -= 1
|
||
|
if self.debug: print >>sys.stderr, 'finished%s' % self.level
|
||
|
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(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()
|