[CRIU] [RFC PATCHv2 32/32] zdtm: zdtm.py: hook up the multi-test launcher to existing group tests infrastructure
Ivan Shapovalov
intelfx at intelfx.name
Sat Mar 12 00:42:31 PST 2016
This adds a new makefile, Makefile.multi, which can be used to launch a
group list file (generated by `zdtm.py group`) with the newly-added
multi-test launcher, and adds relevant glue code to zdtm.py.
This is not by default. The groups can be run in the single-process mode
by passing `--groups=singleprocess` argument to zdtm.py:
$ ./zdtm.py --set=groups run -a --groups=singleprocess
Signed-off-by: Ivan Shapovalov <intelfx at intelfx.name>
---
test/zdtm.py | 45 +++++++++++++++++++++++++++++++---------
test/zdtm/Makefile.multi | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 10 deletions(-)
create mode 100644 test/zdtm/Makefile.multi
diff --git a/test/zdtm.py b/test/zdtm.py
index 5f58959..5a01540 100755
--- a/test/zdtm.py
+++ b/test/zdtm.py
@@ -282,25 +282,29 @@ class test_fail_expected_exc:
#
class zdtm_test:
- def __init__(self, name, desc, flavor, freezer):
+ def __init__(self, name, desc, flavor, freezer, opts, env = {}, makefile = None):
self.__name = name
self.__desc = desc
self.__freezer = None
- self.__make_action('cleanout')
+ self.__makefile = makefile
+ self.__make_action('cleanout', env = env)
self.__pid = 0
self.__flavor = flavor
self.__freezer = freezer
self._bins = [ name ]
- self._env = {}
+ self._env = env
self._deps = desc.get('deps', [])
self.auto_reap = True
+
def __make_action(self, act, env = None, root = None):
sys.stdout.flush() # Not to let make's messages appear before ours
tpath = self.__name + '.' + act
s_args = ['make', '--no-print-directory', \
'-C', os.path.dirname(tpath), \
os.path.basename(tpath)]
+ if self.__makefile is not None:
+ s_args += ['-f', self.__makefile]
if env:
env = dict(os.environ, **env)
@@ -443,7 +447,7 @@ class zdtm_test:
class inhfd_test:
- def __init__(self, name, desc, flavor, freezer):
+ def __init__(self, name, desc, flavor, freezer, opts):
self.__name = os.path.basename(name)
print "Load %s" % name
self.__fdtyp = imp.load_source(self.__name, name)
@@ -534,9 +538,9 @@ class inhfd_test:
pass
-class groups_test(zdtm_test):
- def __init__(self, name, desc, flavor, freezer):
- zdtm_test.__init__(self, 'zdtm/lib/groups', desc, flavor, freezer)
+class groups_test_multiprocess(zdtm_test):
+ def __init__(self, name, desc, flavor, freezer, opts):
+ zdtm_test.__init__(self, 'zdtm/lib/groups', desc, flavor, freezer, opts)
if flavor.ns:
self.__real_name = name
self.__subs = map(lambda x: x.strip(), open(name).readlines())
@@ -582,8 +586,26 @@ class groups_test(zdtm_test):
if not 'PASS' in res.split():
raise test_fail_exc("sub %s result check" % test)
+class groups_test_singleprocess(zdtm_test):
+ def __init__(self, name, desc, flavor, freezer, opts):
+ zdtm_test.__init__(self, name, desc, flavor, freezer, opts,
+ env = { 'ZDTM_PREFIX': os.path.relpath(os.getcwd(), os.path.dirname(name)) },
+ makefile = os.path.relpath("zdtm/Makefile.multi", os.path.dirname(name)))
+
+ # the `name` is not a binary, so don't mention it in self._bins
+ self._bins = [ 'zdtm/launcher/launcher' ] + map(lambda x: x.strip(), open(name).readlines())
+
+def groups_test(name, desc, flavor, freezer, opts):
+ if opts['groups_mode'] == "multiprocess":
+ return groups_test_multiprocess(name, desc, flavor, freezer, opts)
+ elif opts['groups_mode'] == "singleprocess":
+ return groups_test_singleprocess(name, desc, flavor, freezer, opts)
+ else:
+ raise ValueError("groups test mode '%s' does not exist" % opts['groups_mode'])
+
test_classes = { 'zdtm': zdtm_test, 'inhfd': inhfd_test, 'groups': groups_test }
+test_classes_flat = [ zdtm_test, inhfd_test, groups_test_multiprocess, groups_test_singleprocess ]
#
# CRIU when launched using CLI
@@ -960,7 +982,7 @@ def do_run_test(tname, tdesc, flavs, opts):
if opts['dry_run']:
continue
flav = flavors[f](opts)
- t = tclass(tname, tdesc, flav, fcg)
+ t = tclass(tname, tdesc, flav, fcg, opts)
cr_api = criu_cli(opts)
try:
@@ -1047,7 +1069,7 @@ class launcher:
nd = ('nocr', 'norst', 'pre', 'iters', 'page_server', 'sibling', \
'fault', 'keep_img', 'report', 'snaps', 'sat', \
'dedup', 'sbs', 'freezecg', 'user', 'dry_run', \
- 'keep_going', "list_failures")
+ 'keep_going', "list_failures", "groups_mode")
arg = repr((name, desc, flavor, { d: self.__opts[d] for d in nd }))
if self.__use_log:
@@ -1446,6 +1468,8 @@ rp.add_argument("-T", "--tests", help = "Regexp")
rp.add_argument("-f", "--flavor", help = "Flavor to run")
rp.add_argument("-x", "--exclude", help = "Exclude tests from --all run", action = 'append')
+rp.add_argument("--groups-mode", help = "Mode of operation for the 'groups' test set",
+ choices = ['multiprocess', 'singleprocess'], default = 'multiprocess')
rp.add_argument("--sibling", help = "Restore tests as siblings", action = 'store_true')
rp.add_argument("--pre", help = "Do some pre-dumps before dump (n[:pause])")
rp.add_argument("--snaps", help = "Instead of pre-dumps do full dumps", action = 'store_true')
@@ -1493,7 +1517,8 @@ if opts['debug']:
sys.settrace(traceit)
criu_cli.available()
-for tst in test_classes.values():
+for tst in test_classes_flat:
tst.available()
opts['action'](opts)
+# vim: set ts=8 sw=8 tw=0 noet ft=python :
diff --git a/test/zdtm/Makefile.multi b/test/zdtm/Makefile.multi
new file mode 100644
index 0000000..78b8ede
--- /dev/null
+++ b/test/zdtm/Makefile.multi
@@ -0,0 +1,54 @@
+# this file is ran from group descriptor directory, currently test/groups,
+# but it is abstracted away using $ZDTM_PREFIX (which should point to test/).
+
+include $(ZDTM_PREFIX)/zdtm/Makefile.inc
+
+define get-tests =
+$(addprefix $(ZDTM_PREFIX)/,$(shell cat $(basename $@)))
+endef
+
+define get-test-dirs =
+$(patsubst %/,%,$(sort $(dir $(shell cat $(basename $@)))))
+endef
+
+define get-test-names-for-dir =
+$(notdir $(addprefix $(ZDTM_PREFIX)/,$(shell grep -F "$(1)/" $(basename $@))))
+endef
+
+LAUNCHER := $(ZDTM_PREFIX)/zdtm/launcher/launcher
+
+# This rule starts launcher with appropriate arguments.
+#
+# Here we need to construct the argument string to pass to the launcher.
+# The per-test arguments are generated by special targets in per-dir makefiles,
+# which is flexible but pretty complex to use from another makefile.
+#
+# First, there are some arguments (--pidfile and --outfile) which need to be
+# derived from per-launch data (such as group name) in order to avoid
+# parallel launches clobbering each other's results. To construct these
+# arguments, we call `make GROUPNAME.args-global` in Makefile.live.
+# (Note: the zdtm/lib directory does not have special meaning; Makefile.live
+# simply needs to be run from zdtm/* and not from zdtm.)
+#
+# Finally, there are some per-test arguments. To construct these, we call
+# `make foo.args-multi foo.args` for each directory in the set we run
+# (those targets are repeated for each test in that directory in the set).
+# Again, these make invocations are grouped by directory to reduce overhead.
+# To each per-directory make invocation we also pass a ZDTM_PREFIX variable
+# which contains the path from us to that directory. The per-directory makefile
+# then prefixes all pathes it prints with the contents of that veriable.
+%.pid: %.build
+ $(LAUNCHER) $(shell $(make) -s -C $(ZDTM_PREFIX)/zdtm/lib -f ../Makefile.live $(basename $@).args-global) $(foreach d,$(get-test-dirs),$(shell $(make) -s -C $(ZDTM_PREFIX)/$(d) ZDTM_PATH_PREFIX=$(ZDTM_PREFIX)/$(d) ZDTM_NAME_PREFIX=$(basename $@). $(foreach t,$(call get-test-names-for-dir,$(d)),$(t).args-multi $(t).args)))
+
+%.out: %.pid
+ -kill -TERM `cat $<`
+
+%.cleanout: %
+ $(Q) $(RM) -r -f $<.out* $<.pid* $<.test* $<.*.test*
+
+.SECONDEXPANSION:
+
+# This rule builds tests, grouping them by directory to reduce overhead of
+# performing nested invocations of make.
+%.build: $$(addsuffix .c,$$(get-tests))
+ $(Q) set -e; $(foreach d,$(get-test-dirs),$(MAKE) --no-print-directory -C $(ZDTM_PREFIX)/$(d) $(call get-test-names-for-dir,$(d));)
--
2.7.2
More information about the CRIU
mailing list