test_node.cpp
Go to the documentation of this file.
1 // Unit tests for node tags
2 // Author: Max Schwarz <max.schwarz@ais.uni-bonn.de>
3 
4 #include <catch_ros/catch.hpp>
5 
6 #include "../../src/launch/launch_config.h"
7 
8 #include <boost/filesystem.hpp>
9 
10 #include "core_utils.h"
11 #include "node_utils.h"
12 #include "param_utils.h"
13 
14 using namespace rosmon::launch;
15 
16 TEST_CASE("node basic", "[node]")
17 {
18  LaunchConfig config;
19  config.parseString(R"EOF(
20  <launch>
21  <node name="test_node" pkg="rosmon_core" type="abort" />
22  </launch>
23  )EOF");
24 
25  config.evaluateParameters();
26 
27  auto nodes = config.nodes();
28  CAPTURE(nodes);
29 
30  REQUIRE(nodes.size() == 1);
31 
32  auto node = getNode(nodes, "test_node");
33 
34  CHECK(node->name() == "test_node");
35  CHECK(node->package() == "rosmon_core");
36  CHECK(node->type() == "abort");
37 
38  {
39  namespace fs = boost::filesystem;
40 
41  fs::path executable = node->executable();
42  CAPTURE(executable.string());
43  CHECK((fs::status(executable).permissions() & fs::owner_exe));
44  }
45 }
46 
47 TEST_CASE("node invalid", "[node]")
48 {
50  <launch>
51  <node name="test_node" />
52  </launch>
53  )EOF");
54 }
55 
56 TEST_CASE("node args", "[node]")
57 {
58  LaunchConfig config;
59  config.parseString(R"EOF(
60  <launch>
61  <node name="test_node" pkg="rosmon_core" type="abort" args="arg1 arg2 'long arg'" />
62  </launch>
63  )EOF");
64 
65  config.evaluateParameters();
66 
67  auto nodes = config.nodes();
68  CAPTURE(nodes);
69 
70  REQUIRE(nodes.size() == 1);
71 
72  auto node = getNode(nodes, "test_node");
73 
74  auto args = node->extraArguments();
75 
76  REQUIRE(args.size() == 3);
77  CHECK(args[0] == "arg1");
78  CHECK(args[1] == "arg2");
79  CHECK(args[2] == "long arg");
80 }
81 
82 TEST_CASE("node respawn", "[node]")
83 {
84  LaunchConfig config;
85  config.parseString(R"EOF(
86  <launch>
87  <node name="test_node" pkg="rosmon_core" type="abort" respawn="true" respawn_delay="10" />
88  </launch>
89  )EOF");
90 
91  config.evaluateParameters();
92 
93  auto nodes = config.nodes();
94  CAPTURE(nodes);
95 
96  REQUIRE(nodes.size() == 1);
97 
98  auto node = getNode(nodes, "test_node");
99 
100  CHECK(node->respawn());
101  CHECK(node->respawnDelay().toSec() == Approx(10.0));
102 }
103 
104 TEST_CASE("node required", "[node]")
105 {
106  LaunchConfig config;
107  config.parseString(R"EOF(
108  <launch>
109  <node name="test_node" pkg="rosmon_core" type="abort" required="true" />
110  </launch>
111  )EOF");
112 
113  config.evaluateParameters();
114 
115  auto nodes = config.nodes();
116  CAPTURE(nodes);
117 
118  REQUIRE(nodes.size() == 1);
119 
120  auto node = getNode(nodes, "test_node");
121 
122  CHECK(node->required());
123 }
124 
125 TEST_CASE("node ns", "[node]")
126 {
127  LaunchConfig config;
128  config.parseString(R"EOF(
129  <launch>
130  <node name="test_node" pkg="rosmon_core" type="abort" ns="namespace" />
131 
132  <group ns="ns1">
133  <node name="test_node" pkg="rosmon_core" type="abort" />
134 
135  <node name="test_node" pkg="rosmon_core" type="abort" ns="namespace" />
136  </group>
137  </launch>
138  )EOF");
139 
140  config.evaluateParameters();
141 
142  auto nodes = config.nodes();
143  CAPTURE(nodes);
144 
145  REQUIRE(nodes.size() == 3);
146 
147  {
148  auto node = getNode(nodes, "test_node", "/namespace");
149  CHECK(node->namespaceString() == "/namespace");
150  }
151  {
152  auto node = getNode(nodes, "test_node", "/ns1");
153  CHECK(node->namespaceString() == "/ns1");
154  }
155  {
156  auto node = getNode(nodes, "test_node", "/ns1/namespace");
157  CHECK(node->namespaceString() == "/ns1/namespace");
158  }
159 }
160 
161 TEST_CASE("node clear_params", "[node]")
162 {
163  LaunchConfig config;
164  config.parseString(R"EOF(
165  <launch>
166  <node name="test_node_on" pkg="rosmon_core" type="abort" clear_params="true" />
167  <node name="test_node_off" pkg="rosmon_core" type="abort" clear_params="false" />
168  <node name="test_node_def" pkg="rosmon_core" type="abort" />
169  </launch>
170  )EOF");
171 
172  config.evaluateParameters();
173 
174  auto nodes = config.nodes();
175  CAPTURE(nodes);
176 
177  CHECK(getNode(nodes, "test_node_on")->clearParams() == true);
178  CHECK(getNode(nodes, "test_node_off")->clearParams() == false);
179  CHECK(getNode(nodes, "test_node_def")->clearParams() == false);
180 }
181 
182 TEST_CASE("node cwd", "[node]")
183 {
184  LaunchConfig config;
185  config.parseString(R"EOF(
186  <launch>
187  <node name="test_node" pkg="rosmon_core" type="abort" cwd="/my_cwd/" />
188  </launch>
189  )EOF");
190 
191  config.evaluateParameters();
192 
193  auto nodes = config.nodes();
194  CAPTURE(nodes);
195 
196  auto node = getNode(nodes, "test_node");
197 
198  CHECK(node->workingDirectory() == "/my_cwd/");
199 }
200 
201 TEST_CASE("node launch-prefix", "[node]")
202 {
203  LaunchConfig config;
204  config.parseString(R"EOF(
205  <launch>
206  <node name="test_node" pkg="rosmon_core" type="abort" launch-prefix="echo my command is:" />
207  </launch>
208  )EOF");
209 
210  config.evaluateParameters();
211 
212  auto nodes = config.nodes();
213  CAPTURE(nodes);
214 
215  auto node = getNode(nodes, "test_node");
216 
217  auto prefix = node->launchPrefix();
218  CAPTURE(prefix);
219 
220  REQUIRE(prefix.size() == 4);
221  CHECK(prefix[0] == "echo");
222  CHECK(prefix[1] == "my");
223  CHECK(prefix[2] == "command");
224  CHECK(prefix[3] == "is:");
225 }
226 
227 TEST_CASE("node remap", "[remap]")
228 {
229  LaunchConfig config;
230  config.parseString(R"EOF(
231  <launch>
232  <node name="test_node" pkg="rosmon_core" type="abort">
233  <remap from="private1" to="/global_target" />
234  <remap from="private2" to="local_target" />
235  </node>
236  </launch>
237  )EOF");
238 
239  config.evaluateParameters();
240 
241  auto nodes = config.nodes();
242  CAPTURE(nodes);
243 
244  auto node = getNode(nodes, "test_node");
245 
246  auto remappings = node->remappings();
247  CAPTURE(printMapping(remappings));
248 
249  CHECK(remappings.size() == 2);
250  CHECK(remappings.at("private1") == "/global_target");
251  CHECK(remappings.at("private2") == "local_target");
252 }
253 
254 TEST_CASE("node output attr", "[output]")
255 {
256  SECTION("ignore")
257  {
258  LaunchConfig config;
260  config.parseString(R"EOF(
261  <launch>
262  <node name="test_node" pkg="rosmon_core" type="abort" output="log">
263  </node>
264  </launch>
265  )EOF");
266 
267  auto node = getNode(config.nodes(), "test_node");
268  CHECK(!node->stdoutDisplayed());
269  }
270 
271  SECTION("obey")
272  {
273  LaunchConfig config;
275  config.parseString(R"EOF(
276  <launch>
277  <node name="test_node" pkg="rosmon_core" type="abort">
278  </node>
279  </launch>
280  )EOF");
281 
282  auto node = getNode(config.nodes(), "test_node");
283  CHECK(!node->stdoutDisplayed());
284  }
285 
286  SECTION("obey log")
287  {
288  LaunchConfig config;
290  config.parseString(R"EOF(
291  <launch>
292  <node name="test_node" pkg="rosmon_core" type="abort" output="log">
293  </node>
294  </launch>
295  )EOF");
296 
297  auto node = getNode(config.nodes(), "test_node");
298  CHECK(!node->stdoutDisplayed());
299  }
300 
301  SECTION("obey screen")
302  {
303  LaunchConfig config;
305  config.parseString(R"EOF(
306  <launch>
307  <node name="test_node" pkg="rosmon_core" type="abort" output="screen">
308  </node>
309  </launch>
310  )EOF");
311 
312  auto node = getNode(config.nodes(), "test_node");
313  CHECK(node->stdoutDisplayed());
314  }
315 }
316 
317 // rosmon extensions
318 
319 TEST_CASE("node enable-coredumps", "[node]")
320 {
321  LaunchConfig config;
322  config.parseString(R"EOF(
323  <launch>
324  <node name="test_node_on" pkg="rosmon_core" type="abort" enable-coredumps="true" />
325  <node name="test_node_off" pkg="rosmon_core" type="abort" enable-coredumps="false" />
326  </launch>
327  )EOF");
328 
329  config.evaluateParameters();
330 
331  auto nodes = config.nodes();
332  CAPTURE(nodes);
333 
334  CHECK(getNode(nodes, "test_node_on")->coredumpsEnabled() == true);
335  CHECK(getNode(nodes, "test_node_off")->coredumpsEnabled() == false);
336 }
337 
338 TEST_CASE("node memory/cpu limit", "[node]")
339 {
340  LaunchConfig config;
341  config.parseString(R"EOF(
342  <launch>
343  <node name="test_node_default" pkg="rosmon_core" type="abort" />
344  <node name="test_node_custom" pkg="rosmon_core" type="abort" rosmon-memory-limit="200" rosmon-cpu-limit="0.2" />
345 
346  <group rosmon-memory-limit="100" enable-coredumps="false">
347  <node name="test_node_grouped" pkg="rosmon_core" type="abort" />
348  </group>
349  </launch>
350  )EOF");
351 
352  config.evaluateParameters();
353 
354  auto nodes = config.nodes();
355  CAPTURE(nodes);
356 
357  auto def = getNode(nodes, "test_node_default");
358  CHECK(def->memoryLimitByte() == rosmon::launch::DEFAULT_MEMORY_LIMIT);
359  CHECK(def->cpuLimit() == Approx(rosmon::launch::DEFAULT_CPU_LIMIT));
360 
361  auto custom = getNode(nodes, "test_node_custom");
362  CHECK(custom->memoryLimitByte() == 200);
363  CHECK(custom->cpuLimit() == Approx(0.2f));
364 
365  auto grouped = getNode(nodes, "test_node_grouped");
366  CHECK(grouped->memoryLimitByte() == 100);
367  CHECK(!grouped->coredumpsEnabled());
368 }
const std::vector< Node::Ptr > & nodes() const
rosmon::launch::Node::Ptr getNode(const std::vector< rosmon::launch::Node::Ptr > &nodes, const std::string &name, const std::string &namespaceString)
Definition: node_utils.cpp:23
static void requireParsingException(const std::string &input)
Definition: core_utils.h:11
void parseString(const std::string &input, bool onlyArguments=false)
float f(float t)
Definition: husl.c:142
TEST_CASE("node basic","[node]")
Definition: test_node.cpp:16
constexpr uint64_t DEFAULT_MEMORY_LIMIT
Definition: launch_config.h:29
void setOutputAttrMode(OutputAttr mode)
constexpr double DEFAULT_CPU_LIMIT
Definition: launch_config.h:28
std::string printMapping(const std::map< std::string, std::string > &mapping)
Definition: node_utils.cpp:10


rosmon_core
Author(s): Max Schwarz
autogenerated on Sat Jan 9 2021 03:35:43