File: test_synchronization.py

package info (click to toggle)
pyscard 2.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,348 kB
  • sloc: python: 8,718; ansic: 1,971; makefile: 51; sh: 7
file content (98 lines) | stat: -rw-r--r-- 3,418 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# pylint: disable=missing-module-docstring
# pylint: disable=missing-class-docstring
# pylint: disable=missing-function-docstring
# pylint: disable=too-few-public-methods

from __future__ import annotations

import pytest

import smartcard.Synchronization


@pytest.mark.parametrize(
    "defined_methods, names, modified_methods",
    (
        # Nothing should be wrapped (str version)
        pytest.param(set(), "", set(), id="wrap nothing (str)"),
        pytest.param({"a"}, "", set(), id="wrap nothing (a, str)"),
        pytest.param({"a", "b"}, "", set(), id="wrap nothing (a+b, str)"),
        # Nothing should be wrapped (iterable version)
        pytest.param(set(), [], set(), id="wrap nothing (list)"),
        pytest.param({"a"}, [], set(), id="wrap nothing (a, list)"),
        pytest.param({"a", "b"}, [], set(), id="wrap nothing (a+b, list)"),
        # Everything should be wrapped
        pytest.param(set(), None, set(), id="wrap all"),
        pytest.param({"a"}, None, {"a"}, id="wrap all (a)"),
        pytest.param({"a", "b"}, None, {"a", "b"}, id="wrap all (a+b)"),
        # Only "a" should be wrapped (str version)
        pytest.param({"a"}, "a", {"a"}, id="wrap a only (a, str)"),
        pytest.param({"a", "b"}, "a", {"a"}, id="wrap a only (a+b, str)"),
        # Only "a" should be wrapped (list version)
        pytest.param({"a"}, ["a"], {"a"}, id="wrap a only (a, list)"),
        pytest.param({"a", "b"}, ["a"], {"a"}, id="wrap a only (a+b, list)"),
    ),
)
def test_synchronize(
    defined_methods: set[str],
    names: None | str | list[str],
    modified_methods: set[str],
):
    """Verify synchronize() wraps class methods as expected."""

    method_map = {method: lambda self: None for method in defined_methods}
    class_ = type("A", (object,), method_map)

    smartcard.Synchronization.synchronize(class_, names)

    for modified_method in modified_methods:
        assert getattr(class_, modified_method) is not method_map[modified_method]
    for unmodified_method in defined_methods - modified_methods:
        assert getattr(class_, unmodified_method) is method_map[unmodified_method]


def test_synchronization_reentrant_lock():
    """Verify Synchronization mutex locks are re-entrant by default."""

    class A(smartcard.Synchronization.Synchronization):
        def level_1(self):
            self.level_2()

        def level_2(self):
            return self

    smartcard.Synchronization.synchronize(A)

    instance = A()
    # If the synchronization lock is NOT re-entrant by default,
    # the test suite will hang when it reaches this line.
    instance.level_1()


def test_synchronization_wrapping():
    """Verify synchronized functions have correct names and docstrings."""

    class A(smartcard.Synchronization.Synchronization):
        def apple(self):
            """KEEP ME"""

    smartcard.Synchronization.synchronize(A)

    assert A.apple.__name__ == "apple"
    assert "KEEP ME" in A.apple.__doc__


def test_synchronization_kwargs():
    """Verify synchronized functions support arguments and keyword arguments."""

    class A(smartcard.Synchronization.Synchronization):
        def positional_only(self, positional, /):
            return positional

        def keyword_only(self, *, keyword):
            return keyword

    smartcard.Synchronization.synchronize(A)

    A().positional_only(True)
    A().keyword_only(keyword=True)