1 #!/usr/bin/env bash
2 #
3 # Usage:
4 # ./TEST.sh <function name>
5 #
6 # These are mostly run from this dir.
7
8 set -o nounset
9 set -o pipefail
10 set -o errexit
11
12 readonly THIS_DIR=$(cd $(dirname $0) && pwd)
13
14 source $THIS_DIR/common.sh
15
16 # We have to invoke opyc like this because byterun uses __import__, which
17 # respects PYTHONPATH. If we use ../bin/opyc, it will use the CPython-compiled
18 # bytecode in the repo, rather than the OPy-compiled bytecode in _tmp/oil-opy.
19 opyc() {
20 python bin/opy_.pyc opyc "$@"
21 }
22
23 oil-opy() {
24 _tmp/oil-opy/bin/oil "$@"
25 }
26
27 # TODO:
28 # - Run with oil.ovm{,-dbg}
29
30 # 3/2018 byterun results:
31 #
32 # Ran 28 tests, 4 failures
33 # asdl/arith_parse_test.pyc core/glob_test.pyc core/lexer_gen_test.pyc osh/lex_test.pyc
34 #
35
36 oil-unit() {
37 local dir=${1:-_tmp/repo-with-opy}
38 local vm=${2:-cpython} # byterun or cpython
39
40 pushd $dir
41
42 #$OPYC run core/cmd_exec_test.pyc
43
44 local n=0
45 local -a failures=()
46
47 # TODO: Share with test/unit.sh.
48 #for t in {build,test,native,asdl,core,osh,test,tools}/*_test.py; do
49 for t in {asdl,core,frontend,osh,ysh}/*_test.pyc; do
50
51 echo $t
52 if test $vm = byterun; then
53
54 set +o errexit
55 set +o nounset # for empty array!
56
57 # Note: adding PYTHONPATH screws things up, I guess because it's the HOST
58 # interpreter pythonpath.
59 opyc run $t
60 status=$?
61
62 if test $status -ne 0; then
63 failures=("${failures[@]}" $t)
64 fi
65 (( n++ ))
66
67 elif test $vm = cpython; then
68 PYTHONPATH=. python $t
69 #(( n++ ))
70
71 else
72 die "Invalid VM $vm"
73 fi
74 done
75 popd
76
77 if test $vm = byterun; then
78 echo "Ran $n tests, ${#failures[@]} failures"
79 echo "${failures[@]}"
80 fi
81 }
82
83 oil-unit-byterun() {
84 oil-unit '' byterun
85 }
86
87 readonly -a FAILED=(
88 asdl/demo_asdl_test.pyc
89 )
90
91 oil-byterun-failed() {
92 #set +o errexit
93
94 for t in "${FAILED[@]}"; do
95
96 echo
97 echo ---
98 echo --- $t
99 echo ---
100
101 pushd _tmp/repo-with-opy
102 opyc run $t
103 popd
104 done
105 }
106
107 byterun-unit() {
108 pushd $THIS_DIR/..
109 for t in opy/byterun/test_*.py; do
110 echo
111 echo "*** $t"
112 echo
113 PYTHONPATH=. $t
114 done
115 popd
116 }
117
118
119 # TODO: Fix this!
120 opy-unit() {
121 for t in compiler2/*_test.py; do
122 echo $t
123 $t
124 done
125 }
126
127 # Isolated failures.
128
129 # File "/home/andy/git/oilshell/oil/bin/../opy/byterun/pyvm2.py", line 288, in manage_block_stack
130 # block = self.frame.block_stack[-1]
131 # IndexError: list index out of range
132
133 generator-exception() {
134 testdata/generator_exception.py
135 ../bin/opyc run testdata/generator_exception.py
136 }
137
138 generator-exception-diff() {
139 rm -f -v testdata/generator_exception.pyc
140 testdata/generator_exception.py
141
142 pushd testdata
143 python -c 'import generator_exception'
144 popd
145
146 echo ---
147 ../bin/opyc compile testdata/generator_exception.py _tmp/ge-opy.pyc
148
149 ../bin/opyc dis testdata/generator_exception.pyc > _tmp/ge-cpython.txt
150 ../bin/opyc dis _tmp/ge-opy.pyc > _tmp/ge-opy.txt
151
152 diff -u _tmp/ge-{cpython,opy}.txt
153 }
154
155 # TypeError: unbound method append() must be called with SubPattern instance as
156 # first argument (got tuple instance instead)
157
158 regex-compile() {
159 testdata/regex_compile.py
160 echo ---
161 ../bin/opyc run testdata/regex_compile.py
162 }
163
164 re-dis() {
165 ../bin/opyc dis /usr/lib/python2.7/sre_parse.pyc
166 }
167
168 # Spec tests under byterun.
169 spec() {
170 local action=$1 # e.g. 'smoke' or 'all'
171 shift
172
173 pushd $THIS_DIR/..
174
175 # TODO: Should be OSH_ALT instead of OSH_OVM?
176 # Usually it is dev build vs. release build, but here it is CPython vs.
177 # byterun.
178
179 # HACK to get around __import__ problem with byterun.
180
181 OSH_LIST="bin/osh $OSH_BYTERUN" test/spec.sh $action "$@"
182 popd
183 }
184
185 # The way to tickle the 'import' bug. We need to wrap SOME functions in
186 # pyobj.Function. Otherwise it will run too fast!
187
188 opy-speed-test() {
189 opyc-compile testdata/speed.py _tmp/speed.pyc
190 opyc-compile testdata/speed_main.py _tmp/speed_main.pyc
191
192 cp _tmp/speed.pyc _tmp/speed.opyc
193
194 # For logging
195 local n=10000
196 #local n=10
197
198 # 7 ms
199 echo PYTHON
200 time python _tmp/speed.opyc $n
201
202 # 205 ms. So it's 30x slower. Makes sense.
203 echo OPY
204 time opyc-run _tmp/speed.opyc $n
205
206 #
207 # byterun Import bug regression test!
208 #
209
210 # 7 ms
211 echo PYTHON
212 time python _tmp/speed_main.pyc $n
213
214 # 205 ms. So it's 30x slower. Makes sense.
215 echo OPY
216 time opyc-run _tmp/speed_main.pyc $n
217 }
218
219 # Compare execution.
220 # Although some of these are mostly there for disassembly.
221 gold() {
222 set +o errexit
223
224 mkdir -p _tmp
225
226 for script in gold/*.py; do
227
228 $script > _tmp/gold-cpython.txt 2>&1
229
230 # As a test, disable LOAD_FAST, etc. The output should still be the same.
231 ../bin/opyc run --fast-ops=0 $script > _tmp/gold-opy-byterun.txt 2>&1
232
233 if diff -u _tmp/gold-{cpython,opy-byterun}.txt; then
234 echo "OK $script"
235 else
236 echo "FAIL $script"
237 return 1
238 fi
239 done
240 }
241
242 compile-with-cpython() {
243 local path=${1:-gold/with_statement.py}
244 local pyc=${path}c
245 rm --verbose -f $pyc
246 pushd $(dirname $path)
247 python -c "import $(basename $path .py)"
248 popd
249 ls -l $pyc
250
251 ../bin/opyc dis $pyc
252 }
253
254 # Print something 99 parentheses deep! It causes a MemoryError in the parser,
255 # but 98 doesn't. I noticed MAXSTACK = 1500 in Parser/parser.h.
256 pgen-stack() {
257 python -c '
258 import sys
259 n = int(sys.argv[1])
260 print "(" * n
261 print "42"
262 print ")" * n
263 ' 99 > _tmp/deep.py
264
265 python _tmp/deep.py
266 }
267
268 if test $(basename $0) = 'TEST.sh'; then
269 "$@"
270 fi