OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.conch.test.test_helper -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
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, REVERS
E_VIDEO | |
9 | |
10 from twisted.trial import unittest | |
11 | |
12 WIDTH = 80 | |
13 HEIGHT = 24 | |
14 | |
15 class BufferTestCase(unittest.TestCase): | |
16 def setUp(self): | |
17 self.term = helper.TerminalBuffer() | |
18 self.term.connectionMade() | |
19 | |
20 def testInitialState(self): | |
21 self.assertEquals(self.term.width, WIDTH) | |
22 self.assertEquals(self.term.height, HEIGHT) | |
23 self.assertEquals(str(self.term), | |
24 '\n' * (HEIGHT - 1)) | |
25 self.assertEquals(self.term.reportCursorPosition(), (0, 0)) | |
26 | |
27 | |
28 def test_initialPrivateModes(self): | |
29 """ | |
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. | |
32 """ | |
33 self.assertEqual( | |
34 {privateModes.AUTO_WRAP: True, | |
35 privateModes.CURSOR_MODE: True}, | |
36 self.term.privateModes) | |
37 | |
38 | |
39 def test_carriageReturn(self): | |
40 """ | |
41 C{"\r"} moves the cursor to the first column in the current row. | |
42 """ | |
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)) | |
48 | |
49 | |
50 def test_linefeed(self): | |
51 """ | |
52 C{"\n"} moves the cursor to the next row without changing the column. | |
53 """ | |
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)) | |
58 | |
59 | |
60 def test_newline(self): | |
61 """ | |
62 C{write} transforms C{"\n"} into C{"\r\n"}. | |
63 """ | |
64 self.term.cursorForward(5) | |
65 self.term.cursorDown(3) | |
66 self.assertEqual(self.term.reportCursorPosition(), (5, 3)) | |
67 self.term.write("\n") | |
68 self.assertEqual(self.term.reportCursorPosition(), (0, 4)) | |
69 | |
70 | |
71 def test_setPrivateModes(self): | |
72 """ | |
73 Verify that L{helper.TerminalBuffer.setPrivateModes} changes the Set | |
74 Mode (SM) state to "set" for the private modes it is passed. | |
75 """ | |
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) | |
81 | |
82 | |
83 def test_resetPrivateModes(self): | |
84 """ | |
85 Verify that L{helper.TerminalBuffer.resetPrivateModes} changes the Set | |
86 Mode (SM) state to "reset" for the private modes it is passed. | |
87 """ | |
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) | |
93 | |
94 | |
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)) | |
102 | |
103 def testCursorUp(self): | |
104 self.term.cursorUp(5) | |
105 self.assertEquals(self.term.reportCursorPosition(), (0, 0)) | |
106 | |
107 self.term.cursorDown(20) | |
108 self.term.cursorUp(1) | |
109 self.assertEquals(self.term.reportCursorPosition(), (0, 19)) | |
110 | |
111 self.term.cursorUp(19) | |
112 self.assertEquals(self.term.reportCursorPosition(), (0, 0)) | |
113 | |
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)) | |
121 | |
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)) | |
132 | |
133 def testCursorPositioning(self): | |
134 self.term.cursorPosition(3, 9) | |
135 self.assertEquals(self.term.reportCursorPosition(), (3, 9)) | |
136 | |
137 def testSimpleWriting(self): | |
138 s = "Hello, world." | |
139 self.term.write(s) | |
140 self.assertEquals( | |
141 str(self.term), | |
142 s + '\n' + | |
143 '\n' * (HEIGHT - 2)) | |
144 | |
145 def testOvertype(self): | |
146 s = "hello, world." | |
147 self.term.write(s) | |
148 self.term.cursorBackward(len(s)) | |
149 self.term.resetModes([modes.IRM]) | |
150 self.term.write("H") | |
151 self.assertEquals( | |
152 str(self.term), | |
153 ("H" + s[1:]) + '\n' + | |
154 '\n' * (HEIGHT - 2)) | |
155 | |
156 def testInsert(self): | |
157 s = "ello, world." | |
158 self.term.write(s) | |
159 self.term.cursorBackward(len(s)) | |
160 self.term.setModes([modes.IRM]) | |
161 self.term.write("H") | |
162 self.assertEquals( | |
163 str(self.term), | |
164 ("H" + s) + '\n' + | |
165 '\n' * (HEIGHT - 2)) | |
166 | |
167 def testWritingInTheMiddle(self): | |
168 s = "Hello, world." | |
169 self.term.cursorDown(5) | |
170 self.term.cursorForward(5) | |
171 self.term.write(s) | |
172 self.assertEquals( | |
173 str(self.term), | |
174 '\n' * 5 + | |
175 (self.term.fill * 5) + s + '\n' + | |
176 '\n' * (HEIGHT - 7)) | |
177 | |
178 def testWritingWrappedAtEndOfLine(self): | |
179 s = "Hello, world." | |
180 self.term.cursorForward(WIDTH - 5) | |
181 self.term.write(s) | |
182 self.assertEquals( | |
183 str(self.term), | |
184 s[:5].rjust(WIDTH) + '\n' + | |
185 s[5:] + '\n' + | |
186 '\n' * (HEIGHT - 3)) | |
187 | |
188 def testIndex(self): | |
189 self.term.index() | |
190 self.assertEquals(self.term.reportCursorPosition(), (0, 1)) | |
191 self.term.cursorDown(HEIGHT) | |
192 self.assertEquals(self.term.reportCursorPosition(), (0, HEIGHT - 1)) | |
193 self.term.index() | |
194 self.assertEquals(self.term.reportCursorPosition(), (0, HEIGHT - 1)) | |
195 | |
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)) | |
203 | |
204 def test_nextLine(self): | |
205 """ | |
206 C{nextLine} positions the cursor at the beginning of the row below the | |
207 current row. | |
208 """ | |
209 self.term.nextLine() | |
210 self.assertEquals(self.term.reportCursorPosition(), (0, 1)) | |
211 self.term.cursorForward(5) | |
212 self.assertEquals(self.term.reportCursorPosition(), (5, 1)) | |
213 self.term.nextLine() | |
214 self.assertEquals(self.term.reportCursorPosition(), (0, 2)) | |
215 | |
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)) | |
226 | |
227 def testSingleShifts(self): | |
228 self.term.singleShift2() | |
229 self.term.write('Hi') | |
230 | |
231 ch = self.term.getCharacter(0, 0) | |
232 self.assertEquals(ch[0], 'H') | |
233 self.assertEquals(ch[1].charset, G2) | |
234 | |
235 ch = self.term.getCharacter(1, 0) | |
236 self.assertEquals(ch[0], 'i') | |
237 self.assertEquals(ch[1].charset, G0) | |
238 | |
239 self.term.singleShift3() | |
240 self.term.write('!!') | |
241 | |
242 ch = self.term.getCharacter(2, 0) | |
243 self.assertEquals(ch[0], '!') | |
244 self.assertEquals(ch[1].charset, G3) | |
245 | |
246 ch = self.term.getCharacter(3, 0) | |
247 self.assertEquals(ch[0], '!') | |
248 self.assertEquals(ch[1].charset, G0) | |
249 | |
250 def testShifting(self): | |
251 s1 = "Hello" | |
252 s2 = "World" | |
253 s3 = "Bye!" | |
254 self.term.write("Hello\n") | |
255 self.term.shiftOut() | |
256 self.term.write("World\n") | |
257 self.term.shiftIn() | |
258 self.term.write("Bye!\n") | |
259 | |
260 g = G0 | |
261 h = 0 | |
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 | |
268 h += 1 | |
269 | |
270 def testGraphicRendition(self): | |
271 self.term.selectGraphicRendition(BOLD, UNDERLINE, BLINK, REVERSE_VIDEO) | |
272 self.term.write('W') | |
273 self.term.selectGraphicRendition(NORMAL) | |
274 self.term.write('X') | |
275 self.term.selectGraphicRendition(BLINK) | |
276 self.term.write('Y') | |
277 self.term.selectGraphicRendition(BOLD) | |
278 self.term.write('Z') | |
279 | |
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) | |
286 | |
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) | |
293 | |
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) | |
300 | |
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) | |
307 | |
308 def testColorAttributes(self): | |
309 s1 = "Merry xmas" | |
310 s2 = "Just kidding" | |
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") | |
316 | |
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) | |
327 | |
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) | |
338 | |
339 def testEraseLine(self): | |
340 s1 = 'line 1' | |
341 s2 = 'line 2' | |
342 s3 = 'line 3' | |
343 self.term.write('\n'.join((s1, s2, s3)) + '\n') | |
344 self.term.cursorPosition(1, 1) | |
345 self.term.eraseLine() | |
346 | |
347 self.assertEquals( | |
348 str(self.term), | |
349 s1 + '\n' + | |
350 '\n' + | |
351 s3 + '\n' + | |
352 '\n' * (HEIGHT - 4)) | |
353 | |
354 def testEraseToLineEnd(self): | |
355 s = 'Hello, world.' | |
356 self.term.write(s) | |
357 self.term.cursorBackward(5) | |
358 self.term.eraseToLineEnd() | |
359 self.assertEquals( | |
360 str(self.term), | |
361 s[:-5] + '\n' + | |
362 '\n' * (HEIGHT - 2)) | |
363 | |
364 def testEraseToLineBeginning(self): | |
365 s = 'Hello, world.' | |
366 self.term.write(s) | |
367 self.term.cursorBackward(5) | |
368 self.term.eraseToLineBeginning() | |
369 self.assertEquals( | |
370 str(self.term), | |
371 s[-4:].rjust(len(s)) + '\n' + | |
372 '\n' * (HEIGHT - 2)) | |
373 | |
374 def testEraseDisplay(self): | |
375 self.term.write('Hello world\n') | |
376 self.term.write('Goodbye world\n') | |
377 self.term.eraseDisplay() | |
378 | |
379 self.assertEquals( | |
380 str(self.term), | |
381 '\n' * (HEIGHT - 1)) | |
382 | |
383 def testEraseToDisplayEnd(self): | |
384 s1 = "Hello world" | |
385 s2 = "Goodbye world" | |
386 self.term.write('\n'.join((s1, s2, ''))) | |
387 self.term.cursorPosition(5, 1) | |
388 self.term.eraseToDisplayEnd() | |
389 | |
390 self.assertEquals( | |
391 str(self.term), | |
392 s1 + '\n' + | |
393 s2[:5] + '\n' + | |
394 '\n' * (HEIGHT - 3)) | |
395 | |
396 def testEraseToDisplayBeginning(self): | |
397 s1 = "Hello world" | |
398 s2 = "Goodbye world" | |
399 self.term.write('\n'.join((s1, s2))) | |
400 self.term.cursorPosition(5, 1) | |
401 self.term.eraseToDisplayBeginning() | |
402 | |
403 self.assertEquals( | |
404 str(self.term), | |
405 '\n' + | |
406 s2[6:].rjust(len(s2)) + '\n' + | |
407 '\n' * (HEIGHT - 3)) | |
408 | |
409 def testLineInsertion(self): | |
410 s1 = "Hello world" | |
411 s2 = "Goodbye world" | |
412 self.term.write('\n'.join((s1, s2))) | |
413 self.term.cursorPosition(7, 1) | |
414 self.term.insertLine() | |
415 | |
416 self.assertEquals( | |
417 str(self.term), | |
418 s1 + '\n' + | |
419 '\n' + | |
420 s2 + '\n' + | |
421 '\n' * (HEIGHT - 4)) | |
422 | |
423 def testLineDeletion(self): | |
424 s1 = "Hello world" | |
425 s2 = "Middle words" | |
426 s3 = "Goodbye world" | |
427 self.term.write('\n'.join((s1, s2, s3))) | |
428 self.term.cursorPosition(9, 1) | |
429 self.term.deleteLine() | |
430 | |
431 self.assertEquals( | |
432 str(self.term), | |
433 s1 + '\n' + | |
434 s3 + '\n' + | |
435 '\n' * (HEIGHT - 3)) | |
436 | |
437 class FakeDelayedCall: | |
438 called = False | |
439 cancelled = False | |
440 def __init__(self, fs, timeout, f, a, kw): | |
441 self.fs = fs | |
442 self.timeout = timeout | |
443 self.f = f | |
444 self.a = a | |
445 self.kw = kw | |
446 | |
447 def active(self): | |
448 return not (self.cancelled or self.called) | |
449 | |
450 def cancel(self): | |
451 self.cancelled = True | |
452 # self.fs.calls.remove(self) | |
453 | |
454 def call(self): | |
455 self.called = True | |
456 self.f(*self.a, **self.kw) | |
457 | |
458 class FakeScheduler: | |
459 def __init__(self): | |
460 self.calls = [] | |
461 | |
462 def callLater(self, timeout, f, *a, **kw): | |
463 self.calls.append(FakeDelayedCall(self, timeout, f, a, kw)) | |
464 return self.calls[-1] | |
465 | |
466 class ExpectTestCase(unittest.TestCase): | |
467 def setUp(self): | |
468 self.term = helper.ExpectableBuffer() | |
469 self.term.connectionMade() | |
470 self.fs = FakeScheduler() | |
471 | |
472 def testSimpleString(self): | |
473 result = [] | |
474 d = self.term.expect("hello world", timeout=1, scheduler=self.fs) | |
475 d.addCallback(result.append) | |
476 | |
477 self.term.write("greeting puny earthlings\n") | |
478 self.failIf(result) | |
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()) | |
484 | |
485 def testBrokenUpString(self): | |
486 result = [] | |
487 d = self.term.expect("hello world") | |
488 d.addCallback(result.append) | |
489 | |
490 self.failIf(result) | |
491 self.term.write("hello ") | |
492 self.failIf(result) | |
493 self.term.write("worl") | |
494 self.failIf(result) | |
495 self.term.write("d") | |
496 self.failUnless(result) | |
497 self.assertEquals(result[0].group(), "hello world") | |
498 | |
499 | |
500 def testMultiple(self): | |
501 result = [] | |
502 d1 = self.term.expect("hello ") | |
503 d1.addCallback(result.append) | |
504 d2 = self.term.expect("world") | |
505 d2.addCallback(result.append) | |
506 | |
507 self.failIf(result) | |
508 self.term.write("hello") | |
509 self.failIf(result) | |
510 self.term.write(" ") | |
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") | |
516 | |
517 def testSynchronous(self): | |
518 self.term.write("hello world") | |
519 | |
520 result = [] | |
521 d = self.term.expect("hello world") | |
522 d.addCallback(result.append) | |
523 self.failUnless(result) | |
524 self.assertEquals(result[0].group(), "hello world") | |
525 | |
526 def testMultipleSynchronous(self): | |
527 self.term.write("goodbye world") | |
528 | |
529 result = [] | |
530 d1 = self.term.expect("bye") | |
531 d1.addCallback(result.append) | |
532 d2 = self.term.expect("world") | |
533 d2.addCallback(result.append) | |
534 | |
535 self.assertEquals(len(result), 2) | |
536 self.assertEquals(result[0].group(), "bye") | |
537 self.assertEquals(result[1].group(), "world") | |
538 | |
539 def _cbTestTimeoutFailure(self, res): | |
540 self.assert_(hasattr(res, 'type')) | |
541 self.assertEqual(res.type, helper.ExpectationTimeout) | |
542 | |
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() | |
547 | |
548 def testOverlappingTimeout(self): | |
549 self.term.write("not zoomtastic") | |
550 | |
551 result = [] | |
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) | |
556 | |
557 self.fs.calls[0].call() | |
558 | |
559 self.assertEquals(len(result), 1) | |
560 self.assertEquals(result[0].group(), "zoom") | |
OLD | NEW |