Example #1
0
File: tests.py Project: LLNL/ATS
    def getResults(self):
        "Return a dictionary containing the essential information about this test."
        if not hasattr(self, 'timelimit'):
            self.timelimit = None
        if self.depends_on is None:
            ds = 0
        else:
            ds = self.depends_on.serialNumber

        if self.output:
            out = ['Captured output, see log.']
        else:
            out = []

        # various integers are used to reconstruct the test/group relationships
        # See the coding in management.py that prints atsr.py

        result = AttributeDict(
            name=self.name,
            serialNumber=self.serialNumber,
            groupNumber=self.groupNumber,
            groupSerialNumber=self.groupSerialNumber,
            runOrder=self.runOrder,
            status=self.status,
            batch=self.batch,
            expectedResult=self.expectedResult,
            message=self.message,
            startDateTime=self.startDateTime,
            endDateTime=self.endDateTime,
            options=self.options,
            directory=self.directory,
            notes=self.notes,
            output=out,
            independent=self.independent,
            block=self.block,
            timelimit=self.timelimit,
            commandList=self.commandList,
            commandLine=self.commandLine,
            elapsedTime=self.elapsedTime(),
            executable=str(self.executable),
            priority=self.priority,
            totalPriority=self.totalPriority,
            depends_on_serial=ds,
            dependents_serial=[d.serialNumber for d in self.dependents],
            waitUntil_serial=[t.serialNumber for t in self.waitUntil])
        return result
Example #2
0
File: machines.py Project: LLNL/ATS
    def getResults(self):
        """
A child might replace this to put more information in the results,
but probaby wants to call the parent and then update the
dictionary this method returns.

Return AttributeDict of machine-specific facts for manager postprocessing state.
Include results from the scheduler.
"""
        result = AttributeDict()
        result.update(self.scheduler.getResults())
        result.update(
            dict(name=self.name,
                 numberTestsRunningMax=self.numberTestsRunningMax,
                 hardLimit=self.hardLimit,
                 naptime=self.naptime))
        return result
Example #3
0
 def getResults(self):
     """Results for the atsr file."""
     return AttributeDict(scheduler=self.name)
