[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