Rework handling of GFP flags
This commit is contained in:
parent
84073ba0ce
commit
82c8af8842
@ -427,8 +427,11 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Memory allocation flags<br>(gfp_mask)</td>
|
<td>Memory allocation flags<br>(gfp_mask)</td>
|
||||||
<td class="trigger_proc_gfp_mask text--align-right"></td>
|
<td class="trigger_proc_gfp_mask text--align-right"></td>
|
||||||
<td>These flags are used to control the kernel internal memory allocation<br>
|
<td>These flags are also called GFP (get free pages) flags. They control the kernel-internal memory
|
||||||
GFP stands for <code>__get_free_pages()</code>.</td>
|
allocation.<br>
|
||||||
|
Some OOM variants include the individual flags in addition to the hexadecimal representation. The flags
|
||||||
|
are calculated if they are not specified.
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Node mask to show on which CPU Cores this process can run<br>(nodemask)</td>
|
<td>Node mask to show on which CPU Cores this process can run<br>(nodemask)</td>
|
||||||
@ -936,6 +939,7 @@ window.onerror = function (msg, url, lineNo, columnNo, errorObj) {
|
|||||||
<ol>
|
<ol>
|
||||||
<li>Fix memory calculation in summary section</li>
|
<li>Fix memory calculation in summary section</li>
|
||||||
<li>Fix calculation of GFP flags</li>
|
<li>Fix calculation of GFP flags</li>
|
||||||
|
<li>Rework handling of GFP flags</li>
|
||||||
<li>...</li>
|
<li>...</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
175
OOMAnalyser.py
175
OOMAnalyser.py
@ -377,6 +377,18 @@ class BaseKernelConfig:
|
|||||||
(see https://github.com/torvalds/linux/commit/e67d4ca79aaf9d13a00d229b1b1c96b86828e8ba#diff-020720d0699e3ae1afb6fcd815ca8500)
|
(see https://github.com/torvalds/linux/commit/e67d4ca79aaf9d13a00d229b1b1c96b86828e8ba#diff-020720d0699e3ae1afb6fcd815ca8500)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
gfp_reverse_lookup = []
|
||||||
|
"""
|
||||||
|
Sorted list of flags used to do a reverse lookup.
|
||||||
|
|
||||||
|
This list doesn't contain all flags. It contains the "useful flags" (GFP_*) as
|
||||||
|
well as "modifier flags" (__GFP_*). "Plain flags" (___GFP_*) are not part of
|
||||||
|
this list.
|
||||||
|
|
||||||
|
@type: List(str)
|
||||||
|
@see: _gfp_create_reverse_lookup()
|
||||||
|
"""
|
||||||
|
|
||||||
pstable_items = [
|
pstable_items = [
|
||||||
"pid",
|
"pid",
|
||||||
"uid",
|
"uid",
|
||||||
@ -445,6 +457,103 @@ class BaseKernelConfig:
|
|||||||
if self.EXTRACT_PATTERN_OVERLAY:
|
if self.EXTRACT_PATTERN_OVERLAY:
|
||||||
self.EXTRACT_PATTERN.update(self.EXTRACT_PATTERN_OVERLAY)
|
self.EXTRACT_PATTERN.update(self.EXTRACT_PATTERN_OVERLAY)
|
||||||
|
|
||||||
|
self._gfp_calc_all_values()
|
||||||
|
self.gfp_reverse_lookup = self._gfp_create_reverse_lookup()
|
||||||
|
|
||||||
|
def _gfp_calc_all_values(self):
|
||||||
|
"""
|
||||||
|
Calculate decimal values for all GFP flags and store in in GFP_FLAGS[<flag>]["_value"]
|
||||||
|
"""
|
||||||
|
# __pragma__ ('jsiter')
|
||||||
|
for flag in self.GFP_FLAGS:
|
||||||
|
value = self._gfp_flag2decimal(flag)
|
||||||
|
self.GFP_FLAGS[flag]["_value"] = value
|
||||||
|
# __pragma__ ('nojsiter')
|
||||||
|
|
||||||
|
def _gfp_flag2decimal(self, flag):
|
||||||
|
"""\
|
||||||
|
Convert a single flag into a decimal value.
|
||||||
|
|
||||||
|
The flags can be concatenated with "|" or "~" and negated with "~". The
|
||||||
|
flags will be processed from left to right. Parentheses are not supported.
|
||||||
|
"""
|
||||||
|
if flag not in self.GFP_FLAGS:
|
||||||
|
error("No definition for flag {} found".format(flag))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
value = self.GFP_FLAGS[flag]["value"]
|
||||||
|
if isinstance(value, int):
|
||||||
|
return value
|
||||||
|
|
||||||
|
tokenlist = iter(re.split("([|&])", value))
|
||||||
|
operator = "|" # set to process first flag
|
||||||
|
negate_rvalue = False
|
||||||
|
lvalue = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
token = next(tokenlist)
|
||||||
|
except StopIteration:
|
||||||
|
break
|
||||||
|
token = token.strip()
|
||||||
|
if token in ["|", "&"]:
|
||||||
|
operator = token
|
||||||
|
continue
|
||||||
|
|
||||||
|
if token.startswith("~"):
|
||||||
|
token = token[1:]
|
||||||
|
negate_rvalue = True
|
||||||
|
|
||||||
|
if token.isdigit():
|
||||||
|
rvalue = int(token)
|
||||||
|
elif token.startswith("0x") and token[2:].isdigit():
|
||||||
|
rvalue = int(token, 16)
|
||||||
|
else:
|
||||||
|
# it's not a decimal nor a hexadecimal value - reiterate assuming it's a flag string
|
||||||
|
rvalue = self._gfp_flag2decimal(token)
|
||||||
|
|
||||||
|
if negate_rvalue:
|
||||||
|
rvalue = ~rvalue
|
||||||
|
|
||||||
|
if operator == "|":
|
||||||
|
lvalue |= rvalue
|
||||||
|
elif operator == "&":
|
||||||
|
lvalue &= rvalue
|
||||||
|
|
||||||
|
operator = None
|
||||||
|
negate_rvalue = False
|
||||||
|
|
||||||
|
return lvalue
|
||||||
|
|
||||||
|
def _gfp_create_reverse_lookup(self):
|
||||||
|
"""
|
||||||
|
Create a sorted list of flags used to do a reverse lookup from value to the flag.
|
||||||
|
|
||||||
|
@rtype: List(str)
|
||||||
|
"""
|
||||||
|
# __pragma__ ('jsiter')
|
||||||
|
useful = [
|
||||||
|
key
|
||||||
|
for key in self.GFP_FLAGS
|
||||||
|
if key.startswith("GFP") and self.GFP_FLAGS[key]["_value"] != 0
|
||||||
|
]
|
||||||
|
useful = sorted(
|
||||||
|
useful, key=lambda key: self.GFP_FLAGS[key]["_value"], reverse=True
|
||||||
|
)
|
||||||
|
modifier = [
|
||||||
|
key
|
||||||
|
for key in self.GFP_FLAGS
|
||||||
|
if key.startswith("__GFP") and self.GFP_FLAGS[key]["_value"] != 0
|
||||||
|
]
|
||||||
|
modifier = sorted(
|
||||||
|
modifier, key=lambda key: self.GFP_FLAGS[key]["_value"], reverse=True
|
||||||
|
)
|
||||||
|
# __pragma__ ('nojsiter')
|
||||||
|
|
||||||
|
# useful + modifier produces a string with all values concatenated
|
||||||
|
res = useful
|
||||||
|
res.extend(modifier)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
class KernelConfig_4_6(BaseKernelConfig):
|
class KernelConfig_4_6(BaseKernelConfig):
|
||||||
# Support changes:
|
# Support changes:
|
||||||
@ -1029,9 +1138,8 @@ class OOMAnalyser:
|
|||||||
flags = self.oom_result.details["trigger_proc_gfp_flags"]
|
flags = self.oom_result.details["trigger_proc_gfp_flags"]
|
||||||
del self.oom_result.details["trigger_proc_gfp_flags"]
|
del self.oom_result.details["trigger_proc_gfp_flags"]
|
||||||
else:
|
else:
|
||||||
flags, unknown = self._hex2flags(
|
flags, unknown = self._gfp_hex2flags(
|
||||||
self.oom_result.details["trigger_proc_gfp_mask"],
|
self.oom_result.details["trigger_proc_gfp_mask"],
|
||||||
self.oom_result.kconfig.GFP_FLAGS,
|
|
||||||
)
|
)
|
||||||
if unknown:
|
if unknown:
|
||||||
flags.append("0x{0:x}".format(unknown))
|
flags.append("0x{0:x}".format(unknown))
|
||||||
@ -1101,77 +1209,26 @@ class OOMAnalyser:
|
|||||||
self.oom_result.details["_pstable"][pid] = {}
|
self.oom_result.details["_pstable"][pid] = {}
|
||||||
self.oom_result.details["_pstable"][pid].update(details)
|
self.oom_result.details["_pstable"][pid].update(details)
|
||||||
|
|
||||||
def _hex2flags(self, hexvalue, flag_definition):
|
def _gfp_hex2flags(self, hexvalue):
|
||||||
"""\
|
"""\
|
||||||
Convert the hexadecimal value into flags specified by definition
|
Convert the hexadecimal value into flags specified by definition
|
||||||
|
|
||||||
@return: list of flags and the decimal sum of all unknown flags
|
@return: Unsorted list of flags and the sum of all unknown flags as integer
|
||||||
|
@rtype: List(str), int
|
||||||
"""
|
"""
|
||||||
remaining = int(hexvalue, 16)
|
remaining = int(hexvalue, 16)
|
||||||
converted_flags = []
|
converted_flags = []
|
||||||
|
|
||||||
# __pragma__ ('jsiter')
|
for flag in self.oom_result.kconfig.gfp_reverse_lookup:
|
||||||
for flag in flag_definition:
|
value = self.oom_result.kconfig.GFP_FLAGS[flag]["_value"]
|
||||||
value = self._flag2decimal(flag, flag_definition)
|
|
||||||
if (remaining & value) == value:
|
if (remaining & value) == value:
|
||||||
# delete flag by "and" with a reverted mask
|
# delete flag by "and" with a reverted mask
|
||||||
remaining &= ~value
|
remaining &= ~value
|
||||||
converted_flags.append(flag)
|
converted_flags.append(flag)
|
||||||
# __pragma__ ('nojsiter')
|
|
||||||
|
|
||||||
|
converted_flags.sort()
|
||||||
return converted_flags, remaining
|
return converted_flags, remaining
|
||||||
|
|
||||||
def _flag2decimal(self, flag, flag_definition):
|
|
||||||
"""\
|
|
||||||
Convert a single flag into a decimal value
|
|
||||||
"""
|
|
||||||
if flag not in flag_definition:
|
|
||||||
error("No definition for flag {} found".format(flag))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
value = flag_definition[flag]["value"]
|
|
||||||
if isinstance(value, int):
|
|
||||||
return value
|
|
||||||
|
|
||||||
tokenlist = iter(re.split("([|&])", value))
|
|
||||||
operator = "|" # set to process first flag
|
|
||||||
negate_rvalue = False
|
|
||||||
lvalue = 0
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
token = next(tokenlist)
|
|
||||||
except StopIteration:
|
|
||||||
break
|
|
||||||
token = token.strip()
|
|
||||||
if token in ["|", "&"]:
|
|
||||||
operator = token
|
|
||||||
continue
|
|
||||||
|
|
||||||
if token.startswith("~"):
|
|
||||||
token = token[1:]
|
|
||||||
negate_rvalue = True
|
|
||||||
|
|
||||||
if token.isdigit():
|
|
||||||
rvalue = int(token)
|
|
||||||
elif token.startswith("0x") and token[2:].isdigit():
|
|
||||||
rvalue = int(token, 16)
|
|
||||||
else:
|
|
||||||
# it's not a decimal nor a hexadecimal value - reiterate assuming it's a flag string
|
|
||||||
rvalue = self._flag2decimal(token, flag_definition)
|
|
||||||
|
|
||||||
if negate_rvalue:
|
|
||||||
rvalue = ~rvalue
|
|
||||||
|
|
||||||
if operator == "|":
|
|
||||||
lvalue |= rvalue
|
|
||||||
elif operator == "&":
|
|
||||||
lvalue &= rvalue
|
|
||||||
|
|
||||||
operator = None
|
|
||||||
negate_rvalue = False
|
|
||||||
|
|
||||||
return lvalue
|
|
||||||
|
|
||||||
def _convert_numeric_results_to_integer(self):
|
def _convert_numeric_results_to_integer(self):
|
||||||
"""Convert all *_pages and *_kb to integer"""
|
"""Convert all *_pages and *_kb to integer"""
|
||||||
# __pragma__ ('jsiter')
|
# __pragma__ ('jsiter')
|
||||||
|
174
test.py
174
test.py
@ -189,18 +189,20 @@ class TestInBrowser(TestBase):
|
|||||||
trigger_proc_gfp_mask = self.driver.find_element(
|
trigger_proc_gfp_mask = self.driver.find_element(
|
||||||
By.CLASS_NAME, "trigger_proc_gfp_mask"
|
By.CLASS_NAME, "trigger_proc_gfp_mask"
|
||||||
)
|
)
|
||||||
# 0x201da:
|
# 0x201da will split into
|
||||||
# __GFP_HIGHMEM 2 0x02
|
# GFP_HIGHUSER_MOVABLE 0x200da
|
||||||
# __GFP_MOVABLE 8 0x08
|
# (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | __GFP_HIGHMEM | __GFP_MOVABLE)
|
||||||
# __GFP_RECLAIMABLE 16 0x10
|
# __GFP_WAIT 0x10
|
||||||
# __GFP_IO 64 0x40
|
# __GFP_IO 0x40
|
||||||
# __GFP_FS 128 0x80
|
# __GFP_FS 0x80
|
||||||
# __GFP_COLD 256 0x100
|
# __GFP_HARDWALL 0x20000
|
||||||
# __GFP_HARDWALL 131072 0x20000
|
# __GFP_HIGHMEM 0x02
|
||||||
# 0x201da
|
# __GFP_MOVABLE 0x08
|
||||||
|
# __GFP_COLD 0x100
|
||||||
|
# sum: 0x201da
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
trigger_proc_gfp_mask.text,
|
trigger_proc_gfp_mask.text,
|
||||||
"0x201da (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_RECLAIMABLE | __GFP_IO | __GFP_FS | __GFP_COLD | __GFP_HARDWALL)",
|
"0x201da (GFP_HIGHUSER_MOVABLE | __GFP_COLD)",
|
||||||
"Unexpected GFP Mask",
|
"Unexpected GFP Mask",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -257,6 +259,14 @@ class TestInBrowser(TestBase):
|
|||||||
trigger_proc_gfp_mask = self.driver.find_element(
|
trigger_proc_gfp_mask = self.driver.find_element(
|
||||||
By.CLASS_NAME, "trigger_proc_gfp_mask"
|
By.CLASS_NAME, "trigger_proc_gfp_mask"
|
||||||
)
|
)
|
||||||
|
# 0xcc0 will split into
|
||||||
|
# GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
|
||||||
|
# __GFP_RECLAIM (___GFP_DIRECT_RECLAIM | ___GFP_KSWAPD_RECLAIM)
|
||||||
|
# ___GFP_DIRECT_RECLAIM 0x400
|
||||||
|
# ___GFP_KSWAPD_RECLAIM 0x800
|
||||||
|
# __GFP_IO 0x40
|
||||||
|
# __GFP_FS 0x80
|
||||||
|
# sum: 0xCC0
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
trigger_proc_gfp_mask.text, "0xcc0 (GFP_KERNEL)", "Unexpected GFP Mask"
|
trigger_proc_gfp_mask.text, "0xcc0 (GFP_KERNEL)", "Unexpected GFP Mask"
|
||||||
)
|
)
|
||||||
@ -653,19 +663,19 @@ Hardware name: HP ProLiant DL385 G7, BIOS A18 12/08/2012
|
|||||||
"CPU: 4 PID: 29481 Comm: sed Not tainted 4.6.0-514 #1",
|
"CPU: 4 PID: 29481 Comm: sed Not tainted 4.6.0-514 #1",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
OOMAnalyser.KernelConfigRhel7(),
|
OOMAnalyser.KernelConfig_3_10_EL7(),
|
||||||
"CPU: 4 PID: 29481 Comm: sed Not tainted 3.10.0-1062.9.1.el7.x86_64 #1",
|
"CPU: 4 PID: 29481 Comm: sed Not tainted 3.10.0-1062.9.1.el7.x86_64 #1",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
OOMAnalyser.KernelConfig_5_0(),
|
OOMAnalyser.KernelConfig_5_1(),
|
||||||
"CPU: 4 PID: 29481 Comm: sed Not tainted 5.5.1 #1",
|
"CPU: 4 PID: 29481 Comm: sed Not tainted 5.5.1 #1",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
OOMAnalyser.KernelConfig_5_8(),
|
OOMAnalyser.KernelConfig_5_18(),
|
||||||
"CPU: 4 PID: 29481 Comm: sed Not tainted 5.23.0 #1",
|
"CPU: 4 PID: 29481 Comm: sed Not tainted 5.23.0 #1",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
OOMAnalyser.KernelConfig_5_8(),
|
OOMAnalyser.KernelConfig_5_18(),
|
||||||
"CPU: 4 PID: 29481 Comm: sed Not tainted 6.12.0 #1",
|
"CPU: 4 PID: 29481 Comm: sed Not tainted 6.12.0 #1",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -685,6 +695,142 @@ Hardware name: HP ProLiant DL385 G7, BIOS A18 12/08/2012
|
|||||||
% (type(kcfg), type(result), kversion),
|
% (type(kcfg), type(result), kversion),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_007_gfp_processing(self):
|
||||||
|
"""Test processing GFP flags"""
|
||||||
|
oom = OOMAnalyser.OOMEntity(OOMAnalyser.OOMDisplay.example_rhel7)
|
||||||
|
analyser = OOMAnalyser.OOMAnalyser(oom)
|
||||||
|
success = analyser.analyse()
|
||||||
|
self.assertTrue(success, "OOM analysis failed")
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
analyser.oom_result.kconfig.release,
|
||||||
|
(3, 10, ".el7."),
|
||||||
|
"Wrong KernelConfig release",
|
||||||
|
)
|
||||||
|
|
||||||
|
for flag, hex_value in [
|
||||||
|
("__GFP_DMA", 0x01),
|
||||||
|
("__GFP_WAIT", 0x10),
|
||||||
|
("__GFP_IO", 0x40),
|
||||||
|
("__GFP_FS", 0x80),
|
||||||
|
("GFP_KERNEL", 0xD0), # __GFP_WAIT | __GFP_IO | __GFP_FS
|
||||||
|
("__GFP_UNKNOWN", 0x00), # unknown GFP flag
|
||||||
|
]:
|
||||||
|
self.assertEqual(
|
||||||
|
analyser.oom_result.kconfig._gfp_flag2decimal(flag),
|
||||||
|
hex_value,
|
||||||
|
"Invalid decimal value for %s" % flag,
|
||||||
|
)
|
||||||
|
|
||||||
|
for hex_value, flags_expected, unknown_expected in [
|
||||||
|
(
|
||||||
|
"0x01",
|
||||||
|
["__GFP_DMA"],
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
("0x05", ["__GFP_DMA", "__GFP_DMA32"], 0),
|
||||||
|
(
|
||||||
|
"0x5000000", # 0x1000000 + 0x4000000
|
||||||
|
["__GFP_WRITE"],
|
||||||
|
0x4000000,
|
||||||
|
),
|
||||||
|
("0x201da", ["GFP_HIGHUSER_MOVABLE", "__GFP_COLD"], 0),
|
||||||
|
]:
|
||||||
|
flags_calculated, unknown_calculated = analyser._gfp_hex2flags(hex_value)
|
||||||
|
self.assertEqual(
|
||||||
|
flags_calculated,
|
||||||
|
flags_expected,
|
||||||
|
"Invalid flag(s) for hex value %s" % hex_value,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
unknown_calculated,
|
||||||
|
unknown_expected,
|
||||||
|
"Invalid remaining / not resolved decimal flag value",
|
||||||
|
)
|
||||||
|
|
||||||
|
oom = OOMAnalyser.OOMEntity(OOMAnalyser.OOMDisplay.example_ubuntu2110)
|
||||||
|
analyser = OOMAnalyser.OOMAnalyser(oom)
|
||||||
|
success = analyser.analyse()
|
||||||
|
self.assertTrue(success, "OOM analysis failed")
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
analyser.oom_result.kconfig.release,
|
||||||
|
(5, 8, ""),
|
||||||
|
"Wrong KernelConfig release",
|
||||||
|
)
|
||||||
|
|
||||||
|
for flag, hex_value in [
|
||||||
|
("__GFP_DMA", 0x01),
|
||||||
|
("__GFP_IO", 0x40),
|
||||||
|
("__GFP_FS", 0x80),
|
||||||
|
(
|
||||||
|
"GFP_KERNEL",
|
||||||
|
0xCC0,
|
||||||
|
), # (__GFP_RECLAIM (___GFP_DIRECT_RECLAIM | ___GFP_KSWAPD_RECLAIM) | __GFP_IO | __GFP_FS)
|
||||||
|
("__GFP_UNKNOWN", 0x00), # unknown GFP flag
|
||||||
|
]:
|
||||||
|
self.assertEqual(
|
||||||
|
analyser.oom_result.kconfig._gfp_flag2decimal(flag),
|
||||||
|
hex_value,
|
||||||
|
"Invalid decimal value for %s" % flag,
|
||||||
|
)
|
||||||
|
|
||||||
|
for hex_value, flags_expected, unknown_expected in [
|
||||||
|
(
|
||||||
|
"0x01",
|
||||||
|
["__GFP_DMA"],
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
("0x05", ["__GFP_DMA", "__GFP_DMA32"], 0),
|
||||||
|
(
|
||||||
|
"0x4001000", # 0x1000 + 0x4000000
|
||||||
|
["__GFP_WRITE"],
|
||||||
|
0x4000000,
|
||||||
|
),
|
||||||
|
]:
|
||||||
|
flags_calculated, unknown_calculated = analyser._gfp_hex2flags(hex_value)
|
||||||
|
self.assertEqual(
|
||||||
|
flags_calculated,
|
||||||
|
flags_expected,
|
||||||
|
"Invalid flag(s) for hex value %s" % hex_value,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
unknown_calculated,
|
||||||
|
unknown_expected,
|
||||||
|
"Invalid remaining / not resolved decimal flag value",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_008_kversion_check(self):
|
||||||
|
"""Test check for minimum kernel version"""
|
||||||
|
oom = OOMAnalyser.OOMEntity(OOMAnalyser.OOMDisplay.example_rhel7)
|
||||||
|
analyser = OOMAnalyser.OOMAnalyser(oom)
|
||||||
|
|
||||||
|
for kversion, min_version, expected_result in (
|
||||||
|
("5.19-rc6", (5, 16, ""), True),
|
||||||
|
("5.19-rc6", (5, 19, ""), True),
|
||||||
|
("5.19-rc6", (5, 20, ""), False),
|
||||||
|
("5.18.6-arch1-1", (5, 18, ""), True),
|
||||||
|
("5.18.6-arch1-1", (5, 1, ""), True),
|
||||||
|
("5.18.6-arch1-1", (5, 19, ""), False),
|
||||||
|
("5.13.0-1028-aws #31~20.04.1-Ubuntu", (5, 14, ""), False),
|
||||||
|
("5.13.0-1028-aws #31~20.04.1-Ubuntu", (5, 13, ""), True),
|
||||||
|
("5.13.0-1028-aws #31~20.04.1-Ubuntu", (5, 13, "-aws"), True),
|
||||||
|
("5.13.0-1028-aws #31~20.04.1-Ubuntu", (5, 13, "not_in_version"), False),
|
||||||
|
("5.13.0-1028-aws #31~20.04.1-Ubuntu", (5, 12, ""), True),
|
||||||
|
("4.14.288", (5, 0, ""), False),
|
||||||
|
("4.14.288", (4, 14, ""), True),
|
||||||
|
("3.10.0-514.6.1.el7.x86_64 #1", (3, 11, ""), False),
|
||||||
|
("3.10.0-514.6.1.el7.x86_64 #1", (3, 10, ".el7."), True),
|
||||||
|
("3.10.0-514.6.1.el7.x86_64 #1", (3, 10, ""), True),
|
||||||
|
("3.10.0-514.6.1.el7.x86_64 #1", (3, 9, ""), True),
|
||||||
|
):
|
||||||
|
self.assertEqual(
|
||||||
|
analyser._check_kversion_greater_equal(kversion, min_version),
|
||||||
|
expected_result,
|
||||||
|
'Failed to compare kernel version "%s" with minimum version "%s"'
|
||||||
|
% (kversion, min_version),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
Loading…
Reference in New Issue
Block a user