Example #4
0
File: tests.py Project: LLNL/ATS
class AtsTest(object):
    "One test script to run, and how to run it."
    stuck = {
    }  # test options that pertain to any new instance, file persistant
    glued = {}  # test options that pertain to any new instance, persistant.
    tacked = {}  # test options that pertain to any new instance, and which
    # pertain to instances created before end of current source.
    grouped = {}  # test options that apply within the current group only.
    serialNumber = 0  #counter
    waitUntil = []  # list of tests that must be disposed of first
    waitUntilAccumulatorStack = []
    waitUntilAccumulator = []
    group = None
    groupCounter = 0

    def setName(self, name):
        """Set the name of this test.
           Set namebase to a version without special chars or blanks.
        """
        self.name = name
        self.namebase = re.sub('\W', '_', name)
        #print "DEBUG setName = %s\n" % self.name

    def __init__(self, *fixedargs, **options):
        "Must not throw an exception -- object must always get created."
        super(AtsTest, self).__init__()
        AtsTest.serialNumber += 1
        AtsTest.waitUntilAccumulator.append(self)
        # populate attributes
        self.serialNumber = AtsTest.serialNumber
        if AtsTest.group is None:
            AtsTest.groupCounter += 1
            self.group = AtsTestGroup(AtsTest.groupCounter)
        else:
            self.group = AtsTest.group
        self.group.append(self)
        self.groupNumber = self.group.number
        self.groupSerialNumber = len(self.group)
        self.waitUntil = AtsTest.waitUntil  #never modify this, it may be shared.
        self.runOrder = 0  # to aid in diagnosis of wait, priority
        self.depends_on = None
        self.dependents = []
        self.expectedResult = PASSED
        self.setName("uninitialized")
        self.set(INVALID, "New test, unitialized")
        self.srunRelativeNode = -1
        self.numNodesToUse = -1
        self.priority = -1
        self.totalPriority = -1
        self.startDateTime = curDateTime()
        self.endDateTime = curDateTime()
        self.output = []  #magic output, newlines and magic removed.
        self.notes = []  #note from the run
        self.block = ''
        # these will all get changed below but want them set to something for getResults
        self.level = 0
        self.independent = False
        self.np = 1
        self.priority = 1
        self.totalPriority = 1
        self.directory = ''
        self.batch = False
        self.clas = ''

        self.combineOutput = False
        self.outname = ''
        self.shortoutname = ''
        self.errname = ''
        self.outhandle = None
        self.errhandle = None

        self.commandList = ['not run']
        # this is just used for documentation
        self.commandLine = 'not run'

        rootdict = dict(ATSROOT=configuration.ATSROOT)

        # Combine the options: first the defaults, then the glued, then the tacked,
        # then the stuck, then the test options.
        self.options = AttributeDict(
            script='',
            clas=[],
            executable='',
            directory='',
        )
        try:
            self.options.update(configuration.options.testDefaults)
            self.options.update(AtsTest.glued)
            self.options.update(AtsTest.tacked)
            self.options.update(AtsTest.stuck)
            self.options.update(AtsTest.grouped)
            self.options.update(options)
        except Exception as e:
            self.set(INVALID, 'Bad options: ' + e)
            return

        self.level = self.options['level']
        self.np = self.options['np']
        self.priority = self.options.get('priority', max(1, self.np))
        self.totalPriority = self.priority

        self.testStdout = self.options['testStdout']
        outOpts = ['file', 'terminal', 'both']
        if not self.testStdout in outOpts:
            msg = 'Invalid setting for option testStdout: ' + self.testStdout
            raise AtsError(msg)

        if configuration.options.allInteractive:
            self.batch = False
        else:
            self.batch = self.options['batch']

        if configuration.options.combineOutErr:
            self.combineOutput = True
        else:
            self.combineOutput = False

        # process the arguments
        # Note: old interface was script, clas='', **options
        # Now allow for possibility of no script, or clas as unnamed second
        # positional
        lc = len(fixedargs)
        if lc > 2:
            self.set(INVALID, 'Too many positional arguments to test command.')
            return
        elif lc == 2:
            self.options['script'] = fixedargs[0]
            self.options['clas'] = fixedargs[1]
        elif lc == 1:
            self.options['script'] = fixedargs[0]
        script = self.options['script']
        clas = self.options['clas']
        if isinstance(clas, str):
            clas = configuration.machine.split(clas)
        self.clas = [c % self.options for c in clas]
        executable = str(self.options.get('executable'))
        self.directory = self.options['directory']

        if executable == '1':
            if not script:
                self.set(INVALID, "executable = 1 requires a first argument.")
                return

            script = script.replace('$ATSROOT', configuration.ATSROOT)
            if len(configuration.ATSROOT) == 0:
                script = script[1:]  # remove leading "/" or "\"
            script = script % rootdict
            self.executable = Executable(script)
            if self.directory == '':
                self.directory = os.getcwd()
            path = self.executable.path
            junk, filename = os.path.split(path)
        else:
            if executable:
                executable = executable.replace('$ATSROOT',
                                                configuration.ATSROOT)
                self.executable = Executable(executable % rootdict)
            else:
                self.executable = configuration.defaultExecutable

            if script:
                script = abspath(script) % self.options
                self.clas.insert(0, script)
                if self.directory == '':
                    self.directory, filename = os.path.split(script)
            else:
                if self.directory == '':
                    self.directory = os.getcwd()
                junk, filename = os.path.split(self.executable.path)

        name, junk = os.path.splitext(filename)
        self.setName(self.options.get('name', name))
        label = self.options.get('label', '')
        if label:
            label = str(label).strip()
            self.setName(self.name + '(' + label + ')')

        if debug():
            log("Results of parsing test arguments", echo=False)
            log.indent()
            log("Name:", self.name, echo=False)
            log("Options:", echo=False)
            log.indent()
            for k in self.options:
                log(k, ": ", self.options[k], echo=False)
            log.dedent()
            log("Executable path:", self.executable.path, echo=False)
            log("Directory:", self.directory, echo=False)
            log.dedent()

        self.independent = self.options.get('independent', False)
        if not self.independent:
            # the lower() is due to peculiarities on at least the Mac
            # where os.chdir() seems to change case partially.
            self.block = self.directory.lower()

        if not self.executable.is_valid():
            self.set(INVALID, 'Executable "%s" not valid.' % self.executable)
            return

        if not os.path.isdir(self.directory):
            self.set(INVALID, 'Directory not valid: %s' % self.directory)

        if script and not is_valid_file(script):
            self.set(INVALID, "Script %s does not exist." % script)
            return

        self.fileOutNamesSet()

        #set the timelimit
        try:
            tl = options.get('timelimit', None)
            if tl is None:
                self.timelimit = configuration.timelimit
            else:
                self.timelimit = Duration(tl)
        except AtsError as msg:
            self.set(INVALID, msg)
            return

        if self.priority <= 0:
            self.set(SKIPPED, 'Test has priority <= zero.')
            return

        # if the test ends up BATCHED, such jobs are legal.

        if self.batch and configuration.options.nobatch:
            self.set(SKIPPED, "Batch not available")

        elif self.batch:
            problem = configuration.batchmachine.canRun(self)
            if not problem:
                if configuration.options.skip:
                    self.set(SKIPPED, "BACH skipped due to skip flag")
                else:
                    self.set(BATCHED, "Ready to run in batch.")
            else:
                self.set(SKIPPED, problem)

        else:
            problem = configuration.machine.canRun(self)
            if not problem:
                self.set(CREATED, "Ready to run interactively.")
            elif configuration.options.allInteractive or \
               configuration.options.nobatch or \
               self.groupNumber:
                self.set(SKIPPED, problem)
            else:
                self.set(BATCHED, problem)
                self.notes.append(\
                    "Changed to batch since unable to run interactively on this machine.")

    def __hash__(self):
        return hash(self.serialNumber)

    def __ge__(self, other):
        return self.totalPriority >= other.totalPriority

    def __gt__(self, other):
        return self.totalPriority > other.totalPriority

    def __le__(self, other):
        return self.totalPriority <= other.totalPriority

    def __lt__(self, other):
        return self.totalPriority < other.totalPriority

    def __eq__(self, other):
        return self.serialNumber == other.serialNumber

    def __ne__(self, other):
        return self.serialNumber != other.serialNumber

    def __invert__(self):
        """Responds to the ~ operator by setting the expected status FAILED,
           returning this test object. Note unusual alteration of an operand.
           This lets us specify that a test should fail.
        """
        self.expectedResult = FAILED
        return self

    def addDependent(self, d):
        "Add a dependent test to this one."
        if self.status is FILTERED:
            d.set(FILTERED,
                  "depends on %s that has been filtered out." % self.name)
        elif self.status is SKIPPED:
            d.set(SKIPPED,
                  "Ancestor %s status is %s" % (self.name, self.status))
        elif self.expectedResult is not PASSED:
            d.set(SKIPPED,
                  "depends on %s that is not expected to pass." % self.name)
        elif self.status is BATCHED:
            d.set(BATCHED, "Child of batch job must be batch also.")

        if self.depends_on is not None:
            self.depends_on.addDependent(d)
        self.dependents.append(d)
        d.depends_on = self

    def getResults(self):
        "Return a dictionary containing the essential information about this test."
        if not hasattr(self, 'timelimit'):
            self.timelimit = None
        if self.depends_on is None:
            ds = 0
        else:
            ds = self.depends_on.serialNumber

        if self.output:
            out = ['Captured output, see log.']
        else:
            out = []

        # various integers are used to reconstruct the test/group relationships
        # See the coding in management.py that prints atsr.py

        result = AttributeDict(
            name=self.name,
            serialNumber=self.serialNumber,
            groupNumber=self.groupNumber,
            groupSerialNumber=self.groupSerialNumber,
            runOrder=self.runOrder,
            status=self.status,
            batch=self.batch,
            expectedResult=self.expectedResult,
            message=self.message,
            startDateTime=self.startDateTime,
            endDateTime=self.endDateTime,
            options=self.options,
            directory=self.directory,
            notes=self.notes,
            output=out,
            independent=self.independent,
            block=self.block,
            timelimit=self.timelimit,
            commandList=self.commandList,
            commandLine=self.commandLine,
            elapsedTime=self.elapsedTime(),
            executable=str(self.executable),
            priority=self.priority,
            totalPriority=self.totalPriority,
            depends_on_serial=ds,
            dependents_serial=[d.serialNumber for d in self.dependents],
            waitUntil_serial=[t.serialNumber for t in self.waitUntil])
        return result

    def __str__(self):
        return str(self.status) + ' ' + self.name + ' ' + self.message

    def __repr__(self):
        return "Test #%d %s %s" % (self.serialNumber, self.name, self.status)

    def __bool__(self):
        "It is not proper to test the truth of a test."
        self.set(FAILED, 'if test(...) not allowed.')
        log(self, echo=True)
        return 0

    def setStartDateTime(self):
        "Sets date and time in the form of yyyy-mm-dd hh:mm:ss for database"
        self.startDateTime = curDateTime()
        self.startTime = time.time()

    def setEndDateTime(self):
        "Sets date and time in the form of yyyy-mm-dd hh:mm:ss for database"
        self.endDateTime = curDateTime()
        self.endTime = time.time()

    def elapsedTime(self):
        "Returns formatted elapsed time of the run."
        try:
            e = self.endTime
            s = self.startTime
            elapsed = e - s
        except AttributeError as foo:
            elapsed = 0.0

        if elapsed < 60.0:
            fmtStr = '%.2f sec' % elapsed
        else:
            fmtStr = hms(elapsed)

        return fmtStr

    def set(self, status, message):
        "Set a new status."
        self.status = status
        self.message = str(message)
        if status in (CREATED, RUNNING, INVALID, BATCHED):
            return
        if status is PASSED:
            if PASSED is self.expectedResult:
                return
            else:
                self.notes.append("Test unexpectedly PASSED, setting to FAIL")
                self.status = FAILED
                return
