blob: 62ee9822dfa9d591a7d5180e89cff87827d3d97c [file] [log] [blame]
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import collections
import copy
import json
import unittest
import _test_damo_common
_test_damo_common.add_damo_dir_to_syspath()
import _damon
class TestDamon(unittest.TestCase):
def test_kvpairs_transition(self):
target = _damon.DamonTarget(1234, [_damon.DamonRegion(10, 20)])
target_kvpairs = target.to_kvpairs()
self.assertEqual(type(target_kvpairs), collections.OrderedDict)
self.assertEqual(list(target_kvpairs.keys()),
['pid', 'obsolete', 'regions'])
self.assertEqual(target,
_damon.DamonTarget.from_kvpairs(target_kvpairs))
damos = _damon.Damos(
_damon.DamosAccessPattern([0, 10], [5, 8], _damon.unit_percent,
[54, 88], _damon.unit_usec),
'pageout', None,
None,
_damon.DamosQuotas(100, 1024, 1000, [80, 76, 24]),
_damon.DamosWatermarks('free_mem_rate', 5000000, 800, 500,
200),
[_damon.DamosFilter('memcg', True, memcg_path='/foo/bar'),
_damon.DamosFilter('anon', False)],
None, None)
damos_kvpairs = damos.to_kvpairs()
self.assertEqual(type(damos_kvpairs), collections.OrderedDict)
self.assertEqual(list(damos_kvpairs.keys()),
['action', 'dests', 'access_pattern', 'apply_interval_us',
'quotas', 'watermarks', 'filters', 'stats'])
self.assertEqual(list(damos_kvpairs['stats'].keys()),
['nr_tried', 'sz_tried', 'nr_applied', 'sz_applied',
'sz_ops_filter_passed', 'qt_exceeds', 'nr_snapshots',
'max_nr_snapshots'])
self.assertEqual(damos, _damon.Damos.from_kvpairs(damos_kvpairs))
ctx = _damon.DamonCtx('paddr', [target],
_damon.DamonIntervals(5000, 100000, 1000000),
_damon.DamonNrRegionsRange(10, 1000),
[damos])
ctx_kvpairs = ctx.to_kvpairs()
self.assertEqual(type(ctx_kvpairs), collections.OrderedDict)
self.assertEqual(list(ctx_kvpairs.keys()),
['ops', 'targets', 'intervals', 'nr_regions', 'sample_control',
'schemes'])
self.assertEqual(ctx, _damon.DamonCtx.from_kvpairs(ctx_kvpairs))
kdamond = _damon.Kdamond('off', 123, [ctx])
kdamond_kvpairs = kdamond.to_kvpairs()
self.assertEqual(type(kdamond_kvpairs), collections.OrderedDict)
self.assertEqual(list(kdamond_kvpairs.keys()),
['state', 'pid', 'refresh_ms', 'contexts'])
self.assertEqual(kdamond,
_damon.Kdamond.from_kvpairs(kdamond_kvpairs))
def test_damos_default_immutable(self):
damos = _damon.Damos()
before = damos.quotas.time_ms
damos.quotas.time_ms = 123
damos = _damon.Damos()
self.assertEqual(before, damos.quotas.time_ms)
def test_damos_eq(self):
damos = _damon.Damos(
access_pattern=_damon.DamosAccessPattern([4096,
18446744073709551615], [0.0, 0.0], _damon.unit_percent,
[1000000, 4294900000], _damon.unit_usec),
action='stat', target_nid=None,
apply_interval_us=None,
quotas=_damon.DamosQuotas(time_ms=0, sz_bytes=584792941,
reset_interval_ms=1000, weights=[0,0,0]),
watermarks=_damon.DamosWatermarks(
_damon.damos_wmarks_metric_none,0,0,0,0),
filters=[], stats=None)
damos2 = copy.deepcopy(damos)
self.assertEqual(damos, damos2)
damos2.filters = [_damon.DamosFilter(filter_type='memcg',
matching=True, memcg_path='/foo/bar/')]
self.assertNotEqual(damos, damos2)
intervals = _damon.DamonIntervals(5000, 100000, 1000000)
pattern_human = _damon.DamosAccessPattern([123, 456],
[15, 35], _damon.unit_percent,
[5000000, 19000000], _damon.unit_usec)
pattern_machine = _damon.DamosAccessPattern([123, 456],
[3, 7], _damon.unit_samples,
[50, 190], _damon.unit_aggr_intervals)
damos.access_pattern = pattern_human
damos2 = copy.deepcopy(damos)
damos2.access_pattern = pattern_machine
self.assertNotEqual(damos, damos2)
self.assertTrue(damos.effectively_equal(damos2, intervals))
self.assertTrue(damos.effectively_equal(damos2, intervals))
def test_damos_action_validity(self):
exception_raised = False
try:
_damon.Damos(action='foo')
except:
exception_raised = True
self.assertTrue(exception_raised)
for action in _damon.damos_actions:
exception_raised = False
try:
_damon.Damos(action=action)
except:
exception_raised = True
self.assertFalse(exception_raised)
def test_damon_intervals(self):
self.assertEqual(_damon.DamonIntervals(),
_damon.DamonIntervals(5000, 100000, 1000000))
_test_damo_common.test_input_expects(self,
lambda x: _damon.DamonIntervals.from_kvpairs(json.loads(x)),
{
json.dumps({'sample_us': 5000, 'aggr_us': 100000,
'ops_update_us': 1000000}):
_damon.DamonIntervals(5000, 100000, 1000000),
json.dumps({'sample_us': '5ms', 'aggr_us': '0.1s',
'ops_update_us': '1s'}):
_damon.DamonIntervals(5000, 100000, 1000000)})
self.assertEqual('%s' % _damon.DamonIntervals(5000, 100000, 1000000),
'sample 5 ms, aggr 100 ms, update 1 s')
self.assertEqual('%s' %
_damon.DamonIntervals(5000, 100000, 1000000).to_str(True),
'sample 5000, aggr 100000, update 1000000')
intervals_kvpairs = _damon.DamonIntervals(5000, 100000, 1000000).to_kvpairs()
del intervals_kvpairs['intervals_goal']
self.assertEqual(
intervals_kvpairs,
{'sample_us': '5 ms', 'aggr_us': '100 ms',
'ops_update_us': '1 s',
})
def test_damon_nr_regions_range(self):
self.assertEqual(_damon.DamonNrRegionsRange(),
_damon.DamonNrRegionsRange(10, 1000))
expect = _damon.DamonNrRegionsRange(10, 1000)
_test_damo_common.test_input_expects(self,
lambda x: _damon.DamonNrRegionsRange(*x),
{
tuple([10, '1000']): expect,
tuple(['10', '1000']): expect,
tuple(['10', '1,000']): expect})
_test_damo_common.test_input_expects(self,
lambda x: _damon.DamonNrRegionsRange.from_kvpairs(
json.loads(x)),
{
json.dumps({'min': 10, 'max': 1000}):
expect,
json.dumps(
{'min': '10', 'max': '1000'}):
expect,
json.dumps(
{'min': '10', 'max': '1,000'}):
expect})
self.assertEqual('%s' % _damon.DamonNrRegionsRange(10, 1000),
'[10, 1,000]')
self.assertEqual(
'%s' % _damon.DamonNrRegionsRange(10, 1000).to_str(True),
'[10, 1000]')
self.assertEqual(_damon.DamonNrRegionsRange(10, 1000).to_kvpairs(),
{'min': '10', 'max': '1,000'})
self.assertEqual(_damon.DamonNrRegionsRange(10, 1000).to_kvpairs(
raw=True),
{'min': '10', 'max': '1000'})
def test_damon_region(self):
_test_damo_common.test_input_expects(self,
lambda x: _damon.DamonRegion(*x),
{
tuple([123, '456']): _damon.DamonRegion(123, 456),
tuple(['123', '456']): _damon.DamonRegion(123, 456),
tuple(['1,234', '4,567']): _damon.DamonRegion(1234, 4567),
tuple(['1K', '4K']): _damon.DamonRegion(1024, 4096),
})
_test_damo_common.test_input_expects(self,
lambda x: _damon.DamonRegion.from_kvpairs(json.loads(x)),
{
json.dumps({'start': '123', 'end': '456'}):
_damon.DamonRegion(123, 456),
json.dumps({'start': '1234', 'end': '4567'}):
_damon.DamonRegion(1234, 4567),
json.dumps({'start': '1,234', 'end': '4,567'}):
_damon.DamonRegion(1234, 4567),
json.dumps({'start': '1K', 'end': '4K'}):
_damon.DamonRegion(1024, 4096),
})
self.assertEqual('%s' % _damon.DamonRegion(123, 456),
'[123, 456) (333 B)')
self.assertEqual('%s' % _damon.DamonRegion(123, 456).to_str(raw=True),
'[123, 456) (333)')
self.assertEqual(_damon.DamonRegion(1234, 5678).to_kvpairs(),
{'start': '1,234', 'end': '5,678'})
self.assertEqual(_damon.DamonRegion(1234, 5678).to_kvpairs(raw=True),
{'start': '1234', 'end': '5678'})
def test_damos_access_pattern(self):
self.assertEqual(_damon.DamosAccessPattern(),
_damon.DamosAccessPattern(['min', 'max'],
['min', 'max'], _damon.unit_percent,
['min', 'max'], _damon.unit_usec))
intervals = _damon.DamonIntervals(5000, 100000, 1000000)
pattern_human = _damon.DamosAccessPattern([123, '4,567'],
[15, '10,000'], _damon.unit_percent,
['5,000,000', '190,000,000'], _damon.unit_usec)
pattern_machine = _damon.DamosAccessPattern([123, 4567],
[3, '2,000'], _damon.unit_samples,
[50, '1,900'], _damon.unit_aggr_intervals)
self.assertEqual(
pattern_human.converted_for_units(
_damon.unit_samples,
_damon.unit_aggr_intervals, intervals),
pattern_machine)
self.assertEqual(
pattern_machine.converted_for_units(
_damon.unit_percent, _damon.unit_usec, intervals),
pattern_human)
self.assertTrue(
pattern_human.effectively_equal(pattern_machine, intervals))
for converted in [
pattern_human.converted_for_units(_damon.unit_samples,
_damon.unit_aggr_intervals, intervals),
pattern_machine.converted_for_units(
_damon.unit_percent, _damon.unit_usec, intervals)]:
self.assertEqual(type(converted.nr_acc_min_max[0].samples), int)
self.assertEqual(type(converted.nr_acc_min_max[1].samples), int)
self.assertEqual(type(converted.nr_acc_min_max[0].percent), int)
self.assertEqual(type(converted.nr_acc_min_max[1].percent), int)
self.assertEqual(type(converted.age_min_max[0].aggr_intervals), int)
self.assertEqual(type(converted.age_min_max[1].aggr_intervals), int)
self.assertEqual(type(converted.age_min_max[0].usec), int)
self.assertEqual(type(converted.age_min_max[1].usec), int)
exception_raised = False
try:
_damon.DamosAccessPattern(nr_accesses=[0, 100], nr_accesses_unit='foo')
except:
exception_raised = True
self.assertTrue(exception_raised)
exception_raised = False
try:
_damon.DamosAccessPattern(age=[0, 100], age_unit='bar')
except:
exception_raised = True
self.assertTrue(exception_raised)
def test_damos_quotas(self):
self.assertEqual(_damon.DamosQuotas(),
_damon.DamosQuotas(0, 0, 'max', [0, 0, 0]))
def test_damos_watermarks(self):
self.assertEqual(_damon.DamosWatermarks(),
_damon.DamosWatermarks(_damon.damos_wmarks_metric_none,
0, 0, 0, 0))
def test_damon_nr_accesses(self):
intervals = _damon.DamonIntervals('5ms', '100ms', '1s')
nr_acc = _damon.DamonNrAccesses(4, _damon.unit_samples)
nr_acc_2 = _damon.DamonNrAccesses(4, _damon.unit_samples)
self.assertEqual(nr_acc, nr_acc_2)
nr_acc_2 = _damon.DamonNrAccesses(6, _damon.unit_samples)
self.assertNotEqual(nr_acc, nr_acc_2)
nr_acc.add_unset_unit(intervals)
self.assertEqual(nr_acc.samples, 4)
self.assertEqual(nr_acc.percent, 20)
self.assertEqual('%s' % nr_acc.to_str(_damon.unit_samples, raw=False),
'4 %s' % _damon.unit_samples)
self.assertEqual('%s' % nr_acc.to_str(_damon.unit_percent, raw=False),
'20 %')
nr_acc = _damon.DamonNrAccesses(20, _damon.unit_percent)
nr_acc_2 = _damon.DamonNrAccesses(20, _damon.unit_percent)
self.assertEqual(nr_acc, nr_acc_2)
nr_acc_2 = _damon.DamonNrAccesses(25, _damon.unit_percent)
self.assertNotEqual(nr_acc, nr_acc_2)
nr_acc.add_unset_unit(intervals)
self.assertEqual(nr_acc.samples, 4)
self.assertEqual(nr_acc.percent, 20)
self.assertEqual('%s' % nr_acc.to_str(_damon.unit_samples, raw=False),
'4 %s' % _damon.unit_samples)
self.assertEqual('%s' % nr_acc.to_str(_damon.unit_percent, raw=False),
'20 %')
nr_acc = _damon.DamonNrAccesses.from_kvpairs(
{'samples': 12, 'percent': 45})
self.assertEqual(nr_acc.samples, 12)
self.assertEqual(nr_acc.percent, 45)
nr_acc = _damon.DamonNrAccesses.from_kvpairs(
{'samples': '12', 'percent': '45%'})
self.assertEqual(nr_acc.samples, 12)
self.assertEqual(nr_acc.percent, 45)
def test_damon_age(self):
intervals = _damon.DamonIntervals('5ms', '100ms', '1s')
age = _damon.DamonAge(15, _damon.unit_aggr_intervals)
age_2 = _damon.DamonAge(15, _damon.unit_aggr_intervals)
self.assertEqual(age, age_2)
age_2 = _damon.DamonAge(18, _damon.unit_aggr_intervals)
self.assertNotEqual(age, age_2)
age.add_unset_unit(intervals)
self.assertEqual(age.aggr_intervals, 15)
self.assertEqual(age.usec, 1500000)
self.assertEqual(
'%s' % age.to_str(_damon.unit_aggr_intervals, raw=False),
'15 %s' % _damon.unit_aggr_intervals)
self.assertEqual('%s' % age.to_str(_damon.unit_usec, raw=False),
'1 s 500 ms')
age = _damon.DamonAge.from_kvpairs({'usec': 12, 'aggr_intervals': 456})
self.assertEqual(age.usec, 12)
self.assertEqual(age.aggr_intervals, 456)
def test_best_effort_target_arrange(self):
updated_targets = [
_damon.DamonTarget(pid=1),
_damon.DamonTarget(pid=2, obsolete=True),
_damon.DamonTarget(pid=3),
_damon.DamonTarget(pid=4, obsolete=True),
]
new_targets = [
_damon.DamonTarget(pid=5),
_damon.DamonTarget(pid=6),
_damon.DamonTarget(pid=7),
]
expect_targets = [
_damon.DamonTarget(pid=1),
_damon.DamonTarget(pid=5),
_damon.DamonTarget(pid=3),
_damon.DamonTarget(pid=6),
_damon.DamonTarget(pid=7),
]
result_targets = _damon.best_effort_target_arrange(
updated_targets, new_targets)
self.assertEqual(result_targets, expect_targets)
if __name__ == '__main__':
unittest.main()