1 | #!/usr/bin/env python2
|
2 | """
|
3 | split.test.py: Tests for split.py
|
4 | """
|
5 |
|
6 | import unittest
|
7 |
|
8 | from core import state
|
9 | from core import test_lib
|
10 | from osh import split # module under test
|
11 |
|
12 |
|
13 | def _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 |
|
31 | class 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 |
|
165 | class 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 |
|
181 | if __name__ == '__main__':
|
182 | unittest.main()
|