# Didn't pass, skip the dependents. (One could argue about this.)
        for d in self.dependents:
            if d.status is CREATED:
                d.set(SKIPPED, "Ancestor test %s %s" % (self.name, status))
# Didn't pass, but is that ok?
        if status is self.expectedResult:
            self.notes.append("Expected status achieved, %s" % status)
            self.status = EXPECTED

    def stick(cls, **options):
        """Add keyword/value pairs for subsequent tests in this file.
        """
        cls.stuck.update(options)

    stick = classmethod(stick)

    def waitNewSource(cls):
        cls.waitUntilAccumulatorStack.append(cls.waitUntilAccumulator[:])

    waitNewSource = classmethod(waitNewSource)

    def waitEndSource(cls):
        s = cls.waitUntilAccumulatorStack.pop()
        cls.waitUntilAccumulator = s[:]
        cls.waitUntil = s[:]

    waitEndSource = classmethod(waitEndSource)

    def wait(cls):
        "Create a wait boundary"
        cls.waitUntil = cls.waitUntilAccumulator[:]

    wait = classmethod(wait)

    def newGroup(cls, independent=False, **kw):
        "Sets counters so next test(s) in same AtsTestGroup"
        cls.endGroup()
        cls.groupCounter += 1
        cls.group = AtsTestGroup(cls.groupCounter)
        cls.grouped = kw
        cls.grouped['independent'] = independent

    newGroup = classmethod(newGroup)

    def endGroup(cls):
        "End this group"
        cls.group = None
        cls.grouped = {}

    endGroup = classmethod(endGroup)

    def unstick(cls, *kw):
        "Remove the named sticky options. With no arg, remove all."
        if kw:
            for k in kw:
                if k in cls.stuck:
                    del cls.stuck[k]
        else:
            cls.stuck.clear()

    unstick = classmethod(unstick)

    def tack(cls, **options):
        """Add keyword/value pairs for subsequent tests in descendent files.
           A current tacked value overrules glue
        """
        cls.tacked.update(options)

    tack = classmethod(tack)

    def untack(cls, *kw):
        "Remove the named tacked options"
        if kw:
            for k in kw:
                if k in cls.tacked:
                    del cls.tacked[k]
        else:
            cls.tacked.clear()

    untack = classmethod(untack)

    def glue(cls, **options):
        """Add keyword/value pairs for subsequent tests in ANY file.
           A current sticky value overrules glue
        """
        cls.glued.update(options)

    glue = classmethod(glue)

    def unglue(cls, *kw):
        "Remove the named glued options"
        if kw:
            for k in kw:
                if k in cls.glued:
                    del cls.glued[k]
        else:
            cls.glued.clear()

    unglue = classmethod(unglue)

    def checkGlue(cls, *kw):
        """Returns the value of the named glue options.
           If the named options does not exists, None is returned.
        """
        if kw:
            for k in kw:
                if k in cls.glued:
                    return cls.glued[k]
                else:
                    return None

    checkGlue = classmethod(checkGlue)

    def getOptions(cls):
        """Returns the dictionary of effective value of the test options
           outside of any test. Useful for debugging option problems.
           Class method.
        """
        opt = configuration.options
        options = dict(
            np=0,
            batch=0,
            level=1,
            keep=opt.keep,
            hideOutput=int(opt.hideOutput),
            testStdout=opt.testStdout,
            globalPrerunScript=opt.globalPrerunScript,
            globalPostrunScript=opt.globalPostrunScript,
            script='',
            clas='',
            executable='',
        )
        options.update(AtsTest.glued)
        options.update(AtsTest.tacked)
        options.update(AtsTest.stuck)
        return options

    getOptions = classmethod(getOptions)

    def restart(self):
        AtsTest.stuck = {}
        AtsTest.glued = {}
        AtsTest.tacked = {}
        AtsTest.grouped = {}
        AtsTest.groupCounter = 0
        AtsTest.groupNumber = 0
        AtsTest.serialNumber = 0
        AtsTest.waitUntil = []
        AtsTest.waitUntilAccumulator = []
        AtsTest.waitUntilAccumulatorStack = []

    restart = classmethod(restart)

    def recordOutput(self, groupFailure):
        """Standard recorder for test. Some tests have a very large amount of output,
           so this does direct output rather than keep it in the test object.
           groupFailure is used if one member of a group died.
        """
        failures = [FAILED, TIMEDOUT, HALTED]
        # What we're going to do with the output file:
        checkit = self.options.get('check', False)
        keep = self.options.get('keep')
        magic = self.options.get('magic', '#ATS:')

        if checkit:
            self.notes.append(
                'Please check the results of this test manually.')
            log('Please check the results of this test manually.', echo=True)

        if configuration.options.skip:
            return

        if self.testStdout != 'terminal':
            try:
                f = open(self.outname, 'r')
            except IOError as e:
                self.notes = ['Missing output file.']
                log('Missing output file', self.outname, e)
                return

            if magic is not None:  # Check for output that starts with magic phrase
                n = 0
                M = len(magic)
                for line in f:
                    n += 1
                    if line.startswith(magic):
                        self.output.append(line[M:-1])
            f.close()

        failed = self.status in failures
        lookatit = checkit or failed
        keepit = (keep > 0) or lookatit or groupFailure
        hideIt = self.options.get('hideOutput')
        if keepit and (self.testStdout != 'terminal'):
            log.indent()
            if magic is not None:
                log('%d lines of output in %s' % (n, self.shortoutname),
                    echo=lookatit)
            else:
                log('Output in %s' % self.shortoutname, echo=lookatit)
            log.dedent()

        else:
            self.fileOutDelete()

        if not hideIt and self.output:
            log("Captured output:", echo=False, logging=True)
            log.indent()
            for line in self.output:
                log(line, echo=False, logging=True)
            log.dedent()

    # =============================================================
    def stdOutLocGet(self):
        return self.testStdout

    def fileHandleGet(self):
        if self.outhandle is None:
            self.outhandle = open(self.outname, 'w')

        if self.combineOutput:
            self.errhandle = self.outhandle
        else:
            if self.errhandle is None:
                self.errhandle = open(self.errname, 'w')

        return self.outhandle, self.errhandle

    def fileHandleClose(self):
        if self.outhandle is not None:
            self.outhandle.close()
            self.outhandle = None

            if not self.combineOutput:
                if self.errhandle is not None:
                    self.errhandle.close()
            self.errhandle = None

    def fileOutNamesSet(self):
        logdir = log.directory
        fileName = ("%04d" % self.serialNumber) + "." + self.namebase + '.log'
        prerunScript = ("%04d" % self.serialNumber
                        ) + "." + self.namebase + '_global_prerun.log'
        postrunScript = ("%04d" % self.serialNumber
                         ) + "." + self.namebase + '_global_postrun.log'

        self.outname = os.path.join(logdir, fileName)
        self.globalPrerunScript_outname = os.path.join(logdir, prerunScript)
        self.globalPostrunScript_outname = os.path.join(logdir, postrunScript)
        self.shortoutname = fileName

        if self.combineOutput:
            self.errname = self.outname
        else:
            self.errname = self.outname + '.err'

    def fileOutDelete(self):
        if os.path.exists(self.outname):
            try:
                os.unlink(self.outname)
            except:
                log('Not able to delete %s' % self.outname,
                    echo=True,
                    logging=True)

        if not self.combineOutput:
            if os.path.exists(self.errname):
                try:
                    os.unlink(self.errname)
                except:
                    log('Not able to delete %s' % self.errname,
                        echo=True,
                        logging=True)
        pass
