Qinusty pushed to branch Qinusty/531-fetch-retries-on-terminate at BuildStream / buildstream
Commits:
- 
7f74ce40
by Josh Smith at 2018-08-15T16:02:53Z
4 changed files:
- + tests/frontend/interruptions.py
- + tests/frontend/interruptions/elements/delaymock.bst
- + tests/frontend/interruptions/plugins/delayed.py
- + tests/frontend/interruptions/project.conf
Changes:
| 1 | +import pytest
 | |
| 2 | +import os
 | |
| 3 | +import signal
 | |
| 4 | +import re
 | |
| 5 | +import time
 | |
| 6 | +import multiprocessing as mp
 | |
| 7 | +from multiprocessing import Process
 | |
| 8 | +from multiprocessing.queues import Queue
 | |
| 9 | + | |
| 10 | +from buildstream import _yaml
 | |
| 11 | +from tests.testutils import cli
 | |
| 12 | + | |
| 13 | + | |
| 14 | +DATA_DIR = os.path.join(
 | |
| 15 | +    os.path.dirname(os.path.realpath(__file__)),
 | |
| 16 | +    "interruptions",
 | |
| 17 | +)
 | |
| 18 | + | |
| 19 | + | |
| 20 | +def cli_run_in_process(cli, path, args):
 | |
| 21 | +    def do_run(cli, path, args, queue):
 | |
| 22 | +        result = cli.run(project=path, args=args)
 | |
| 23 | +        queue.put(result.output)
 | |
| 24 | +        queue.put(result.stderr)
 | |
| 25 | + | |
| 26 | +    queue = mp.Queue()
 | |
| 27 | +    p = mp.Process(target=do_run, args=[cli, path, args, queue])
 | |
| 28 | +    p.start()
 | |
| 29 | +    return queue, p
 | |
| 30 | + | |
| 31 | + | |
| 32 | +@pytest.mark.datafiles(DATA_DIR)
 | |
| 33 | +def test_interrupt_fetch(cli, datafiles):
 | |
| 34 | +    path = os.path.join(datafiles.dirname, datafiles.basename)
 | |
| 35 | + | |
| 36 | +    queue, proc = cli_run_in_process(cli, path, args=['--on-error', 'terminate',
 | |
| 37 | +                                                      'fetch', 'delaymock.bst'])
 | |
| 38 | +    # Wait a few seconds, fetch should then be in progress. With DelayedMockSource
 | |
| 39 | +    # fetch should take 20s unless terminated
 | |
| 40 | +    time.sleep(3)
 | |
| 41 | +    os.kill(proc.pid, signal.SIGINT)
 | |
| 42 | + | |
| 43 | +    # 5 second timeout
 | |
| 44 | +    try:
 | |
| 45 | +        output = queue.get(timeout=3)
 | |
| 46 | +        stderr = queue.get(timeout=3)
 | |
| 47 | +    except mp.queues.Empty:
 | |
| 48 | +        assert False, 'Fetch failed to terminate'
 | |
| 49 | + | |
| 50 | +    matches = re.findall(r'FAILURE\s*Fetch', stderr)
 | |
| 51 | +    assert len(matches), "Unexpected success"
 | |
| 52 | + | |
| 53 | +    matches = re.findall(r'STATUS\s*Fetch terminating', stderr)
 | |
| 54 | +    assert len(matches) != 0, "Fetch failed to terminate"
 | |
| 55 | +    assert len(matches) == 1, "Fetch attempted to terminate more than once" | 
| 1 | +kind: import
 | |
| 2 | + | |
| 3 | +sources:
 | |
| 4 | +  - kind: delayed | |
| \ No newline at end of file | 
| 1 | +import time
 | |
| 2 | +from buildstream import Source, SourceError, Consistency
 | |
| 3 | + | |
| 4 | + | |
| 5 | +class DelayedMockSource(Source):
 | |
| 6 | + | |
| 7 | +    def configure(self, node):
 | |
| 8 | +        pass
 | |
| 9 | + | |
| 10 | +    def preflight(self):
 | |
| 11 | +        pass
 | |
| 12 | + | |
| 13 | +    def get_unique_key(self):
 | |
| 14 | +        return {}
 | |
| 15 | + | |
| 16 | +    def get_consistency(self):
 | |
| 17 | +        return Consistency.RESOLVED
 | |
| 18 | + | |
| 19 | +    def get_ref(self):
 | |
| 20 | +        return None
 | |
| 21 | + | |
| 22 | +    def set_ref(self, ref, node):
 | |
| 23 | +        pass
 | |
| 24 | + | |
| 25 | +    def fetch(self):
 | |
| 26 | +        LOOP_FOR = 40
 | |
| 27 | +        def prog_percent(prog):
 | |
| 28 | +            return "{}%".format(float(i)/float(LOOP_FOR) * 100)
 | |
| 29 | +        for i in range(LOOP_FOR):
 | |
| 30 | +            time.sleep(0.5)
 | |
| 31 | +            self.status("Mock Source progress {}".format(prog_percent(i)))
 | |
| 32 | + | |
| 33 | +    def stage(self, directory):
 | |
| 34 | +        pass
 | |
| 35 | + | |
| 36 | + | |
| 37 | +def setup():
 | |
| 38 | +    return DelayedMockSource | 
| 1 | +name: interruptions
 | |
| 2 | +element-path: elements
 | |
| 3 | +plugins:
 | |
| 4 | +- origin: local
 | |
| 5 | +  path: plugins
 | |
| 6 | +  sources:
 | |
| 7 | +    delayed: 0 | |
| \ No newline at end of file | 
