OILS
/
osh
/
glob_test.py
1 |
#!/usr/bin/env python2
|
2 |
"""
|
3 |
glob_test.py: Tests for glob.py
|
4 |
"""
|
5 |
from __future__ import print_function
|
6 |
|
7 |
import re
|
8 |
import unittest
|
9 |
|
10 |
from frontend import match
|
11 |
from osh import glob_
|
12 |
|
13 |
|
14 |
class GlobEscapeTest(unittest.TestCase):
|
15 |
def testEscapeUnescape(self):
|
16 |
esc = glob_.GlobEscape
|
17 |
unesc = glob_.GlobUnescape
|
18 |
|
19 |
pairs = [
|
20 |
(r'\*.py', '*.py'),
|
21 |
(r'\?.py', '?.py'),
|
22 |
(r'\[a\-z\]\[\[\:punct\:\]\]', '[a-z][[:punct:]]'),
|
23 |
(r'\\n', r'\n'),
|
24 |
]
|
25 |
for e, u in pairs:
|
26 |
self.assertEqual(e, esc(u))
|
27 |
self.assertEqual(u, unesc(e))
|
28 |
|
29 |
def testLooksLikeGlob(self):
|
30 |
# The way to test bash behavior is:
|
31 |
# $ shopt -s nullglob; argv [ # not a glob
|
32 |
# $ shopt -s nullglob; argv [] # is a glob
|
33 |
# $ shopt -s nullglob; argv [][ # is a glob
|
34 |
CASES = [
|
35 |
(r'[]', True),
|
36 |
(r'[a]', True),
|
37 |
(r'[][', True),
|
38 |
(r'][', False), # no balanced pair
|
39 |
(r'\[]', False), # no balanced pair
|
40 |
(r'[', False), # no balanced pair
|
41 |
(r']', False), # no balanced pair
|
42 |
(r'echo', False),
|
43 |
(r'status=0', False),
|
44 |
(r'*', True),
|
45 |
(r'\*', False),
|
46 |
(r'\*.sh', False),
|
47 |
('\\', False),
|
48 |
('*\\', True),
|
49 |
('?', True),
|
50 |
]
|
51 |
for pat, expected in CASES:
|
52 |
self.assertEqual(expected, glob_.LooksLikeGlob(pat),
|
53 |
'%s: expected %r' % (pat, expected))
|
54 |
|
55 |
def testGlobStripRegexes(self):
|
56 |
s = 'aabbccdd'
|
57 |
|
58 |
# ${v%c*} # shortest suffix
|
59 |
m = re.match('^(.*)c.*$', s)
|
60 |
self.assertEqual('aabbc', m.group(1))
|
61 |
|
62 |
# ${v%%c*} # longest suffix
|
63 |
m = re.match('^(.*?)c.*$', s)
|
64 |
self.assertEqual('aabb', m.group(1))
|
65 |
|
66 |
# ${v#*b} # shortest prefix
|
67 |
m = re.match('^.*?b(.*)$', s)
|
68 |
self.assertEqual('bccdd', m.group(1))
|
69 |
|
70 |
# ${v##*b} # longest prefix
|
71 |
m = re.match('^.*b(.*)$', s)
|
72 |
self.assertEqual('ccdd', m.group(1))
|
73 |
|
74 |
def testPatSubRegexes(self):
|
75 |
# x=~/git/oil
|
76 |
# ${x//git*/X/}
|
77 |
|
78 |
# git*
|
79 |
r1 = re.compile('git.*')
|
80 |
result = r1.sub('X', '~/git/oil')
|
81 |
self.assertEqual('~/X', result)
|
82 |
|
83 |
r2 = re.compile('[a-z]')
|
84 |
result = r2.sub('X', 'a-b-c')
|
85 |
self.assertEqual('X-X-X', result)
|
86 |
|
87 |
# Substitute the first one only
|
88 |
r2 = re.compile('[a-z]')
|
89 |
result = r2.sub('X', 'a-b-c', count=1)
|
90 |
self.assertEqual('X-b-c', result)
|
91 |
|
92 |
|
93 |
def _ReadTokens(s):
|
94 |
lex = match.GlobLexer(s)
|
95 |
return list(lex.Tokens())
|
96 |
|
97 |
|
98 |
class GlobParserTest(unittest.TestCase):
|
99 |
def testGlobLexer(self):
|
100 |
print(_ReadTokens(''))
|
101 |
print(_ReadTokens('*.py'))
|
102 |
print(_ReadTokens(r'\*.py'))
|
103 |
print(_ReadTokens('[abc]'))
|
104 |
print(_ReadTokens('\\')) # Enf
|
105 |
print(_ReadTokens('\\x'))
|
106 |
print(_ReadTokens(r'\\'))
|
107 |
print(_ReadTokens(r'[[:alpha:]]'))
|
108 |
print(_ReadTokens(r'[?]'))
|
109 |
|
110 |
def testGlobParser(self):
|
111 |
CASES = [
|
112 |
# (glob input, expected AST, expected extended regexp, has error)
|
113 |
('*.py', r'.*\.py', False),
|
114 |
('*.?', r'.*\..', False),
|
115 |
('<*>', r'<.*>', False),
|
116 |
('\**+', r'\*.*\+', False),
|
117 |
('\**', r'\*.*', False),
|
118 |
('*.[ch]pp', r'.*\.[ch]pp', False),
|
119 |
|
120 |
# not globs
|
121 |
('abc', 'abc', False),
|
122 |
('\\*', '\\*', False),
|
123 |
('c:\\foo', 'c:foo', False),
|
124 |
('strange]one', 'strange\\]one', False),
|
125 |
|
126 |
# character class globs
|
127 |
('[[:space:]abc]', '[[:space:]abc]', False),
|
128 |
('[abc]', '[abc]', False),
|
129 |
(r'[\a\b\c]', r'[\a\b\c]', False),
|
130 |
('[abc\[]', r'[abc\[]', False),
|
131 |
('[!not]', '[^not]', False),
|
132 |
('[^also_not]', '[^also_not]', False),
|
133 |
('[!*?!\\[]', '[^*?!\\[]', False),
|
134 |
('[!\]foo]', r'[^]foo]', False),
|
135 |
|
136 |
# invalid globs
|
137 |
('not_closed[a-z', 'not_closed\\[a-z', True),
|
138 |
('[[:spa[ce:]]', '\\[\\[:spa\\[ce:\\]\\]', True),
|
139 |
|
140 |
# Regression test for IndexError.
|
141 |
('[', '\\[', True),
|
142 |
('\\', '\\\\', True),
|
143 |
(']', '\\]', False),
|
144 |
]
|
145 |
for glob, expected_ere, expected_err in CASES:
|
146 |
print('===')
|
147 |
print(glob)
|
148 |
regex, warnings = glob_.GlobToERE(glob)
|
149 |
self.assertEqual(
|
150 |
expected_ere, regex, 'Expected %r to translate to %r, got %r' %
|
151 |
(glob, expected_ere, regex))
|
152 |
|
153 |
print('regex : %s' % regex)
|
154 |
print('warnings: %s' % warnings)
|
155 |
|
156 |
|
157 |
if __name__ == '__main__':
|
158 |
unittest.main()
|