Allow specifying a list of functions taking a target and returning context managers inside
TargetConf, which is then used by a
Target.from_conf_setup() method to stream target objects configured by these context managers. This allows running the same tests under different conditions, with arbitrary setup and teardown code.
CAVEAT: this works when only one expression is being executed. When executing more, the same Target objects will be reused without calling the context manager. Since solely re-using a Target object will not automatically setup the board accordingly (something has to call some code to do it), it would not be very useful.
The easiest way to make that work would be keeping a reference to the setup function in each Target object, and have the main affected step call it explicitly (e.g. in TestBundle.from_target()
). At this point, it may be cleaner to just add a new parameter to from_target()` to specify some arbitrary setup to do.
target-conf: setup: - !var lisa.tests.foo.mysetup1 - !var lisa.tests.foo.mysetup2
from contextlib import contextmanager @contextmanager def mysetup1(target): target.write_value('/sys/myfile', "start1") try: yield finally: target.write_value('/sys/myfile', "stop1") @contextmanager def mysetup2(target): target.write_value('/sys/myfile', "start2") try: yield finally: target.write_value('/sys/myfile', "stop2")
Note: the setup context managers will be executed for each expression, since
exekall needs to compute all the values of an expression before starting computing the next one.
Note 2: Parametric context managers can be achieved by using
!call tag in target_conf.yml:
target_conf.yml, in a way similar to decorators with parameters:
target-conf: setup: - !call:lisa.tests.foo.make_setup files_start: /sys/myfile: start1 /sys/myfile2: start1 files_stop: /sys/myfile: stop1 /sys/myfile2: stop1 - !call:lisa.tests.foo.make_setup files_start: /sys/myfile: start2 /sys/myfile2: start2 files_stop: /sys/myfile: stop2 /sys/myfile2: stop2
from contextlib import contextmanager def make_setup(files_start, files_stop): @contextmanager def setup(tg): for path, value in files_start.items(): tg.write_value(path, str(value)) try: yield finally: for path, value in files_stop.items(): tg.write_value(path, str(value)) return setup