1 | #!/usr/bin/env python2
|
2 | """display_test.py: Tests for display.py."""
|
3 | from __future__ import print_function
|
4 |
|
5 | import cStringIO
|
6 | import sys
|
7 | import unittest
|
8 |
|
9 | from core import comp_ui # module under test
|
10 | from core import pyos
|
11 | from core import util
|
12 |
|
13 | import line_input
|
14 |
|
15 |
|
16 | class 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 |
|
114 | class 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 |
|
151 | class 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 |
|
176 | if __name__ == '__main__':
|
177 | unittest.main()
|