Coverage for tests/unit/test_utils.py: 100%
72 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-05-02 08:55 -0600
« prev ^ index » next coverage.py v7.4.4, created at 2024-05-02 08:55 -0600
1"""Test functions in es_testbed.helpers.utils"""
3# pylint: disable=missing-function-docstring,redefined-outer-name
4import typing as t
5import pytest
6from dotmap import DotMap
7from es_testbed.defaults import (
8 ilmhot,
9 ilmwarm,
10 ilmcold,
11 ilmfrozen,
12 ilmdelete,
13)
14from es_testbed.exceptions import TestbedMisconfig
15from es_testbed.helpers.utils import build_ilm_phase, build_ilm_policy, doc_gen
17FMAP: t.Dict[str, t.Dict] = {
18 'hot': ilmhot(),
19 'warm': ilmwarm(),
20 'cold': ilmcold(),
21 'frozen': ilmfrozen(),
22 'delete': ilmdelete(),
23}
24REPO: str = 'repo'
25TIERS: t.Sequence[str] = ['hot', 'warm', 'cold', 'frozen', 'delete']
26TREPO: t.Dict[str, t.Union[str, None]] = {
27 'hot': None,
28 'warm': None,
29 'cold': REPO,
30 'frozen': REPO,
31 'delete': None,
32}
35def searchable(
36 repo: str = None, fm: bool = None
37) -> t.Union[t.Dict[str, t.Dict[str, str]], None]:
38 if repo:
39 return {
40 'searchable_snapshot': {
41 'snapshot_repository': repo,
42 'force_merge_index': fm,
43 }
44 }
45 return {}
48def forcemerge(
49 fm: bool = False, mns: int = 1
50) -> t.Union[t.Dict[str, t.Dict[str, str]], None]:
51 if fm:
52 return {'forcemerge': {'max_num_segments': mns}}
53 return {}
56@pytest.fixture
57def tiertestval():
58 def _tiertestval(tier: str, repo: str = None, fm: bool = False, mns: int = 1):
59 retval = {tier: FMAP[tier]}
60 retval[tier]['actions'].update(searchable(repo=repo, fm=fm))
61 kwargs = {'fm': fm, 'mns': mns} if tier in ['hot', 'warm'] else {}
62 retval[tier]['actions'].update(forcemerge(**kwargs))
63 return retval
65 return _tiertestval
68@pytest.fixture
69def builtphase():
70 def _builtphase(tier: str, repo: str = None, fm: bool = False, mns: int = 1):
71 return build_ilm_phase(tier, actions=forcemerge(fm=fm, mns=mns), repo=repo)
73 return _builtphase
76def test_build_ilm_phase_defaults(builtphase, tiertestval):
77 for tier in TIERS:
78 assert builtphase(tier, repo=TREPO[tier]) == tiertestval(tier, repo=TREPO[tier])
81def test_build_ilm_phase_add_action():
82 expected = {'foo': 'bar'}
83 tier = 'warm'
84 assert build_ilm_phase(tier, actions=expected)[tier]['actions'] == expected
87def test_build_ilm_phase_fail_repo(builtphase):
88 with pytest.raises(TestbedMisconfig):
89 builtphase('cold', repo=None)
92# This allows me to run multiple testing scenarios in the same test space
93def test_build_ilm_policy(tiertestval):
94 # 3 tests building different ILM policies with different tiers
95 tgroups = [
96 ['hot', 'delete'],
97 ['hot', 'frozen', 'delete'],
98 ['hot', 'cold', 'delete'],
99 ]
100 # Each tier group corresponds to a forcemerge plan by list index, with each index a
101 # tuple for forcemerge True/False and max_num_segment count
102 fmerge = [(False, 0), (False, 0), (True, 3)]
103 for idx, tgrp in enumerate(tgroups): # Iterate over testing scenarios
104 phases = {} # Build out the phase dict for each scenario
105 fm, mns = fmerge[idx] # Extract whether to use forcemerge by index/tuple
106 for tier in tgrp: # Iterate over each tier in the testing scenario
107 kwargs = {'fm': fm} if tier in ['cold', 'frozen'] else {}
108 phases.update(
109 tiertestval(tier, repo=TREPO[tier], **kwargs)
110 ) # Update with values per tier
111 if fm: # If we're doing forcemerge
112 phases['hot']['actions'].update(
113 forcemerge(fm=fm, mns=mns)
114 ) # Update the hot tier
115 # To keep the line more readable, build the kwargs as a dict first
116 kwargs = {'repository': REPO, 'forcemerge': fm, 'max_num_segments': mns}
117 # Then pass it as **kwargs
118 assert build_ilm_policy(tgrp, **kwargs) == {'phases': phases}
119 # Our policy is easier to build at the last minute rather than constantly
120 # passing dict['phases']['tier']
123def test_build_ilm_policy_fail_repo():
124 with pytest.raises(TestbedMisconfig):
125 build_ilm_policy(['hot', 'frozen'], repository=None)
128@pytest.fixture
129def fieldmatch():
130 def _fieldmatch(val: str, num: int):
131 return f'{val}{num}'
133 return _fieldmatch
136def test_doc_gen_matching(fieldmatch):
137 i = 0
138 for res in doc_gen(count=3, start_at=0, match=True):
139 doc = DotMap(res)
140 tests = [
141 (doc.message, 'message'),
142 (doc.nested.key, 'nested'),
143 (doc.deep.l1.l2.l3, 'deep'),
144 ]
145 for test in tests:
146 dm, val = test
147 assert dm == fieldmatch(val, i)
148 i += 1