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