[test] Add unit tests for ACP and ALRU cleaning policy parameters

- Add tests for wake-up and flush-max-buffers parameter validation
- Test parameter boundary values and error conditions
- Cover parameter parsing from configuration strings
- Verify set_param_cleaning_policy commands construction
- Test proper handling of different cleaning policies in configure_cache

These tests ensure the proper validation and handling of cleaning policy
parameters introduced in the previous commits.
This commit is contained in:
td-zhangshun 2025-04-16 11:13:18 +08:00 committed by Netlops
parent 09764e0e15
commit 5f0a32cddb
3 changed files with 221 additions and 6 deletions

77
README-TD.md Normal file
View File

@ -0,0 +1,77 @@
# Test Cas_Config
```
python3 -m venv test_env
source test_env/bin/activate
pip3 install pytest
pytest test/utils_tests/opencas-py-tests/test_cas_config_01.py -vv
```
```shell
pytest test/utils_tests/opencas-py-tests/test_cas_config_01.py -vv
================================================================================== test session starts ==================================================================================
platform linux -- Python 3.10.12, pytest-8.3.5, pluggy-1.5.0 -- /root/workspace/git/open-cas-linux/open-cas_env/bin/python3
cachedir: .pytest_cache
rootdir: /root/workspace/git/open-cas-linux
collected 56 items
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_exception PASSED [ 1%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_no_vertag PASSED [ 3%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_comments_only PASSED [ 5%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config0-cores_config0-ConflictingConfigException] PASSED [ 7%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config1-cores_config1-ConflictingConfigException] PASSED [ 8%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config2-cores_config2-ConflictingConfigException] PASSED [ 10%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config3-cores_config3-AlreadyConfiguredException] PASSED [ 12%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config4-cores_config4-AlreadyConfiguredException] PASSED [ 14%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config5-cores_config5-KeyError] PASSED [ 16%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_inconsistent_configs[caches_config6-cores_config6-ConflictingConfigException] PASSED [ 17%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_is_empty_non_empty PASSED [ 19%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_double_add_cache PASSED [ 21%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_double_add_core PASSED [ 23%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_insert_core_no_cache PASSED [ 25%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_add_same_cache_symlinked_01 PASSED [ 26%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_add_same_cache_symlinked_02 PASSED [ 28%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_add_same_core_symlinked_01 PASSED [ 30%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_add_same_core_symlinked_02 PASSED [ 32%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_get_by_id_path_not_found PASSED [ 33%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_to_file[caches_config0-cores_config0] PASSED [ 35%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_to_file[caches_config1-cores_config1] PASSED [ 37%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_to_file[caches_config2-cores_config2] PASSED [ 39%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_to_file[caches_config3-cores_config3] PASSED [ 41%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_to_file[caches_config4-cores_config4] PASSED [ 42%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_insert_cache_insert_core_to_file[caches_config0-cores_config0] PASSED [ 44%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_insert_cache_insert_core_to_file[caches_config1-cores_config1] PASSED [ 46%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_insert_cache_insert_core_to_file[caches_config2-cores_config2] PASSED [ 48%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cas_config_from_file_insert_cache_insert_core_to_file[caches_config3-cores_config3] PASSED [ 50%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-100-500-None] PASSED [ 51%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-0-1-None] PASSED [ 53%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-10000-9999-None] PASSED [ 55%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp--1-500-ValueError] PASSED [ 57%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-10001-500-ValueError] PASSED [ 58%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-abc-500-ValueError] PASSED [ 60%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-100-0-ValueError] PASSED [ 62%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-100-10001-ValueError] PASSED [ 64%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[acp-100-abc-ValueError] PASSED [ 66%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-100-500-None] PASSED [ 67%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-0-1-None] PASSED [ 69%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-3599-10000-None] PASSED [ 71%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru--1-500-ValueError] PASSED [ 73%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-3601-500-ValueError] PASSED [ 75%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-abc-500-ValueError] PASSED [ 76%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-100-0-ValueError] PASSED [ 78%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-100-10001-ValueError] PASSED [ 80%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[alru-100-abc-ValueError] PASSED [ 82%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_cleaning_policy_parameters[nop-100-500-None] PASSED [ 83%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=acp,wake_up=100,flush_max_buffers=500-None] PASSED [ 85%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=alru,wake_up=60,flush_max_buffers=100-None] PASSED [ 87%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=acp,wake_up=10001,flush_max_buffers=500-ValueError] PASSED [ 89%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=acp,wake_up=100,flush_max_buffers=0-ValueError] PASSED [ 91%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=alru,wake_up=3601,flush_max_buffers=100-ValueError] PASSED [ 92%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=alru,wake_up=100,flush_max_buffers=10001-ValueError] PASSED [ 94%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_cache_config_from_line_with_cleaning_parameters[1 /dev/dummy WT cleaning_policy=nop,wake_up=100,flush_max_buffers=500-None] PASSED [ 96%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_set_param_cleaning_policy PASSED [ 98%]
test/utils_tests/opencas-py-tests/test_cas_config_01.py::test_configure_cache_cleaning_policy PASSED [100%]
================================================================================== 56 passed in 0.14s ===================================================================================
```