Example #5
0
File: tests.py Project: LLNL/ATS
    def __init__(self, *fixedargs, **options):
        "Must not throw an exception -- object must always get created."
        super(AtsTest, self).__init__()
        AtsTest.serialNumber += 1
        AtsTest.waitUntilAccumulator.append(self)
        # populate attributes
        self.serialNumber = AtsTest.serialNumber
        if AtsTest.group is None:
            AtsTest.groupCounter += 1
            self.group = AtsTestGroup(AtsTest.groupCounter)
        else:
            self.group = AtsTest.group
        self.group.append(self)
        self.groupNumber = self.group.number
        self.groupSerialNumber = len(self.group)
        self.waitUntil = AtsTest.waitUntil  #never modify this, it may be shared.
        self.runOrder = 0  # to aid in diagnosis of wait, priority
        self.depends_on = None
        self.dependents = []
        self.expectedResult = PASSED
        self.setName("uninitialized")
        self.set(INVALID, "New test, unitialized")
        self.srunRelativeNode = -1
        self.numNodesToUse = -1
        self.priority = -1
        self.totalPriority = -1
        self.startDateTime = curDateTime()
        self.endDateTime = curDateTime()
        self.output = []  #magic output, newlines and magic removed.
        self.notes = []  #note from the run
        self.block = ''
        # these will all get changed below but want them set to something for getResults
        self.level = 0
        self.independent = False
        self.np = 1
        self.priority = 1
        self.totalPriority = 1
        self.directory = ''
        self.batch = False
        self.clas = ''

        self.combineOutput = False
        self.outname = ''
        self.shortoutname = ''
        self.errname = ''
        self.outhandle = None
        self.errhandle = None

        self.commandList = ['not run']
        # this is just used for documentation
        self.commandLine = 'not run'

        rootdict = dict(ATSROOT=configuration.ATSROOT)

        # Combine the options: first the defaults, then the glued, then the tacked,
        # then the stuck, then the test options.
        self.options = AttributeDict(
            script='',
            clas=[],
            executable='',
            directory='',
        )
        try:
            self.options.update(configuration.options.testDefaults)
            self.options.update(AtsTest.glued)
            self.options.update(AtsTest.tacked)
            self.options.update(AtsTest.stuck)
            self.options.update(AtsTest.grouped)
            self.options.update(options)
        except Exception as e:
            self.set(INVALID, 'Bad options: ' + e)
            return

        self.level = self.options['level']
        self.np = self.options['np']
        self.priority = self.options.get('priority', max(1, self.np))
        self.totalPriority = self.priority

        self.testStdout = self.options['testStdout']
        outOpts = ['file', 'terminal', 'both']
        if not self.testStdout in outOpts:
            msg = 'Invalid setting for option testStdout: ' + self.testStdout
            raise AtsError(msg)

        if configuration.options.allInteractive:
            self.batch = False
        else:
            self.batch = self.options['batch']

        if configuration.options.combineOutErr:
            self.combineOutput = True
        else:
            self.combineOutput = False

        # process the arguments
        # Note: old interface was script, clas='', **options
        # Now allow for possibility of no script, or clas as unnamed second
        # positional
        lc = len(fixedargs)
        if lc > 2:
            self.set(INVALID, 'Too many positional arguments to test command.')
            return
        elif lc == 2:
            self.options['script'] = fixedargs[0]
            self.options['clas'] = fixedargs[1]
        elif lc == 1:
            self.options['script'] = fixedargs[0]
        script = self.options['script']
        clas = self.options['clas']
        if isinstance(clas, str):
            clas = configuration.machine.split(clas)
        self.clas = [c % self.options for c in clas]
        executable = str(self.options.get('executable'))
        self.directory = self.options['directory']

        if executable == '1':
            if not script:
                self.set(INVALID, "executable = 1 requires a first argument.")
                return

            script = script.replace('$ATSROOT', configuration.ATSROOT)
            if len(configuration.ATSROOT) == 0:
                script = script[1:]  # remove leading "/" or "\"
            script = script % rootdict
            self.executable = Executable(script)
            if self.directory == '':
                self.directory = os.getcwd()
            path = self.executable.path
            junk, filename = os.path.split(path)
        else:
            if executable:
                executable = executable.replace('$ATSROOT',
                                                configuration.ATSROOT)
                self.executable = Executable(executable % rootdict)
            else:
                self.executable = configuration.defaultExecutable

            if script:
                script = abspath(script) % self.options
                self.clas.insert(0, script)
                if self.directory == '':
                    self.directory, filename = os.path.split(script)
            else:
                if self.directory == '':
                    self.directory = os.getcwd()
                junk, filename = os.path.split(self.executable.path)

        name, junk = os.path.splitext(filename)
        self.setName(self.options.get('name', name))
        label = self.options.get('label', '')
        if label:
            label = str(label).strip()
            self.setName(self.name + '(' + label + ')')

        if debug():
            log("Results of parsing test arguments", echo=False)
            log.indent()
            log("Name:", self.name, echo=False)
            log("Options:", echo=False)
            log.indent()
            for k in self.options:
                log(k, ": ", self.options[k], echo=False)
            log.dedent()
            log("Executable path:", self.executable.path, echo=False)
            log("Directory:", self.directory, echo=False)
            log.dedent()

        self.independent = self.options.get('independent', False)
        if not self.independent:
            # the lower() is due to peculiarities on at least the Mac
            # where os.chdir() seems to change case partially.
            self.block = self.directory.lower()

        if not self.executable.is_valid():
            self.set(INVALID, 'Executable "%s" not valid.' % self.executable)
            return

        if not os.path.isdir(self.directory):
            self.set(INVALID, 'Directory not valid: %s' % self.directory)

        if script and not is_valid_file(script):
            self.set(INVALID, "Script %s does not exist." % script)
            return

        self.fileOutNamesSet()

        #set the timelimit
        try:
            tl = options.get('timelimit', None)
            if tl is None:
                self.timelimit = configuration.timelimit
            else:
                self.timelimit = Duration(tl)
        except AtsError as msg:
            self.set(INVALID, msg)
            return

        if self.priority <= 0:
            self.set(SKIPPED, 'Test has priority <= zero.')
            return

        # if the test ends up BATCHED, such jobs are legal.

        if self.batch and configuration.options.nobatch:
            self.set(SKIPPED, "Batch not available")

        elif self.batch:
            problem = configuration.batchmachine.canRun(self)
            if not problem:
                if configuration.options.skip:
                    self.set(SKIPPED, "BACH skipped due to skip flag")
                else:
                    self.set(BATCHED, "Ready to run in batch.")
            else:
                self.set(SKIPPED, problem)

        else:
            problem = configuration.machine.canRun(self)
            if not problem:
                self.set(CREATED, "Ready to run interactively.")
            elif configuration.options.allInteractive or \
               configuration.options.nobatch or \
               self.groupNumber:
                self.set(SKIPPED, problem)
            else:
                self.set(BATCHED, problem)
                self.notes.append(\
                    "Changed to batch since unable to run interactively on this machine.")
