OILS / core / comp_ui_test.py View on Github | oilshell.org

177 lines, 117 significant
1#!/usr/bin/env python2
2"""display_test.py: Tests for display.py."""
3from __future__ import print_function
4
5import cStringIO
6import sys
7import unittest
8
9from core import comp_ui # module under test
10from core import pyos
11from core import util
12
13import line_input
14
15
16class VisualTest(unittest.TestCase):
17
18 def testPrintPacked(self):
19 matches = ['foo', 'bar', 'spam', 'eggs', 'python', 'perl']
20 longest_match_len = max(len(m) for m in matches)
21 max_lines = 10
22
23 for width in (1, 10, 20, 30, 40, 50):
24 f = cStringIO.StringIO()
25 n = comp_ui._PrintPacked(matches, longest_match_len, width,
26 max_lines, f)
27
28 out = f.getvalue()
29 lines = out.splitlines()
30 max_len = max(len(line) for line in lines)
31
32 print('WIDTH = %d' % width)
33 print('reported lines = %d' % n)
34 print('measured lines = %d' % len(lines))
35 print('max_len = %d' % max_len)
36
37 # Make sure it fits in the width!
38
39 # NOTE: This is too conservative because of non-printable characters
40 # like \n and ANSI escapes
41 if width != 1:
42 self.assertLess(max_len, width)
43
44 print('')
45
46 def testLongStringAndSkinnyTerminal(self):
47 matches = ['foo' * 10, 'bar' * 10, 'spams' * 10, 'zzz']
48 longest_match_len = max(len(m) for m in matches)
49
50 for width in (1, 10, 20, 30, 40, 50):
51 f = cStringIO.StringIO()
52 n = comp_ui._PrintPacked(matches, longest_match_len, width, 10, f)
53
54 out = f.getvalue()
55 lines = out.splitlines()
56 max_len = max(len(line) for line in lines)
57
58 print('WIDTH = %d' % width)
59 print('reported lines = %d' % n)
60 print('measured lines = %d' % len(lines))
61 print('max_len = %d' % max_len)
62 print('')
63
64 def testTooMany(self):
65 matches = ['--flag%d' % i for i in xrange(100)]
66 longest_match_len = max(len(m) for m in matches)
67
68 for width in (1, 10, 20, 30, 40, 50, 60):
69 f = cStringIO.StringIO()
70 n = comp_ui._PrintPacked(matches, longest_match_len, width, 10, f)
71
72 out = f.getvalue()
73 lines = out.splitlines()
74 max_len = max(len(line) for line in lines)
75
76 print('WIDTH = %d' % width)
77 print('reported lines = %d' % n)
78 # Count newlines since last one doesn't have a newline
79 print('measured lines = %d' % out.count('\n'))
80 print('max_len = %d' % max_len)
81 print('')
82
83 #print(out)
84
85 def testPrintLong(self):
86 matches = ['--all', '--almost-all', '--verbose']
87 longest_match_len = max(len(m) for m in matches)
88 descriptions = {
89 '--all': 'show all ' * 10, # truncate
90 '--almost-all': 'foo',
91 '--verbose': 'bar'
92 }
93
94 max_lines = 10
95 for width in (1, 10, 20, 30, 40, 50, 60):
96 f = cStringIO.StringIO()
97 n = comp_ui._PrintLong(matches, longest_match_len, width,
98 max_lines, descriptions, f)
99
100 out = f.getvalue()
101 lines = out.splitlines()
102 max_len = max(len(line) for line in lines)
103
104 print('WIDTH = %d' % width)
105 print('reported lines = %d' % n)
106 # Count newlines since last one doesn't have a newline
107 print('measured lines = %d' % out.count('\n'))
108 print('max_len = %d' % max_len)
109 print('')
110
111 #print(out)
112
113
114class UiTest(unittest.TestCase):
115
116 def testDisplays(self):
117 comp_ui_state = comp_ui.State()
118 prompt_state = comp_ui.PromptState()
119 debug_f = util.DebugFile(sys.stdout)
120 signal_safe = pyos.InitSignalSafe()
121
122 # terminal width
123 d1 = comp_ui.NiceDisplay(80, comp_ui_state, prompt_state, debug_f,
124 line_input, signal_safe)
125 d2 = comp_ui.MinimalDisplay(comp_ui_state, prompt_state, debug_f)
126
127 prompt_state.SetLastPrompt('$ ')
128
129 for disp in [d1, d2]:
130 # This one is important
131 disp.EraseLines()
132 disp.Reset()
133
134 # These are related but we can just set them separately.
135 comp_ui_state.line_until_tab = 'echo ' # for returning to the prompt
136 comp_ui_state.display_pos = 5 # Strip this off every candidate
137
138 disp.PrintRequired('hello')
139 disp.PrintOptional('hello')
140
141 matches = ['echo one', 'echo two']
142 disp.PrintCandidates(None, matches, None)
143
144 # This needs to be aware of the terminal width.
145 # It's a bit odd since it's called as a side effect of the PromptEvaluator.
146 # That class knows about styles and so forth.
147
148 disp.ShowPromptOnRight('RIGHT')
149
150
151class PromptTest(unittest.TestCase):
152
153 def testNoEscapes(self):
154 for prompt in ["> ", "osh>", "[[]][[]][][]]][["]:
155 self.assertEqual(comp_ui._PromptLen(prompt), len(prompt))
156
157 def testValidEscapes(self):
158 self.assertEqual(
159 comp_ui._PromptLen("\x01\033[01;34m\x02user\x01\033[00m\x02 >"),
160 len("user >"))
161 self.assertEqual(comp_ui._PromptLen("\x01\x02\x01\x02\x01\x02"), 0)
162 self.assertEqual(
163 comp_ui._PromptLen("\x01\x02 hi \x01hi\x02 \x01\x02 hello"),
164 len(" hi hello"))
165
166 def testNewline(self):
167 self.assertEqual(comp_ui._PromptLen("\n"), 0)
168 self.assertEqual(comp_ui._PromptLen("abc\ndef"), 3)
169 self.assertEqual(comp_ui._PromptLen(""), 0)
170
171 def testControlCharacters(self):
172 self.assertEqual(comp_ui._PromptLen("\xef"), 1)
173 self.assertEqual(comp_ui._PromptLen("\x03\x05"), 2)
174
175
176if __name__ == '__main__':
177 unittest.main()