OILS / osh / split_test.py View on Github | oils.pub

182 lines, 117 significant
1#!/usr/bin/env python2
2"""
3split.test.py: Tests for split.py
4"""
5
6import unittest
7
8from core import state
9from core import test_lib
10from osh import split # module under test
11
12
13def _RunSplitCases(test, sp, cases):
14 for expected_parts, s, allow_escape in cases:
15 spans = sp.Split(s, allow_escape)
16 if 0:
17 print('%r: %s' % (s, spans))
18 else:
19 # Verbose for debugging
20 print(repr(s))
21 for span in spans:
22 print(' %s %s' % span)
23
24 parts = split._SpansToParts(s, spans)
25 print('PARTS %s' % parts)
26
27 test.assertEqual(expected_parts, parts,
28 '%r: %s != %s' % (s, expected_parts, parts))
29
30
31class SplitTest(unittest.TestCase):
32
33 def testSpansToParts(self):
34 sp = split.IfsSplitter(split.DEFAULT_IFS, '')
35
36 s = 'one\\ two'
37 spans = sp.Split(s, False)
38 print(spans)
39
40 parts = split._SpansToParts(s, spans)
41 self.assertEqual(['one\\', 'two'], parts)
42
43 spans = sp.Split(s, True) # allow_escape
44 parts = split._SpansToParts(s, spans)
45 self.assertEqual(['one two'], parts)
46
47 # NOTE: Only read builtin supports max_results
48 return
49
50 parts = split._SpansToParts(s, spans, max_results=1)
51 self.assertEqual(['one\\ two'], parts)
52
53 print(spans)
54
55 parts = split._SpansToParts(s, spans, max_results=1)
56 self.assertEqual(['one two'], parts)
57
58 def testTrailingWhitespaceBug(self):
59 # Bug: these differed
60 CASES = [
61 (['x y'], r' x\ y', True),
62 (['ab '], r' ab\ ', True),
63 (['ab '], r' ab\ ', True),
64 ]
65 sp = split.IfsSplitter(split.DEFAULT_IFS, '')
66 _RunSplitCases(self, sp, CASES)
67
68 def testDefaultIfs(self):
69 CASES = [
70 ([], '', True),
71 (['a'], 'a', True),
72 (['a'], ' a ', True),
73 (['ab'], '\tab\n', True),
74 (['a', 'b'], 'a b\n', True),
75 (['a b'], r'a\ b', True),
76 (['a\\', 'b'], r'a\ b', False),
77 ([r'\*.sh'], r'\\*.sh', True),
78 (['Aa', 'b', ' a b'], 'Aa b \\ a\\ b', True),
79 ]
80
81 sp = split.IfsSplitter(split.DEFAULT_IFS, '')
82 _RunSplitCases(self, sp, CASES)
83
84 self.assertEqual(r'a\ _b', sp.Escape('a _b'))
85
86 def testMixedIfs(self):
87 CASES = [
88 ([], '', True),
89 (['a', 'b'], 'a_b', True),
90 (['a', 'b'], ' a b ', True),
91 (['a', 'b'], 'a _ b', True),
92 (['a', 'b'], ' a _ b ', True),
93 (['a', '', 'b'], 'a _ _ b', True),
94 (['a', '', 'b'], 'a __ b', True),
95 (['a', '', '', 'b'], 'a _ _ _ b', True),
96 (['a'], ' a _ ', True),
97
98 # NOTES:
99 # - This cases REQUIRES ignoring leading whitespace. The state machine
100 # can't handle it. Contrast with the case above.
101 # - We get three spans with index 1 because of the initial rule to
102 # ignore whitespace, and then EMIT_EMPTY. Seems harmless for now?
103 (['', 'a'], ' _ a _ ', True),
104
105 # Backslash escape
106 (['a b'], r'a\ b', True),
107 (['a\\', 'b'], r'a\ b', False),
108 ]
109
110 # IFS='_ '
111 sp = split.IfsSplitter(' ', '_')
112 _RunSplitCases(self, sp, CASES)
113
114 self.assertEqual('a\ \_b', sp.Escape('a _b'))
115
116 def testWhitespaceOnly(self):
117 CASES = [
118 ([], '', True),
119 ([], '\t', True),
120 (['a'], 'a\t', True),
121 (['a', 'b'], '\t\ta\tb\t', True),
122
123 # Backslash escape
124 (['a\tb'], 'a\\\tb', True),
125 (['a\\', 'b'], 'a\\\tb', False),
126 ]
127
128 # IFS='_ '
129 sp = split.IfsSplitter('\t', '')
130 _RunSplitCases(self, sp, CASES)
131
132 self.assertEqual('a b', sp.Escape('a b'))
133 self.assertEqual('a\\\tb', sp.Escape('a\tb'))
134
135 def testOtherOnly(self):
136 CASES = [
137 ([], '', True),
138 ([''], '_', True),
139 (['a'], 'a_', True),
140 (['', '', 'a', 'b'], '__a_b_', True),
141
142 # Backslash escape
143 (['a_b'], r'a\_b', True),
144 (['a\\', 'b'], r'a\_b', False),
145 ]
146
147 # IFS='_ '
148 sp = split.IfsSplitter('', '_')
149 _RunSplitCases(self, sp, CASES)
150
151 def testTwoOther(self):
152 CASES = [
153 (['a', '', 'b', '', '', 'c', 'd'], 'a__b---c_d', True),
154
155 # Backslash escape
156 (['a_-b'], r'a\_\-b', True),
157 (['a\\', '\\', 'b'], r'a\_\-b', False),
158 ]
159
160 # IFS='_ '
161 sp = split.IfsSplitter('', '_-')
162 _RunSplitCases(self, sp, CASES)
163
164
165class SplitContextTest(unittest.TestCase):
166
167 def testSplitForWordEval(self):
168 arena = test_lib.MakeArena('<SplitContextTest>')
169 mem = state.Mem('', [], arena, [], {})
170 # This is the default
171 #state.SetGlobalString(mem, 'IFS', split.DEFAULT_IFS)
172
173 splitter = split.SplitContext(mem)
174
175 # Can pass allow_escape=False
176 for s in ['', ' foo bar ', '\\']:
177 result = splitter.SplitForWordEval(s)
178 print(result)
179
180
181if __name__ == '__main__':
182 unittest.main()