Example #6
0
File: machines.py Project: LLNL/ATS
 def getResults(self):
     "Return machine-specific facts for manager postprocessing state."
     return AttributeDict(name=self.label())
Example #7
0
def init(clas = '', adder = None, examiner=None):
    """Called by manager.init(class, adder, examiner)
       Initialize configuration and process command-line options; create log,
       options, inputFiles, timelimit, machine, and batchmatchine.
       Call backs to machine and to adder/examiner for options.
    """
    global log, options, inputFiles, timelimit, machine, batchmachine,\
           defaultExecutable, ATSROOT, cuttime

    init_debugClass = False

    if init_debugClass:
        print("DEBUG init entered clas=%s " % (clas))

    # get the machine and possible batch facility
    machineDirs = MACHINE_DIR

    # delete, not needed, handled above
    #if MACHINE_OVERRIDE_DIR:
    #    machineDirs.append(MACHINE_OVERRIDE_DIR)

    machineList = []
    for machineDir in machineDirs:
       log('machineDir', machineDir)
       machineList.extend([os.path.join(machineDir,x) for x in os.listdir(machineDir) if x.endswith('.py') and not x.endswith('__init__.py')])
       sys.path.insert(0, machineDir)

    #machineList = []
    #for machineDir in machineDirs:
    #    print("DEBUG machineDir=%s " % (machineDir))
    #    machineList.extend(
    #        [os.path.join(machineDir,x) for x in os.listdir(machineDir)
    #         if x.endswith('.py') and not x.endswith('__init__.py')])

    machine = None
    batchmachine = None
    specFoundIn = ''
    bspecFoundIn = ''

    if init_debugClass:
        print("DEBUG init 100")
        print(machineDirs)
        print(machineList)
        print(MACHINE_TYPE)
        print("DEBUG init 200")

    for full_path in machineList:
        moduleName = ''
        fname = os.path.basename(full_path)
        # print "DEBUG 000 fname = %s" % fname
        f = open(full_path, 'r')
        for line in f:
            if line.startswith('#ATS:') and not machine:
                items = line[5:-1].split()
                machineName, moduleName, machineClass, npMaxH = items
                if init_debugClass:
                    print("DEBUG init machineName=%s moduleName=%s machineClass=%s npMaxH=%s" %
                          (machineName, moduleName, machineClass, npMaxH))

                # print "DEBUG init MACHINE_TYPE=%s machineName=%s moduleName=%s machineClass=%s npMaxH=%s" % (MACHINE_TYPE, machineName, moduleName, machineClass, npMaxH)

                if machineName == MACHINE_TYPE:
                    if moduleName == "SELF":
                        moduleName, junk = os.path.splitext(fname)
                    specFoundIn = full_path
                    print(f"from ats.atsMachines.{moduleName} "
                          f"import {machineClass} as Machine")
                    try:
                        machine_factory = get_machine_factory(moduleName,
                                                              machineClass)
                    except ModuleNotFoundError:
                        machine_factory = get_machine_factory(moduleName,
                                                              machineClass,
                                                              machine_package='atsMachines')
                    machine = machine_factory(machineName, int(npMaxH))

            elif line.startswith('#BATS:') and not batchmachine:
                items = line[6:-1].split()
                machineName, moduleName, machineClass, npMaxH = items

                if machineName == BATCH_TYPE:
                    if moduleName == "SELF":
                        moduleName, junk = os.path.splitext(fname)
                    bspecFoundIn = full_path
                    try:
                        machine_factory = get_machine_factory(moduleName,
                                                              machineClass)
                    except ModuleNotFoundError:
                        machine_factory = get_machine_factory(moduleName,
                                                              machineClass,
                                                              machine_package='atsMachines')
                    batchmachine = machine_factory(moduleName, int(npMaxH))
        f.close()

        if machine and batchmachine:
            break

    if machine is None:
        terminal("No machine specifications for", SYS_TYPE, "found, using generic.")
        machine = machines.Machine('generic', -1)

