add test for RX7000 fan speed range parsing

This commit is contained in:
Jussi Kuokkanen 2024-01-25 15:37:45 +02:00
parent 832abc5422
commit 5784d42ffa
8 changed files with 62 additions and 11 deletions

View File

@ -238,6 +238,10 @@ If TuxClocker shows up with no items, there may be a problem with connecting to
![Settings](screenshots/settings.png)
# Developing
### Tests
NOTE: building tests requires passing `-Dtest=true` to meson.
Tests are located in `src/test`. Run them with `meson test`.
### Formatting

View File

@ -6,6 +6,7 @@ option('library', type: 'boolean', value: 'true', description: 'Build library')
option('gui', type: 'boolean', value: 'true', description: 'Build Qt GUI')
# Disabled by default to not break builds
option('cli', type: 'boolean', value: 'false', description: 'Build CLI')
option('test', type: 'boolean', value: 'false', description: 'Build tests')
option('require-python-hwdata', type: 'boolean', value: 'false',
description: 'Require python-hwdata for prettier AMD GPU names')
option('require-amd', type: 'boolean', value: 'false',

View File

@ -10,6 +10,8 @@ if need_version
version_string_def = '-DTUXCLOCKER_VERSION_STRING="@0@"'.format(version_string)
endif
fplus_inc = include_directories('include/deps/FunctionalPlus/include')
# OpenSSL is used for hash functions
openssl_dep = dependency('openssl')
@ -54,3 +56,5 @@ endif
if get_option('cli')
subdir('tuxclocker-cli')
endif
subdir('test')

View File

@ -423,18 +423,12 @@ std::vector<TreeNode<DeviceNode>> getFanSpeedWriteRX7000(AMDGPUData data) {
if (!std::ifstream{fanCurvePath}.good())
return {};
auto contentsRaw = fileContents(fanCurvePath);
if (!contentsRaw.has_value())
auto contents = fileContents(fanCurvePath);
if (!contents.has_value())
return {};
// Replace the space in 'fan speed' with underscore, see doc/amd-pptables/rx7000-fancurve
// to fit the format parsePstateRangeLine expects
// Little cursed, but this allows us to use the same algorithm
auto contents =
fplus::replace_tokens(std::string{"fan speed"}, std::string{"fan_speed"}, *contentsRaw);
// We don't care acout the temps, since we set all points to desired speed
auto speedRange = parsePstateRangeLine("FAN_CURVE(fan_speed)", contents);
auto speedRange = fromFanCurveContents(*contents);
if (!speedRange.has_value())
return {};
@ -451,7 +445,7 @@ std::vector<TreeNode<DeviceNode>> getFanSpeedWriteRX7000(AMDGPUData data) {
// TODO: do we even need to care about setting same temperature?
// Might be slow to do this every assignment
auto lines = pstateSectionLines("OD_FAN_CURVE", contents);
auto lines = pstateSectionLines("OD_FAN_CURVE", *contents);
std::ofstream file{fanCurvePath};
if (lines.empty() || !file.good())
return AssignmentError::UnknownError;

View File

@ -73,6 +73,16 @@ std::optional<Range<int>> parsePstateRangeLineWithRead(std::string title, AMDGPU
return parsePstateRangeLine(title, *contents);
}
std::optional<Range<int>> fromFanCurveContents(const std::string &contentsRaw) {
// Replace the space in 'fan speed' with underscore, see doc/amd-pptables/rx7000-fancurve
// to fit the format parsePstateRangeLine expects
// Little cursed, but this allows us to use the same algorithm
auto contents =
fplus::replace_tokens(std::string{"fan speed"}, std::string{"fan_speed"}, contentsRaw);
return parsePstateRangeLine("FAN_CURVE(fan_speed)", contents);
}
std::optional<std::pair<int, int>> parseLineValuePair(const std::string &line) {
auto words = fplus::split_one_of(std::string{" "}, false, line);

View File

@ -47,6 +47,8 @@ std::optional<TuxClocker::Device::Range<int>> parsePstateRangeLine(
std::optional<TuxClocker::Device::Range<int>> parsePstateRangeLineWithRead(
std::string title, AMDGPUData data);
std::optional<TuxClocker::Device::Range<int>> fromFanCurveContents(const std::string &contents);
std::optional<std::pair<int, int>> parseLineValuePair(const std::string &line);
std::optional<int> parseLineValue(const std::string &line);

28
src/plugins/Tests.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <AMDUtils.hpp>
#include <fplus/fplus.hpp>
#include <iostream>
#include <Utils.hpp>
using namespace TuxClocker::Device;
std::optional<Range<int>> fromFanCurveContents(const std::string &contentsRaw) {
auto contents =
fplus::replace_tokens(std::string{"fan speed"}, std::string{"fan_speed"}, contentsRaw);
return parsePstateRangeLine("FAN_CURVE(fan_speed)", contents);
}
int fanCurveParse() {
auto contents = fileContents(PROJECT_ROOT "/doc/amd-pptables/rx7000-fancurve");
if (!contents.has_value()) {
std::cerr << "Couldn't read sample file\n";
return 1;
}
auto range = fromFanCurveContents(*contents);
if (!range.has_value()) {
return 1;
}
return !(range->min == 15 && range->max == 100);
}
int main() { return fanCurveParse(); }

View File

@ -1,5 +1,4 @@
patterns_inc = include_directories('../include/deps/patterns/include/mpark')
fplus_inc = include_directories('../include/deps/FunctionalPlus/include')
req_amd = get_option('require-amd')
libdrm_amdgpu = cc.find_library('drm_amdgpu', required : req_amd)
@ -71,3 +70,12 @@ if get_option('plugins-cpu')
install : true,
link_with : libtuxclocker)
endif
tests = executable('tests', 'Tests.cpp', 'AMDUtils.cpp', 'Utils.cpp',
# Find sample AMD files
cpp_args : '-DPROJECT_ROOT="@0@"'.format(meson.source_root()),
include_directories : [incdir, fplus_inc],
dependencies : [ libdrm_amdgpu, libdrm_dep, boost_dep ])
test('AMD parsing', tests,
protocol : 'exitcode')