Skip to content

Commit

Permalink
tools: tc-testing: Introduce plugin architecture
Browse files Browse the repository at this point in the history
This should be a general test architecture, and yet allow specific
tests to be done.  Introduce a plugin architecture.

An individual test has 4 stages, setup/execute/verify/teardown.  Each
plugin gets a chance to run a function at each stage, plus one call
before all the tests are called ("pre" suite) and one after all the
tests are called ("post" suite).  In addition, just before each
command is executed, the plugin gets a chance to modify the command
using the "adjust_command" hook.  This makes the test suite quite
flexible.

Future patches will take some functionality out of the tdc.py script and
place it in plugins.

To use the plugins, place the implementation in the plugins directory
and run tdc.py.  It will notice the plugins and use them.

Signed-off-by: Brenda J. Butler <bjb@mojatatu.com>
Acked-by: Lucas Bates <lucasb@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Brenda J. Butler authored and David S. Miller committed Feb 15, 2018
1 parent 6fac733 commit 93707cb
Show file tree
Hide file tree
Showing 5 changed files with 368 additions and 58 deletions.
74 changes: 74 additions & 0 deletions tools/testing/selftests/tc-testing/TdcPlugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3

class TdcPlugin:
def __init__(self):
super().__init__()
print(' -- {}.__init__'.format(self.sub_class))

def pre_suite(self, testcount, testidlist):
'''run commands before test_runner goes into a test loop'''
self.testcount = testcount
self.testidlist = testidlist
if self.args.verbose > 1:
print(' -- {}.pre_suite'.format(self.sub_class))

def post_suite(self, index):
'''run commands after test_runner completes the test loop
index is the last ordinal number of test that was attempted'''
if self.args.verbose > 1:
print(' -- {}.post_suite'.format(self.sub_class))

def pre_case(self, test_ordinal, testid):
'''run commands before test_runner does one test'''
if self.args.verbose > 1:
print(' -- {}.pre_case'.format(self.sub_class))
self.args.testid = testid
self.args.test_ordinal = test_ordinal

def post_case(self):
'''run commands after test_runner does one test'''
if self.args.verbose > 1:
print(' -- {}.post_case'.format(self.sub_class))

def pre_execute(self):
'''run command before test-runner does the execute step'''
if self.args.verbose > 1:
print(' -- {}.pre_execute'.format(self.sub_class))

def post_execute(self):
'''run command after test-runner does the execute step'''
if self.args.verbose > 1:
print(' -- {}.post_execute'.format(self.sub_class))

def adjust_command(self, stage, command):
'''adjust the command'''
if self.args.verbose > 1:
print(' -- {}.adjust_command {}'.format(self.sub_class, stage))

# if stage == 'pre':
# pass
# elif stage == 'setup':
# pass
# elif stage == 'execute':
# pass
# elif stage == 'verify':
# pass
# elif stage == 'teardown':
# pass
# elif stage == 'post':
# pass
# else:
# pass

return command

def add_args(self, parser):
'''Get the plugin args from the command line'''
self.argparser = parser
return self.argparser

def check_args(self, args, remaining):
'''Check that the args are set correctly'''
self.args = args
if self.args.verbose > 1:
print(' -- {}.check_args'.format(self.sub_class))
104 changes: 104 additions & 0 deletions tools/testing/selftests/tc-testing/creating-plugins/AddingPlugins.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
tdc - Adding plugins for tdc

Author: Brenda J. Butler - bjb@mojatatu.com

ADDING PLUGINS
--------------

A new plugin should be written in python as a class that inherits from TdcPlugin.
There are some examples in plugin-lib.

The plugin can be used to add functionality to the test framework,
such as:

- adding commands to be run before and/or after the test suite
- adding commands to be run before and/or after the test cases
- adding commands to be run before and/or after the execute phase of the test cases
- ability to alter the command to be run in any phase:
pre (the pre-suite stage)
prepare
execute
verify
teardown
post (the post-suite stage)
- ability to add to the command line args, and use them at run time


The functions in the class should follow the following interfaces:

def __init__(self)
def pre_suite(self, testcount, testidlist) # see "PRE_SUITE" below
def post_suite(self, ordinal) # see "SKIPPING" below
def pre_case(self, test_ordinal, testid) # see "PRE_CASE" below
def post_case(self)
def pre_execute(self)
def post_execute(self)
def adjust_command(self, stage, command) # see "ADJUST" below
def add_args(self, parser) # see "ADD_ARGS" below
def check_args(self, args, remaining) # see "CHECK_ARGS" below


PRE_SUITE

This method takes a testcount (number of tests to be run) and
testidlist (array of test ids for tests that will be run). This is
useful for various things, including when an exception occurs and the
rest of the tests must be skipped. The info is stored in the object,
and the post_suite method can refer to it when dumping the "skipped"
TAP output. The tdc.py script will do that for the test suite as
defined in the test case, but if the plugin is being used to run extra
tests on each test (eg, check for memory leaks on associated
co-processes) then that other tap output can be generated in the
post-suite method using this info passed in to the pre_suite method.


SKIPPING

The post_suite method will receive the ordinal number of the last
test to be attempted. It can use this info when outputting
the TAP output for the extra test cases.


PRE_CASE

The pre_case method will receive the ordinal number of the test
and the test id. Useful for outputing the extra test results.


ADJUST

The adjust_command method receives a string representing
the execution stage and a string which is the actual command to be
executed. The plugin can adjust the command, based on the stage of
execution.

The stages are represented by the following strings:

'pre'
'setup'
'command'
'verify'
'teardown'
'post'

The adjust_command method must return the adjusted command so tdc
can use it.


ADD_ARGS

The add_args method receives the argparser object and can add
arguments to it. Care should be taken that the new arguments do not
conflict with any from tdc.py or from other plugins that will be used
concurrently.

The add_args method should return the argparser object.


CHECK_ARGS

The check_args method is so that the plugin can do validation on
the args, if needed. If there is a problem, and Exception should
be raised, with a string that explains the problem.

eg: raise Exception('plugin xxx, arg -y is wrong, fix it')
27 changes: 27 additions & 0 deletions tools/testing/selftests/tc-testing/plugin-lib/README-PLUGINS
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
tdc.py will look for plugins in a directory plugins off the cwd.
Make a set of numbered symbolic links from there to the actual plugins.
Eg:

tdc.py
plugin-lib/
plugins/
__init__.py
10-rootPlugin.py -> ../plugin-lib/rootPlugin.py
20-valgrindPlugin.py -> ../plugin-lib/valgrindPlugin.py
30-nsPlugin.py -> ../plugin-lib/nsPlugin.py


tdc.py will find them and use them.


rootPlugin
Check if the uid is root. If not, bail out.

valgrindPlugin
Run the command under test with valgrind, and produce an extra set of TAP results for the memory tests.
This plugin will write files to the cwd, called vgnd-xxx.log. These will contain
the valgrind output for test xxx. Any file matching the glob 'vgnd-*.log' will be
deleted at the end of the run.

nsPlugin
Run all the commands in a network namespace.
Empty file.
Loading

0 comments on commit 93707cb

Please sign in to comment.