API
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 
7 SCENARIO( "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 
217 SCENARIO( "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 
280 SCENARIO( "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.