Changes in tests/pybin/tools.py [630c4bb:a83012bf]
- File:
-
- 1 edited
-
tests/pybin/tools.py (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
tests/pybin/tools.py
r630c4bb ra83012bf 23 23 24 24 # helper functions to run terminal commands 25 def sh(*cmd, timeout = False, output_file = None, input_file = None, input_text = None, error = subprocess.STDOUT, ignore_dry_run = False , pass_fds = []):25 def sh(*cmd, timeout = False, output_file = None, input_file = None, input_text = None, error = subprocess.STDOUT, ignore_dry_run = False): 26 26 try: 27 27 cmd = list(cmd) … … 65 65 **({'input' : bytes(input_text, encoding='utf-8')} if input_text else {'stdin' : input_file}), 66 66 stdout = output_file, 67 stderr = error, 68 pass_fds = pass_fds 67 stderr = error 69 68 ) as proc: 70 69 71 70 try: 72 out, errout= proc.communicate(71 out, _ = proc.communicate( 73 72 timeout = settings.timeout.single if timeout else None 74 73 ) 75 74 76 return proc.returncode, out.decode("latin-1") if out else None , errout.decode("latin-1") if errout else None75 return proc.returncode, out.decode("latin-1") if out else None 77 76 except subprocess.TimeoutExpired: 78 77 if settings.timeout2gdb: 79 78 print("Process {} timeout".format(proc.pid)) 80 79 proc.communicate() 81 return 124, str(None) , "Subprocess Timeout 2 gdb"80 return 124, str(None) 82 81 else: 83 82 proc.send_signal(signal.SIGABRT) 84 83 proc.communicate() 85 return 124, str(None) , "Subprocess Timeout 2 gdb"84 return 124, str(None) 86 85 87 86 except Exception as ex: … … 106 105 return (False, "No file") 107 106 108 code, out , err= sh("file", fname, output_file=subprocess.PIPE)107 code, out = sh("file", fname, output_file=subprocess.PIPE) 109 108 if code != 0: 110 return (False, "'file EXPECT' failed with code {} '{}'".format(code, err))109 return (False, "'file EXPECT' failed with code {}".format(code)) 111 110 112 111 match = re.search(".*: (.*)", out) … … 191 190 ] 192 191 cmd = [s for s in cmd if s] 193 return sh(*cmd, output_file=output_file, error=error , pass_fds=settings.make_jobfds)192 return sh(*cmd, output_file=output_file, error=error) 194 193 195 194 def make_recon(target): … … 242 241 # move a file 243 242 def mv(source, dest): 244 ret, _ , _= sh("mv", source, dest)243 ret, _ = sh("mv", source, dest) 245 244 return ret 246 245 247 246 # cat one file into the other 248 247 def cat(source, dest): 249 ret, _ , _= sh("cat", source, output_file=dest)248 ret, _ = sh("cat", source, output_file=dest) 250 249 return ret 251 250 … … 290 289 # system 291 290 ################################################################################ 292 def jobserver_version(): 293 make_ret, out, err = sh('make', '.test_makeflags', '-j2', output_file=subprocess.PIPE, error=subprocess.PIPE) 294 if make_ret != 0: 295 print("ERROR: cannot find Makefile jobserver version", file=sys.stderr) 296 print(" test returned : {} '{}'".format(make_ret, err), file=sys.stderr) 291 # count number of jobs to create 292 def job_count( options, tests ): 293 # check if the user already passed in a number of jobs for multi-threading 294 if not options.jobs: 295 make_flags = os.environ.get('MAKEFLAGS') 296 force = bool(make_flags) 297 make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None 298 if make_jobs_fds : 299 tokens = os.read(int(make_jobs_fds.group(2)), 1024) 300 options.jobs = len(tokens) 301 os.write(int(make_jobs_fds.group(3)), tokens) 302 else : 303 if settings.distribute: 304 ret, jstr = sh("distcc", "-j", output_file=subprocess.PIPE, ignore_dry_run=True) 305 if ret == 0: 306 options.jobs = int(jstr.strip()) 307 else : 308 options.jobs = multiprocessing.cpu_count() 309 else: 310 options.jobs = multiprocessing.cpu_count() 311 else : 312 force = True 313 314 # make sure we have a valid number of jobs that corresponds to user input 315 if options.jobs <= 0 : 316 print('ERROR: Invalid number of jobs', file=sys.stderr) 297 317 sys.exit(1) 298 318 299 re_jobs = re.search("--jobserver-(auth|fds)", out) 300 if not re_jobs: 301 print("ERROR: cannot find Makefile jobserver version", file=sys.stderr) 302 print(" MAKEFLAGS are : '{}'".format(out), file=sys.stderr) 303 sys.exit(1) 304 305 return "--jobserver-{}".format(re_jobs.group(1)) 306 307 def prep_recursive_make(N): 308 if N < 2: 309 return [] 310 311 # create the pipe 312 (r, w) = os.pipe() 313 314 # feel it with N-1 tokens, (Why N-1 and not N, I don't know it's in the manpage for make) 315 os.write(w, b'+' * (N - 1)); 316 317 # prep the flags for make 318 make_flags = ["-j{}".format(N), "--jobserver-auth={},{}".format(r, w)] 319 320 # tell make about the pipes 321 os.environ["MAKEFLAGS"] = os.environ["MFLAGS"] = " ".join(make_flags) 322 323 # make sure pass the pipes to our children 324 settings.update_make_fds(r, w) 325 326 return make_flags 327 328 def prep_unlimited_recursive_make(): 329 # prep the flags for make 330 make_flags = ["-j"] 331 332 # tell make about the pipes 333 os.environ["MAKEFLAGS"] = os.environ["MFLAGS"] = "-j" 334 335 return make_flags 336 337 338 def eval_hardware(): 339 # we can create as many things as we want 340 # how much hardware do we have? 341 if settings.distribute: 342 # remote hardware is allowed 343 # how much do we have? 344 ret, jstr, _ = sh("distcc", "-j", output_file=subprocess.PIPE, ignore_dry_run=True) 345 return int(jstr.strip()) if ret == 0 else multiprocessing.cpu_count() 346 else: 347 # remote isn't allowed, use local cpus 348 return multiprocessing.cpu_count() 349 350 # count number of jobs to create 351 def job_count( options ): 352 # check if the user already passed in a number of jobs for multi-threading 353 make_env = os.environ.get('MAKEFLAGS') 354 make_flags = make_env.split() if make_env else None 355 jobstr = jobserver_version() 356 357 if options.jobs and make_flags: 358 print('WARNING: -j options should not be specified when called form Make', file=sys.stderr) 359 360 # Top level make is calling the shots, just follow 361 if make_flags: 362 # do we have -j and --jobserver-... 363 jobopt = None 364 exists_fds = None 365 for f in make_flags: 366 jobopt = f if f.startswith("-j") else jobopt 367 exists_fds = f if f.startswith(jobstr) else exists_fds 368 369 # do we have limited parallelism? 370 if exists_fds : 371 try: 372 rfd, wfd = tuple(exists_fds.split('=')[1].split(',')) 373 except: 374 print("ERROR: jobserver has unrecoginzable format, was '{}'".format(exists_fds), file=sys.stderr) 375 sys.exit(1) 376 377 # read the token pipe to count number of available tokens and restore the pipe 378 # this assumes the test suite script isn't invoked in parellel with something else 379 tokens = os.read(int(rfd), 65536) 380 os.write(int(wfd), tokens) 381 382 # the number of tokens is off by one for obscure but well documented reason 383 # see man make for more details 384 options.jobs = len(tokens) + 1 385 386 # do we have unlimited parallelism? 387 elif jobopt and jobopt != "-j1": 388 # check that this actually make sense 389 if jobopt != "-j": 390 print("ERROR: -j option passed by make but no {}, was '{}'".format(jobstr, jobopt), file=sys.stderr) 391 sys.exit(1) 392 393 options.jobs = eval_hardware() 394 flags = prep_unlimited_recursive_make() 395 396 397 # then no parallelism 398 else: 399 options.jobs = 1 400 401 # keep all flags make passed along, except the weird 'w' which is about subdirectories 402 flags = [f for f in make_flags if f != 'w'] 403 404 # Arguments are calling the shots, fake the top level make 405 elif options.jobs : 406 407 # make sure we have a valid number of jobs that corresponds to user input 408 if options.jobs < 0 : 409 print('ERROR: Invalid number of jobs', file=sys.stderr) 410 sys.exit(1) 411 412 flags = prep_recursive_make(options.jobs) 413 414 # Arguments are calling the shots, fake the top level make, but 0 is a special case 415 elif options.jobs == 0: 416 options.jobs = eval_hardware() 417 flags = prep_unlimited_recursive_make() 418 419 # No one says to run in parallel, then don't 420 else : 421 options.jobs = 1 422 flags = [] 423 424 # Make sure we call make as expected 425 settings.update_make_cmd( flags ) 426 427 # return the job count 428 return options.jobs 319 return min( options.jobs, len(tests) ), force 429 320 430 321 # enable core dumps for all the test children … … 443 334 distcc_hash = os.path.join(settings.SRCDIR, '../tools/build/distcc_hash') 444 335 config = "%s-%s" % (settings.arch.target, settings.debug.path) 445 _, out , _= sh(distcc_hash, config, output_file=subprocess.PIPE, ignore_dry_run=True)336 _, out = sh(distcc_hash, config, output_file=subprocess.PIPE, ignore_dry_run=True) 446 337 return out.strip() 447 338 … … 483 374 484 375 if not os.path.isfile(core): 485 return 1, "ERR No core dump , expected '{}' (limit soft: {} hard: {})".format(core,*resource.getrlimit(resource.RLIMIT_CORE))376 return 1, "ERR No core dump (limit soft: {} hard: {})".format(*resource.getrlimit(resource.RLIMIT_CORE)) 486 377 487 378 try: 488 ret, out, err = sh('gdb', '-n', path, core, '-batch', '-x', cmd, output_file=subprocess.PIPE) 489 if ret == 0: 490 return 0, out 491 else: 492 return 1, err 379 return sh('gdb', '-n', path, core, '-batch', '-x', cmd, output_file=subprocess.PIPE) 493 380 except: 494 381 return 1, "ERR Could not read core with gdb"
Note:
See TracChangeset
for help on using the changeset viewer.