• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LudovicRousseau / PyKCS11 / 16367380199

18 Jul 2025 09:31AM UTC coverage: 93.474% (+5.9%) from 87.592%
16367380199

push

github

LudovicRousseau
IsNum(): CKA_HW_FEATURE_TYPE is also a numeric value

Thanks to Ivan Wallis for the bug report
"Venafi PKCS#11 Library fails with Unkown PKCS#11 type () during findObjects #140"
Closes: https://github.com/LudovicRousseau/PyKCS11/issues/140

5529 of 5915 relevant lines covered (93.47%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.81
/test/test_load.py
1
# pylint: disable=missing-module-docstring
2
# pylint: disable=missing-class-docstring
3
# pylint: disable=missing-function-docstring
4

5
import gc
1✔
6
import os
1✔
7
import platform
1✔
8
import shutil
1✔
9
import unittest
1✔
10
from pathlib import Path
1✔
11
from tempfile import TemporaryDirectory
1✔
12

13
from PyKCS11 import PyKCS11
1✔
14

15

16
class TestUtil(unittest.TestCase):
1✔
17
    def setUp(self):
1✔
18
        self.pkcs11 = PyKCS11.PyKCS11Lib()
1✔
19
        self.tmpdir = TemporaryDirectory()
1✔
20
        self.lib1_name = os.environ["PYKCS11LIB"]
1✔
21
        # create a tmp copy of the main lib
22
        # to use as a different library in tests
23
        self.lib2_name = str(Path(self.tmpdir.name) / Path(self.lib1_name).name)
1✔
24
        shutil.copy(self.lib1_name, self.tmpdir.name)
1✔
25

26
    def tearDown(self):
1✔
27
        del self.pkcs11
1✔
28
        if platform.system() != "Windows":
1✔
29
            self.tmpdir.cleanup()
1✔
30
        del self.tmpdir
1✔
31
        del self.lib1_name
1✔
32
        del self.lib2_name
1✔
33

34
    def openSession(self, lib):
1✔
35
        slot = lib.getSlotList(tokenPresent=True)[0]
1✔
36
        return lib.openSession(slot, PyKCS11.CKF_SERIAL_SESSION)
1✔
37

38
    def test_load(self):
1✔
39
        # create two instances with default library
40
        lib1 = PyKCS11.PyKCS11Lib().load()
1✔
41
        lib2 = PyKCS11.PyKCS11Lib().load()
1✔
42

43
        # expect two instances with the same library loaded
44
        self.assertTrue(hasattr(lib1, "pkcs11dll_filename"))
1✔
45
        self.assertTrue(hasattr(lib2, "pkcs11dll_filename"))
1✔
46
        self.assertEqual(len(lib1._loaded_libs), 1)
1✔
47
        self.assertEqual(len(lib2._loaded_libs), 1)
1✔
48

49
        self.openSession(lib1)
1✔
50

51
        # unload the first library
52
        del lib1
1✔
53
        gc.collect()
1✔
54

55
        # one instance remaining, the library is still in use
56
        self.openSession(lib2)
1✔
57
        self.assertEqual(len(lib2._loaded_libs), 1)
1✔
58

59
    def test_multiple_load(self):
1✔
60
        # load two different libraries
61
        lib1 = PyKCS11.PyKCS11Lib().load(self.lib1_name)
1✔
62
        lib2 = PyKCS11.PyKCS11Lib().load(self.lib2_name)
1✔
63

64
        # _loaded_libs is shared across all instances
65
        # check the value in self.pkcs11
66
        self.assertEqual(len(self.pkcs11._loaded_libs), 2)
1✔
67
        lib1 = PyKCS11.PyKCS11Lib()  # unload lib1
1✔
68
        self.assertEqual(len(self.pkcs11._loaded_libs), 1)
1✔
69
        lib2 = PyKCS11.PyKCS11Lib()  # unload lib2
1✔
70
        self.assertEqual(len(self.pkcs11._loaded_libs), 0)
1✔
71

72
    def test_invalid_load(self):
1✔
73
        # Library not found
74
        lib = "nolib"
1✔
75
        with self.assertRaises(PyKCS11.PyKCS11Error) as cm:
1✔
76
            self.pkcs11.load(lib)
1✔
77
        the_exception = cm.exception
1✔
78
        self.assertEqual(the_exception.value, -1)
1✔
79
        self.assertEqual(the_exception.text, lib)
1✔
80
        self.assertEqual(str(the_exception), f"Load ({lib})")
1✔
81
        self.assertEqual(len(self.pkcs11._loaded_libs), 0)
1✔
82

83
        # C_GetFunctionList() not found
84
        if platform.system() == "Linux":
1✔
85
            # GNU/Linux
86
            lib = "libc.so.6"
1✔
87
        elif platform.system() == "Darwin":
×
88
            # macOS
89
            lib = "/usr/lib/libSystem.B.dylib"
×
90
        else:
91
            # Windows
92
            lib = "WinSCard.dll"
×
93

94
        with self.assertRaises(PyKCS11.PyKCS11Error) as cm:
1✔
95
            self.pkcs11.load(lib)
1✔
96
        the_exception = cm.exception
1✔
97
        self.assertEqual(the_exception.value, -4)
1✔
98
        self.assertEqual(the_exception.text, lib)
1✔
99
        self.assertEqual(str(the_exception), f"C_GetFunctionList() not found ({lib})")
1✔
100
        self.assertEqual(len(self.pkcs11._loaded_libs), 0)
1✔
101

102
        # try to load the improper lib another time
103
        with self.assertRaises(PyKCS11.PyKCS11Error) as cm:
1✔
104
            self.pkcs11.load(lib)
1✔
105
        the_exception = cm.exception
1✔
106
        self.assertEqual(the_exception.value, -4)
1✔
107
        self.assertEqual(the_exception.text, lib)
1✔
108
        self.assertEqual(str(the_exception), f"C_GetFunctionList() not found ({lib})")
1✔
109
        self.assertEqual(len(self.pkcs11._loaded_libs), 0)
1✔
110

111
        # finally, load a valid library
112
        self.pkcs11.load()
1✔
113
        self.assertEqual(len(self.pkcs11._loaded_libs), 1)
1✔
114

115
    def test_specific_load(self):
1✔
116
        # load two different libraries sequentially
117
        self.pkcs11.load(self.lib1_name)
1✔
118
        self.pkcs11.load(self.lib2_name)
1✔
119

120
        # the second load should've unloaded the first library
121
        self.assertEqual(len(self.pkcs11._loaded_libs), 1)
1✔
122
        self.assertEqual(self.pkcs11.pkcs11dll_filename, self.lib2_name)
1✔
123

124
        # reload the first library
125
        self.pkcs11 = PyKCS11.PyKCS11Lib()
1✔
126
        self.pkcs11.load(self.lib1_name)
1✔
127

128
        # try to open a session
129
        self.assertIsNotNone(self.openSession(self.pkcs11))
1✔
130

131
    def test_unload(self):
1✔
132
        self.pkcs11.load().unload()
1✔
133
        # no pkcs11dll_filename should remain after unload
134
        self.assertIsNone(self.pkcs11.pkcs11dll_filename)
1✔
135

136
        self.pkcs11.load()
1✔
137
        self.openSession(self.pkcs11)
1✔
138
        # one library has been loaded
139
        self.assertEqual(len(self.pkcs11._loaded_libs), 1)
1✔
140
        self.assertIsNotNone(self.pkcs11.pkcs11dll_filename)
1✔
141

142
        self.pkcs11.unload()
1✔
143
        gc.collect()
1✔
144
        # manually unloaded the library using gc.collect()
145
        self.assertEqual(len(self.pkcs11._loaded_libs), 0)
1✔
146
        self.assertIsNone(self.pkcs11.pkcs11dll_filename)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc