API
 
Loading...
Searching...
No Matches
indiCompRuleConfig_test.cpp
Go to the documentation of this file.
1#if(__cplusplus == 201703L)
2
3#include "../../../tests/catch2/catch.hpp"
4
5#include "../indiCompRuleConfig.hpp"
6
7SCENARIO( "configuring basic rules", "[stateRuleEngine::ruleConfig]" )
8{
9 GIVEN("single rules in a config file")
10 {
11 WHEN("a numValRule using defaults")
12 {
13 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1" },
14 {"ruleType", "property", "element", "target" },
15 {"numVal", "dev.prop", "elem", "1.234" } );
16 mx::app::appConfigurator config;
17 config.readConfig("/tmp/ruleConfig_test.conf");
18
19 indiRuleMaps maps;
20
21 loadRuleConfig(maps, config);
22
23 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
24 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
25 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
26 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
27 REQUIRE(static_cast<numValRule*>(maps.rules["rule1"])->target() == 1.234);
28 REQUIRE(static_cast<numValRule*>(maps.rules["rule1"])->tol() == 1e-6);
29 }
30
31 WHEN("a numValRule changing defaults")
32 {
33 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1", "rule1", "rule1" },
34 {"ruleType", "priority", "comp", "property", "element", "target", "tol" },
35 {"numVal", "warning", "GtEq", "dev.prop", "elem", "1.234", "1e-8" } );
36 mx::app::appConfigurator config;
37 config.readConfig("/tmp/ruleConfig_test.conf");
38
39 indiRuleMaps maps;
40
41 loadRuleConfig(maps, config);
42
43 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::warning);
44 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::GtEq);
45 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
46 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
47 REQUIRE(static_cast<numValRule*>(maps.rules["rule1"])->target() == 1.234);
48 REQUIRE(static_cast<numValRule*>(maps.rules["rule1"])->tol() == 1e-8);
49 }
50
51 WHEN("a txtValRule using defaults")
52 {
53 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1" },
54 {"ruleType", "property", "element", "target" },
55 {"txtVal", "dev.prop", "elem", "xxx" } );
56 mx::app::appConfigurator config;
57 config.readConfig("/tmp/ruleConfig_test.conf");
58
59 indiRuleMaps maps;
60
61 loadRuleConfig(maps, config);
62
63 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
64 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
65 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
66 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
67 REQUIRE(static_cast<txtValRule*>(maps.rules["rule1"])->target() == "xxx");
68 }
69
70 WHEN("a txtValRule changing defaults")
71 {
72 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1", "rule1" },
73 {"ruleType", "priority", "comp", "property", "element", "target" },
74 {"txtVal", "alert", "Neq", "dev.prop", "elem", "xxx" } );
75 mx::app::appConfigurator config;
76 config.readConfig("/tmp/ruleConfig_test.conf");
77
78 indiRuleMaps maps;
79
80 loadRuleConfig(maps, config);
81
82 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::alert);
83 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Neq);
84 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
85 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
86 REQUIRE(static_cast<txtValRule*>(maps.rules["rule1"])->target() == "xxx");
87
88 }
89
90 WHEN("a swValRule using defaults")
91 {
92 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1" },
93 {"ruleType", "property", "element" },
94 {"swVal", "dev.prop", "elem"} );
95 mx::app::appConfigurator config;
96 config.readConfig("/tmp/ruleConfig_test.conf");
97
98 indiRuleMaps maps;
99
100 loadRuleConfig(maps, config);
101
102 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
103 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
104 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
105 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
106 REQUIRE(static_cast<swValRule*>(maps.rules["rule1"])->target() == pcf::IndiElement::On);
107 }
108
109 WHEN("a swValRule changing defaults")
110 {
111 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1", "rule1" },
112 {"ruleType", "priority", "comp", "property", "element", "target" },
113 {"swVal", "info", "Neq", "dev.prop", "elem", "Off" } );
114 mx::app::appConfigurator config;
115 config.readConfig("/tmp/ruleConfig_test.conf");
116
117 indiRuleMaps maps;
118
119 loadRuleConfig(maps, config);
120
121 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::info);
122 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Neq);
123 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->property() == maps.props["dev.prop"]);
124 REQUIRE(static_cast<onePropRule*>(maps.rules["rule1"])->element() == "elem");
125 REQUIRE(static_cast<swValRule*>(maps.rules["rule1"])->target() == pcf::IndiElement::Off);
126
127 }
128
129 WHEN("an elCompNumRule using defaults")
130 {
131 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1" },
132 {"ruleType", "property1", "element1", "property2", "element2" },
133 {"elCompNum", "dev1.prop1", "elem1", "dev2.prop2", "elem2" } );
134 mx::app::appConfigurator config;
135 config.readConfig("/tmp/ruleConfig_test.conf");
136
137 indiRuleMaps maps;
138
139 loadRuleConfig(maps, config);
140
141 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
142 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
143 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property1() == maps.props["dev1.prop1"]);
144 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element1() == "elem1");
145 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property2() == maps.props["dev2.prop2"]);
146 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element2() == "elem2");
147
148 }
149
150 WHEN("an elCompTxtRule using defaults")
151 {
152 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1" },
153 {"ruleType", "property1", "element1", "property2", "element2" },
154 {"elCompTxt", "dev1.prop1", "elem1", "dev2.prop2", "elem2" } );
155 mx::app::appConfigurator config;
156 config.readConfig("/tmp/ruleConfig_test.conf");
157
158 indiRuleMaps maps;
159
160 loadRuleConfig(maps, config);
161
162 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
163 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
164 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property1() == maps.props["dev1.prop1"]);
165 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element1() == "elem1");
166 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property2() == maps.props["dev2.prop2"]);
167 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element2() == "elem2");
168
169 }
170
171 WHEN("an elCompSwRule using defaults")
172 {
173 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1", "rule1" },
174 {"ruleType", "property1", "element1", "property2", "element2" },
175 {"elCompSw", "dev1.prop1", "elem1", "dev2.prop2", "elem2" } );
176 mx::app::appConfigurator config;
177 config.readConfig("/tmp/ruleConfig_test.conf");
178
179 indiRuleMaps maps;
180
181 loadRuleConfig(maps, config);
182
183 REQUIRE(maps.rules["rule1"]->priority() == rulePriority::none);
184 REQUIRE(maps.rules["rule1"]->comparison() == ruleComparison::Eq);
185 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property1() == maps.props["dev1.prop1"]);
186 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element1() == "elem1");
187 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->property2() == maps.props["dev2.prop2"]);
188 REQUIRE(static_cast<twoPropRule*>(maps.rules["rule1"])->element2() == "elem2");
189
190 }
191
192 WHEN("a ruleCompRule using defaults")
193 {
194 //This requires configuring the other rules too
195 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf",
196 {"ruleA", "ruleA", "ruleA", "rule3", "rule3", "rule3", "rule3", "rule4", "rule4", "rule4", "rule4" },
197 {"ruleType", "rule1", "rule2", "ruleType", "property", "element", "target", "ruleType", "property", "element", "target" },
198 {"ruleComp", "rule3", "rule4", "txtVal", "dev3.propQ", "elem", "xxx", "txtVal", "dev4.propR", "mele", "yyy" }
199 );
200 mx::app::appConfigurator config;
201 config.readConfig("/tmp/ruleConfig_test.conf");
202
203 indiRuleMaps maps;
204
205 loadRuleConfig(maps, config);
206
207 REQUIRE(maps.rules["ruleA"]->priority() == rulePriority::none);
208 REQUIRE(maps.rules["ruleA"]->comparison() == ruleComparison::Eq);
209
210 REQUIRE(static_cast<ruleCompRule*>(maps.rules["ruleA"])->rule1() == maps.rules["rule3"]);
211 REQUIRE(static_cast<ruleCompRule*>(maps.rules["ruleA"])->rule2() == maps.rules["rule4"]);
212
213 }
214 }
215}
216
217SCENARIO( "configuring the demo", "[stateRuleEngine::ruleConfig]" )
218{
219 GIVEN("the demo")
220 {
221 WHEN("the demo as writen")
222 {
223 std::ofstream fout;
224 fout.open("/tmp/ruleConfig_test.conf");
225 fout << "[fwfpm-fpm]\n";
226 fout << "ruleType=swVal\n";
227 fout << "priority=none\n";
228 fout << "comp=Eq\n";
229 fout << "property=fwfpm.filterName\n";
230 fout << "element=fpm\n";
231 fout << "target=On\n";
232 fout << "\n";
233 fout << "[fwfpm-READY]\n";
234 fout << "ruleType=txtVal\n";
235 fout << "property=fwfpm.fsm_state\n";
236 fout << "element=state\n";
237 fout << "target=READY\n";
238 fout << "\n";
239 fout << "[fwfpm-fpm-READY]\n";
240 fout << "ruleType=ruleComp\n";
241 fout << "comp=And\n";
242 fout << "rule1=fwfpm-READY\n";
243 fout << "rule2=fwfpm-fpm\n";
244 fout << "\n";
245 fout << "[fwfpm-stagesci1-neq]\n";
246 fout << "ruleType=elCompSw\n";
247 fout << "property1=fwfpm.filterName\n";
248 fout << "element1=fpm\n";
249 fout << "property2=stagesci1.presetName\n";
250 fout << "element2=fpm\n";
251 fout << "comp=Neq\n";
252 fout << "\n";
253 fout << "[fwfpm-fpm-stagesci-fpm]\n";
254 fout << "ruleType=ruleComp\n";
255 fout << "priority=caution\n";
256 fout << "rule1=fwfpm-fpm-READY\n";
257 fout << "rule2=fwfpm-stagesci1-neq\n";
258 fout << "comp=And\n";
259 fout.close();
260
261 mx::app::appConfigurator config;
262 config.readConfig("/tmp/ruleConfig_test.conf");
263
264 indiRuleMaps maps;
265
266 loadRuleConfig(maps, config);
267
268 ruleCompRule * rcr = dynamic_cast<ruleCompRule *>(maps.rules["fwfpm-fpm-stagesci-fpm"]);
269
270 const indiCompRule * r1 = rcr->rule1();
271 const indiCompRule * r2 = rcr->rule2();
272
273 REQUIRE(r1 == maps.rules["fwfpm-fpm-READY"]);
274 REQUIRE(r2 == maps.rules["fwfpm-stagesci1-neq"]);
275
276 }
277 }
278}
279
280SCENARIO( "rule configurations with errors", "[stateRuleEngine::ruleConfig]" )
281{
282 GIVEN("single rules in a config file")
283 {
284 WHEN("no rule sections given")
285 {
286 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1" },
287 {"property"},
288 {"dev.prop"} );
289 mx::app::appConfigurator config;
290 //By adding this to the config list we remove if from the "unused" so it won't get detected by loadRuleConfig
291 config.add("rule1.prop", "", "", argType::Required, "rule1", "property", false, "string", "");
292 config.readConfig("/tmp/ruleConfig_test.conf");
293
294 indiRuleMaps maps;
295
296 bool caught = false;
297 try
298 {
299 loadRuleConfig(maps, config);
300 }
301 catch(const mx::err::invalidconfig & e)
302 {
303 caught = true;
304 }
305 catch(...)
306 {
307 }
308
309 REQUIRE(caught==true);
310 }
311
312 WHEN("an invalid rule")
313 {
314 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1" },
315 {"ruleType", "property", "element", "target" },
316 {"badRule", "dev.prop", "elem", "1.234" } );
317 mx::app::appConfigurator config;
318 config.readConfig("/tmp/ruleConfig_test.conf");
319
320 indiRuleMaps maps;
321
322 bool caught = false;
323 try
324 {
325 loadRuleConfig(maps, config);
326 }
327 catch(const mx::err::notimpl & e)
328 {
329 caught = true;
330 }
331 catch(...)
332 {
333 }
334
335 REQUIRE(caught==true);
336 }
337 }
338 GIVEN("ruleComp rules with errors")
339 {
340 WHEN("a ruleCompRule with rule1 not found")
341 {
342 //This requires configuring the other rules too
343 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf",
344 {"ruleA", "ruleA", "ruleA", "rule3", "rule3", "rule3", "rule3", "rule4", "rule4", "rule4", "rule4" },
345 {"ruleType", "rule1", "rule2", "ruleType", "property", "element", "target", "ruleType", "property", "element", "target" },
346 {"ruleComp", "rule6", "rule4", "txtVal", "dev3.propQ", "elem", "xxx", "txtVal", "dev4.propR", "mele", "yyy" }
347 );
348 mx::app::appConfigurator config;
349 config.readConfig("/tmp/ruleConfig_test.conf");
350
351 indiRuleMaps maps;
352
353 bool caught = false;
354 try
355 {
356 loadRuleConfig(maps, config);
357 }
358 catch(...)
359 {
360 caught = true;
361 }
362
363 REQUIRE(caught == true);
364
365 }
366
367 WHEN("a ruleCompRule with rule1 self-referencing")
368 {
369 //This requires configuring the other rules too
370 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf",
371 {"ruleA", "ruleA", "ruleA", "rule3", "rule3", "rule3", "rule3", "rule4", "rule4", "rule4", "rule4" },
372 {"ruleType", "rule1", "rule2", "ruleType", "property", "element", "target", "ruleType", "property", "element", "target" },
373 {"ruleComp", "ruleA", "rule4", "txtVal", "dev3.propQ", "elem", "xxx", "txtVal", "dev4.propR", "mele", "yyy" }
374 );
375 mx::app::appConfigurator config;
376 config.readConfig("/tmp/ruleConfig_test.conf");
377
378 indiRuleMaps maps;
379
380 bool caught = false;
381 try
382 {
383 loadRuleConfig(maps, config);
384 }
385 catch(...)
386 {
387 caught = true;
388 }
389
390 REQUIRE(caught == true);
391
392 }
393 WHEN("a ruleCompRule with rule2 not found")
394 {
395 //This requires configuring the other rules too
396 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf",
397 {"ruleA", "ruleA", "ruleA", "rule3", "rule3", "rule3", "rule3", "rule4", "rule4", "rule4", "rule4" },
398 {"ruleType", "rule1", "rule2", "ruleType", "property", "element", "target", "ruleType", "property", "element", "target" },
399 {"ruleComp", "rule3", "rule5", "txtVal", "dev3.propQ", "elem", "xxx", "txtVal", "dev4.propR", "mele", "yyy" }
400 );
401 mx::app::appConfigurator config;
402 config.readConfig("/tmp/ruleConfig_test.conf");
403
404 indiRuleMaps maps;
405
406 bool caught = false;
407 try
408 {
409 loadRuleConfig(maps, config);
410 }
411 catch(...)
412 {
413 caught = true;
414 }
415
416 REQUIRE(caught == true);
417
418 }
419
420 WHEN("a ruleCompRule with rule2 self-referencing")
421 {
422 //This requires configuring the other rules too
423 mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf",
424 {"ruleA", "ruleA", "ruleA", "rule3", "rule3", "rule3", "rule3", "rule4", "rule4", "rule4", "rule4" },
425 {"ruleType", "rule1", "rule2", "ruleType", "property", "element", "target", "ruleType", "property", "element", "target" },
426 {"ruleComp", "rule3", "ruleA", "txtVal", "dev3.propQ", "elem", "xxx", "txtVal", "dev4.propR", "mele", "yyy" }
427 );
428 mx::app::appConfigurator config;
429 config.readConfig("/tmp/ruleConfig_test.conf");
430
431 indiRuleMaps maps;
432
433 bool caught = false;
434 try
435 {
436 loadRuleConfig(maps, config);
437 }
438 catch(...)
439 {
440 caught = true;
441 }
442
443 REQUIRE(caught == true);
444
445 }
446 }
447}
448
449#endif
#define GIVEN(desc)
Definition catch.hpp:17763
#define WHEN(desc)
Definition catch.hpp:17765
#define SCENARIO(...)
Definition catch.hpp:17760
#define REQUIRE(...)
Definition catch.hpp:17676
void loadRuleConfig(indiRuleMaps &maps, std::map< std::string, ruleRuleKeys > &rrkMap, mx::app::appConfigurator &config)
Load the rule and properties maps for a rule engine from a configuration file.
@ GtEq
Greater than or equal to.
@ Neq
Not equal.
@ none
Don't publish.
@ warning
Warning – something is probably wrong, you should check.
@ alert
Alert – something is definitely wrong, you should take action.
@ info
For information only.
Virtual base-class for all rules.
Structure to provide management of the rule and property maps.
Compare the value of a number element to a target.
void target(const double &tgt)
Set the target for the comparison.
void tol(const double &t)
Set the tolerance.
A rule base class for testing an element in one property.
void property(pcf::IndiProperty *property)
Set the property pointer.
void element(const std::string &el)
Set the element name.
A rule to compare two rules.
void rule2(indiCompRule *r)
Set the pointer to the second rule.
void rule1(indiCompRule *r)
Set the pointer to the first rule.
Compare the value of a switch to a target value.
void target(const pcf::IndiElement::SwitchStateType &ss)
Set the target for the comparison.
A rule base class for testing elements in two properties.
void property1(pcf::IndiProperty *property)
Set the first property pointer.
void element2(const std::string &el)
Set the second element name.
void element1(const std::string &el)
Set the first element name.
void property2(pcf::IndiProperty *property)
Set the second property pointer.
Compare the value of a text element to a target value.
void target(const std::string &target)
Set the target for the comparison.