Skip to content

add a manifest for cpufreq scaling test (Bugfix)#2425

Open
stanley31huang wants to merge 9 commits into
mainfrom
add-manifest-for-cpufreq
Open

add a manifest for cpufreq scaling test (Bugfix)#2425
stanley31huang wants to merge 9 commits into
mainfrom
add-manifest-for-cpufreq

Conversation

@stanley31huang
Copy link
Copy Markdown
Collaborator

@stanley31huang stanley31huang commented Mar 25, 2026

Description

add a manifest for cpufreq scaling test, as this feature is not supported on new i.MX9 SoC

Resolved issues

Documentation

Tests

test result when cpu policy is available

https://certification.canonical.com/hardware/202501-36212/submission/488805/

test result when cpu policy is unavailable

ubuntu@juju-8ab9e7-7:~$ checkbox-cli control 10.102.181.187
Connecting to 10.102.181.187:18871. Timeout: 600s
Agent is using sideloaded providers
=========[ Bootstrap com.canonical.contrib::cpufreq_policy_list (1/1) ]=========
--------------------------------------------------------------------------------
Outcome: job passed
There were no tests to select from!

@stanley31huang stanley31huang added the ce-oem The PR only contains to the ce-oem provider under the contrib area label Mar 25, 2026
@seankingyang
Copy link
Copy Markdown
Contributor

LGTM~
Could you add more explain more about what kind of CPU not support the cpu scalling (ie intel_pstate amd-pstate amd-pstate-epp )?

Comment thread contrib/checkbox-ce-oem/checkbox-provider-ce-oem/units/cpu/jobs.pxu Outdated
@tomli380576
Copy link
Copy Markdown
Contributor

also should we update checkbox-provider-ce-oem/units/cpu/jobs.pxu to use this manifest?

@stanley31huang stanley31huang marked this pull request as draft March 31, 2026 05:51
@stanley31huang stanley31huang force-pushed the add-manifest-for-cpufreq branch from 7468d5c to 827dc0c Compare April 22, 2026 05:17
@stanley31huang stanley31huang marked this pull request as ready for review April 22, 2026 05:22
fix black issue
@stanley31huang
Copy link
Copy Markdown
Collaborator Author

this PR will change the CPU governor test as following scenario

  1. In the resource job, it will print out all CPU policy with avaiable scaling governor
  2. the corresponding CPU governor tests will be run based on governor listed in available scaling governor.
  3. Remove cpu driver detect test as it's not supported for all platform.

revised the cpu scaling test classes
fix black8
fix format and compatible with py35
@stanley31huang stanley31huang force-pushed the add-manifest-for-cpufreq branch from 74b7a8a to 6b22300 Compare April 23, 2026 05:38
update test job and scripts
fix coding style check issue
updated job requires
fix for no available cpu policy
@tomli380576 tomli380576 self-assigned this May 21, 2026
Copy link
Copy Markdown
Contributor

@tomli380576 tomli380576 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comments are mostly refactoring suggestions, lmk if i misunderstood anything

Comment thread contrib/checkbox-ce-oem/checkbox-provider-ce-oem/bin/cpufreq_governors.py Outdated
Comment on lines +722 to +735
def test_governor(self) -> bool:
"""
Run the CPU Scaling Governor Test.

This function is a placeholder for running the CPU scaling governor
test. It should be implemented in the subclasses for specific
governors.

Returns:
bool: True if the test passes, False otherwise.
"""
raise NotImplementedError(
"This method should be implemented in subclass."
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the more idiomatic way to do this is with an abstract base class:

-class CPUScalingTest
+class CPUScalingTest(abc.ABC)

then at the method definition, decorate it:

@abc.abstractmethod
def test_governor(self) -> bool:
    # no need to write anything in the method body
    pass

this can also prevent the base class from being constructed altogether.

Comment on lines +504 to +514
_registry = {}

@classmethod
def register(cls, key):
"""Register test classes by governor name."""

def decorator(test_cls):
cls._registry[key] = test_cls
return test_cls

return decorator
Copy link
Copy Markdown
Contributor

@tomli380576 tomli380576 May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: i think it's less convoluted to just use a dict in main and put the class names in there:

# inside main

TEST_CLASSES = {
    "powersave": PowersaveCPUScalingTest
    "schedutil": SchedutilCPUScalingTest
    # ...other ones
}

if args.governor not in TEST_CLASSES:
    raise SystemExit("Unavailable governor: {}".format(args.governor))

# governor available, do the rest of main
for governor, test_class in TEST_CLASSES.items():
    # do stuff

this can also eliminate the .create() method and allow main() to use normal class constructors

class CPUScalingTest:
"""A class for CPU scaling test operations."""

test_description = ""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the child classes this was changed to description, did you mean to use 2 different names?

If not, a more robust way to enforce the existence of test_description is to use an abstract property

# requires the parent class to be abstract

class CPUScalingTest(abc.ABC):
    @property
    @abc.abstractmethod
    def test_description() -> str:
        pass

class UserspaceCPUScalingTest(CPUScalingTest):
    @property
    def test_description() -> str:
        return "some test description"

# access it like a normal property

t = UserspaceCPUScalingTest()
print(t.test_description)

If the child class doesn't implement test_description, python will raise this:

TypeError: Can't instantiate abstract class UserspaceCPUScalingTest with abstract methods test_description

because not implementing the entire ABC's interface makes the child class implicitly abstract, thus cannot be constructed.

print("cpb: {}".format(self.get_cpb(policy)))
print()
return True
self.policy = policy
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason why we need to keep overwriting self.policy?

Comment on lines +526 to +548
@classmethod
def create(cls, governor, policy=0):
"""
Create a test instance by governor name.

Args:
governor (str): The name of the governor test to create.
policy (int): The CPU policy number to be used (default is 0).

Returns:
CPUScalingTest: An instance of the appropriate test class.

Raises:
ValueError: If the governor is not supported.
"""
test_class = cls._registry.get(governor.lower())
if test_class is None:
raise ValueError(
"Governor '{}' not supported. Available: {}".format(
governor, ", ".join(sorted(cls._registry.keys()))
)
)
return test_class(policy=policy)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the comment on 514

probe_governor_module(args.governor)
if not getattr(test, "test_{}".format(args.governor))():
logging.error(
"Governor '%s' is not supported by CPU policy%s",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use .format()

except AttributeError:
logging.error("Given governor is not supported")
except ValueError as err:
logging.error(str(err))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: depending on if you want to see the literal ValueError string, you could use repr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ce-oem The PR only contains to the ce-oem provider under the contrib area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants