Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • tests/pybin/tools.py

    r630c4bb ra83012bf  
    2323
    2424# 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 = []):
     25def sh(*cmd, timeout = False, output_file = None, input_file = None, input_text = None, error = subprocess.STDOUT, ignore_dry_run = False):
    2626        try:
    2727                cmd = list(cmd)
     
    6565                                **({'input' : bytes(input_text, encoding='utf-8')} if input_text else {'stdin' : input_file}),
    6666                                stdout  = output_file,
    67                                 stderr  = error,
    68                                 pass_fds = pass_fds
     67                                stderr  = error
    6968                        ) as proc:
    7069
    7170                                try:
    72                                         out, errout = proc.communicate(
     71                                        out, _ = proc.communicate(
    7372                                                timeout = settings.timeout.single if timeout else None
    7473                                        )
    7574
    76                                         return proc.returncode, out.decode("latin-1") if out else None, errout.decode("latin-1") if errout else None
     75                                        return proc.returncode, out.decode("latin-1") if out else None
    7776                                except subprocess.TimeoutExpired:
    7877                                        if settings.timeout2gdb:
    7978                                                print("Process {} timeout".format(proc.pid))
    8079                                                proc.communicate()
    81                                                 return 124, str(None), "Subprocess Timeout 2 gdb"
     80                                                return 124, str(None)
    8281                                        else:
    8382                                                proc.send_signal(signal.SIGABRT)
    8483                                                proc.communicate()
    85                                                 return 124, str(None), "Subprocess Timeout 2 gdb"
     84                                                return 124, str(None)
    8685
    8786        except Exception as ex:
     
    106105                return (False, "No file")
    107106
    108         code, out, err = sh("file", fname, output_file=subprocess.PIPE)
     107        code, out = sh("file", fname, output_file=subprocess.PIPE)
    109108        if code != 0:
    110                 return (False, "'file EXPECT' failed with code {} '{}'".format(code, err))
     109                return (False, "'file EXPECT' failed with code {}".format(code))
    111110
    112111        match = re.search(".*: (.*)", out)
     
    191190        ]
    192191        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)
    194193
    195194def make_recon(target):
     
    242241# move a file
    243242def mv(source, dest):
    244         ret, _, _ = sh("mv", source, dest)
     243        ret, _ = sh("mv", source, dest)
    245244        return ret
    246245
    247246# cat one file into the other
    248247def cat(source, dest):
    249         ret, _, _ = sh("cat", source, output_file=dest)
     248        ret, _ = sh("cat", source, output_file=dest)
    250249        return ret
    251250
     
    290289#               system
    291290################################################################################
    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
     292def 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)
    297317                sys.exit(1)
    298318
    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
    429320
    430321# enable core dumps for all the test children
     
    443334        distcc_hash = os.path.join(settings.SRCDIR, '../tools/build/distcc_hash')
    444335        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)
    446337        return out.strip()
    447338
     
    483374
    484375        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))
    486377
    487378        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)
    493380        except:
    494381                return 1, "ERR Could not read core with gdb"
Note: See TracChangeset for help on using the changeset viewer.