Merge pull request #179 from micrakow/seq_tests

Basic sequential cut off tests
This commit is contained in:
Michał Mielewczyk 2019-11-21 17:36:31 +01:00 committed by GitHub
commit 1ffe1dd0a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 353 additions and 25 deletions

View File

@ -895,6 +895,8 @@ int set_param_namespace_handle_option(char *namespace, char *opt, const char **a
int handle_set_param()
{
int err = 0;
if (command_args_values.params_count == 0) {
cas_printf(LOG_ERR, "Error: No parameters specified!\n");
return FAILURE;
@ -902,15 +904,20 @@ int handle_set_param()
switch (command_args_values.params_type) {
case PARAM_TYPE_CORE:
return core_params_set(command_args_values.cache_id,
err = core_params_set(command_args_values.cache_id,
command_args_values.core_id,
cas_core_params);
case PARAM_TYPE_CACHE:
return cache_params_set(command_args_values.cache_id,
err = cache_params_set(command_args_values.cache_id,
cas_cache_params);
default:
return FAILURE;
err = FAILURE;
}
if (err)
cas_printf(LOG_ERR, "Setting runtime parameter failed!\n");
return err;
}
/*****************************************************************************
@ -985,6 +992,7 @@ int get_param_namespace_handle_option(char *namespace, char *opt, const char **a
int handle_get_param()
{
int format = TEXT;
int err = 0;
if (OUTPUT_FORMAT_CSV == command_args_values.output_format) {
format = RAW_CSV;
@ -992,15 +1000,20 @@ int handle_get_param()
switch (command_args_values.params_type) {
case PARAM_TYPE_CORE:
return core_params_get(command_args_values.cache_id,
err = core_params_get(command_args_values.cache_id,
command_args_values.core_id,
cas_core_params, format);
case PARAM_TYPE_CACHE:
return cache_params_get(command_args_values.cache_id,
err = cache_params_get(command_args_values.cache_id,
cas_cache_params, format);
default:
return FAILURE;
err = FAILURE;
}
if (err)
cas_printf(LOG_ERR, "Getting runtime parameter failed!\n");
return err;
}
static cli_option set_state_cache_mode_options[] = {

View File

@ -1,6 +1,6 @@
# Preface
This document contains guidlines and BKMs for writing tests. Following these
This document contains guidelines and BKMs for writing tests. Following these
will significantly reduce number of comments you will receive on the code
review and will speed up the process of merging your patch.

View File

@ -123,8 +123,18 @@ class Cache:
def set_seq_cutoff_parameters(self, seq_cutoff_param: SeqCutOffParameters):
return casadm.set_param_cutoff(self.cache_id,
seq_cutoff_param.threshold,
seq_cutoff_param.policy)
threshold=seq_cutoff_param.threshold,
policy=seq_cutoff_param.policy)
def set_seq_cutoff_threshold(self, threshold: Size):
return casadm.set_param_cutoff(self.cache_id,
threshold=threshold,
policy=None)
def set_seq_cutoff_policy(self, policy: SeqCutOffPolicy):
return casadm.set_param_cutoff(self.cache_id,
threshold=None,
policy=policy)
def set_cleaning_policy(self, cleaning_policy: CleaningPolicy):
return casadm.set_param_cleaning(self.cache_id, cleaning_policy)

View File

@ -32,6 +32,14 @@ class SeqCutOffPolicy(Enum):
never = 2
DEFAULT = full
@classmethod
def from_name(cls, name):
for policy_name, policy in SeqCutOffPolicy.__members__.items():
if name == policy_name:
return policy
raise ValueError(f"{name} is not a valid sequential cut off name")
class EvictionPolicy(Enum):
lru = 0
@ -106,6 +114,7 @@ class SeqCutOffParameters:
seq_cut_off_params = SeqCutOffParameters()
seq_cut_off_params.policy = SeqCutOffPolicy.full
seq_cut_off_params.threshold = Size(1024, Unit.KibiByte)
return seq_cut_off_params
# TODO: Use case for this will be to iterate over configurations (kernel params such as

View File

@ -254,15 +254,10 @@ def get_param_cleaning_acp(cache_id: int, output_format: OutputFormat = None,
def set_param_cutoff(cache_id: int, core_id: int = None, threshold: Size = None,
policy: SeqCutOffPolicy = None):
_threshold = None if threshold is None else threshold.get_value(Unit.KibiByte)
if core_id is None:
command = set_param_cutoff_cmd(
cache_id=str(cache_id), threshold=_threshold,
policy=policy.name)
else:
command = set_param_cutoff_cmd(
cache_id=str(cache_id), core_id=str(core_id),
threshold=_threshold, policy=policy.name)
_threshold = None if threshold is None else int(threshold.get_value(Unit.KibiByte))
command = set_param_cutoff_cmd(
cache_id=cache_id, core_id=core_id,
threshold=_threshold, policy=policy)
output = TestRun.executor.run(command)
if output.exit_code != 0:
raise Exception(

View File

@ -198,9 +198,10 @@ def get_seq_cut_off_parameters(cache_id: int, core_id: int):
seq_cut_off_params = SeqCutOffParameters()
for line in casadm_output:
if 'threshold' in line:
seq_cut_off_params.threshold = line.split(',')[1]
seq_cut_off_params.threshold = Size(int(line.split(',')[1]), Unit.KibiByte)
if 'policy' in line:
seq_cut_off_params.policy = SeqCutOffPolicy(line.split(',')[1])
seq_cut_off_params.policy = SeqCutOffPolicy.from_name(line.split(',')[1])
return seq_cut_off_params
def get_casadm_version():

View File

@ -190,11 +190,11 @@ def set_param_cutoff_cmd(cache_id: str, core_id: str = None, threshold: str = No
policy: str = None, shortcut: bool = False):
add_params = ""
if core_id is not None:
add_params += (" -j " if shortcut else " --core-id ") + core_id
add_params += (" -j " if shortcut else " --core-id ") + str(core_id)
if threshold is not None:
add_params += (" -t " if shortcut else " --threshold ") + threshold
add_params += (" -t " if shortcut else " --threshold ") + str(threshold)
if policy is not None:
add_params += (" -p " if shortcut else " --policy ") + policy
add_params += (" -p " if shortcut else " --policy ") + policy.name
return _set_param_cmd(namespace="seq-cutoff", cache_id=cache_id,
additional_params=add_params, shortcut=shortcut)

View File

@ -17,6 +17,10 @@ class CoreStatus(Enum):
detached = 3
SEQ_CUTOFF_THRESHOLD_MAX = Size(4194181, Unit.KibiByte)
SEQ_CUT_OFF_THRESHOLD_DEFAULT = Size(1, Unit.MebiByte)
class Core(Device):
def __init__(self, core_device: str, cache_id: int):
self.core_device = Device(core_device)
@ -54,6 +58,12 @@ class Core(Device):
def get_seq_cut_off_parameters(self):
return get_seq_cut_off_parameters(self.cache_id, self.core_id)
def get_seq_cut_off_policy(self):
return get_seq_cut_off_parameters(self.cache_id, self.core_id).policy
def get_seq_cut_off_threshold(self):
return get_seq_cut_off_parameters(self.cache_id, self.core_id).threshold
def get_dirty_blocks(self):
return self.get_core_statistics()["dirty"]
@ -77,5 +87,15 @@ class Core(Device):
assert self.get_dirty_blocks().get_value(Unit.Blocks4096) == 0
def set_seq_cutoff_parameters(self, seq_cutoff_param: SeqCutOffParameters):
casadm.set_param_cutoff(self.cache_id, self.core_id,
seq_cutoff_param.threshold, seq_cutoff_param.policy)
return casadm.set_param_cutoff(self.cache_id, self.core_id,
seq_cutoff_param.threshold, seq_cutoff_param.policy)
def set_seq_cutoff_threshold(self, threshold: Size):
return casadm.set_param_cutoff(self.cache_id, self.core_id,
threshold=threshold,
policy=None)
def set_seq_cutoff_policy(self, policy: SeqCutOffPolicy):
return casadm.set_param_cutoff(self.cache_id, self.core_id,
threshold=None,
policy=policy)

View File

@ -0,0 +1,280 @@
#
# Copyright(c) 2019 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause-Clear
#
import pytest
import random
from ctypes import c_uint32
from api.cas import casadm
from api.cas.cache_config import SeqCutOffPolicy
from api.cas.core import SEQ_CUTOFF_THRESHOLD_MAX, SEQ_CUT_OFF_THRESHOLD_DEFAULT
from api.cas.casadm import set_param_cutoff_cmd
from core.test_run import TestRun
from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan
from test_utils.size import Size, Unit
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_default_params():
"""
title: Default sequential cut-off threshold & policy test
description: Test if proper default threshold and policy is set after cache start
pass_criteria:
- "Full" shall be default sequential cut-off policy
- There shall be default 1MiB (1024kiB) value for sequential cut-off threshold
"""
with TestRun.step("Test prepare (start cache and add core)"):
cache, cores = prepare()
with TestRun.step("Getting sequential cut-off parameters"):
params = cores[0].get_seq_cut_off_parameters()
with TestRun.step("Check if proper sequential cut off policy is set as a default"):
if params.policy != SeqCutOffPolicy.DEFAULT:
TestRun.fail(f"Wrong sequential cut off policy set: {params.policy} "
f"should be {SeqCutOffPolicy.DEFAULT}")
with TestRun.step("Check if proper sequential cut off threshold is set as a default"):
if params.threshold != SEQ_CUT_OFF_THRESHOLD_DEFAULT:
TestRun.fail(f"Wrong sequential cut off threshold set: {params.threshold} "
f"should be {SEQ_CUT_OFF_THRESHOLD_DEFAULT}")
@pytest.mark.parametrize("policy", SeqCutOffPolicy)
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_set_get_policy_core(policy):
"""
title: Sequential cut-off policy set/get test for core
description: |
Test if CAS is setting proper sequential cut-off policy for core and
returns previously set value
pass_criteria:
- Sequential cut-off policy obtained from get-param command for the first core must be
the same as the one used in set-param command
- Sequential cut-off policy obtained from get-param command for the second core must be
proper default value
"""
with TestRun.step("Test prepare (start cache and add 2 cores)"):
cache, cores = prepare(cores_count=2)
with TestRun.step(f"Setting core sequential cut off policy mode to {policy}"):
cores[0].set_seq_cutoff_policy(policy)
with TestRun.step("Check if proper sequential cut off policy was set for the first core"):
if cores[0].get_seq_cut_off_policy() != policy:
TestRun.fail(f"Wrong sequential cut off policy set: "
f"{cores[0].get_seq_cut_off_policy()} "
f"should be {policy}")
with TestRun.step("Check if proper default sequential cut off policy was set for the "
"second core"):
if cores[1].get_seq_cut_off_policy() != SeqCutOffPolicy.DEFAULT:
TestRun.fail(f"Wrong default sequential cut off policy: "
f"{cores[1].get_seq_cut_off_policy()} "
f"should be {SeqCutOffPolicy.DEFAULT}")
@pytest.mark.parametrize("policy", SeqCutOffPolicy)
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_set_get_policy_cache(policy):
"""
title: Sequential cut-off policy set/get test for cache
description: |
Test if CAS is setting proper sequential cut-off policy for whole cache and
returns previously set value
pass_criteria:
- Sequential cut-off policy obtained from get-param command for each of 3 cores must be the
same as the one used in set-param command for cache
"""
with TestRun.step("Test prepare (start cache and add 3 cores)"):
cache, cores = prepare(cores_count=3)
with TestRun.step(f"Setting sequential cut off policy mode {policy} for cache"):
cache.set_seq_cutoff_policy(policy)
for i in TestRun.iteration(range(0, len(cores)), "Verifying if proper policy was set"):
with TestRun.step(f"Check if proper sequential cut off policy was set for core"):
if cores[i].get_seq_cut_off_policy() != policy:
TestRun.fail(f"Wrong core sequential cut off policy: "
f"{cores[i].get_seq_cut_off_policy()} "
f"should be {policy}")
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_policy_load():
"""
title: Sequential cut-off policy set/get test with cache load between
description: |
Set each possible policy for different core, stop cache, test if after cache load
sequential cut-off policy value previously set is being loaded correctly for each core.
pass_criteria:
- Sequential cut-off policy obtained from get-param command after cache load
must be the same as the one used in set-param command before cache stop
- Sequential cut-off policy loaded for the last core should be the default one
"""
with TestRun.step(f"Test prepare (start cache and add {len(SeqCutOffPolicy) + 1} cores)"):
# Create as many cores as many possible policies including default one
cache, cores = prepare(cores_count=len(SeqCutOffPolicy) + 1)
policies = [policy for policy in SeqCutOffPolicy]
for i, core in TestRun.iteration(enumerate(cores[:-1]), "Set all possible policies "
"except the default one"):
with TestRun.step(f"Setting cache sequential cut off policy mode to "
f"{policies[i]}"):
cores[i].set_seq_cutoff_policy(policies[i])
with TestRun.step("Stopping cache"):
cache.stop()
with TestRun.step("Loading cache"):
loaded_cache = casadm.load_cache(cache.cache_device)
with TestRun.step("Getting cores from loaded cache"):
cores = loaded_cache.get_core_devices()
for i, core in TestRun.iteration(enumerate(cores[:-1]), "Check if proper policies have "
"been loaded"):
with TestRun.step(f"Check if proper sequential cut off policy was loaded"):
if cores[i].get_seq_cut_off_policy() != policies[i]:
TestRun.fail(f"Wrong sequential cut off policy loaded: "
f"{cores[i].get_seq_cut_off_policy()} "
f"should be {policies[i]}")
with TestRun.step(f"Check if proper (default) sequential cut off policy was loaded for "
f"last core"):
if cores[len(SeqCutOffPolicy)].get_seq_cut_off_policy() != SeqCutOffPolicy.DEFAULT:
TestRun.fail(f"Wrong sequential cut off policy loaded: "
f"{cores[len(SeqCutOffPolicy)].get_seq_cut_off_policy()} "
f"should be {SeqCutOffPolicy.DEFAULT}")
@pytest.mark.parametrize("threshold", random.sample(
range((int(SEQ_CUTOFF_THRESHOLD_MAX.get_value(Unit.KibiByte)) + 1),
c_uint32(-1).value), 3))
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_set_invalid_threshold(threshold):
"""
title: Invalid sequential cut-off threshold test
description: Test if CAS is allowing setting invalid sequential cut-off threshold
pass_criteria:
- Setting invalid sequential cut-off threshold should be blocked
"""
with TestRun.step("Test prepare (start cache and add core)"):
cache, cores = prepare()
_threshold = Size(threshold, Unit.KibiByte)
with TestRun.step(f"Setting cache sequential cut off threshold to out of range value: "
f"{_threshold}"):
command = set_param_cutoff_cmd(
cache_id=str(cache.cache_id), core_id=str(cores[0].core_id),
threshold=str(int(_threshold.get_value())))
output = TestRun.executor.run_expect_fail(command)
if "Invalid sequential cutoff threshold, must be in the range 1-4194181"\
not in output.stderr:
TestRun.fail("Command succeeded (should fail)!")
with TestRun.step(f"Setting cache sequential cut off threshold "
f"to value passed as a float"):
command = set_param_cutoff_cmd(
cache_id=str(cache.cache_id), core_id=str(cores[0].core_id),
threshold=str(_threshold.get_value()))
output = TestRun.executor.run_expect_fail(command)
if "Invalid sequential cutoff threshold, must be a correct unsigned decimal integer"\
not in output.stderr:
TestRun.fail("Command succeeded (should fail)!")
@pytest.mark.parametrize("threshold", random.sample(
range(1, int(SEQ_CUTOFF_THRESHOLD_MAX.get_value(Unit.KibiByte))), 3))
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_set_get_threshold(threshold):
"""
title: Sequential cut-off threshold set/get test
description: |
Test if CAS is setting proper sequential cut-off threshold and returns
previously set value
pass_criteria:
- Sequential cut-off threshold obtained from get-param command must be the same as
the one used in set-param command
"""
with TestRun.step("Test prepare (start cache and add core)"):
cache, cores = prepare()
_threshold = Size(threshold, Unit.KibiByte)
with TestRun.step(f"Setting cache sequential cut off threshold to "
f"{_threshold}"):
cores[0].set_seq_cutoff_threshold(_threshold)
with TestRun.step("Check if proper sequential cut off threshold was set"):
if cores[0].get_seq_cut_off_threshold() != _threshold:
TestRun.fail(f"Wrong sequential cut off threshold set: "
f"{cores[0].get_seq_cut_off_threshold()} "
f"should be {_threshold}")
@pytest.mark.parametrize("threshold", random.sample(
range(1, int(SEQ_CUTOFF_THRESHOLD_MAX.get_value(Unit.KibiByte))), 3))
@pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand]))
@pytest.mark.require_disk("core", DiskTypeLowerThan("cache"))
def test_seq_cutoff_threshold_load(threshold):
"""
title: Sequential cut-off threshold set/get test with cache load between
description: |
Test if after cache load sequential cut-off threshold
value previously set is being loaded correctly. Each of possible sequential cut-off
policies is set for different core.
pass_criteria:
- Sequential cut-off threshold obtained from get-param command after cache load
must be the same as the one used in set-param command before cache stop
"""
with TestRun.step("Test prepare (start cache and add core)"):
cache, cores = prepare()
_threshold = Size(threshold, Unit.KibiByte)
with TestRun.step(f"Setting cache sequential cut off threshold to "
f"{_threshold}"):
cores[0].set_seq_cutoff_threshold(_threshold)
with TestRun.step("Stopping cache"):
cache.stop()
with TestRun.step("Loading cache"):
loaded_cache = casadm.load_cache(cache.cache_device)
with TestRun.step("Getting core from loaded cache"):
cores_load = loaded_cache.get_core_devices()
with TestRun.step("Check if proper sequential cut off policy was loaded"):
if cores_load[0].get_seq_cut_off_threshold() != _threshold:
TestRun.fail(f"Wrong sequential cut off threshold set: "
f"{cores_load[0].get_seq_cut_off_threshold()} "
f"should be {_threshold}")
def prepare(cores_count=1):
cache_device = TestRun.disks['cache']
core_device = TestRun.disks['core']
cache_device.create_partitions([Size(500, Unit.MebiByte)])
partitions = []
for x in range(cores_count):
partitions.append(Size(1, Unit.GibiByte))
core_device.create_partitions(partitions)
cache_part = cache_device.partitions[0]
core_parts = core_device.partitions
TestRun.LOGGER.info("Staring cache")
cache = casadm.start_cache(cache_part, force=True)
TestRun.LOGGER.info("Adding core devices")
core_list = []
for core_part in core_parts:
core_list.append(cache.add_core(core_dev=core_part))
return cache, core_list