Skip to content

Commit

Permalink
New parser for CpuSMTControl and tests update (#3521)
Browse files Browse the repository at this point in the history
* Add CpuSMTControl parser

Signed-off-by: Jitka Obselkova <[email protected]>

* Rework current tests

Signed-off-by: Jitka Obselkova <[email protected]>

Signed-off-by: Jitka Obselkova <[email protected]>
(cherry picked from commit c0c3fb8)
  • Loading branch information
jobselko authored and Sachin Patil committed Sep 15, 2022
1 parent fd614e7 commit b2bcbc2
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 45 deletions.
65 changes: 57 additions & 8 deletions insights/parsers/smt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
CpuSMTActive - file ``/sys/devices/system/cpu/smt/active``
----------------------------------------------------------
CpuSMTControl - file ``/sys/devices/system/cpu/smt/control``
------------------------------------------------------------
CpuCoreOnline - files matching ``/sys/devices/system/cpu/cpu[0-9]*/online``
---------------------------------------------------------------------------
CpuSiblings - files matching ``/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list``
Expand Down Expand Up @@ -33,7 +35,7 @@ class CpuSMTActive(Parser):
SkipException: When content is empty or cannot be parsed.
Examples:
>>> cpu_smt.on
>>> cpu_smt_active.on
True
"""
def parse_content(self, content):
Expand All @@ -42,11 +44,57 @@ def parse_content(self, content):
self.on = bool(int(content[0]))


@parser(Specs.cpu_smt_control)
class CpuSMTControl(Parser):
"""
Class for parsing ``/sys/devices/system/cpu/smt/control`` file.
Reports whether SMT is user-controllable.
Four settings are possible::
on: SMT enabled
off: SMT disabled
forceoff: SMT disabled, cannot change at runtime
notsupported: CPU does not support SMT
Typical output of this command is::
off
Raises:
SkipException: When content is empty or cannot be parsed.
Examples:
>>> cpu_smt_control.on
False
>>> cpu_smt_control.modifiable
True
>>> cpu_smt_control.supported
True
"""
SMT_CONTROL = {
"on": [True, True, True],
"off": [False, True, True],
"forceoff": [False, False, True],
"notsupported": [False, False, False]
}

def parse_content(self, content):
if not content:
raise SkipException("No content.")

values = self.SMT_CONTROL[content[0]]

self.on = values[0]
self.modifiable = values[1]
self.supported = values[2]


@parser(Specs.cpu_cores)
class CpuCoreOnline(Parser):
"""
Class for parsing ``/sys/devices/system/cpu/cpu[0-9]*/online`` matching files.
Reports whether a CPU core is online. Cpu0 is always online, so it does not have the "online" file.
Class for parsing ``/sys/devices/system/cpu/cpu[0-9]*/online`` matching files. Reports whether
a CPU core is online. Cpu0 is always online, so it does not have the "online" file.
Typical output of this command is::
Expand All @@ -58,9 +106,9 @@ class CpuCoreOnline(Parser):
SkipException: When content is empty or cannot be parsed
Examples:
>>> cpu_core.core_id
>>> cpu_core_online.core_id
0
>>> cpu_core.on
>>> cpu_core_online.on
True
"""
cpu_core_path = r'/sys/devices/system/cpu/cpu(\d+)/online'
Expand All @@ -78,8 +126,8 @@ def __repr__(self):
@parser(Specs.cpu_siblings)
class CpuSiblings(Parser):
"""
Class for parsing ``/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list`` matching files.
Reports CPU core siblings.
Class for parsing ``/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list``
matching files. Reports CPU core siblings.
Typical output of this command is::
Expand All @@ -103,7 +151,8 @@ def parse_content(self, content):
if not content:
raise SkipException("No content.")

# The separator in the sibling list may be either in the format 0-1 or 0,2 depending on the CPU model
# The separator in the sibling list may be either in the format 0-1 or 0,2 depending on
# the CPU model
if "-" in content[0]:
cpu_range = [int(x) for x in content[0].split("-")]
self.siblings = [x for x in range(cpu_range[0], cpu_range[1] + 1)]
Expand Down
1 change: 1 addition & 0 deletions insights/specs/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class DefaultSpecs(Specs):
cpu_cores = glob_file("sys/devices/system/cpu/cpu[0-9]*/online")
cpu_siblings = glob_file("sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list")
cpu_smt_active = simple_file("sys/devices/system/cpu/smt/active")
cpu_smt_control = simple_file("sys/devices/system/cpu/smt/control")
cpu_vulns = glob_file("sys/devices/system/cpu/vulnerabilities/*")
cpuinfo = simple_file("/proc/cpuinfo")
cpupower_frequency_info = simple_command("/usr/bin/cpupower -c all frequency-info")
Expand Down
91 changes: 54 additions & 37 deletions insights/tests/parsers/test_smt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,79 @@
import pytest

from insights.parsers import smt, SkipException
from insights.parsers.smt import CpuSMTActive, CpuCoreOnline, CpuSiblings
from insights.parsers.smt import CpuSMTActive, CpuSMTControl, CpuCoreOnline, CpuSiblings
from insights.tests import context_wrap


def test_cpu_smt_active():
with pytest.raises(SkipException):
CpuSMTActive(context_wrap(""))
@pytest.mark.parametrize("setting, on", [
("0", False),
("1", True)
])
def test_cpu_smt_active(setting, on):
p = CpuSMTActive(context_wrap(setting))
assert p.on == on

p = CpuSMTActive(context_wrap("1"))
assert p.on
p = CpuSMTActive(context_wrap("0"))
assert not p.on

@pytest.mark.parametrize("setting, on, modifiable, supported", [
("on", True, True, True),
("off", False, True, True),
("forceoff", False, False, True),
("notsupported", False, False, False)
])
def test_cpu_smt_control(setting, on, modifiable, supported):
p = CpuSMTControl(context_wrap(setting))
assert p.on == on
assert p.modifiable == modifiable
assert p.supported == supported

def test_cpu_core_online():
with pytest.raises(SkipException):
CpuCoreOnline(context_wrap(""))

@pytest.mark.parametrize("setting, on, status", [
(0, False, "Offline"),
(1, True, "Online")
])
def test_cpu_core_online(setting, on, status):
path = "/sys/devices/system/cpu/cpu{0}/online"
p = CpuCoreOnline(context_wrap("0", path=path.format(0)))
assert p.core_id == 0
assert not p.on
assert repr(p) == "[Core 0: Offline]"
p = CpuCoreOnline(context_wrap("1", path=path.format(1)))
assert p.core_id == 1
assert p.on
assert repr(p) == "[Core 1: Online]"

p = CpuCoreOnline(context_wrap(str(setting), path=path.format(setting)))
assert p.core_id == setting
assert p.on == on
assert repr(p) == "[Core {0}: {1}]".format(setting, status)

def test_cpu_siblings():
with pytest.raises(SkipException):
CpuSiblings(context_wrap(""))

@pytest.mark.parametrize("setting, core_id, siblings", [
("0,2", 0, [0, 2]),
("1-3", 3, [1, 2, 3]),
("1", 1, [1])
])
def test_cpu_siblings(setting, core_id, siblings):
path = "/sys/devices/system/cpu/cpu{0}/topology/thread_siblings_list"
p = CpuSiblings(context_wrap("0,2", path=path.format(0)))
assert p.core_id == 0
assert p.siblings == [0, 2]
assert repr(p) == "[Core 0 Siblings: [0, 2]]"
p = CpuSiblings(context_wrap("1-3", path=path.format(3)))
assert p.core_id == 3
assert p.siblings == [1, 2, 3]
assert repr(p) == "[Core 3 Siblings: [1, 2, 3]]"
p = CpuSiblings(context_wrap("1", path=path.format(1)))
assert p.core_id == 1
assert p.siblings == [1]
assert repr(p) == "[Core 1 Siblings: [1]]"

p = CpuSiblings(context_wrap(setting, path=path.format(core_id)))
assert p.core_id == core_id
assert p.siblings == siblings
assert repr(p) == "[Core {0} Siblings: {1}]".format(core_id, siblings)


@pytest.mark.parametrize("parser", [
CpuSMTActive,
CpuSMTControl,
CpuCoreOnline,
CpuSiblings
])
def test_exceptions(parser):
with pytest.raises(SkipException):
parser(context_wrap(""))


def test_doc_examples():
path_cpu_core_online = "/sys/devices/system/cpu/cpu0/online"
path_cpu_siblings = "/sys/devices/system/cpu/cpu0/topology/thread_siblings_list"

env = {
"cpu_smt": CpuSMTActive(context_wrap("1")),
"cpu_core": CpuCoreOnline(context_wrap("1", path=path_cpu_core_online)),
"cpu_siblings": CpuSiblings(context_wrap("0,2", path=path_cpu_siblings))
"cpu_smt_active": CpuSMTActive(context_wrap("1")),
"cpu_smt_control": CpuSMTControl(context_wrap("off")),
"cpu_core_online": CpuCoreOnline(context_wrap("1", path=path_cpu_core_online)),
"cpu_siblings": CpuSiblings(context_wrap("0,2", path=path_cpu_siblings)),
}
failed, total = doctest.testmod(smt, globs=env)
assert failed == 0

0 comments on commit b2bcbc2

Please sign in to comment.