^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env python3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) tdc.py - Linux tc (Traffic Control) unit test driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) Copyright (C) 2017 Lucas Bates <lucasb@mojatatu.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) import argparse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) import importlib
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) import json
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) import subprocess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) import time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) import traceback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) from collections import OrderedDict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) from string import Template
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) from tdc_config import *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) from tdc_helper import *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) import TdcPlugin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) from TdcResults import *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) class PluginDependencyException(Exception):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) def __init__(self, missing_pg):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) self.missing_pg = missing_pg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) class PluginMgrTestFail(Exception):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) def __init__(self, stage, output, message):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) self.stage = stage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) self.output = output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) self.message = message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) class PluginMgr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) def __init__(self, argparser):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) super().__init__()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) self.plugins = {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) self.plugin_instances = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) self.failed_plugins = {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) self.argparser = argparser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) # TODO, put plugins in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) plugindir = os.getenv('TDC_PLUGIN_DIR', './plugins')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for dirpath, dirnames, filenames in os.walk(plugindir):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) for fn in filenames:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (fn.endswith('.py') and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) not fn == '__init__.py' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) not fn.startswith('#') and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) not fn.startswith('.#')):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mn = fn[0:-3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) foo = importlib.import_module('plugins.' + mn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) self.plugins[mn] = foo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) self.plugin_instances.append(foo.SubPlugin())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) def load_plugin(self, pgdir, pgname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pgname = pgname[0:-3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) foo = importlib.import_module('{}.{}'.format(pgdir, pgname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) self.plugins[pgname] = foo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) self.plugin_instances.append(foo.SubPlugin())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) self.plugin_instances[-1].check_args(self.args, None)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) def get_required_plugins(self, testlist):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) Get all required plugins from the list of test cases and return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) all unique items.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) reqs = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) for t in testlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if 'requires' in t['plugins']:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if isinstance(t['plugins']['requires'], list):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) reqs.extend(t['plugins']['requires'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) reqs.append(t['plugins']['requires'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) except KeyError:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) reqs = get_unique_item(reqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return reqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) def load_required_plugins(self, reqs, parser, args, remaining):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) Get all required plugins from the list of test cases and load any plugin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) that is not already enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pgd = ['plugin-lib', 'plugin-lib-custom']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) pnf = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for r in reqs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if r not in self.plugins:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) fname = '{}.py'.format(r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) source_path = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) for d in pgd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pgpath = '{}/{}'.format(d, fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if os.path.isfile(pgpath):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) source_path.append(pgpath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if len(source_path) == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) print('ERROR: unable to find required plugin {}'.format(r))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pnf.append(fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) elif len(source_path) > 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) print('WARNING: multiple copies of plugin {} found, using version found')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) print('at {}'.format(source_path[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pgdir = source_path[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pgdir = pgdir.split('/')[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) self.load_plugin(pgdir, fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if len(pnf) > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) raise PluginDependencyException(pnf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) parser = self.call_add_args(parser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) (args, remaining) = parser.parse_known_args(args=remaining, namespace=args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) def call_pre_suite(self, testcount, testidlist):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pgn_inst.pre_suite(testcount, testidlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) def call_post_suite(self, index):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) for pgn_inst in reversed(self.plugin_instances):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) pgn_inst.post_suite(index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) def call_pre_case(self, caseinfo, *, test_skip=False):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pgn_inst.pre_case(caseinfo, test_skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) except Exception as ee:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) print('exception {} in call to pre_case for {} plugin'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) format(ee, pgn_inst.__class__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) print('test_ordinal is {}'.format(test_ordinal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) print('testid is {}'.format(caseinfo['id']))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) raise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) def call_post_case(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) for pgn_inst in reversed(self.plugin_instances):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) pgn_inst.post_case()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) def call_pre_execute(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pgn_inst.pre_execute()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) def call_post_execute(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) for pgn_inst in reversed(self.plugin_instances):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pgn_inst.post_execute()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) def call_add_args(self, parser):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) parser = pgn_inst.add_args(parser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return parser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) def call_check_args(self, args, remaining):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pgn_inst.check_args(args, remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) def call_adjust_command(self, stage, command):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) for pgn_inst in self.plugin_instances:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) command = pgn_inst.adjust_command(stage, command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) def set_args(self, args):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) self.args = args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) @staticmethod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) def _make_argparser(args):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) self.argparser = argparse.ArgumentParser(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) description='Linux TC unit tests')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) def replace_keywords(cmd):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) For a given executable command, substitute any known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) variables contained within NAMES with the correct values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tcmd = Template(cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) subcmd = tcmd.safe_substitute(NAMES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return subcmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) def exec_cmd(args, pm, stage, command):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) Perform any required modifications on an executable command, then run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) it in a subprocess and return the results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if len(command.strip()) == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return None, None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if '$' in command:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) command = replace_keywords(command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) command = pm.call_adjust_command(stage, command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if args.verbose > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) print('command "{}"'.format(command))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) proc = subprocess.Popen(command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) shell=True,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) stdout=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) stderr=subprocess.PIPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) env=ENVIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) (rawout, serr) = proc.communicate(timeout=NAMES['TIMEOUT'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if proc.returncode != 0 and len(serr) > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) foutput = serr.decode("utf-8", errors="ignore")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) foutput = rawout.decode("utf-8", errors="ignore")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) except subprocess.TimeoutExpired:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) foutput = "Command \"{}\" timed out\n".format(command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) proc.returncode = 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) proc.stdout.close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) proc.stderr.close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return proc, foutput
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) def prepare_env(args, pm, stage, prefix, cmdlist, output = None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) Execute the setup/teardown commands for a test case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) Optionally terminate test execution if the command fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if args.verbose > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) print('{}'.format(prefix))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for cmdinfo in cmdlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if isinstance(cmdinfo, list):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) exit_codes = cmdinfo[1:]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) cmd = cmdinfo[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) exit_codes = [0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cmd = cmdinfo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if not cmd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) (proc, foutput) = exec_cmd(args, pm, stage, cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if proc and (proc.returncode not in exit_codes):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) print('', file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) print("{} *** Could not execute: \"{}\"".format(prefix, cmd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) print("\n{} *** Error message: \"{}\"".format(prefix, foutput),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) print("returncode {}; expected {}".format(proc.returncode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) exit_codes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) print("\n{} *** Aborting test run.".format(prefix), file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) print("\n\n{} *** stdout ***".format(proc.stdout), file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) print("\n\n{} *** stderr ***".format(proc.stderr), file=sys.stderr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) raise PluginMgrTestFail(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) stage, output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) '"{}" did not complete successfully'.format(prefix))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) def run_one_test(pm, args, index, tidx):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) global NAMES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) result = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) tresult = ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) tap = ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) res = TestResult(tidx['id'], tidx['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if args.verbose > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) print("\t====================\n=====> ", end="")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) print("Test " + tidx["id"] + ": " + tidx["name"])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if 'skip' in tidx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if tidx['skip'] == 'yes':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) res = TestResult(tidx['id'], tidx['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) res.set_result(ResultState.skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) res.set_errormsg('Test case designated as skipped.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pm.call_pre_case(tidx, test_skip=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) pm.call_post_execute()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) # populate NAMES with TESTID for this test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) NAMES['TESTID'] = tidx['id']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pm.call_pre_case(tidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) prepare_env(args, pm, 'setup', "-----> prepare stage", tidx["setup"])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (args.verbose > 0):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) print('-----> execute stage')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pm.call_pre_execute()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) (p, procout) = exec_cmd(args, pm, 'execute', tidx["cmdUnderTest"])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) exit_code = p.returncode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) exit_code = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) pm.call_post_execute()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (exit_code is None or exit_code != int(tidx["expExitCode"])):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) print("exit: {!r}".format(exit_code))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) print("exit: {}".format(int(tidx["expExitCode"])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #print("exit: {!r} {}".format(exit_code, int(tidx["expExitCode"])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) res.set_result(ResultState.fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) res.set_failmsg('Command exited with {}, expected {}\n{}'.format(exit_code, tidx["expExitCode"], procout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) print(procout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if args.verbose > 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) print('-----> verify stage')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) match_pattern = re.compile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) str(tidx["matchPattern"]), re.DOTALL | re.MULTILINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) (p, procout) = exec_cmd(args, pm, 'verify', tidx["verifyCmd"])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if procout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) match_index = re.findall(match_pattern, procout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if len(match_index) != int(tidx["matchCount"]):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) res.set_result(ResultState.fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) res.set_failmsg('Could not match regex pattern. Verify command output:\n{}'.format(procout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) res.set_result(ResultState.success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) elif int(tidx["matchCount"]) != 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) res.set_result(ResultState.fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) res.set_failmsg('No output generated by verify command.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) res.set_result(ResultState.success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) prepare_env(args, pm, 'teardown', '-----> teardown stage', tidx['teardown'], procout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) pm.call_post_case()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) index += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) # remove TESTID from NAMES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) del(NAMES['TESTID'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) def test_runner(pm, args, filtered_tests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) Driver function for the unit tests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) Prints information about the tests being run, executes the setup and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) teardown commands and the command under test itself. Also determines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) success/failure based on the information in the test case and generates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) TAP output accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) testlist = filtered_tests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) tcount = len(testlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) index = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) tap = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) badtest = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) stage = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) emergency_exit = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) emergency_exit_message = ''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) tsr = TestSuiteReport()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) pm.call_pre_suite(tcount, [tidx['id'] for tidx in testlist])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) except Exception as ee:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ex_type, ex, ex_tb = sys.exc_info()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) print('Exception {} {} (caught in pre_suite).'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) format(ex_type, ex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) traceback.print_tb(ex_tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) emergency_exit_message = 'EMERGENCY EXIT, call_pre_suite failed with exception {} {}\n'.format(ex_type, ex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) emergency_exit = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) stage = 'pre-SUITE'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if emergency_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) pm.call_post_suite(index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return emergency_exit_message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if args.verbose > 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) print('give test rig 2 seconds to stabilize')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) time.sleep(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) for tidx in testlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if "flower" in tidx["category"] and args.device == None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) errmsg = "Tests using the DEV2 variable must define the name of a "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) errmsg += "physical NIC with the -d option when running tdc.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) errmsg += "Test has been skipped."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if args.verbose > 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) print(errmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) res = TestResult(tidx['id'], tidx['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) res.set_result(ResultState.skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) res.set_errormsg(errmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) tsr.add_resultdata(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) badtest = tidx # in case it goes bad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) res = run_one_test(pm, args, index, tidx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) tsr.add_resultdata(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) except PluginMgrTestFail as pmtf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ex_type, ex, ex_tb = sys.exc_info()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) stage = pmtf.stage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) message = pmtf.message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) output = pmtf.output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) res = TestResult(tidx['id'], tidx['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) res.set_result(ResultState.skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) res.set_errormsg(pmtf.message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) res.set_failmsg(pmtf.output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) tsr.add_resultdata(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) index += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) print(message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) print('Exception {} {} (caught in test_runner, running test {} {} {} stage {})'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) format(ex_type, ex, index, tidx['id'], tidx['name'], stage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) print('---------------')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) print('traceback')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) traceback.print_tb(ex_tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) print('---------------')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if stage == 'teardown':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) print('accumulated output for this test:')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if pmtf.output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) print(pmtf.output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) print('---------------')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) index += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) # if we failed in setup or teardown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) # fill in the remaining tests with ok-skipped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) count = index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if tcount + 1 != count:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) for tidx in testlist[count - 1:]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) res = TestResult(tidx['id'], tidx['name'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) res.set_result(ResultState.skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) msg = 'skipped - previous {} failed {} {}'.format(stage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) index, badtest.get('id', '--Unknown--'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) res.set_errormsg(msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) tsr.add_resultdata(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) count += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if args.pause:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) print('Want to pause\nPress enter to continue ...')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if input(sys.stdin):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) print('got something on stdin')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) pm.call_post_suite(index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return tsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) def has_blank_ids(idlist):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) Search the list for empty ID fields and return true/false accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return not(all(k for k in idlist))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) def load_from_file(filename):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) Open the JSON file containing the test cases and return them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) as list of ordered dictionary objects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) with open(filename) as test_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) testlist = json.load(test_data, object_pairs_hook=OrderedDict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) except json.JSONDecodeError as jde:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) print('IGNORING test case file {}\n\tBECAUSE: {}'.format(filename, jde))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) testlist = list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) idlist = get_id_list(testlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (has_blank_ids(idlist)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) for k in testlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) k['filename'] = filename
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return testlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) def args_parse():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) Create the argument parser.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) parser = argparse.ArgumentParser(description='Linux TC unit tests')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return parser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) def set_args(parser):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) Set the command line arguments for tdc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) parser.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) '--outfile', type=str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) help='Path to the file in which results should be saved. ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 'Default target is the current directory.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) parser.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) '-p', '--path', type=str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) help='The full path to the tc executable to use')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) sg = parser.add_argument_group(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 'selection', 'select which test cases: ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 'files plus directories; filtered by categories plus testids')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ag = parser.add_argument_group(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 'action', 'select action to perform on selected test cases')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) sg.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) '-D', '--directory', nargs='+', metavar='DIR',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) help='Collect tests from the specified directory(ies) ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) '(default [tc-tests])')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) sg.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) '-f', '--file', nargs='+', metavar='FILE',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) help='Run tests from the specified file(s)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) sg.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) '-c', '--category', nargs='*', metavar='CATG', default=['+c'],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) help='Run tests only from the specified category/ies, ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 'or if no category/ies is/are specified, list known categories.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sg.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) '-e', '--execute', nargs='+', metavar='ID',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) help='Execute the specified test cases with specified IDs')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ag.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) '-l', '--list', action='store_true',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) help='List all test cases, or those only within the specified category')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ag.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) '-s', '--show', action='store_true', dest='showID',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) help='Display the selected test cases')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ag.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) '-i', '--id', action='store_true', dest='gen_id',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) help='Generate ID numbers for new test cases')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) parser.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) '-v', '--verbose', action='count', default=0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) help='Show the commands that are being run')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) parser.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) '--format', default='tap', const='tap', nargs='?',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) choices=['none', 'xunit', 'tap'],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) help='Specify the format for test results. (Default: TAP)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) parser.add_argument('-d', '--device',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) help='Execute test cases that use a physical device, ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 'where DEVICE is its name. (If not defined, tests ' +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 'that require a physical device will be skipped)')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) parser.add_argument(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) '-P', '--pause', action='store_true',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) help='Pause execution just before post-suite stage')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return parser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) def check_default_settings(args, remaining, pm):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) Process any arguments overriding the default settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) and ensure the settings are correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) # Allow for overriding specific settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) global NAMES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if args.path != None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) NAMES['TC'] = args.path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if args.device != None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) NAMES['DEV2'] = args.device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if 'TIMEOUT' not in NAMES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) NAMES['TIMEOUT'] = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if not os.path.isfile(NAMES['TC']):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) print("The specified tc path " + NAMES['TC'] + " does not exist.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) exit(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) pm.call_check_args(args, remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) def get_id_list(alltests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) Generate a list of all IDs in the test cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return [x["id"] for x in alltests]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) def check_case_id(alltests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) Check for duplicate test case IDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) idl = get_id_list(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return [x for x in idl if idl.count(x) > 1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) def does_id_exist(alltests, newid):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) Check if a given ID already exists in the list of test cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) idl = get_id_list(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return (any(newid == x for x in idl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) def generate_case_ids(alltests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) If a test case has a blank ID field, generate a random hex ID for it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) and then write the test cases back to disk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) import random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) for c in alltests:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (c["id"] == ""):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) newid = str('{:04x}'.format(random.randrange(16**4)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (does_id_exist(alltests, newid)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) c['id'] = newid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ufilename = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) for c in alltests:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if ('filename' in c):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ufilename.append(c['filename'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ufilename = get_unique_item(ufilename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) for f in ufilename:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) testlist = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) for t in alltests:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if 'filename' in t:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if t['filename'] == f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) del t['filename']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) testlist.append(t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) outfile = open(f, "w")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) json.dump(testlist, outfile, indent=4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) outfile.write("\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) outfile.close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) def filter_tests_by_id(args, testlist):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) Remove tests from testlist that are not in the named id list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) If id list is empty, return empty list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) newlist = list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if testlist and args.execute:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) target_ids = args.execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if isinstance(target_ids, list) and (len(target_ids) > 0):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) newlist = list(filter(lambda x: x['id'] in target_ids, testlist))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return newlist
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) def filter_tests_by_category(args, testlist):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) Remove tests from testlist that are not in a named category.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) '''
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) answer = list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if args.category and testlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) test_ids = list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) for catg in set(args.category):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if catg == '+c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) print('considering category {}'.format(catg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) for tc in testlist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if catg in tc['category'] and tc['id'] not in test_ids:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) answer.append(tc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) test_ids.append(tc['id'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) def get_test_cases(args):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) If a test case file is specified, retrieve tests from that file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) Otherwise, glob for all json files in subdirectories and load from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) each one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) Also, if requested, filter by category, and add tests matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) certain ids.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) import fnmatch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) flist = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) testdirs = ['tc-tests']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if args.file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) # at least one file was specified - remove the default directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) testdirs = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) for ff in args.file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if not os.path.isfile(ff):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) print("IGNORING file " + ff + "\n\tBECAUSE does not exist.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) flist.append(os.path.abspath(ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if args.directory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) testdirs = args.directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) for testdir in testdirs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) for root, dirnames, filenames in os.walk(testdir):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) for filename in fnmatch.filter(filenames, '*.json'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) candidate = os.path.abspath(os.path.join(root, filename))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if candidate not in testdirs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) flist.append(candidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) alltestcases = list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for casefile in flist:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) alltestcases = alltestcases + (load_from_file(casefile))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) allcatlist = get_test_categories(alltestcases)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) allidlist = get_id_list(alltestcases)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) testcases_by_cats = get_categorized_testlist(alltestcases, allcatlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) idtestcases = filter_tests_by_id(args, alltestcases)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) cattestcases = filter_tests_by_category(args, alltestcases)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) cat_ids = [x['id'] for x in cattestcases]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if args.execute:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if args.category:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) alltestcases = cattestcases + [x for x in idtestcases if x['id'] not in cat_ids]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) alltestcases = idtestcases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if cat_ids:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) alltestcases = cattestcases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) # just accept the existing value of alltestcases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) # which has been filtered by file/directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return allcatlist, allidlist, testcases_by_cats, alltestcases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) def set_operation_mode(pm, parser, args, remaining):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) Load the test case data and process remaining arguments to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) what the script should do for this run, and call the appropriate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ucat, idlist, testcases, alltests = get_test_cases(args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if args.gen_id:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (has_blank_ids(idlist)):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) alltests = generate_case_ids(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) print("No empty ID fields found in test files.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) duplicate_ids = check_case_id(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (len(duplicate_ids) > 0):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) print("The following test case IDs are not unique:")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) print(str(set(duplicate_ids)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) print("Please correct them before continuing.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) exit(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if args.showID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) for atest in alltests:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) print_test_case(atest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if isinstance(args.category, list) and (len(args.category) == 0):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) print("Available categories:")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) print_sll(ucat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if args.list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) list_test_cases(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if len(alltests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) req_plugins = pm.get_required_plugins(alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) args = pm.load_required_plugins(req_plugins, parser, args, remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) except PluginDependencyException as pde:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) print('The following plugins were not found:')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) print('{}'.format(pde.missing_pg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) catresults = test_runner(pm, args, alltests)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if args.format == 'none':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) print('Test results output suppression requested\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) print('\nAll test results: \n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if args.format == 'xunit':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) suffix = 'xml'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) res = catresults.format_xunit()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) elif args.format == 'tap':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) suffix = 'tap'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) res = catresults.format_tap()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) print(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) print('\n\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if not args.outfile:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) fname = 'test-results.{}'.format(suffix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) fname = args.outfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) with open(fname, 'w') as fh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) fh.write(res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) fh.close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if os.getenv('SUDO_UID') is not None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) os.chown(fname, uid=int(os.getenv('SUDO_UID')),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) gid=int(os.getenv('SUDO_GID')))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) print('No tests found\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) def main():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) Start of execution; set up argument parser and get the arguments,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) and start operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) parser = args_parse()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) parser = set_args(parser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pm = PluginMgr(parser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) parser = pm.call_add_args(parser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) (args, remaining) = parser.parse_known_args()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) args.NAMES = NAMES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) pm.set_args(args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) check_default_settings(args, remaining, pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if args.verbose > 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) print('args is {}'.format(args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) set_operation_mode(pm, parser, args, remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) exit(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if __name__ == "__main__":
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) main()