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

1"""Test functions in es_testbed.helpers.utils""" 

2 

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 

16 

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} 

33 

34 

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 {} 

46 

47 

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 {} 

54 

55 

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 

64 

65 return _tiertestval 

66 

67 

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) 

72 

73 return _builtphase 

74 

75 

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]) 

79 

80 

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 

85 

86 

87def test_build_ilm_phase_fail_repo(builtphase): 

88 with pytest.raises(TestbedMisconfig): 

89 builtphase('cold', repo=None) 

90 

91 

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'] 

121 

122 

123def test_build_ilm_policy_fail_repo(): 

124 with pytest.raises(TestbedMisconfig): 

125 build_ilm_policy(['hot', 'frozen'], repository=None) 

126 

127 

128@pytest.fixture 

129def fieldmatch(): 

130 def _fieldmatch(val: str, num: int): 

131 return f'{val}{num}' 

132 

133 return _fieldmatch 

134 

135 

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