source: mod_gnutls/test/mgstest/__init__.py

mod_gnutls/0.12.0
Last change on this file was 0fe2130, checked in by Fiona Klute <fiona.klute@…>, 12 months ago

Simplify lockfile handling

It's much easier to just not enter the lockfile context if it's not
needed than to have a special case in the context manager.

  • Property mode set to 100644
File size: 2.9 KB
Line 
1#!/usr/bin/python3
2
3# Copyright 2019-2020 Fiona Klute
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Python modules for the mod_gnutls test suite."""
18
19import fcntl
20import os
21import os.path
22import sys
23
24from contextlib import contextmanager
25from unittest import SkipTest
26
27
28class TestExpectationFailed(Exception):
29    """Raise if a test failed. The constructor should be called with a
30    string describing the problem."""
31    pass
32
33
34@contextmanager
35def lockfile(file):
36    """Context manager for an optional file-based mutex.
37
38    The process must hold a lock on the given file before entering the
39    context. The lock is released when leaving the context.
40
41    """
42    with open(file, 'w') as lockfile:
43        try:
44            print(f'Aquiring lock on {file}...', file=sys.stderr)
45            fcntl.flock(lockfile, fcntl.LOCK_EX)
46            print(f'Got lock on {file}.', file=sys.stderr)
47            yield lockfile
48        finally:
49            print(f'Unlocking {file}...', file=sys.stderr)
50            fcntl.flock(lockfile, fcntl.LOCK_UN)
51            print(f'Unlocked {file}.', file=sys.stderr)
52
53
54def first_line_match(regexp, file):
55    """Return the first match of the regular expression in file (by line),
56    or None. Technically applicable to any iterable containing
57    strings, not just files opened for reading.
58    """
59    for line in file:
60        m = regexp.search(line)
61        if m:
62            return m
63    return None
64
65
66def require_match(regexp, file, error_message=None):
67    """Return the first match of the regular expression in file (by line),
68    or raise TestExpectationFailed.
69
70    If error_message is not None the exception message will be that
71    string, otherwise a generic message containing the regular
72    expression pattern. Technically applicable to any iterable
73    containing strings, not just files opened for reading.
74
75    """
76    m = first_line_match(regexp, file)
77    if m:
78        return m
79
80    if error_message:
81        raise TestExpectationFailed(error_message)
82    else:
83        raise TestExpectationFailed(f'No match found for {regexp.pattern}!')
84
85
86def require_apache_modules(*modules):
87    """Raise unittest.SkipTest if any of the given module files (full file
88    name) is not present in AP_LIBEXECDIR.
89
90    """
91    mod_dir = os.environ['AP_LIBEXECDIR']
92    for mod in modules:
93        if not os.path.isfile(os.path.join(mod_dir, mod)):
94            raise SkipTest(f'{mod} not found, skipping.')
Note: See TracBrowser for help on using the repository browser.