# create the option set
    usage = "usage: %prog [options] [input files]"
    parser = OptionParser(usage=usage, version="%prog " + version.version)
    addOptions(parser)
    machine.addOptions(parser)
# add the --nobatch option but force it true if no batch facility here.
    parser.add_option('--nobatch', action='store_true', dest='nobatch', default=(batchmachine is None),
        help = 'Do not run batch jobs.')
    if batchmachine:
        batchmachine.addOptions(parser)
# user callback?
    if adder is not None:
        adder(parser)
# parse the command line
    if clas:
        import shlex
        argv = shlex.split(clas)
    else:
        argv = sys.argv[1:]
    (toptions, inputFiles) = parser.parse_args(argv)

# immediately make the options a real dictionary -- the way optparse leaves it
# is misleading.
    options = AttributeDict()
    for k in vars(toptions).keys():
        options[k] = getattr(toptions, k)

# set up the test default options so the machine(s) can add to it
    options['testDefaults'] = AttributeDict(np=1,
        batch=0,
        level=1,
        keep = options.keep,
        hideOutput = options.hideOutput,
        verbose = options.verbose,
        testStdout = options.testStdout,
        globalPrerunScript = options.globalPrerunScript,
        globalPostrunScript = options.globalPostrunScript,
        sequential = options.sequential,
        nosrun = options.nosrun,
        salloc = options.salloc
        )

