Example #1
0
def main():
  """Entry point into the SLASH2 Test Suite.
  Deals with argument parsing and main configuration."""

  #Reset colorama after prints
  #  init(autoreset=True)

  parser = ArgumentParser(description="SLASH2 Test Suite")
  parser.add_argument("-v", "--verbose", action="count",
    help="increase verbosity", default=0)
  parser.add_argument("-l", "--log-file", help="log output to a file",
    default=None)
  parser.add_argument("-c", "--config-file",
    help="path to slash2 test suite config",
    default="tsuite.conf")
  parser.add_argument("-s", "--source", choices=["src", "svn"],
    help="build from src or svn", default="src")
  parser.add_argument("-x", "--ignore-tests", help="ignore a test set, folder name", default=[], nargs="*")
  parser.add_argument("-i", "--ignore", help="list of processes to ignore. Defaults to none.", default=[], nargs="*")
  parser.add_argument("-a", "--only",   help="list of processes to perform. Defaults to all.", default=[], nargs="*")
  parser.add_argument("-o", "--overrides", help="Override value in config. -s section:value=something ...",
    nargs="+")

  args = parser.parse_args()

  #Get log level
  level = [logging.WARNING, logging.INFO, logging.DEBUG]\
      [2 if args.verbose > 2 else args.verbose]

  log.setLevel(level)

  fmtstr = '%(asctime)s %(name)-8s %(levelname)-8s %(message)s'

  #Pretty output if colorama is installed
  try:
    from colorama import init, Fore, Style
    fmtstr = '{0}%(asctime)s{1} {2}%(name)-8s{1} {4}{3}%(levelname)-8s{1}{5} {0}%(message)s{1}'.format(
              Fore.WHITE, Fore.RESET, Fore.BLUE, Fore.CYAN, Style.BRIGHT, Style.RESET_ALL
            )

    class ColorFormatter(logging.Formatter):

      colors = {
        logging.INFO     : (Fore.GREEN, Fore.WHITE),
        logging.DEBUG    : (Fore.MAGENTA, Fore.WHITE),
        logging.ERROR    : (Fore.RED, Fore.YELLOW),
        logging.CRITICAL : (Fore.RED, Fore.RED)
      }

      def __init__(self, fmt="%(levelno)s: %(msg)s"):
        logging.Formatter.__init__(self, fmt, "%H:%M")

      def format(self, record):

        format_orig = self._fmt

        color, text = self.colors[logging.DEBUG]
        if record.levelno in self.colors:
          color, text = self.colors[record.levelno]

        self._fmt = '%(asctime)s %(name)-8s {4}{3}%(levelname)-8s{1}{5} {6}%(message)s{1}'.format(
          Fore.WHITE, Fore.RESET, Fore.WHITE, color, Style.NORMAL, Style.RESET_ALL, text
        )

        result = logging.Formatter.format(self, record)

        self._fmt = format_orig
        return result

    fmt = ColorFormatter()
    hdlr = logging.StreamHandler(sys.stdout)

    hdlr.setFormatter(fmt)
    logging.root.addHandler(hdlr)
    logging.root.setLevel(level)
  except ImportError:
    logging.basicConfig(level=level,
      format=fmtstr,
      datefmt='%H:%M'
    )


  #Setup file log
  if args.log_file:
    fch = logging.FileHandler(args.log_file)
    fch.setLevel(level)
    fch.setFormatter(
      logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
    )
    log.addHandler(fch)

  #Check for config file
  conf = ConfigParser()

  if len(conf.read(args.config_file)) == 0:
    log.fatal("Unable to read configuration file!")
    sys.exit(1)

  #Required sections; check for their existence

  sections = {
    "tsuite": [
      "rootdir",
      "logbase"
    ],
    "slash2": [
      "conf",
      "mds_gdb", "ion_gdb", "mnt_gdb"
    ],
    "tests": [
      "tsetdir",
      "excluded"
    ],
    "mongo": [
      "host"
    ]
  }

  #Building from source or svn

  if args.source == "svn":
    sections["svn"] = [
      "svnroot"
    ]
  else:
    sections["source"] = [
      "srcroot"
    ]

  #Apply configuration overrides
  if args.overrides:
    overreg = re.compile(r"^(\w+):(\w+)=(.+?)$")
    for override in args.overrides:
      match = overreg.match(override)
      if match:
        section, key, value = match.groups()
        if section not in conf._sections or key not in conf._sections[section]:
          print "Override {0} does not override an existing config value!".format(override)
          sys.exit(1)
        conf._sections[section][key] = value

  #Check that the required sections exist
  missing = check_subset(list(sections), list(conf._sections))
  if len(missing) != 0:
    log.fatal("Configuration file is missing sections!")
    log.fatal("Missing: {}".format(", ".join(missing)))
    sys.exit(1)

  #Check that all the fields listed are present
  #in each section
  for section in sections:
    missing = check_subset(
      sections[section],
      conf._sections[section]
    )
    if len(missing) != 0:
      log.fatal("Missing fields in {} section!".format(section))
      log.fatal("Missing: {}".format(", ".join(missing)))
      sys.exit(1)

  if "timeout" not in conf._sections["slash2"]:
    conf._sections["slash2"]["timeout"] = None

  log.info("Configuration file loaded successfully!")

  tsetdir = conf._sections["tests"]["tsetdir"]
  tsets = []
  try:
    #Consider all directories in tset_dir to have tsets to be ran

    tsets = [tset for tset in os.listdir(tsetdir) \
            if os.path.isdir(os.path.join(tsetdir, tset)) and not tset.startswith(".")]
  except OSError, e:
    log.critical("Unable to gather tset sets from the tseting directory!")
    sys.exit(1)