]> git.proxmox.com Git - rustc.git/blob - src/binaryen/scripts/test/support.py
New upstream version 1.23.0+dfsg1
[rustc.git] / src / binaryen / scripts / test / support.py
1 #! /usr/bin/env python
2
3 # Copyright 2016 WebAssembly Community Group participants
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import filecmp
18 import os
19 import shutil
20 import subprocess
21 import sys
22 import tempfile
23
24
25 def _open_archive(tarfile, tmp_dir):
26 with tempfile.TemporaryFile(mode='w+') as f:
27 try:
28 subprocess.check_call(['tar', '-xvf', tarfile], cwd=tmp_dir, stdout=f)
29 except Exception:
30 f.seek(0)
31 sys.stderr.write(f.read())
32 raise
33 return os.listdir(tmp_dir)
34
35
36 def _files_same(dir1, dir2, basenames):
37 diff = filecmp.cmpfiles(dir1, dir2, basenames)
38 return 0 == len(diff[1] + diff[2])
39
40
41 def _dirs_same(dir1, dir2, basenames):
42 for d in basenames:
43 left = os.path.join(dir1, d)
44 right = os.path.join(dir2, d)
45 if not (os.path.isdir(left) and os.path.isdir(right)):
46 return False
47 diff = filecmp.dircmp(right, right)
48 if 0 != len(diff.left_only + diff.right_only + diff.diff_files +
49 diff.common_funny + diff.funny_files):
50 return False
51 return True
52
53
54 def _move_files(dirfrom, dirto, basenames):
55 for f in basenames:
56 from_file = os.path.join(dirfrom, f)
57 to_file = os.path.join(dirto, f)
58 if os.path.isfile(to_file):
59 os.path.remove(to_file)
60 shutil.move(from_file, to_file)
61
62
63 def _move_dirs(dirfrom, dirto, basenames):
64 for d in basenames:
65 from_dir = os.path.join(dirfrom, d)
66 to_dir = os.path.join(dirto, d)
67 if os.path.isdir(to_dir):
68 shutil.rmtree(to_dir)
69 shutil.move(from_dir, to_dir)
70
71
72 def untar(tarfile, outdir):
73 """Returns True if untar content differs from pre-existing outdir content."""
74 tmpdir = tempfile.mkdtemp()
75 try:
76 untared = _open_archive(tarfile, tmpdir)
77 files = [f for f in untared if os.path.isfile(os.path.join(tmpdir, f))]
78 dirs = [d for d in untared if os.path.isdir(os.path.join(tmpdir, d))]
79 assert len(files) + len(dirs) == len(untared), 'Only files and directories'
80 if _files_same(tmpdir, outdir, files) and _dirs_same(tmpdir, outdir, dirs):
81 # Nothing new or different in the tarfile.
82 return False
83 # Some or all of the files / directories are new.
84 _move_files(tmpdir, outdir, files)
85 _move_dirs(tmpdir, outdir, dirs)
86 return True
87 finally:
88 if os.path.isdir(tmpdir):
89 shutil.rmtree(tmpdir)
90
91
92 def split_wast(wast):
93 # .wast files can contain multiple modules, and assertions for each one.
94 # this splits out a wast into [(module, assertions), ..]
95 # we ignore module invalidity tests here.
96 wast = open(wast).read()
97
98 # if it's a binary, leave it as is
99 if wast[0] == '\0':
100 return [[wast, '']]
101
102 ret = []
103
104 def to_end(j):
105 depth = 1
106 while depth > 0 and j < len(wast):
107 if wast[j] == '"':
108 while 1:
109 j = wast.find('"', j + 1)
110 if wast[j - 1] == '\\':
111 continue
112 break
113 assert j > 0
114 elif wast[j] == '(':
115 depth += 1
116 elif wast[j] == ')':
117 depth -= 1
118 elif wast[j] == ';' and wast[j + 1] == ';':
119 j = wast.find('\n', j)
120 j += 1
121 return j
122
123 i = 0
124 while i >= 0:
125 start = wast.find('(', i)
126 if start >= 0 and wast[start + 1] == ';':
127 # block comment
128 i = wast.find(';)', start + 2)
129 assert i > 0, wast[start:]
130 i += 2
131 continue
132 skip = wast.find(';', i)
133 if skip >= 0 and skip < start and skip + 1 < len(wast):
134 if wast[skip + 1] == ';':
135 i = wast.find('\n', i) + 1
136 continue
137 if start < 0:
138 break
139 i = to_end(start + 1)
140 chunk = wast[start:i]
141 if chunk.startswith('(module'):
142 ret += [(chunk, [])]
143 elif chunk.startswith('(assert_invalid'):
144 continue
145 elif chunk.startswith(('(assert', '(invoke')):
146 ret[-1][1].append(chunk)
147 return ret
148
149
150 def run_command(cmd, expected_status=0, stderr=None,
151 expected_err=None, err_contains=False):
152 if expected_err is not None:
153 assert stderr == subprocess.PIPE or stderr is None,\
154 "Can't redirect stderr if using expected_err"
155 stderr = subprocess.PIPE
156 print 'executing: ', ' '.join(cmd)
157 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr)
158 out, err = proc.communicate()
159 code = proc.returncode
160 if code != expected_status:
161 raise Exception(('run_command failed (%s)' % code, out + str(err or '')))
162 err_correct = expected_err is None or \
163 (expected_err in err if err_contains else expected_err == err)
164 if not err_correct:
165 raise Exception(('run_command unexpected stderr',
166 "expected '%s', actual '%s'" % (expected_err, err)))
167 return out