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 }
193 
194 SCENARIO( "configuring the demo", "[stateRuleEngine::ruleConfig]" )
195 {
196  GIVEN("the demo")
197  {
198  WHEN("the demo as writen")
199  {
200  std::ofstream fout;
201  fout.open("/tmp/ruleConfig_test.conf");
202  fout << "[fwfpm-fpm]\n";
203  fout << "ruleType=swVal\n";
204  fout << "priority=none\n";
205  fout << "comp=Eq\n";
206  fout << "property=fwfpm.filterName\n";
207  fout << "element=fpm\n";
208  fout << "target=On\n";
209  fout << "\n";
210  fout << "[fwfpm-READY]\n";
211  fout << "ruleType=txtVal\n";
212  fout << "property=fwfpm.fsm_state\n";
213  fout << "element=state\n";
214  fout << "target=READY\n";
215  fout << "\n";
216  fout << "[fwfpm-fpm-READY]\n";
217  fout << "ruleType=ruleComp\n";
218  fout << "comp=And\n";
219  fout << "rule1=fwfpm-READY\n";
220  fout << "rule2=fwfpm-fpm\n";
221  fout << "\n";
222  fout << "[fwfpm-stagesci1-neq]\n";
223  fout << "ruleType=elCompSw\n";
224  fout << "property1=fwfpm.filterName\n";
225  fout << "element1=fpm\n";
226  fout << "property2=stagesci1.presetName\n";
227  fout << "element2=fpm\n";
228  fout << "comp=Neq\n";
229  fout << "\n";
230  fout << "[fwfpm-fpm-stagesci-fpm]\n";
231  fout << "ruleType=ruleComp\n";
232  fout << "priority=caution\n";
233  fout << "rule1=fwfpm-fpm-READY\n";
234  fout << "rule2=fwfpm-stagesci1-neq\n";
235  fout << "comp=And\n";
236  fout.close();
237 
238  mx::app::appConfigurator config;
239  config.readConfig("/tmp/ruleConfig_test.conf");
240 
241  indiRuleMaps maps;
242 
243  loadRuleConfig(maps, config);
244 
245  ruleCompRule * rcr = dynamic_cast<ruleCompRule *>(maps.rules["fwfpm-fpm-stagesci-fpm"]);
246 
247  const indiCompRule * r1 = rcr->rule1();
248  const indiCompRule * r2 = rcr->rule2();
249 
250  REQUIRE(r1 == maps.rules["fwfpm-fpm-READY"]);
251  REQUIRE(r2 == maps.rules["fwfpm-stagesci1-neq"]);
252 
253  }
254  }
255 }
256 
257 SCENARIO( "rule configurations with errors", "[stateRuleEngine::ruleConfig]" )
258 {
259  GIVEN("single rules in a config file")
260  {
261  WHEN("no rule sections given")
262  {
263  mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1" },
264  {"property"},
265  {"dev.prop"} );
266  mx::app::appConfigurator config;
267  //By adding this to the config list we remove if from the "unused" so it won't get detected by loadRuleConfig
268  config.add("rule1.prop", "", "", argType::Required, "rule1", "property", false, "string", "");
269  config.readConfig("/tmp/ruleConfig_test.conf");
270 
271  indiRuleMaps maps;
272 
273  bool caught = false;
274  try
275  {
276  loadRuleConfig(maps, config);
277  }
278  catch(const mx::err::invalidconfig & e)
279  {
280  caught = true;
281  }
282  catch(...)
283  {
284  }
285 
286  REQUIRE(caught==true);
287  }
288 
289  WHEN("an invalid rule")
290  {
291  mx::app::writeConfigFile( "/tmp/ruleConfig_test.conf", {"rule1", "rule1", "rule1", "rule1" },
292  {"ruleType", "property", "element", "target" },
293  {"badRule", "dev.prop", "elem", "1.234" } );
294  mx::app::appConfigurator config;
295  config.readConfig("/tmp/ruleConfig_test.conf");
296 
297  indiRuleMaps maps;
298 
299  bool caught = false;
300  try
301  {
302  loadRuleConfig(maps, config);
303  }
304  catch(const mx::err::notimpl & e)
305  {
306  caught = true;
307  }
308  catch(...)
309  {
310  }
311 
312  REQUIRE(caught==true);
313  }
314  }
315 }
316 
317 #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, 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.