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

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