Print this page
11814 test-runner exit code should reflect test results
   1 #!@PYTHON@
   2 
   3 #
   4 # This file and its contents are supplied under the terms of the
   5 # Common Development and Distribution License ("CDDL"), version 1.0.
   6 # You may only use this file in accordance with the terms of version
   7 # 1.0 of the CDDL.
   8 #
   9 # A full copy of the text of the CDDL should have accompanied this
  10 # source.  A copy of the CDDL is also available via the Internet at
  11 # http://www.illumos.org/license/CDDL.
  12 #
  13 
  14 #
  15 # Copyright (c) 2012, 2016 by Delphix. All rights reserved.
  16 # Copyright (c) 2017, Chris Fraire <cfraire@me.com>.
  17 # Copyright 2018 Joyent, Inc.
  18 #
  19 
  20 import ConfigParser
  21 import os
  22 import logging
  23 import platform
  24 from logging.handlers import WatchedFileHandler
  25 from datetime import datetime
  26 from optparse import OptionParser
  27 from pwd import getpwnam
  28 from pwd import getpwuid
  29 from select import select
  30 from subprocess import PIPE
  31 from subprocess import Popen
  32 from sys import argv
  33 from sys import maxint
  34 from threading import Timer
  35 from time import time
  36 
  37 BASEDIR = '/var/tmp/test_results'
  38 KILL = '/usr/bin/kill'
  39 TRUE = '/usr/bin/true'
  40 SUDO = '/usr/bin/sudo'
  41 


  42 # Custom class to reopen the log file in case it is forcibly closed by a test.
  43 class WatchedFileHandlerClosed(WatchedFileHandler):
  44     """Watch files, including closed files.
  45     Similar to (and inherits from) logging.handler.WatchedFileHandler,
  46     except that IOErrors are handled by reopening the stream and retrying.
  47     This will be retried up to a configurable number of times before
  48     giving up, default 5.
  49     """
  50 
  51     def __init__(self, filename, mode='a', encoding=None, delay=0, max_tries=5):
  52         self.max_tries = max_tries
  53         self.tries = 0
  54         WatchedFileHandler.__init__(self, filename, mode, encoding, delay)
  55 
  56     def emit(self, record):
  57         while True:
  58             try:
  59                 WatchedFileHandler.emit(self, record)
  60                 self.tries = 0
  61                 return


  67                 self.tries += 1
  68 
  69 class Result(object):
  70     total = 0
  71     runresults = {'PASS': 0, 'FAIL': 0, 'SKIP': 0, 'KILLED': 0}
  72 
  73     def __init__(self):
  74         self.starttime = None
  75         self.returncode = None
  76         self.runtime = ''
  77         self.stdout = []
  78         self.stderr = []
  79         self.result = ''
  80 
  81     def done(self, proc, killed):
  82         """
  83         Finalize the results of this Cmd.
  84         Report SKIP for return codes 3,4 (NOTINUSE, UNSUPPORTED)
  85         as defined in ../stf/include/stf.shlib
  86         """


  87         Result.total += 1
  88         m, s = divmod(time() - self.starttime, 60)
  89         self.runtime = '%02d:%02d' % (m, s)
  90         self.returncode = proc.returncode
  91         if killed:
  92             self.result = 'KILLED'
  93             Result.runresults['KILLED'] += 1

  94         elif self.returncode is 0:
  95             self.result = 'PASS'
  96             Result.runresults['PASS'] += 1
  97         elif self.returncode is 3 or self.returncode is 4:
  98             self.result = 'SKIP'
  99             Result.runresults['SKIP'] += 1
 100         elif self.returncode is not 0:
 101             self.result = 'FAIL'
 102             Result.runresults['FAIL'] += 1

 103 
 104 
 105 class Output(object):
 106     """
 107     This class is a slightly modified version of the 'Stream' class found
 108     here: http://goo.gl/aSGfv
 109     """
 110     def __init__(self, stream):
 111         self.stream = stream
 112         self._buf = ''
 113         self.lines = []
 114 
 115     def fileno(self):
 116         return self.stream.fileno()
 117 
 118     def read(self, drain=0):
 119         """
 120         Read from the file descriptor. If 'drain' set, read until EOF.
 121         """
 122         while self._read() is not None:


 873 
 874 
 875 def main():
 876     options = parse_args()
 877     testrun = TestRun(options)
 878 
 879     if options.cmd is 'runtests':
 880         find_tests(testrun, options)
 881     elif options.cmd is 'rdconfig':
 882         testrun.read(testrun.logger, options)
 883     elif options.cmd is 'wrconfig':
 884         find_tests(testrun, options)
 885         testrun.write(options)
 886         exit(0)
 887     else:
 888         fail('Unknown command specified')
 889 
 890     testrun.complete_outputdirs()
 891     testrun.run(options)
 892     testrun.summary()
 893     exit(0)
 894 
 895 
 896 if __name__ == '__main__':
 897     main()
   1 #!@PYTHON@
   2 
   3 #
   4 # This file and its contents are supplied under the terms of the
   5 # Common Development and Distribution License ("CDDL"), version 1.0.
   6 # You may only use this file in accordance with the terms of version
   7 # 1.0 of the CDDL.
   8 #
   9 # A full copy of the text of the CDDL should have accompanied this
  10 # source.  A copy of the CDDL is also available via the Internet at
  11 # http://www.illumos.org/license/CDDL.
  12 #
  13 
  14 #
  15 # Copyright (c) 2012, 2016 by Delphix. All rights reserved.
  16 # Copyright (c) 2017, Chris Fraire <cfraire@me.com>.
  17 # Copyright 2019 Joyent, Inc.
  18 #
  19 
  20 import ConfigParser
  21 import os
  22 import logging
  23 import platform
  24 from logging.handlers import WatchedFileHandler
  25 from datetime import datetime
  26 from optparse import OptionParser
  27 from pwd import getpwnam
  28 from pwd import getpwuid
  29 from select import select
  30 from subprocess import PIPE
  31 from subprocess import Popen
  32 from sys import argv
  33 from sys import maxint
  34 from threading import Timer
  35 from time import time
  36 
  37 BASEDIR = '/var/tmp/test_results'
  38 KILL = '/usr/bin/kill'
  39 TRUE = '/usr/bin/true'
  40 SUDO = '/usr/bin/sudo'
  41 
  42 retcode = 0
  43 
  44 # Custom class to reopen the log file in case it is forcibly closed by a test.
  45 class WatchedFileHandlerClosed(WatchedFileHandler):
  46     """Watch files, including closed files.
  47     Similar to (and inherits from) logging.handler.WatchedFileHandler,
  48     except that IOErrors are handled by reopening the stream and retrying.
  49     This will be retried up to a configurable number of times before
  50     giving up, default 5.
  51     """
  52 
  53     def __init__(self, filename, mode='a', encoding=None, delay=0, max_tries=5):
  54         self.max_tries = max_tries
  55         self.tries = 0
  56         WatchedFileHandler.__init__(self, filename, mode, encoding, delay)
  57 
  58     def emit(self, record):
  59         while True:
  60             try:
  61                 WatchedFileHandler.emit(self, record)
  62                 self.tries = 0
  63                 return


  69                 self.tries += 1
  70 
  71 class Result(object):
  72     total = 0
  73     runresults = {'PASS': 0, 'FAIL': 0, 'SKIP': 0, 'KILLED': 0}
  74 
  75     def __init__(self):
  76         self.starttime = None
  77         self.returncode = None
  78         self.runtime = ''
  79         self.stdout = []
  80         self.stderr = []
  81         self.result = ''
  82 
  83     def done(self, proc, killed):
  84         """
  85         Finalize the results of this Cmd.
  86         Report SKIP for return codes 3,4 (NOTINUSE, UNSUPPORTED)
  87         as defined in ../stf/include/stf.shlib
  88         """
  89         global retcode
  90 
  91         Result.total += 1
  92         m, s = divmod(time() - self.starttime, 60)
  93         self.runtime = '%02d:%02d' % (m, s)
  94         self.returncode = proc.returncode
  95         if killed:
  96             self.result = 'KILLED'
  97             Result.runresults['KILLED'] += 1
  98             retcode = 2;
  99         elif self.returncode is 0:
 100             self.result = 'PASS'
 101             Result.runresults['PASS'] += 1
 102         elif self.returncode is 3 or self.returncode is 4:
 103             self.result = 'SKIP'
 104             Result.runresults['SKIP'] += 1
 105         elif self.returncode is not 0:
 106             self.result = 'FAIL'
 107             Result.runresults['FAIL'] += 1
 108             retcode = 1;
 109 
 110 
 111 class Output(object):
 112     """
 113     This class is a slightly modified version of the 'Stream' class found
 114     here: http://goo.gl/aSGfv
 115     """
 116     def __init__(self, stream):
 117         self.stream = stream
 118         self._buf = ''
 119         self.lines = []
 120 
 121     def fileno(self):
 122         return self.stream.fileno()
 123 
 124     def read(self, drain=0):
 125         """
 126         Read from the file descriptor. If 'drain' set, read until EOF.
 127         """
 128         while self._read() is not None:


 879 
 880 
 881 def main():
 882     options = parse_args()
 883     testrun = TestRun(options)
 884 
 885     if options.cmd is 'runtests':
 886         find_tests(testrun, options)
 887     elif options.cmd is 'rdconfig':
 888         testrun.read(testrun.logger, options)
 889     elif options.cmd is 'wrconfig':
 890         find_tests(testrun, options)
 891         testrun.write(options)
 892         exit(0)
 893     else:
 894         fail('Unknown command specified')
 895 
 896     testrun.complete_outputdirs()
 897     testrun.run(options)
 898     testrun.summary()
 899     exit(retcode)
 900 
 901 
 902 if __name__ == '__main__':
 903     main()