Repository navigation
Expand file tree
/
Copy pathtest_python.py
More file actions
179 lines (130 loc) · 5.99 KB
/
Copy pathtest_python.py
File metadata and controls
179 lines (130 loc) · 5.99 KB
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""Smoke tests for the Python interpreter built from source in the image.
Run inside the built image, for example:
docker run --rm -v "$PWD/tests:/tests:ro" \
-e EXPECTED_PYTHON_VERSION=3.11.17 -e EXPECTED_MACHINE=x86_64 \
rocky8-python python3 -m unittest discover -v -s /tests
EXPECTED_PYTHON_VERSION and EXPECTED_MACHINE are optional; the corresponding
checks are skipped when they are not set.
"""
import os
import platform
import subprocess
import sys
import tempfile
import unittest
PYTHON_PREFIX = "/usr/local"
def _square(x):
return x * x
class InterpreterTest(unittest.TestCase):
def test_interpreter_is_source_build(self):
self.assertEqual(sys.prefix, PYTHON_PREFIX)
self.assertTrue(os.path.realpath(sys.executable).startswith(PYTHON_PREFIX + "/bin/"))
def test_python3_on_path_is_source_build(self):
out = subprocess.run(
["python3", "-c", "import sys; print(sys.prefix)"],
check=True, capture_output=True, text=True,
).stdout.strip()
self.assertEqual(out, PYTHON_PREFIX)
def test_version(self):
expected = os.environ.get("EXPECTED_PYTHON_VERSION")
if not expected:
self.skipTest("EXPECTED_PYTHON_VERSION not set")
self.assertEqual(platform.python_version(), expected)
def test_architecture(self):
expected = os.environ.get("EXPECTED_MACHINE")
if not expected:
self.skipTest("EXPECTED_MACHINE not set")
self.assertEqual(platform.machine(), expected)
class ExtensionModuleTest(unittest.TestCase):
"""Modules that depend on the -devel packages installed before the build."""
def test_ssl(self):
import ssl
self.assertIn("OpenSSL", ssl.OPENSSL_VERSION)
ctx = ssl.create_default_context()
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertGreater(ctx.cert_store_stats()["x509_ca"], 0, "no system CA certificates loaded")
def test_hashlib(self):
import _hashlib # noqa: F401 OpenSSL backed hashes
import hashlib
self.assertEqual(
hashlib.sha256(b"abc").hexdigest(),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
)
self.assertEqual(hashlib.md5(b"abc").hexdigest(), "900150983cd24fb0d6963f7d28e17f72")
def test_zlib_and_gzip(self):
import gzip
import zlib
data = b"rocky8-python " * 1000
self.assertEqual(zlib.decompress(zlib.compress(data)), data)
self.assertEqual(gzip.decompress(gzip.compress(data)), data)
def test_ctypes(self):
import ctypes
import ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library("c"))
self.assertEqual(libc.strlen(b"hello"), 5)
def test_decimal_c_accelerator(self):
import _decimal # noqa: F401
import decimal
self.assertEqual(decimal.Decimal("0.1") + decimal.Decimal("0.2"), decimal.Decimal("0.3"))
class RuntimeTest(unittest.TestCase):
def test_json_roundtrip(self):
import json
obj = {"a": [1, 2.5, None, True], "b": "äö€"}
self.assertEqual(json.loads(json.dumps(obj)), obj)
def test_threading(self):
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=4) as pool:
self.assertEqual(list(pool.map(_square, range(10))), [x * x for x in range(10)])
def test_multiprocessing(self):
from multiprocessing import Pool
with Pool(2) as pool:
self.assertEqual(pool.map(_square, range(10)), [x * x for x in range(10)])
def test_asyncio(self):
import asyncio
async def main():
await asyncio.sleep(0)
return 42
self.assertEqual(asyncio.run(main()), 42)
class PackagingTest(unittest.TestCase):
def test_pip(self):
subprocess.run([sys.executable, "-m", "pip", "--version"], check=True, capture_output=True)
def test_venv_with_pip(self):
with tempfile.TemporaryDirectory() as tmp:
venv_dir = os.path.join(tmp, "venv")
subprocess.run([sys.executable, "-m", "venv", venv_dir], check=True)
venv_python = os.path.join(venv_dir, "bin", "python")
out = subprocess.run(
[venv_python, "-c", "import sys; print(sys.prefix != sys.base_prefix)"],
check=True, capture_output=True, text=True,
).stdout.strip()
self.assertEqual(out, "True")
subprocess.run([venv_python, "-m", "pip", "--version"], check=True, capture_output=True)
def _version_tuple(version):
return tuple(int(part) for part in version.split(".")[:3])
class EmsignIncidentTest(unittest.TestCase):
"""Checks for the eMudhra/emSign CA incident (CVE-2026-113470).
pip always trusts its vendored certifi, so it must be new enough to have the fix. The version is checked rather
than the presence of "emSign" certificates, because unaffected emSign roots legitimately remain in the bundles.
"""
MIN_PIP = (26, 2, 2)
MIN_CERTIFI = (2026, 10, 19)
def _pip_version(self, python):
out = subprocess.run(
[python, "-m", "pip", "--version"], check=True, capture_output=True, text=True,
).stdout
return _version_tuple(out.split()[1])
def test_pip_is_fixed(self):
self.assertGreaterEqual(self._pip_version(sys.executable), self.MIN_PIP)
def test_venv_pip_is_fixed(self):
with tempfile.TemporaryDirectory() as tmp:
venv_dir = os.path.join(tmp, "venv")
subprocess.run([sys.executable, "-m", "venv", venv_dir], check=True)
self.assertGreaterEqual(self._pip_version(os.path.join(venv_dir, "bin", "python")), self.MIN_PIP)
def test_certifi_if_installed_is_fixed(self):
try:
import certifi
except ImportError:
self.skipTest("certifi not installed")
self.assertGreaterEqual(_version_tuple(certifi.__version__), self.MIN_CERTIFI)
if __name__ == "__main__":
unittest.main(verbosity=2)