66from pathlib import Path
77from typing import List
88from typing import Optional
9+ from typing import Tuple
910
1011import drgn
1112import pytest
2425CTF_FILE : Optional [str ] = None
2526
2627CORE_DIR = Path .cwd () / "vmcores"
28+ KVER : Optional [KernelVersion ] = None
29+ PROG : Optional [drgn .Program ] = None
2730
2831
2932@pytest .fixture (scope = "session" )
3033def prog () -> drgn .Program :
31- p = drgn .Program ()
32- if VMCORE :
33- p .set_core_dump (VMCORE )
34- elif os .geteuid () == 0 :
35- p .set_kernel ()
36- else :
37- from drgn .internal .sudohelper import open_via_sudo
38-
39- p .set_core_dump (open_via_sudo ("/proc/kcore" , os .O_RDONLY ))
40- if CTF :
41- try :
42- from drgn .helpers .linux .ctf import load_ctf
43-
44- # CTF_FILE may be None here, in which case the default CTF file
45- # location is used (similar to below, where default DWARF debuginfo
46- # is loaded if we don't have a path).
47- load_ctf (p , path = CTF_FILE )
48- p .cache ["using_ctf" ] = True
49- # Mark in-tree modules as having debuginfo, so that the module API
50- # doesn't attempt to load debuginfo implicitly.
51- for module in p .modules ():
52- if isinstance (module , MainModule ) or module_is_in_tree (module ):
53- module .debug_file_status = ModuleFileStatus .DONT_NEED
54- except ModuleNotFoundError :
55- raise Exception ("CTF is not supported, cannot run CTF test" )
56- elif DEBUGINFO :
57- p .load_debug_info (DEBUGINFO )
58- else :
59- # Some UEK versions had mismatched vmlinux build IDs due to packaging
60- # issues. Most have been fixed, but for the remainder, set the main
61- # module's build ID to None manually, forcing drgn to skip verifying
62- # build IDs as it finds debuginfo.
63- ver = KernelVersion .parse (p ["UTS_RELEASE" ].string_ ().decode ())
64- if has_vmlinux_build_id_mismatch (ver ):
65- p .create_loaded_modules ()
66- p .main_module ().build_id = None
67- p .load_default_debug_info ()
68- return p
34+ assert PROG is not None
35+ return PROG
6936
7037
7138@pytest .fixture (scope = "session" )
@@ -96,7 +63,8 @@ def log_global_env_facts(prog, record_testsuite_property):
9663
9764@pytest .fixture (scope = "session" )
9865def kver (prog ):
99- return KernelVersion .parse (prog ["UTS_RELEASE" ].string_ ().decode ())
66+ assert KVER is not None
67+ return KVER
10068
10169
10270def pytest_addoption (parser ):
@@ -154,6 +122,9 @@ def pytest_configure(config):
154122 config .addinivalue_line (
155123 "markers" , "skip_vmcore(name): skip when debugging this core dump"
156124 )
125+ config .addinivalue_line (
126+ "markers" , "kver_min(ver): specify minimum kernel version (x.y.z)"
127+ )
157128
158129 core_dir = config .getoption ("vmcore_dir" )
159130 if core_dir :
@@ -204,11 +175,54 @@ def pytest_configure(config):
204175 if CTF :
205176 print ("TESTING WITH CTF" )
206177
178+ global PROG
179+ PROG = drgn .Program ()
180+ if VMCORE :
181+ PROG .set_core_dump (VMCORE )
182+ elif os .geteuid () == 0 :
183+ PROG .set_kernel ()
184+ else :
185+ from drgn .internal .sudohelper import open_via_sudo
186+
187+ PROG .set_core_dump (open_via_sudo ("/proc/kcore" , os .O_RDONLY ))
188+
189+ global KVER
190+ KVER = KernelVersion .parse (PROG ["UTS_RELEASE" ].string_ ().decode ())
191+ if CTF :
192+ try :
193+ from drgn .helpers .linux .ctf import load_ctf
194+
195+ # CTF_FILE may be None here, in which case the default CTF file
196+ # location is used (similar to below, where default DWARF debuginfo
197+ # is loaded if we don't have a path).
198+ load_ctf (PROG , path = CTF_FILE )
199+ PROG .cache ["using_ctf" ] = True
200+ # Mark in-tree modules as having debuginfo, so that the module API
201+ # doesn't attempt to load debuginfo implicitly.
202+ for module in PROG .modules ():
203+ if isinstance (module , MainModule ) or module_is_in_tree (module ):
204+ module .debug_file_status = ModuleFileStatus .DONT_NEED
205+ except ModuleNotFoundError :
206+ raise Exception ("CTF is not supported, cannot run CTF test" )
207+ elif DEBUGINFO :
208+ PROG .load_debug_info (DEBUGINFO )
209+ else :
210+ # Some UEK versions had mismatched vmlinux build IDs due to packaging
211+ # issues. Most have been fixed, but for the remainder, set the main
212+ # module's build ID to None manually, forcing drgn to skip verifying
213+ # build IDs as it finds debuginfo.
214+ if has_vmlinux_build_id_mismatch (KVER ):
215+ PROG .create_loaded_modules ()
216+ PROG .main_module ().build_id = None
217+ PROG .load_default_debug_info ()
218+
207219
208220def pytest_runtest_setup (item : pytest .Item ):
209221 skip_live = False
210222 vmcore_pats = []
211223 vmcore_skip_pats = []
224+ kver_min : Tuple [int , ...] = (0 ,)
225+ assert KVER is not None
212226
213227 for mark in item .iter_markers ():
214228 if mark .name == "skip_live" :
@@ -217,10 +231,17 @@ def pytest_runtest_setup(item: pytest.Item):
217231 vmcore_pats .append (mark .args [0 ])
218232 if mark .name == "skip_vmcore" :
219233 vmcore_skip_pats .append (mark .args [0 ])
234+ if mark .name == "kver_min" :
235+ kver_min = max (kver_min , tuple (map (int , mark .args [0 ].split ("." ))))
220236
221237 if vmcore_pats and vmcore_skip_pats :
222238 raise ValueError ("Can't mark a test both: vmcore() and skip_vmcore()" )
223239
240+ if KVER .version_tuple < kver_min :
241+ pytest .skip (
242+ f"Skipped test (requires minimum kernel version: { kver_min } )"
243+ )
244+
224245 if VMCORE :
225246 if vmcore_pats :
226247 if not any (fnmatch (VMCORE_NAME , p ) for p in vmcore_pats ):
0 commit comments