View File

@ -476,3 +476,141 @@ def test_cas_config_from_file_insert_cache_insert_core_to_file(
assert set(contents_hashed[cores_index + 1 :]) - set(cores_hashed) == set( assert set(contents_hashed[cores_index + 1 :]) - set(cores_hashed) == set(
["51/dev/mango_core"] ["51/dev/mango_core"]
) )
@pytest.mark.parametrize(
"cleaning_policy,wake_up,flush_max_buffers,expected_exception",
[
("acp", "100", "500", None), # Valid normal values
("acp", "0", "1", None), # Boundary value test - min
("acp", "10000", "9999", None), # Boundary value test - max
("acp", "-1", "500", ValueError), # Invalid wake_up value
("acp", "10001", "500", ValueError), # Out of range wake_up value
("acp", "abc", "500", ValueError), # Non-numeric wake_up value
("acp", "100", "0", ValueError), # Invalid flush_max_buffers value
("acp", "100", "10001", ValueError), # Out of range flush_max_buffers value
("acp", "100", "abc", ValueError), # Non-numeric flush_max_buffers value
("alru", "100", "500", None), # Valid normal values
("alru", "0", "1", None), # Boundary value test - min
("alru", "3599", "10000", None), # Boundary value test - max
("alru", "-1", "500", ValueError), # Invalid wake_up value
("alru", "3601", "500", ValueError), # Out of range wake_up value
("alru", "abc", "500", ValueError), # Non-numeric wake_up value
("alru", "100", "0", ValueError), # Invalid flush_max_buffers value
("alru", "100", "10001", ValueError), # Out of range flush_max_buffers value
("alru", "100", "abc", ValueError), # Non-numeric flush_max_buffers value
("nop", "100", "500", None), # Testing parameters for unsupported cleaning policy
],
)
def test_cache_config_cleaning_policy_parameters(cleaning_policy, wake_up, flush_max_buffers, expected_exception):
"""Test validation of wake_up and flush_max_buffers parameters for different cleaning policies"""
cache = opencas.cas_config.cache_config(1, "/dev/dummy", "WT", cleaning_policy=cleaning_policy)
# Add test parameters
cache.params["wake_up"] = wake_up
cache.params["flush_max_buffers"] = flush_max_buffers
if expected_exception:
with pytest.raises(expected_exception):
cache.check_wake_up_valid(wake_up)
cache.check_flush_max_buffers_valid(flush_max_buffers)
else:
# No exception should be raised
cache.check_wake_up_valid(wake_up)
cache.check_flush_max_buffers_valid(flush_max_buffers)
@pytest.mark.parametrize(
"cache_config_str, exception",
[
("1 /dev/dummy WT cleaning_policy=acp,wake_up=100,flush_max_buffers=500", None),
("1 /dev/dummy WT cleaning_policy=alru,wake_up=60,flush_max_buffers=100", None),
("1 /dev/dummy WT cleaning_policy=acp,wake_up=10001,flush_max_buffers=500", ValueError),
("1 /dev/dummy WT cleaning_policy=acp,wake_up=100,flush_max_buffers=0", ValueError),
("1 /dev/dummy WT cleaning_policy=alru,wake_up=3601,flush_max_buffers=100", ValueError),
("1 /dev/dummy WT cleaning_policy=alru,wake_up=100,flush_max_buffers=10001", ValueError),
("1 /dev/dummy WT cleaning_policy=nop,wake_up=100,flush_max_buffers=500", None),
],
)
def test_cache_config_from_line_with_cleaning_parameters(cache_config_str, exception):
"""Test parsing cache configuration with cleaning policy parameters from config line"""
if exception:
with pytest.raises(exception):
cache = opencas.cas_config.cache_config.from_line(cache_config_str, True)
else:
cache = opencas.cas_config.cache_config.from_line(cache_config_str, True)
assert cache.params.get("cleaning_policy") in ["acp", "alru", "nop"]
assert "wake_up" in cache.params
assert "flush_max_buffers" in cache.params
@patch("opencas.casadm.run_cmd")
def test_set_param_cleaning_policy(mock_run_cmd):
"""Test the set_param_cleaning_policy method call"""
# ACP policy
opencas.casadm.set_param_cleaning_policy("acp", 1, wake_up="100", flush_max_buffers="500")
mock_run_cmd.assert_called_with([
'/sbin/casadm',
'--set-param', '--name', 'cleaning-acp',
'--cache-id', '1',
'--wake-up', '100',
'--flush-max-buffers', '500'
])
# ALRU policy
mock_run_cmd.reset_mock()
opencas.casadm.set_param_cleaning_policy("alru", 2, wake_up="60", flush_max_buffers="200")
mock_run_cmd.assert_called_with([
'/sbin/casadm',
'--set-param', '--name', 'cleaning-alru',
'--cache-id', '2',
'--wake-up', '60',
'--flush-max-buffers', '200'
])
# Nop policy
mock_run_cmd.reset_mock()
opencas.casadm.set_param("cleaning", cache_id=3, policy="nop")
mock_run_cmd.assert_called_with([
'/sbin/casadm',
'--set-param', '--name', 'cleaning',
'--cache-id', '3',
'--policy', 'nop'
])
@patch("opencas.casadm.set_param_cleaning_policy")
@patch("opencas.casadm.set_param")
def test_configure_cache_cleaning_policy(mock_set_param, mock_set_param_cleaning_policy):
"""Test handling different cleaning policies in cache configuration"""
# ACP policy test
cache_acp = opencas.cas_config.cache_config(1, "/dev/dummy", "WT",
cleaning_policy="acp",
wake_up="100",
flush_max_buffers="500")
opencas.configure_cache(cache_acp)
mock_set_param_cleaning_policy.assert_called_once_with(
policy="acp", cache_id=1, wake_up="100", flush_max_buffers="500"
)
mock_set_param.assert_not_called()
# ALRU policy test
mock_set_param.reset_mock()
mock_set_param_cleaning_policy.reset_mock()
cache_alru = opencas.cas_config.cache_config(2, "/dev/dummy", "WT",
cleaning_policy="alru",
wake_up="60",
flush_max_buffers="200")
opencas.configure_cache(cache_alru)
mock_set_param_cleaning_policy.assert_called_once_with(
policy="alru", cache_id=2, wake_up="60", flush_max_buffers="200"
)
mock_set_param.assert_not_called()
# NOP policy test
mock_set_param.reset_mock()
mock_set_param_cleaning_policy.reset_mock()
cache_nop = opencas.cas_config.cache_config(3, "/dev/dummy", "WT", cleaning_policy="nop")
opencas.configure_cache(cache_nop)
mock_set_param.assert_called_once_with("cleaning", cache_id=3, policy="nop")
mock_set_param_cleaning_policy.assert_not_called()

View File

@ -278,9 +278,9 @@ class cas_config(object):
self.check_lazy_startup_valid(param_value) self.check_lazy_startup_valid(param_value)
elif param_name == "target_failover_state": elif param_name == "target_failover_state":
self.check_failover_state_valid(param_value) self.check_failover_state_valid(param_value)
elif param_name == "wake-up": elif param_name == "wake_up":
self.check_wake_up_valid(param_value) self.check_wake_up_valid(param_value)
elif param_name == "flush-max-buffers": elif param_name == "flush_max_buffers":
self.check_flush_max_buffers_valid(param_value) self.check_flush_max_buffers_valid(param_value)
else: else:
raise ValueError(f'{param_name} is invalid parameter name') raise ValueError(f'{param_name} is invalid parameter name')
@ -332,24 +332,24 @@ class cas_config(object):
if self.params.get("cleaning_policy") == "acp": if self.params.get("cleaning_policy") == "acp":
if not wake_up.isdigit(): if not wake_up.isdigit():
raise ValueError(f"{wake_up} is invalid wake-up value for acp cleaning policy") raise ValueError(f"{wake_up} is invalid wake-up value for acp cleaning policy")
if int(wake_up) not in range(0, 10000): if int(wake_up) not in range(0, 10001):
raise ValueError(f"{wake_up} is invalid wake-up value for acp cleaning policy") raise ValueError(f"{wake_up} is invalid wake-up value for acp cleaning policy")
elif self.params.get("cleaning_policy") == "alru": elif self.params.get("cleaning_policy") == "alru":
if not wake_up.isdigit(): if not wake_up.isdigit():
raise ValueError(f"{wake_up} is invalid wake-up value for alru cleaning policy") raise ValueError(f"{wake_up} is invalid wake-up value for alru cleaning policy")
if int(wake_up) not in range(0, 3600): if int(wake_up) not in range(0, 3601):
raise ValueError(f"{wake_up} is invalid wake-up value for alru cleaning policy") raise ValueError(f"{wake_up} is invalid wake-up value for alru cleaning policy")
def check_flush_max_buffers_valid(self, flush_max_buffers): def check_flush_max_buffers_valid(self, flush_max_buffers):
if self.params.get("cleaning_policy") == "acp": if self.params.get("cleaning_policy") == "acp":
if not flush_max_buffers.isdigit(): if not flush_max_buffers.isdigit():
raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for acp cleaning policy") raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for acp cleaning policy")
if int(flush_max_buffers) not in range(1, 10000): if int(flush_max_buffers) not in range(1, 10001):
raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for acp cleaning policy") raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for acp cleaning policy")
elif self.params.get("cleaning_policy") == "alru": elif self.params.get("cleaning_policy") == "alru":
if not flush_max_buffers.isdigit(): if not flush_max_buffers.isdigit():
raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for alru cleaning policy") raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for alru cleaning policy")
if int(flush_max_buffers) not in range(1, 10000): if int(flush_max_buffers) not in range(1, 10001):
raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for alru cleaning policy") raise ValueError(f"{flush_max_buffers} is invalid flush-max-buffers value for alru cleaning policy")
def check_recursive(self): def check_recursive(self):
if not self.device.startswith('/dev/cas'): if not self.device.startswith('/dev/cas'):