]> arthur.barton.de Git - bup.git/blob - conftest.py
MetaStoreWriter.__del__: replace with context management
[bup.git] / conftest.py
1
2 from __future__ import absolute_import, print_function
3 from os.path import basename, dirname, realpath, relpath
4 from time import tzset
5 from traceback import extract_stack
6 import errno
7 import os
8 import pytest
9 import re
10 import subprocess
11 import sys
12 import tempfile
13
14 sys.path[:0] = ['lib']
15
16 from bup import helpers
17 from bup.compat import environ, fsencode
18
19
20 _bup_src_top = realpath(dirname(fsencode(__file__)))
21
22 # The "pwd -P" here may not be appropriate in the long run, but we
23 # need it until we settle the relevant drecurse/exclusion questions:
24 # https://groups.google.com/forum/#!topic/bup-list/9ke-Mbp10Q0
25 os.chdir(realpath(os.getcwd()))
26
27 # Make the test results available to fixtures
28 @pytest.hookimpl(tryfirst=True, hookwrapper=True)
29 def pytest_runtest_makereport(item, call):
30     other_hooks = yield
31     report = other_hooks.get_result()
32     bup = item.__dict__.setdefault('bup', {})
33     bup[report.when + '-report'] = report  # setup, call, teardown
34     item.bup = bup
35
36 def bup_test_sort_order(item):
37     # Pull some slower tests forward to speed parallel runs
38     if item.fspath.basename in ('test_get.py', 'test-index.sh'):
39         return (0, str(item.fspath))
40     return (1, str(item.fspath))
41
42 def pytest_collection_modifyitems(session, config, items):
43     items.sort(key=bup_test_sort_order)
44
45 @pytest.fixture(autouse=True)
46 def no_lingering_errors():
47     def fail_if_errors():
48         if helpers.saved_errors:
49             bt = extract_stack()
50             src_file, src_line, src_func, src_txt = bt[-4]
51             msg = 'saved_errors ' + repr(helpers.saved_errors)
52             assert False, '%s:%-4d %s' % (basename(src_file),
53                                           src_line, msg)
54
55     fail_if_errors()
56     helpers.clear_errors()
57     yield None
58     fail_if_errors()
59     helpers.clear_errors()
60
61 @pytest.fixture(autouse=True)
62 def ephemeral_env_changes():
63     orig_env = environ.copy()
64     yield None
65     for k, orig_v in orig_env.items():
66         v = environ.get(k)
67         if v is not orig_v:
68             environ[k] = orig_v
69             if k == b'TZ':
70                 tzset()
71     for k in environ.keys():
72         if k not in orig_env:
73             del environ[k]
74             if k == b'TZ':
75                 tzset()
76     os.chdir(_bup_src_top)
77
78 # Assumes (of course) this file is at the top-level of the source tree
79 _bup_test_dir = realpath(dirname(fsencode(__file__))) + b'/test'
80 _bup_tmp = _bup_test_dir + b'/tmp'
81 try:
82     os.makedirs(_bup_tmp)
83 except OSError as e:
84     if e.errno != errno.EEXIST:
85         raise
86
87 _safe_path_rx = re.compile(br'[^a-zA-Z0-9_-]')
88
89 @pytest.fixture()
90 def tmpdir(request):
91     if sys.version_info[0] > 2:
92         rp = realpath(fsencode(request.fspath))
93     else:
94         rp = realpath(str(request.fspath))
95     rp = relpath(rp, _bup_test_dir)
96     if request.function:
97         rp += b'-' + fsencode(request.function.__name__)
98     safe = _safe_path_rx.sub(b'-', rp)
99     tmpdir = tempfile.mkdtemp(dir=_bup_tmp, prefix=safe)
100     yield tmpdir
101     if request.node.bup['call-report'].failed:
102         print('\nPreserving:', b'test/' + relpath(tmpdir, _bup_test_dir),
103               file=sys.stderr)
104     else:
105         subprocess.call(['chmod', '-R', 'u+rwX', tmpdir])
106         subprocess.call(['rm', '-rf', tmpdir])