OILS / test / sh_spec_test.py View on Github | oilshell.org

184 lines, 121 significant
1#!/usr/bin/env python2
2
3import cStringIO
4import optparse
5import pprint
6import unittest
7
8from test.sh_spec import * # module under test
9from test import sh_spec
10from test import spec_lib
11
12TEST1 = """\
13#### Env binding in readonly/declare disallowed
14FOO=foo readonly v=$(tests/printenv.py FOO)
15echo "v=$v"
16# Shells allow this misleading construct, but the correct behavior is to
17# disallow it at parse time.
18## OK bash/dash/mksh stdout: v=None
19## OK bash/dash/mksh status: 0
20## status: 2
21"""
22
23TEST2 = """\
24#### Multiline test case
25echo one
26echo two
27## status: 1
28## stderr-json: ""
29## STDOUT:
30one
31two
32## OK dash STDOUT:
33dash1
34dash2
35## END
36## OK mksh STDOUT:
37mksh1
38mksh2
39## END
40"""
41
42
43def Slurp(s):
44 t = Tokenizer(cStringIO.StringIO(s))
45 tokens = []
46 while True:
47 tok = t.peek()
48 print(tok)
49 tokens.append(tok)
50 if tok[1] == EOF:
51 break
52 t.next()
53 return tokens
54
55
56class ShSpecTest(unittest.TestCase):
57
58 def setUp(self):
59 self.TOKENS1 = Slurp(TEST1)
60 t = Tokenizer(cStringIO.StringIO(TEST1))
61 self.CASE1 = ParseTestCase(t)
62 assert self.CASE1 is not None
63
64 self.TOKENS2 = Slurp(TEST2)
65 t = Tokenizer(cStringIO.StringIO(TEST2))
66 self.CASE2 = ParseTestCase(t)
67 assert self.CASE2 is not None
68
69 def testTokenizer(self):
70 #pprint.pprint(TOKENS1)
71
72 types = [type_ for line_num, type_, value in self.TOKENS1]
73 self.assertEqual([
74 TEST_CASE_BEGIN, PLAIN_LINE, PLAIN_LINE, KEY_VALUE, KEY_VALUE,
75 KEY_VALUE, EOF
76 ], types)
77
78 #pprint.pprint(TOKENS2)
79 types2 = [type_ for line_num, type_, value in self.TOKENS2]
80 self.assertEqual([
81 TEST_CASE_BEGIN, PLAIN_LINE, PLAIN_LINE, KEY_VALUE, KEY_VALUE,
82 KEY_VALUE_MULTILINE, PLAIN_LINE, PLAIN_LINE, KEY_VALUE_MULTILINE,
83 PLAIN_LINE, PLAIN_LINE, END_MULTILINE, KEY_VALUE_MULTILINE,
84 PLAIN_LINE, PLAIN_LINE, END_MULTILINE, EOF
85 ], types2)
86
87 def testParsed(self):
88 CASE1 = self.CASE1
89 CASE2 = self.CASE2
90
91 print('CASE1')
92 pprint.pprint(CASE1)
93 print()
94
95 expected = {'status': '0', 'stdout': 'v=None\n', 'qualifier': 'OK'}
96 self.assertEqual(expected, CASE1['bash'])
97 self.assertEqual(expected, CASE1['dash'])
98 self.assertEqual(expected, CASE1['mksh'])
99 self.assertEqual('2', CASE1['status'])
100 self.assertEqual('Env binding in readonly/declare disallowed',
101 CASE1['desc'])
102
103 print('CASE2')
104 pprint.pprint(CASE2)
105 print()
106 print(CreateAssertions(CASE2, 'bash'))
107 self.assertEqual('one\ntwo\n', CASE2['stdout'])
108 self.assertEqual({
109 'qualifier': 'OK',
110 'stdout': 'dash1\ndash2\n'
111 }, CASE2['dash'])
112 self.assertEqual({
113 'qualifier': 'OK',
114 'stdout': 'mksh1\nmksh2\n'
115 }, CASE2['mksh'])
116
117 def testCreateAssertions(self):
118 print(CreateAssertions(self.CASE1, 'bash'))
119
120 def testRunCases(self):
121 this_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
122 repo_root = os.path.dirname(this_dir)
123
124 o = optparse.OptionParser()
125 spec_lib.DefineCommon(o)
126 spec_lib.DefineShSpec(o)
127 opts, _ = o.parse_args(['--tmp-env', os.path.join(repo_root, '_tmp')])
128
129 shells = [('bash', '/bin/bash'),
130 ('osh', os.path.join(repo_root, 'bin/osh'))]
131 env = {}
132 if 0:
133 out_f = sys.stdout
134 else:
135 out_f = cStringIO.StringIO()
136 out = AnsiOutput(out_f, False)
137 RunCases([self.CASE1], lambda i, case: True, shells, env, out, opts)
138 print(repr(out.f.getvalue()))
139
140 def testMakeShellPairs(self):
141 pairs = spec_lib.MakeShellPairs(['bin/osh', '_bin/osh'])
142 print(pairs)
143 self.assertEqual([('osh', 'bin/osh'), ('osh_ALT', '_bin/osh')], pairs)
144
145 pairs = spec_lib.MakeShellPairs(['bin/osh', '_bin/cxx-dbg/osh'])
146 print(pairs)
147 self.assertEqual([('osh', 'bin/osh'), ('osh-cpp', '_bin/cxx-dbg/osh')],
148 pairs)
149
150 pairs = spec_lib.MakeShellPairs(['bin/osh', '_bin/cxx-dbg-sh/osh'])
151 print(pairs)
152 self.assertEqual([('osh', 'bin/osh'),
153 ('osh-cpp', '_bin/cxx-dbg-sh/osh')], pairs)
154
155
156class FunctionsTest(unittest.TestCase):
157
158 def testSuccessOrFailure(self):
159 stats = sh_spec.Stats(3, ['bash', 'dash'])
160
161 stats.Set('num_failed', 0)
162 stats.Set('oils_num_failed', 0)
163 stats.Set('oils_failures_allowed', 0)
164 # zero allowed
165 status = sh_spec._SuccessOrFailure('foo', stats)
166 self.assertEqual(0, status)
167
168 stats.Set('oils_failures_allowed', 1)
169 status = sh_spec._SuccessOrFailure('foo', stats)
170 self.assertEqual(1, status)
171
172 stats.Set('num_failed', 1)
173 stats.Set('oils_num_failed', 1)
174 stats.Set('oils_failures_allowed', 0)
175 status = sh_spec._SuccessOrFailure('foo', stats)
176 self.assertEqual(1, status)
177
178 stats.Set('oils_failures_allowed', 1)
179 status = sh_spec._SuccessOrFailure('foo', stats)
180 self.assertEqual(0, status)
181
182
183if __name__ == '__main__':
184 unittest.main()