# let the machine(s) modify the results or act upon them in other ways.
    machine.examineOptions(options)
    if batchmachine:
        batchmachine.examineOptions(options)
# unpack basic options
    debug(options.debug)
    if options.logdir:
        log.set(directory = options.logdir)
    else:
        dirname = SYS_TYPE + "." + atsStartTime + ".logs"
        log.set(directory = dirname)
    log.mode="w"
    log.logging = 1
# user callback?
    if examiner is not None:
        examiner(options)

    if specFoundIn:
        log("Found specification for", MACHINE_TYPE, "in", specFoundIn)
    else:
        log("No specification found for", MACHINE_TYPE, ', using generic')
    if bspecFoundIn:
        log("Batch specification for ", BATCH_TYPE, "in", bspecFoundIn)

# unpack other options
    cuttime = options.cuttime
    if cuttime is not None:
        cuttime = Duration(cuttime)
    timelimit = Duration(options.timelimit)
    defaultExecutable = executables.Executable(abspath(options.executable))
    # ATSROOT is used in tests.py to allow paths pointed at the executable's directory
    if 'ATSROOT' in os.environ:
        ATSROOT = os.environ['ATSROOT']
    else:
        ATSROOT = os.path.dirname(defaultExecutable.path)
Example #8
0
    def getResults(self):
        """Returns an attribute dictionary containing the state of this
           manager suitable for postprocessing. After forming a potential
           result r, calls any resultsHooks functions (r, manager)
        """
        r = AttributeDict(
            started=self.started,
            options=self.options,
            savedTime=datestamp(long_format=True),
            collectTimeEnded=self.collectTimeEnded,
            badlist=self.badlist,
            filters=self.filters,
            groups={},
            onCollectedRoutines=[f.__name__ for f in self.onCollectedRoutines],
            onPrioritizedRoutines=[
                f.__name__ for f in self.onPrioritizedRoutines
            ],
            onExitRoutines=[f.__name__ for f in self.onExitRoutines],
            onResultsRoutines=[f.__name__ for f in self.onResultsRoutines],
        )
        r.testlist = [t.getResults() for t in self.testlist]

        if not hasattr(self, 'machine'):
            return r  # never initialized, nothing else of interest.

        r.inputFiles = self.inputFiles
        r.verbose = self.verbose
        r.machine = AttributeDict()
        r.batchmachine = None
        for key, value in self.machine.getResults().items():
            r.machine[key] = value
        if self.batchmachine:
            r.batchmachine = AttributeDict()
            for key, value in self.batchmachine.getResults().items():
                r.batchmachine[key] = value
        for hook in self.onResultsRoutines:
            log('   Calling onResults function', hook.__name__, echo=True)
            hook(r, self)
        return r
Example #9
0
testEnvironment = AttributeDict(
    debug=debug,
    manager=manager,
    test=test,
    testif=testif,
    source=source,
    log=log,
    define=define,
    undefine=undefine,
    get=get,
    logDefinitions=logDefinitions,
    filter=filter,
    filterdefs=filterdefs,
    wait=wait,
    stick=stick,
    unstick=unstick,
    tack=tack,
    untack=untack,
    group=group,
    endgroup=endgroup,
    glue=glue,
    unglue=unglue,
    checkGlue=checkGlue,
    getOptions=getOptions,
    sys=sys,
    os=os,
    abspath=abspath,
    AtsError=AtsError,
    is_valid_file=is_valid_file,
    SYS_TYPE=configuration.SYS_TYPE,
    MACHINE_TYPE=configuration.MACHINE_TYPE,
    BATCH_TYPE=configuration.BATCH_TYPE,
    MACHINE_DIR=configuration.MACHINE_DIR,
    onCollected=onCollected,
    onPrioritized=onPrioritized,
    onExit=onExit,
    onSave=onSave,
    getResults=getResults,
)