1
- import unittest
1
+ from twisted . trial import unittest
2
2
3
3
from ometa .grammar import OMeta
4
4
from ometa .protocol import ParserProtocol
5
+ from ometa .runtime import ParseError
5
6
6
7
7
8
testingGrammarSource = """
8
9
9
10
someA = ('a' 'a') -> state('a')
10
11
someB = ('b' 'b') -> state('b')
11
12
someC = ('c' 'c') -> state('c')
13
+ someExc = 'e' -> state.raiseSomething()
12
14
13
- initial = someA
15
+ initial = someA | someExc
14
16
15
17
"""
16
18
testGrammar = OMeta (testingGrammarSource ).parseGrammar ('testGrammar' )
@@ -21,6 +23,10 @@ def __init__(self, transport):
21
23
self .transport = transport
22
24
23
25
26
+ class SomeException (Exception ):
27
+ pass
28
+
29
+
24
30
class StateFactory (object ):
25
31
def __init__ (self , sender , parser ):
26
32
self .sender = sender
@@ -37,10 +43,21 @@ def __call__(self, v):
37
43
self .calls .append (v )
38
44
return self .returnMap .get (v )
39
45
46
+ def raiseSomething (self ):
47
+ raise SomeException ()
48
+
40
49
def connectionLost (self , reason ):
41
50
self .lossReason = reason
42
51
43
52
53
+ class FakeTransport (object ):
54
+ def __init__ (self ):
55
+ self .aborted = False
56
+
57
+ def abortConnection (self ):
58
+ self .aborted = True
59
+
60
+
44
61
class ParserProtocolTestCase (unittest .TestCase ):
45
62
def setUp (self ):
46
63
self .protocol = ParserProtocol (
@@ -140,3 +157,39 @@ def test_connectionLoss(self):
140
157
reason = object ()
141
158
self .protocol .connectionLost (reason )
142
159
self .assertEqual (self .protocol .state .lossReason , reason )
160
+
161
+ def test_parseFailure (self ):
162
+ """
163
+ Parse failures cause connection abortion with the parse error as the
164
+ reason.
165
+ """
166
+ transport = FakeTransport ()
167
+ self .protocol .makeConnection (transport )
168
+ self .protocol .dataReceived ('b' )
169
+ self .failIfEqual (self .protocol .state .lossReason , None )
170
+ self .failUnlessIsInstance (self .protocol .state .lossReason .value ,
171
+ ParseError )
172
+ self .assert_ (transport .aborted )
173
+
174
+ def test_exceptionsRaisedFromState (self ):
175
+ """
176
+ Raising an exception from state methods called from the grammar
177
+ propagate to connectionLost.
178
+ """
179
+ transport = FakeTransport ()
180
+ self .protocol .makeConnection (transport )
181
+ self .protocol .dataReceived ('e' )
182
+ self .failIfEqual (self .protocol .state .lossReason , None )
183
+ self .failUnlessIsInstance (self .protocol .state .lossReason .value ,
184
+ SomeException )
185
+ self .assert_ (transport .aborted )
186
+
187
+ def test_dataIgnoredAfterDisconnection (self ):
188
+ """After connectionLost is called, all incoming data is ignored."""
189
+ transport = FakeTransport ()
190
+ self .protocol .makeConnection (transport )
191
+ reason = object ()
192
+ self .protocol .connectionLost (reason )
193
+ self .protocol .dataReceived ('d' )
194
+ self .assertEqual (self .protocol .state .lossReason , reason )
195
+ self .assert_ (not transport .aborted )
0 commit comments