diff options
Diffstat (limited to 'yarn')
-rwxr-xr-x | yarn | 66 |
1 files changed, 64 insertions, 2 deletions
@@ -50,6 +50,18 @@ class YarnRunner(cliapp.Application): 'run only TEST (this option can be repeated)', metavar='TEST') + self.settings.string( + ['tempdir'], + 'use DIR as the temporary directory for tests; ' + 'it should be empty or not exist', + metavar='DIR') + + self.settings.boolean( + ['snapshot'], + 'make snapshots of test working directory ' + 'after each scenario step; you probably ' + 'want to use this with --tempdir') + def setup(self): self.ts = ttystatus.TerminalStatus(period=0.001) if not self.settings['quiet']: @@ -170,26 +182,43 @@ class YarnRunner(cliapp.Application): if self.settings['no-act']: return True - datadir = tempfile.mkdtemp() + if self.settings['tempdir']: + tempdir = self.settings['tempdir'] + if not os.path.exists(tempdir): + os.mkdir(tempdir) + else: + tempdir = tempfile.mkdtemp() + + os.mkdir(self.scenario_dir(tempdir, scenario)) + datadir = self.datadir(tempdir, scenario) + os.mkdir(datadir) cleanup = [s for s in scenario.steps if s.what == 'FINALLY'] normal = [s for s in scenario.steps if s not in cleanup] ok = True + step_number = 0 for step in normal: exit = self.run_step(datadir, scenario, step, shell_prelude) + step_number += 1 + self.snapshot_datadir( + tempdir, datadir, scenario, step_number, step) if exit != 0: ok = False break for step in cleanup: exit = self.run_step(datadir, scenario, step, shell_prelude) + step_number += 1 + self.snapshot_datadir( + tempdir, datadir, scenario, step_number, step) if exit != 0: ok = False break - shutil.rmtree(datadir) + if not self.settings['snapshot']: + shutil.rmtree(tempdir) return ok @@ -232,6 +261,39 @@ class YarnRunner(cliapp.Application): return exit + def scenario_dir(self, tempdir, scenario): + return os.path.join(tempdir, self.nice(scenario.name)) + + def datadir(self, tempdir, scenario): + sd = self.scenario_dir(tempdir, scenario) + return os.path.join(sd, 'datadir') + + def snapshot_dir(self, tempdir, scenario, step, step_number): + sd = self.scenario_dir(tempdir, scenario) + base = '%03d-%s-%s' % (step_number, step.what, self.nice(step.text)) + return os.path.join(sd, base) + + def snapshot_datadir(self, tempdir, datadir, scenario, step_number, step): + # Use --reflink in case of CoW support, e.g., btrfs. + snapshot = self.snapshot_dir(tempdir, scenario, step, step_number) + cliapp.runcmd( + ['cp', '-a', '--reflink=auto', datadir, snapshot]) + + def nice(self, name): + # Quote a scenario or step name so it forms a nice filename. + nice_chars = "abcdefghijklmnopqrstuvwxyz" + nice_chars += nice_chars.upper() + nice_chars += "0123456789-." + + nice = [] + for c in name: + if c in nice_chars: + nice.append(c) + elif not nice or nice[-1] != '_': + nice.append('_') + nice = ''.join(nice) + return nice + def indent(self, s): return ''.join(' %s\n' % line for line in s.splitlines()) |