]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/tools/advisor/test/test_rule_parser.py
1 # Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 # This source code is licensed under both the GPLv2 (found in the
3 # COPYING file in the root directory) and Apache 2.0 License
4 # (found in the LICENSE.Apache file in the root directory).
8 from advisor
.rule_parser
import RulesSpec
9 from advisor
.db_log_parser
import DatabaseLogs
, DataSource
10 from advisor
.db_options_parser
import DatabaseOptions
13 "stall-too-many-memtables": [
17 "stall-too-many-L0": [
18 'inc-max-subcompactions',
19 'inc-max-bg-compactions',
20 'inc-write-buffer-size',
21 'dec-max-bytes-for-level-base',
22 'inc-l0-slowdown-writes-trigger'
25 'inc-max-bg-compactions',
26 'inc-write-buffer-size',
27 'inc-l0-stop-writes-trigger'
29 "stall-too-many-compaction-bytes": [
30 'inc-max-bg-compactions',
31 'inc-write-buffer-size',
32 'inc-hard-pending-compaction-bytes-limit',
33 'inc-soft-pending-compaction-bytes-limit'
35 "level0-level1-ratio": [
36 'l0-l1-ratio-health-check'
41 class TestAllRulesTriggered(unittest
.TestCase
):
44 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
45 ini_path
= os
.path
.join(this_path
, 'input_files/triggered_rules.ini')
46 self
.db_rules
= RulesSpec(ini_path
)
47 self
.db_rules
.load_rules_from_spec()
48 self
.db_rules
.perform_section_checks()
49 # load the data sources: LOG and OPTIONS
50 log_path
= os
.path
.join(this_path
, 'input_files/LOG-0')
51 options_path
= os
.path
.join(this_path
, 'input_files/OPTIONS-000005')
52 db_options_parser
= DatabaseOptions(options_path
)
53 self
.column_families
= db_options_parser
.get_column_families()
54 db_logs_parser
= DatabaseLogs(log_path
, self
.column_families
)
56 DataSource
.Type
.DB_OPTIONS
: [db_options_parser
],
57 DataSource
.Type
.LOG
: [db_logs_parser
]
60 def test_triggered_conditions(self
):
61 conditions_dict
= self
.db_rules
.get_conditions_dict()
62 rules_dict
= self
.db_rules
.get_rules_dict()
63 # Make sure none of the conditions is triggered beforehand
64 for cond
in conditions_dict
.values():
65 self
.assertFalse(cond
.is_triggered(), repr(cond
))
66 for rule
in rules_dict
.values():
68 rule
.is_triggered(conditions_dict
, self
.column_families
),
72 # # Trigger the conditions as per the data sources.
73 # trigger_conditions(, conditions_dict)
75 # Get the set of rules that have been triggered
76 triggered_rules
= self
.db_rules
.get_triggered_rules(
77 self
.data_sources
, self
.column_families
80 # Make sure each condition and rule is triggered
81 for cond
in conditions_dict
.values():
82 if cond
.get_data_source() is DataSource
.Type
.TIME_SERIES
:
84 self
.assertTrue(cond
.is_triggered(), repr(cond
))
86 for rule
in rules_dict
.values():
87 self
.assertIn(rule
, triggered_rules
)
88 # Check the suggestions made by the triggered rules
89 for sugg
in rule
.get_suggestions():
90 self
.assertIn(sugg
, RuleToSuggestions
[rule
.name
])
92 for rule
in triggered_rules
:
93 self
.assertIn(rule
, rules_dict
.values())
94 for sugg
in RuleToSuggestions
[rule
.name
]:
95 self
.assertIn(sugg
, rule
.get_suggestions())
98 class TestConditionsConjunctions(unittest
.TestCase
):
101 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
102 ini_path
= os
.path
.join(this_path
, 'input_files/test_rules.ini')
103 self
.db_rules
= RulesSpec(ini_path
)
104 self
.db_rules
.load_rules_from_spec()
105 self
.db_rules
.perform_section_checks()
106 # load the data sources: LOG and OPTIONS
107 log_path
= os
.path
.join(this_path
, 'input_files/LOG-1')
108 options_path
= os
.path
.join(this_path
, 'input_files/OPTIONS-000005')
109 db_options_parser
= DatabaseOptions(options_path
)
110 self
.column_families
= db_options_parser
.get_column_families()
111 db_logs_parser
= DatabaseLogs(log_path
, self
.column_families
)
112 self
.data_sources
= {
113 DataSource
.Type
.DB_OPTIONS
: [db_options_parser
],
114 DataSource
.Type
.LOG
: [db_logs_parser
]
117 def test_condition_conjunctions(self
):
118 conditions_dict
= self
.db_rules
.get_conditions_dict()
119 rules_dict
= self
.db_rules
.get_rules_dict()
120 # Make sure none of the conditions is triggered beforehand
121 for cond
in conditions_dict
.values():
122 self
.assertFalse(cond
.is_triggered(), repr(cond
))
123 for rule
in rules_dict
.values():
125 rule
.is_triggered(conditions_dict
, self
.column_families
),
129 # Trigger the conditions as per the data sources.
130 self
.db_rules
.trigger_conditions(self
.data_sources
)
132 # Check for the conditions
133 conds_triggered
= ['log-1-true', 'log-2-true', 'log-3-true']
134 conds_not_triggered
= ['log-4-false', 'options-1-false']
135 for cond
in conds_triggered
:
136 self
.assertTrue(conditions_dict
[cond
].is_triggered(), repr(cond
))
137 for cond
in conds_not_triggered
:
138 self
.assertFalse(conditions_dict
[cond
].is_triggered(), repr(cond
))
140 # Check for the rules
141 rules_triggered
= ['multiple-conds-true']
142 rules_not_triggered
= [
143 'single-condition-false',
144 'multiple-conds-one-false',
145 'multiple-conds-all-false'
147 for rule_name
in rules_triggered
:
148 rule
= rules_dict
[rule_name
]
150 rule
.is_triggered(conditions_dict
, self
.column_families
),
153 for rule_name
in rules_not_triggered
:
154 rule
= rules_dict
[rule_name
]
156 rule
.is_triggered(conditions_dict
, self
.column_families
),
161 class TestSanityChecker(unittest
.TestCase
):
163 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
164 ini_path
= os
.path
.join(this_path
, 'input_files/rules_err1.ini')
165 db_rules
= RulesSpec(ini_path
)
166 db_rules
.load_rules_from_spec()
167 self
.rules_dict
= db_rules
.get_rules_dict()
168 self
.conditions_dict
= db_rules
.get_conditions_dict()
169 self
.suggestions_dict
= db_rules
.get_suggestions_dict()
171 def test_rule_missing_suggestions(self
):
172 regex
= '.*rule must have at least one suggestion.*'
173 with self
.assertRaisesRegex(ValueError, regex
):
174 self
.rules_dict
['missing-suggestions'].perform_checks()
176 def test_rule_missing_conditions(self
):
177 regex
= '.*rule must have at least one condition.*'
178 with self
.assertRaisesRegex(ValueError, regex
):
179 self
.rules_dict
['missing-conditions'].perform_checks()
181 def test_condition_missing_regex(self
):
182 regex
= '.*provide regex for log condition.*'
183 with self
.assertRaisesRegex(ValueError, regex
):
184 self
.conditions_dict
['missing-regex'].perform_checks()
186 def test_condition_missing_options(self
):
187 regex
= '.*options missing in condition.*'
188 with self
.assertRaisesRegex(ValueError, regex
):
189 self
.conditions_dict
['missing-options'].perform_checks()
191 def test_condition_missing_expression(self
):
192 regex
= '.*expression missing in condition.*'
193 with self
.assertRaisesRegex(ValueError, regex
):
194 self
.conditions_dict
['missing-expression'].perform_checks()
196 def test_suggestion_missing_option(self
):
197 regex
= '.*provide option or description.*'
198 with self
.assertRaisesRegex(ValueError, regex
):
199 self
.suggestions_dict
['missing-option'].perform_checks()
201 def test_suggestion_missing_description(self
):
202 regex
= '.*provide option or description.*'
203 with self
.assertRaisesRegex(ValueError, regex
):
204 self
.suggestions_dict
['missing-description'].perform_checks()
207 class TestParsingErrors(unittest
.TestCase
):
209 self
.this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
211 def test_condition_missing_source(self
):
212 ini_path
= os
.path
.join(self
.this_path
, 'input_files/rules_err2.ini')
213 db_rules
= RulesSpec(ini_path
)
214 regex
= '.*provide source for condition.*'
215 with self
.assertRaisesRegex(NotImplementedError, regex
):
216 db_rules
.load_rules_from_spec()
218 def test_suggestion_missing_action(self
):
219 ini_path
= os
.path
.join(self
.this_path
, 'input_files/rules_err3.ini')
220 db_rules
= RulesSpec(ini_path
)
221 regex
= '.*provide action for option.*'
222 with self
.assertRaisesRegex(ValueError, regex
):
223 db_rules
.load_rules_from_spec()
225 def test_section_no_name(self
):
226 ini_path
= os
.path
.join(self
.this_path
, 'input_files/rules_err4.ini')
227 db_rules
= RulesSpec(ini_path
)
228 regex
= 'Parsing error: needed section header:.*'
229 with self
.assertRaisesRegex(ValueError, regex
):
230 db_rules
.load_rules_from_spec()
233 if __name__
== '__main__':