7
7
# list of files which should be linked together and result tested. "link_test"
8
8
# should returns with exitcode 0 if the linking and testing succeeded.
9
9
#
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
+ #
10
14
# abtest.py operates by taking all files from the "before" directory and
11
15
# in each step replacing one of them with a file from the "bad" directory.
12
16
#
41
45
import os
42
46
import subprocess
43
47
import sys
48
+ import tempfile
44
49
45
-
46
- LINKTEST = "./link_test "
50
+ # Specify LINKTEST via `--test`. Default value is './link_test'.
51
+ LINKTEST = ""
47
52
ESCAPE = "\033 [%sm"
48
53
BOLD = ESCAPE % "1"
49
54
RED = ESCAPE % "31"
@@ -234,22 +239,42 @@ def testrun(files):
234
239
return True
235
240
236
241
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 , "*" )
240
265
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 ))
243
268
244
269
for name in files_b :
245
- basename = os . path . basename (name )
270
+ basename = get_basename (name )
246
271
if basename not in basenames_a :
247
272
warn ("There is no corresponding file to '%s' in %s" %
248
273
(name , gooddir ))
249
274
choices = []
250
275
skipped = []
251
276
for name in files_a :
252
- basename = os . path . basename (name )
277
+ basename = get_basename (name )
253
278
if basename not in basenames_b :
254
279
warn ("There is no corresponding file to '%s' in %s" %
255
280
(name , baddir ))
@@ -271,13 +296,25 @@ def perform_test(picks):
271
296
# Note that we iterate over files_a so we don't change the order
272
297
# (cannot use `picks` as it is a dictionary without order)
273
298
for x in files_a :
274
- basename = os . path . basename (x )
299
+ basename = get_basename (x )
275
300
picked = picks .get (basename )
276
301
if picked is None :
277
302
assert basename in skipped
278
303
files .append (x )
279
304
else :
280
305
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
+
281
318
return testrun (files )
282
319
283
320
return perform_test , choices
@@ -332,6 +369,8 @@ def main():
332
369
parser = argparse .ArgumentParser ()
333
370
parser .add_argument ('--a' , dest = 'dir_a' , default = 'before' )
334
371
parser .add_argument ('--b' , dest = 'dir_b' , default = 'after' )
372
+ parser .add_argument ('--rsp' , default = None )
373
+ parser .add_argument ('--test' , default = './link_test' )
335
374
parser .add_argument ('--insane' , help = 'Skip sanity check' ,
336
375
action = 'store_true' )
337
376
parser .add_argument ('--seq' ,
@@ -342,6 +381,9 @@ def main():
342
381
343
382
gooddir = config .dir_a
344
383
baddir = config .dir_b
384
+ rspfile = config .rsp
385
+ global LINKTEST
386
+ LINKTEST = config .test
345
387
346
388
# Preparation phase: Creates a dictionary mapping names to a list of two
347
389
# choices each. The bisection algorithm will pick one choice for each name
@@ -352,7 +394,7 @@ def main():
352
394
perform_test , choices = prepare_functions (config .file , gooddir ,
353
395
goodfile , badfile )
354
396
else :
355
- perform_test , choices = prepare_files (gooddir , baddir )
397
+ perform_test , choices = prepare_files (gooddir , baddir , rspfile )
356
398
357
399
info ("%d bisection choices" % len (choices ))
358
400
0 commit comments