]>
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).
9 from advisor
.db_log_parser
import DatabaseLogs
, DataSource
10 from advisor
.db_options_parser
import DatabaseOptions
11 from advisor
.rule_parser
import RulesSpec
14 "stall-too-many-memtables": ["inc-bg-flush", "inc-write-buffer"],
15 "stall-too-many-L0": [
16 "inc-max-subcompactions",
17 "inc-max-bg-compactions",
18 "inc-write-buffer-size",
19 "dec-max-bytes-for-level-base",
20 "inc-l0-slowdown-writes-trigger",
23 "inc-max-bg-compactions",
24 "inc-write-buffer-size",
25 "inc-l0-stop-writes-trigger",
27 "stall-too-many-compaction-bytes": [
28 "inc-max-bg-compactions",
29 "inc-write-buffer-size",
30 "inc-hard-pending-compaction-bytes-limit",
31 "inc-soft-pending-compaction-bytes-limit",
33 "level0-level1-ratio": ["l0-l1-ratio-health-check"],
37 class TestAllRulesTriggered(unittest
.TestCase
):
40 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
41 ini_path
= os
.path
.join(this_path
, "input_files/triggered_rules.ini")
42 self
.db_rules
= RulesSpec(ini_path
)
43 self
.db_rules
.load_rules_from_spec()
44 self
.db_rules
.perform_section_checks()
45 # load the data sources: LOG and OPTIONS
46 log_path
= os
.path
.join(this_path
, "input_files/LOG-0")
47 options_path
= os
.path
.join(this_path
, "input_files/OPTIONS-000005")
48 db_options_parser
= DatabaseOptions(options_path
)
49 self
.column_families
= db_options_parser
.get_column_families()
50 db_logs_parser
= DatabaseLogs(log_path
, self
.column_families
)
52 DataSource
.Type
.DB_OPTIONS
: [db_options_parser
],
53 DataSource
.Type
.LOG
: [db_logs_parser
],
56 def test_triggered_conditions(self
):
57 conditions_dict
= self
.db_rules
.get_conditions_dict()
58 rules_dict
= self
.db_rules
.get_rules_dict()
59 # Make sure none of the conditions is triggered beforehand
60 for cond
in conditions_dict
.values():
61 self
.assertFalse(cond
.is_triggered(), repr(cond
))
62 for rule
in rules_dict
.values():
64 rule
.is_triggered(conditions_dict
, self
.column_families
), repr(rule
)
67 # # Trigger the conditions as per the data sources.
68 # trigger_conditions(, conditions_dict)
70 # Get the set of rules that have been triggered
71 triggered_rules
= self
.db_rules
.get_triggered_rules(
72 self
.data_sources
, self
.column_families
75 # Make sure each condition and rule is triggered
76 for cond
in conditions_dict
.values():
77 if cond
.get_data_source() is DataSource
.Type
.TIME_SERIES
:
79 self
.assertTrue(cond
.is_triggered(), repr(cond
))
81 for rule
in rules_dict
.values():
82 self
.assertIn(rule
, triggered_rules
)
83 # Check the suggestions made by the triggered rules
84 for sugg
in rule
.get_suggestions():
85 self
.assertIn(sugg
, RuleToSuggestions
[rule
.name
])
87 for rule
in triggered_rules
:
88 self
.assertIn(rule
, rules_dict
.values())
89 for sugg
in RuleToSuggestions
[rule
.name
]:
90 self
.assertIn(sugg
, rule
.get_suggestions())
93 class TestConditionsConjunctions(unittest
.TestCase
):
96 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
97 ini_path
= os
.path
.join(this_path
, "input_files/test_rules.ini")
98 self
.db_rules
= RulesSpec(ini_path
)
99 self
.db_rules
.load_rules_from_spec()
100 self
.db_rules
.perform_section_checks()
101 # load the data sources: LOG and OPTIONS
102 log_path
= os
.path
.join(this_path
, "input_files/LOG-1")
103 options_path
= os
.path
.join(this_path
, "input_files/OPTIONS-000005")
104 db_options_parser
= DatabaseOptions(options_path
)
105 self
.column_families
= db_options_parser
.get_column_families()
106 db_logs_parser
= DatabaseLogs(log_path
, self
.column_families
)
107 self
.data_sources
= {
108 DataSource
.Type
.DB_OPTIONS
: [db_options_parser
],
109 DataSource
.Type
.LOG
: [db_logs_parser
],
112 def test_condition_conjunctions(self
):
113 conditions_dict
= self
.db_rules
.get_conditions_dict()
114 rules_dict
= self
.db_rules
.get_rules_dict()
115 # Make sure none of the conditions is triggered beforehand
116 for cond
in conditions_dict
.values():
117 self
.assertFalse(cond
.is_triggered(), repr(cond
))
118 for rule
in rules_dict
.values():
120 rule
.is_triggered(conditions_dict
, self
.column_families
), repr(rule
)
123 # Trigger the conditions as per the data sources.
124 self
.db_rules
.trigger_conditions(self
.data_sources
)
126 # Check for the conditions
127 conds_triggered
= ["log-1-true", "log-2-true", "log-3-true"]
128 conds_not_triggered
= ["log-4-false", "options-1-false"]
129 for cond
in conds_triggered
:
130 self
.assertTrue(conditions_dict
[cond
].is_triggered(), repr(cond
))
131 for cond
in conds_not_triggered
:
132 self
.assertFalse(conditions_dict
[cond
].is_triggered(), repr(cond
))
134 # Check for the rules
135 rules_triggered
= ["multiple-conds-true"]
136 rules_not_triggered
= [
137 "single-condition-false",
138 "multiple-conds-one-false",
139 "multiple-conds-all-false",
141 for rule_name
in rules_triggered
:
142 rule
= rules_dict
[rule_name
]
144 rule
.is_triggered(conditions_dict
, self
.column_families
), repr(rule
)
146 for rule_name
in rules_not_triggered
:
147 rule
= rules_dict
[rule_name
]
149 rule
.is_triggered(conditions_dict
, self
.column_families
), repr(rule
)
153 class TestSanityChecker(unittest
.TestCase
):
155 this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
156 ini_path
= os
.path
.join(this_path
, "input_files/rules_err1.ini")
157 db_rules
= RulesSpec(ini_path
)
158 db_rules
.load_rules_from_spec()
159 self
.rules_dict
= db_rules
.get_rules_dict()
160 self
.conditions_dict
= db_rules
.get_conditions_dict()
161 self
.suggestions_dict
= db_rules
.get_suggestions_dict()
163 def test_rule_missing_suggestions(self
):
164 regex
= ".*rule must have at least one suggestion.*"
165 with self
.assertRaisesRegex(ValueError, regex
):
166 self
.rules_dict
["missing-suggestions"].perform_checks()
168 def test_rule_missing_conditions(self
):
169 regex
= ".*rule must have at least one condition.*"
170 with self
.assertRaisesRegex(ValueError, regex
):
171 self
.rules_dict
["missing-conditions"].perform_checks()
173 def test_condition_missing_regex(self
):
174 regex
= ".*provide regex for log condition.*"
175 with self
.assertRaisesRegex(ValueError, regex
):
176 self
.conditions_dict
["missing-regex"].perform_checks()
178 def test_condition_missing_options(self
):
179 regex
= ".*options missing in condition.*"
180 with self
.assertRaisesRegex(ValueError, regex
):
181 self
.conditions_dict
["missing-options"].perform_checks()
183 def test_condition_missing_expression(self
):
184 regex
= ".*expression missing in condition.*"
185 with self
.assertRaisesRegex(ValueError, regex
):
186 self
.conditions_dict
["missing-expression"].perform_checks()
188 def test_suggestion_missing_option(self
):
189 regex
= ".*provide option or description.*"
190 with self
.assertRaisesRegex(ValueError, regex
):
191 self
.suggestions_dict
["missing-option"].perform_checks()
193 def test_suggestion_missing_description(self
):
194 regex
= ".*provide option or description.*"
195 with self
.assertRaisesRegex(ValueError, regex
):
196 self
.suggestions_dict
["missing-description"].perform_checks()
199 class TestParsingErrors(unittest
.TestCase
):
201 self
.this_path
= os
.path
.abspath(os
.path
.dirname(__file__
))
203 def test_condition_missing_source(self
):
204 ini_path
= os
.path
.join(self
.this_path
, "input_files/rules_err2.ini")
205 db_rules
= RulesSpec(ini_path
)
206 regex
= ".*provide source for condition.*"
207 with self
.assertRaisesRegex(NotImplementedError, regex
):
208 db_rules
.load_rules_from_spec()
210 def test_suggestion_missing_action(self
):
211 ini_path
= os
.path
.join(self
.this_path
, "input_files/rules_err3.ini")
212 db_rules
= RulesSpec(ini_path
)
213 regex
= ".*provide action for option.*"
214 with self
.assertRaisesRegex(ValueError, regex
):
215 db_rules
.load_rules_from_spec()
217 def test_section_no_name(self
):
218 ini_path
= os
.path
.join(self
.this_path
, "input_files/rules_err4.ini")
219 db_rules
= RulesSpec(ini_path
)
220 regex
= "Parsing error: needed section header:.*"
221 with self
.assertRaisesRegex(ValueError, regex
):
222 db_rules
.load_rules_from_spec()
225 if __name__
== "__main__":