1 | #!/usr/bin/env python2
|
2 | """
|
3 | word_test.py: Tests for word_.py
|
4 | """
|
5 | from __future__ import print_function
|
6 |
|
7 | import unittest
|
8 |
|
9 | from _devbuild.gen.id_kind_asdl import Id
|
10 | from _devbuild.gen.syntax_asdl import word_part_e
|
11 |
|
12 | from core import test_lib
|
13 | from mycpp.mylib import log
|
14 | from osh import cmd_parse # reparse input
|
15 | from osh.cmd_parse_test import assertParseSimpleCommand
|
16 | from osh.word_parse_test import _assertReadWord
|
17 |
|
18 | from osh import word_ # module under test
|
19 |
|
20 |
|
21 | def _DetectAssign(test, word_str, expected):
|
22 | # TODO: This function could be moved to test_lib.
|
23 | log('-' * 80)
|
24 | w = _assertReadWord(test, word_str)
|
25 |
|
26 | actual = word_.DetectShAssignment(w)
|
27 | left_token, close_token, part_offset = actual
|
28 |
|
29 | expected_left, expected_close, expected_part_offset = expected
|
30 |
|
31 | print(left_token, close_token, part_offset)
|
32 | print()
|
33 |
|
34 | if expected_left is None:
|
35 | test.assertEqual(None, left_token)
|
36 | else:
|
37 | test.assertEqual(expected_left, left_token.id)
|
38 |
|
39 | if expected_close is None:
|
40 | test.assertEqual(None, close_token)
|
41 | else:
|
42 | test.assertEqual(expected_left, left_token.id)
|
43 |
|
44 | test.assertEqual(expected_part_offset, part_offset)
|
45 |
|
46 | parse_ctx = test_lib.InitParseContext()
|
47 |
|
48 | if left_token and left_token.id in (Id.Lit_VarLike, Id.Lit_ArrayLhsOpen):
|
49 | more_env = []
|
50 | preparsed = (left_token, close_token, part_offset, w)
|
51 | try:
|
52 | cmd_parse._AppendMoreEnv([preparsed], more_env)
|
53 | except Exception as e:
|
54 | log('Error: %s', e)
|
55 | else:
|
56 | log('more_env: %s', more_env)
|
57 |
|
58 | try:
|
59 | assign_pair = cmd_parse._MakeAssignPair(parse_ctx, preparsed)
|
60 | except Exception as e:
|
61 | log('Error: %s', e)
|
62 | else:
|
63 | log('assign_pair: %s', assign_pair)
|
64 |
|
65 |
|
66 | class WordTest(unittest.TestCase):
|
67 |
|
68 | def testDetectLocation(self):
|
69 | CASES = [
|
70 | ('foobar', (None, None, 0)),
|
71 | ('a[x', (None, None, 0)),
|
72 |
|
73 | # Empty is not valid, there has to be at least one token.
|
74 | ('a[]=$foo$bar', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 2)),
|
75 | ('a[]+=$foo$bar', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 2)),
|
76 | ('s=1', (Id.Lit_VarLike, None, 1)),
|
77 | ('s+=1', (Id.Lit_VarLike, None, 1)),
|
78 | ('a[x]=1', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 3)),
|
79 | ('a[x]+=1', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 3)),
|
80 | ('a[x++]+=1', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 5)),
|
81 | ('a=(1 2 3)', (Id.Lit_VarLike, None, 1)),
|
82 | ('a+=(1 2 3)', (Id.Lit_VarLike, None, 1)),
|
83 |
|
84 | # Empty on RHS
|
85 | ('s=', (Id.Lit_VarLike, None, 1)),
|
86 | ('a[x]=', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 3)),
|
87 |
|
88 | # Tilde sub
|
89 | ('s=~foo', (Id.Lit_VarLike, None, 1)),
|
90 | ('a[x]=~', (Id.Lit_ArrayLhsOpen, Id.Lit_ArrayLhsClose, 3)),
|
91 | ]
|
92 | for word_str, expected in CASES:
|
93 | _DetectAssign(self, word_str, expected)
|
94 |
|
95 | # These don't parse, as they shouldn't. But not the best error message.
|
96 | #w = assertReadWord(self, 'a[x]=(1 2 3)')
|
97 | #w = assertReadWord(self, 'a[x]+=(1 2 3)')
|
98 |
|
99 | TILDE_WORDS = [
|
100 | # These are tilde subs
|
101 | (True, '~'),
|
102 | (True, '~/'),
|
103 | (True, '~/zz'),
|
104 | (True, '~andy'),
|
105 | (True, '~andy/'),
|
106 | (True, '~andy/zz'),
|
107 |
|
108 | # These are not
|
109 | (False, '~bob#'),
|
110 | (False, '~bob#/'),
|
111 | (False, '~bob#/zz'),
|
112 | (False, ''),
|
113 | (False, 'foo'),
|
114 | ]
|
115 |
|
116 | def testTildeDetect(self):
|
117 | for expected, word_str in self.TILDE_WORDS:
|
118 | w = _assertReadWord(self, word_str)
|
119 | detected = word_.TildeDetect(w)
|
120 | print(detected)
|
121 |
|
122 | if detected:
|
123 | self.assertEqual(word_part_e.TildeSub, detected.parts[0].tag())
|
124 | self.assertEqual(True, expected)
|
125 | else:
|
126 | self.assertEqual(False, expected)
|
127 |
|
128 | def testTildeDetectAssignColons(self):
|
129 | # x=~a:~b: etc.
|
130 |
|
131 | words = [w for _, w in self.TILDE_WORDS]
|
132 | assign_str = ':'.join(words)
|
133 | w = _assertReadWord(self, assign_str)
|
134 | word_.TildeDetectAssign(w)
|
135 |
|
136 | print('DETECTED')
|
137 | print(w)
|
138 |
|
139 | actual = 0
|
140 | for part in w.parts:
|
141 | if part.tag() == word_part_e.TildeSub:
|
142 | actual += 1
|
143 |
|
144 | log('tilde sub parts = %d', actual)
|
145 |
|
146 | expected = sum(expected for expected, _ in self.TILDE_WORDS)
|
147 | self.assertEqual(expected, actual)
|
148 |
|
149 | print('')
|
150 |
|
151 | def testFastStrEval(self):
|
152 | node = assertParseSimpleCommand(self, "ls 'my dir' $x foo/$bar ")
|
153 |
|
154 | self.assertEqual(4, len(node.words))
|
155 |
|
156 | ls_w = node.words[0]
|
157 | w1 = node.words[1]
|
158 | w2 = node.words[2]
|
159 | w3 = node.words[3]
|
160 |
|
161 | self.assertEqual('ls', word_.FastStrEval(ls_w))
|
162 | self.assertEqual('my dir', word_.FastStrEval(w1))
|
163 | self.assertEqual(None, word_.FastStrEval(w2))
|
164 | self.assertEqual(None, word_.FastStrEval(w3))
|
165 |
|
166 | # Special case for [ ]
|
167 | node = assertParseSimpleCommand(self, '[ a -lt b ]')
|
168 | self.assertEqual('[', word_.FastStrEval(node.words[0]))
|
169 | self.assertEqual('a', word_.FastStrEval(node.words[1]))
|
170 | self.assertEqual('-lt', word_.FastStrEval(node.words[2]))
|
171 | self.assertEqual('b', word_.FastStrEval(node.words[3]))
|
172 | self.assertEqual(']', word_.FastStrEval(node.words[4]))
|
173 |
|
174 |
|
175 | if __name__ == '__main__':
|
176 | unittest.main()
|