1
# -*- test-case-name: twisted.conch.test.test_helper -*-
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
5
from twisted.conch.insults import helper
6
from twisted.conch.insults.insults import G0, G1, G2, G3
7
from twisted.conch.insults.insults import modes, privateModes
8
from twisted.conch.insults.insults import NORMAL, BOLD, UNDERLINE, BLINK, REVERSE_VIDEO
10
from twisted.trial import unittest
15
class BufferTestCase(unittest.TestCase):
17
self.term = helper.TerminalBuffer()
18
self.term.connectionMade()
20
def testInitialState(self):
21
self.assertEquals(self.term.width, WIDTH)
22
self.assertEquals(self.term.height, HEIGHT)
23
self.assertEquals(str(self.term),
25
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
28
def test_initialPrivateModes(self):
30
Verify that only DEC Auto Wrap Mode (DECAWM) and DEC Text Cursor Enable
31
Mode (DECTCEM) are initially in the Set Mode (SM) state.
34
{privateModes.AUTO_WRAP: True,
35
privateModes.CURSOR_MODE: True},
36
self.term.privateModes)
39
def test_carriageReturn(self):
41
C{"\r"} moves the cursor to the first column in the current row.
43
self.term.cursorForward(5)
44
self.term.cursorDown(3)
45
self.assertEqual(self.term.reportCursorPosition(), (5, 3))
46
self.term.insertAtCursor("\r")
47
self.assertEqual(self.term.reportCursorPosition(), (0, 3))
50
def test_linefeed(self):
52
C{"\n"} moves the cursor to the next row without changing the column.
54
self.term.cursorForward(5)
55
self.assertEqual(self.term.reportCursorPosition(), (5, 0))
56
self.term.insertAtCursor("\n")
57
self.assertEqual(self.term.reportCursorPosition(), (5, 1))
60
def test_newline(self):
62
C{write} transforms C{"\n"} into C{"\r\n"}.
64
self.term.cursorForward(5)
65
self.term.cursorDown(3)
66
self.assertEqual(self.term.reportCursorPosition(), (5, 3))
68
self.assertEqual(self.term.reportCursorPosition(), (0, 4))
71
def test_setPrivateModes(self):
73
Verify that L{helper.TerminalBuffer.setPrivateModes} changes the Set
74
Mode (SM) state to "set" for the private modes it is passed.
76
expected = self.term.privateModes.copy()
77
self.term.setPrivateModes([privateModes.SCROLL, privateModes.SCREEN])
78
expected[privateModes.SCROLL] = True
79
expected[privateModes.SCREEN] = True
80
self.assertEqual(expected, self.term.privateModes)
83
def test_resetPrivateModes(self):
85
Verify that L{helper.TerminalBuffer.resetPrivateModes} changes the Set
86
Mode (SM) state to "reset" for the private modes it is passed.
88
expected = self.term.privateModes.copy()
89
self.term.resetPrivateModes([privateModes.AUTO_WRAP, privateModes.CURSOR_MODE])
90
del expected[privateModes.AUTO_WRAP]
91
del expected[privateModes.CURSOR_MODE]
92
self.assertEqual(expected, self.term.privateModes)
95
def testCursorDown(self):
96
self.term.cursorDown(3)
97
self.assertEquals(self.term.reportCursorPosition(), (0, 3))
98
self.term.cursorDown()
99
self.assertEquals(self.term.reportCursorPosition(), (0, 4))
100
self.term.cursorDown(HEIGHT)
101
self.assertEquals(self.term.reportCursorPosition(), (0, HEIGHT - 1))
103
def testCursorUp(self):
104
self.term.cursorUp(5)
105
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
107
self.term.cursorDown(20)
108
self.term.cursorUp(1)
109
self.assertEquals(self.term.reportCursorPosition(), (0, 19))
111
self.term.cursorUp(19)
112
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
114
def testCursorForward(self):
115
self.term.cursorForward(2)
116
self.assertEquals(self.term.reportCursorPosition(), (2, 0))
117
self.term.cursorForward(2)
118
self.assertEquals(self.term.reportCursorPosition(), (4, 0))
119
self.term.cursorForward(WIDTH)
120
self.assertEquals(self.term.reportCursorPosition(), (WIDTH, 0))
122
def testCursorBackward(self):
123
self.term.cursorForward(10)
124
self.term.cursorBackward(2)
125
self.assertEquals(self.term.reportCursorPosition(), (8, 0))
126
self.term.cursorBackward(7)
127
self.assertEquals(self.term.reportCursorPosition(), (1, 0))
128
self.term.cursorBackward(1)
129
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
130
self.term.cursorBackward(1)
131
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
133
def testCursorPositioning(self):
134
self.term.cursorPosition(3, 9)
135
self.assertEquals(self.term.reportCursorPosition(), (3, 9))
137
def testSimpleWriting(self):
145
def testOvertype(self):
148
self.term.cursorBackward(len(s))
149
self.term.resetModes([modes.IRM])
153
("H" + s[1:]) + '\n' +
156
def testInsert(self):
159
self.term.cursorBackward(len(s))
160
self.term.setModes([modes.IRM])
167
def testWritingInTheMiddle(self):
169
self.term.cursorDown(5)
170
self.term.cursorForward(5)
175
(self.term.fill * 5) + s + '\n' +
178
def testWritingWrappedAtEndOfLine(self):
180
self.term.cursorForward(WIDTH - 5)
184
s[:5].rjust(WIDTH) + '\n' +
190
self.assertEquals(self.term.reportCursorPosition(), (0, 1))
191
self.term.cursorDown(HEIGHT)
192
self.assertEquals(self.term.reportCursorPosition(), (0, HEIGHT - 1))
194
self.assertEquals(self.term.reportCursorPosition(), (0, HEIGHT - 1))
196
def testReverseIndex(self):
197
self.term.reverseIndex()
198
self.assertEquals(self.term.reportCursorPosition(), (0, 0))
199
self.term.cursorDown(2)
200
self.assertEquals(self.term.reportCursorPosition(), (0, 2))
201
self.term.reverseIndex()
202
self.assertEquals(self.term.reportCursorPosition(), (0, 1))
204
def test_nextLine(self):
206
C{nextLine} positions the cursor at the beginning of the row below the
210
self.assertEquals(self.term.reportCursorPosition(), (0, 1))
211
self.term.cursorForward(5)
212
self.assertEquals(self.term.reportCursorPosition(), (5, 1))
214
self.assertEquals(self.term.reportCursorPosition(), (0, 2))
216
def testSaveCursor(self):
217
self.term.cursorDown(5)
218
self.term.cursorForward(7)
219
self.assertEquals(self.term.reportCursorPosition(), (7, 5))
220
self.term.saveCursor()
221
self.term.cursorDown(7)
222
self.term.cursorBackward(3)
223
self.assertEquals(self.term.reportCursorPosition(), (4, 12))
224
self.term.restoreCursor()
225
self.assertEquals(self.term.reportCursorPosition(), (7, 5))
227
def testSingleShifts(self):
228
self.term.singleShift2()
229
self.term.write('Hi')
231
ch = self.term.getCharacter(0, 0)
232
self.assertEquals(ch[0], 'H')
233
self.assertEquals(ch[1].charset, G2)
235
ch = self.term.getCharacter(1, 0)
236
self.assertEquals(ch[0], 'i')
237
self.assertEquals(ch[1].charset, G0)
239
self.term.singleShift3()
240
self.term.write('!!')
242
ch = self.term.getCharacter(2, 0)
243
self.assertEquals(ch[0], '!')
244
self.assertEquals(ch[1].charset, G3)
246
ch = self.term.getCharacter(3, 0)
247
self.assertEquals(ch[0], '!')
248
self.assertEquals(ch[1].charset, G0)
250
def testShifting(self):
254
self.term.write("Hello\n")
256
self.term.write("World\n")
258
self.term.write("Bye!\n")
262
for s in (s1, s2, s3):
263
for i in range(len(s)):
264
ch = self.term.getCharacter(i, h)
265
self.assertEquals(ch[0], s[i])
266
self.assertEquals(ch[1].charset, g)
267
g = g == G0 and G1 or G0
270
def testGraphicRendition(self):
271
self.term.selectGraphicRendition(BOLD, UNDERLINE, BLINK, REVERSE_VIDEO)
273
self.term.selectGraphicRendition(NORMAL)
275
self.term.selectGraphicRendition(BLINK)
277
self.term.selectGraphicRendition(BOLD)
280
ch = self.term.getCharacter(0, 0)
281
self.assertEquals(ch[0], 'W')
282
self.failUnless(ch[1].bold)
283
self.failUnless(ch[1].underline)
284
self.failUnless(ch[1].blink)
285
self.failUnless(ch[1].reverseVideo)
287
ch = self.term.getCharacter(1, 0)
288
self.assertEquals(ch[0], 'X')
289
self.failIf(ch[1].bold)
290
self.failIf(ch[1].underline)
291
self.failIf(ch[1].blink)
292
self.failIf(ch[1].reverseVideo)
294
ch = self.term.getCharacter(2, 0)
295
self.assertEquals(ch[0], 'Y')
296
self.failUnless(ch[1].blink)
297
self.failIf(ch[1].bold)
298
self.failIf(ch[1].underline)
299
self.failIf(ch[1].reverseVideo)
301
ch = self.term.getCharacter(3, 0)
302
self.assertEquals(ch[0], 'Z')
303
self.failUnless(ch[1].blink)
304
self.failUnless(ch[1].bold)
305
self.failIf(ch[1].underline)
306
self.failIf(ch[1].reverseVideo)
308
def testColorAttributes(self):
311
self.term.selectGraphicRendition(helper.FOREGROUND + helper.RED,
312
helper.BACKGROUND + helper.GREEN)
313
self.term.write(s1 + "\n")
314
self.term.selectGraphicRendition(NORMAL)
315
self.term.write(s2 + "\n")
317
for i in range(len(s1)):
318
ch = self.term.getCharacter(i, 0)
319
self.assertEquals(ch[0], s1[i])
320
self.assertEquals(ch[1].charset, G0)
321
self.assertEquals(ch[1].bold, False)
322
self.assertEquals(ch[1].underline, False)
323
self.assertEquals(ch[1].blink, False)
324
self.assertEquals(ch[1].reverseVideo, False)
325
self.assertEquals(ch[1].foreground, helper.RED)
326
self.assertEquals(ch[1].background, helper.GREEN)
328
for i in range(len(s2)):
329
ch = self.term.getCharacter(i, 1)
330
self.assertEquals(ch[0], s2[i])
331
self.assertEquals(ch[1].charset, G0)
332
self.assertEquals(ch[1].bold, False)
333
self.assertEquals(ch[1].underline, False)
334
self.assertEquals(ch[1].blink, False)
335
self.assertEquals(ch[1].reverseVideo, False)
336
self.assertEquals(ch[1].foreground, helper.WHITE)
337
self.assertEquals(ch[1].background, helper.BLACK)
339
def testEraseLine(self):
343
self.term.write('\n'.join((s1, s2, s3)) + '\n')
344
self.term.cursorPosition(1, 1)
345
self.term.eraseLine()
354
def testEraseToLineEnd(self):
357
self.term.cursorBackward(5)
358
self.term.eraseToLineEnd()
364
def testEraseToLineBeginning(self):
367
self.term.cursorBackward(5)
368
self.term.eraseToLineBeginning()
371
s[-4:].rjust(len(s)) + '\n' +
374
def testEraseDisplay(self):
375
self.term.write('Hello world\n')
376
self.term.write('Goodbye world\n')
377
self.term.eraseDisplay()
383
def testEraseToDisplayEnd(self):
386
self.term.write('\n'.join((s1, s2, '')))
387
self.term.cursorPosition(5, 1)
388
self.term.eraseToDisplayEnd()
396
def testEraseToDisplayBeginning(self):
399
self.term.write('\n'.join((s1, s2)))
400
self.term.cursorPosition(5, 1)
401
self.term.eraseToDisplayBeginning()
406
s2[6:].rjust(len(s2)) + '\n' +
409
def testLineInsertion(self):
412
self.term.write('\n'.join((s1, s2)))
413
self.term.cursorPosition(7, 1)
414
self.term.insertLine()
423
def testLineDeletion(self):
427
self.term.write('\n'.join((s1, s2, s3)))
428
self.term.cursorPosition(9, 1)
429
self.term.deleteLine()
437
class FakeDelayedCall:
440
def __init__(self, fs, timeout, f, a, kw):
442
self.timeout = timeout
448
return not (self.cancelled or self.called)
451
self.cancelled = True
452
# self.fs.calls.remove(self)
456
self.f(*self.a, **self.kw)
462
def callLater(self, timeout, f, *a, **kw):
463
self.calls.append(FakeDelayedCall(self, timeout, f, a, kw))
464
return self.calls[-1]
466
class ExpectTestCase(unittest.TestCase):
468
self.term = helper.ExpectableBuffer()
469
self.term.connectionMade()
470
self.fs = FakeScheduler()
472
def testSimpleString(self):
474
d = self.term.expect("hello world", timeout=1, scheduler=self.fs)
475
d.addCallback(result.append)
477
self.term.write("greeting puny earthlings\n")
479
self.term.write("hello world\n")
480
self.failUnless(result)
481
self.assertEquals(result[0].group(), "hello world")
482
self.assertEquals(len(self.fs.calls), 1)
483
self.failIf(self.fs.calls[0].active())
485
def testBrokenUpString(self):
487
d = self.term.expect("hello world")
488
d.addCallback(result.append)
491
self.term.write("hello ")
493
self.term.write("worl")
496
self.failUnless(result)
497
self.assertEquals(result[0].group(), "hello world")
500
def testMultiple(self):
502
d1 = self.term.expect("hello ")
503
d1.addCallback(result.append)
504
d2 = self.term.expect("world")
505
d2.addCallback(result.append)
508
self.term.write("hello")
511
self.assertEquals(len(result), 1)
512
self.term.write("world")
513
self.assertEquals(len(result), 2)
514
self.assertEquals(result[0].group(), "hello ")
515
self.assertEquals(result[1].group(), "world")
517
def testSynchronous(self):
518
self.term.write("hello world")
521
d = self.term.expect("hello world")
522
d.addCallback(result.append)
523
self.failUnless(result)
524
self.assertEquals(result[0].group(), "hello world")
526
def testMultipleSynchronous(self):
527
self.term.write("goodbye world")
530
d1 = self.term.expect("bye")
531
d1.addCallback(result.append)
532
d2 = self.term.expect("world")
533
d2.addCallback(result.append)
535
self.assertEquals(len(result), 2)
536
self.assertEquals(result[0].group(), "bye")
537
self.assertEquals(result[1].group(), "world")
539
def _cbTestTimeoutFailure(self, res):
540
self.assert_(hasattr(res, 'type'))
541
self.assertEqual(res.type, helper.ExpectationTimeout)
543
def testTimeoutFailure(self):
544
d = self.term.expect("hello world", timeout=1, scheduler=self.fs)
545
d.addBoth(self._cbTestTimeoutFailure)
546
self.fs.calls[0].call()
548
def testOverlappingTimeout(self):
549
self.term.write("not zoomtastic")
552
d1 = self.term.expect("hello world", timeout=1, scheduler=self.fs)
553
d1.addBoth(self._cbTestTimeoutFailure)
554
d2 = self.term.expect("zoom")
555
d2.addCallback(result.append)
557
self.fs.calls[0].call()
559
self.assertEquals(len(result), 1)
560
self.assertEquals(result[0].group(), "zoom")