Skip to content

Commit bcb8ef2

Browse files
author
Yuanfang Chen
committed
abtest.py: support bisection based on a response file
Also makes LINK_TEST customizable from commandline with `--test` option.
1 parent f08a2fc commit bcb8ef2

File tree

1 file changed

+53
-11
lines changed

1 file changed

+53
-11
lines changed

llvm/utils/abtest.py

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
# list of files which should be linked together and result tested. "link_test"
88
# should returns with exitcode 0 if the linking and testing succeeded.
99
#
10+
# If a response file is provided, only the object files that are listed in the
11+
# file are inspected. In addition, the "link_test" is called with a temporary
12+
# response file representing one iteration of bisection.
13+
#
1014
# abtest.py operates by taking all files from the "before" directory and
1115
# in each step replacing one of them with a file from the "bad" directory.
1216
#
@@ -41,9 +45,10 @@
4145
import os
4246
import subprocess
4347
import sys
48+
import tempfile
4449

45-
46-
LINKTEST = "./link_test"
50+
# Specify LINKTEST via `--test`. Default value is './link_test'.
51+
LINKTEST = ""
4752
ESCAPE = "\033[%sm"
4853
BOLD = ESCAPE % "1"
4954
RED = ESCAPE % "31"
@@ -234,22 +239,42 @@ def testrun(files):
234239
return True
235240

236241

237-
def prepare_files(gooddir, baddir):
238-
files_a = find(gooddir, "*")
239-
files_b = find(baddir, "*")
242+
def prepare_files(gooddir, baddir, rspfile):
243+
files_a = []
244+
files_b = []
245+
246+
if rspfile is not None:
247+
def get_basename(name):
248+
# remove prefix
249+
if name.startswith(gooddir):
250+
return name[len(gooddir):]
251+
if name.startswith(baddir):
252+
return name[len(baddir):]
253+
assert False, ""
254+
255+
with open(rspfile, "r") as rf:
256+
for line in rf.read().splitlines():
257+
for obj in line.split():
258+
assert not os.path.isabs(obj), "TODO: support abs path"
259+
files_a.append(gooddir + "/" + obj)
260+
files_b.append(baddir + "/" + obj)
261+
else:
262+
get_basename = lambda name: os.path.basename(name)
263+
files_a = find(gooddir, "*")
264+
files_b = find(baddir, "*")
240265

241-
basenames_a = set(map(os.path.basename, files_a))
242-
basenames_b = set(map(os.path.basename, files_b))
266+
basenames_a = set(map(get_basename, files_a))
267+
basenames_b = set(map(get_basename, files_b))
243268

244269
for name in files_b:
245-
basename = os.path.basename(name)
270+
basename = get_basename(name)
246271
if basename not in basenames_a:
247272
warn("There is no corresponding file to '%s' in %s" %
248273
(name, gooddir))
249274
choices = []
250275
skipped = []
251276
for name in files_a:
252-
basename = os.path.basename(name)
277+
basename = get_basename(name)
253278
if basename not in basenames_b:
254279
warn("There is no corresponding file to '%s' in %s" %
255280
(name, baddir))
@@ -271,13 +296,25 @@ def perform_test(picks):
271296
# Note that we iterate over files_a so we don't change the order
272297
# (cannot use `picks` as it is a dictionary without order)
273298
for x in files_a:
274-
basename = os.path.basename(x)
299+
basename = get_basename(x)
275300
picked = picks.get(basename)
276301
if picked is None:
277302
assert basename in skipped
278303
files.append(x)
279304
else:
280305
files.append(picked)
306+
307+
# If response file is used, create a temporary response file for the
308+
# picked files.
309+
if rspfile is not None:
310+
with tempfile.NamedTemporaryFile('w', suffix='.rsp',
311+
delete=False) as tf:
312+
tf.write(" ".join(files))
313+
tf.flush()
314+
ret = testrun([tf.name])
315+
os.remove(tf.name)
316+
return ret
317+
281318
return testrun(files)
282319

283320
return perform_test, choices
@@ -332,6 +369,8 @@ def main():
332369
parser = argparse.ArgumentParser()
333370
parser.add_argument('--a', dest='dir_a', default='before')
334371
parser.add_argument('--b', dest='dir_b', default='after')
372+
parser.add_argument('--rsp', default=None)
373+
parser.add_argument('--test', default='./link_test')
335374
parser.add_argument('--insane', help='Skip sanity check',
336375
action='store_true')
337376
parser.add_argument('--seq',
@@ -342,6 +381,9 @@ def main():
342381

343382
gooddir = config.dir_a
344383
baddir = config.dir_b
384+
rspfile = config.rsp
385+
global LINKTEST
386+
LINKTEST = config.test
345387

346388
# Preparation phase: Creates a dictionary mapping names to a list of two
347389
# choices each. The bisection algorithm will pick one choice for each name
@@ -352,7 +394,7 @@ def main():
352394
perform_test, choices = prepare_functions(config.file, gooddir,
353395
goodfile, badfile)
354396
else:
355-
perform_test, choices = prepare_files(gooddir, baddir)
397+
perform_test, choices = prepare_files(gooddir, baddir, rspfile)
356398

357399
info("%d bisection choices" % len(choices))
358400

0 commit comments

Comments
 (0)