API
 
Loading...
Searching...
No Matches
xindiserver_test.cpp
Go to the documentation of this file.
1/** \file xindiserver_test.cpp
2 * \brief Catch2 tests for the xindiserver app.
3 * \author Jared R. Males (jaredmales@gmail.com)
4 *
5 * \ingroup xindiserver_files
6 */
7
8#include "../../../tests/testXWC.hpp"
9
10#include "../xindiserver.hpp"
11
12using namespace MagAOX::app;
13
14namespace libXWCTest
15{
16
17/** \defgroup xindiserver_unit_test xindiserver Unit Tests
18 * \brief Unit tests for the xindiserver application.
19 *
20 * \ingroup application_unit_test
21 */
22
23/// Namespace for `xindiserver` unit tests.
24/** \ingroup xindiserver_unit_test
25 */
26namespace xindiserverTest
27{
28
29/// \cond DOXYGEN_SUPPRESS_TEST_HARNESS
30struct xindiserver_test
31{
32 void indiserver_m( xindiserver &xi, const int &m )
33 {
34 xi.indiserver_m = m;
35 }
36 void indiserver_n( xindiserver &xi, const bool &n )
37 {
38 xi.indiserver_n = n;
39 }
40 void indiserver_p( xindiserver &xi, const int &p )
41 {
42 xi.indiserver_p = p;
43 }
44 void indiserver_v( xindiserver &xi, const int &v )
45 {
46 xi.indiserver_v = v;
47 }
48 void indiserver_x( xindiserver &xi, const bool &x )
49 {
50 xi.indiserver_x = x;
51 }
52 void m_local( xindiserver &xi, const std::vector<std::string> &ml )
53 {
54 xi.m_local = ml;
55 }
56 void m_remote( xindiserver &xi, const std::vector<std::string> &mr )
57 {
58 xi.m_remote = mr;
59 }
60
61 tunnelMapT &tunnelMap( xindiserver &xi )
62 {
63 return xi.m_tunnels;
64 }
65};
66/// \endcond
67
68/// Verify xindiserver builds command lines and tunnel-derived driver lists consistently.
69/**
70 * \ingroup xindiserver_unit_test
71 */
72SCENARIO( "xindiserver constructs inserver options", "[xindiserver]" )
73{
74 // clang-format off
75 #ifdef XINDISERVER_TEST_DOXYGEN_REF
76 xindiserver::constructIndiserverCommand( *(std::vector<std::string> *)nullptr );
77 xindiserver::addRemoteDrivers( *(std::vector<std::string> *)nullptr );
78 xindiserver::addLocalDrivers( *(std::vector<std::string> *)nullptr );
79 loadSSHTunnelConfigs( *(tunnelMapT *)nullptr, *(mx::app::appConfigurator *)nullptr );
80 #endif
81 // clang-format on
82
83 GIVEN( "A default constructed xindiserver" )
84 {
85 xindiserver xi;
86 xindiserver_test xi_test;
87
88 int rv;
89
90 WHEN( "Option m with argument provided" )
91 {
92 std::vector<std::string> clargs;
93 xi_test.indiserver_m( xi, 100 );
94
95 rv = xi.constructIndiserverCommand( clargs );
96 REQUIRE( rv == 0 );
97 REQUIRE( clargs.size() == 3 );
98 REQUIRE( clargs[0] == "indiserver" );
99 REQUIRE( clargs[1] == "-m" );
100 REQUIRE( clargs[2] == "100" );
101 }
102
103 WHEN( "Option n provided" )
104 {
105 std::vector<std::string> clargs;
106 xi_test.indiserver_n( xi, true );
107
108 rv = xi.constructIndiserverCommand( clargs );
109 REQUIRE( rv == 0 );
110 REQUIRE( clargs.size() == 2 );
111 REQUIRE( clargs[0] == "indiserver" );
112 REQUIRE( clargs[1] == "-n" );
113 }
114
115 WHEN( "Option p provided with argument" )
116 {
117 std::vector<std::string> clargs;
118 xi_test.indiserver_p( xi, 2000 );
119
120 rv = xi.constructIndiserverCommand( clargs );
121 REQUIRE( rv == 0 );
122 REQUIRE( clargs.size() == 3 );
123 REQUIRE( clargs[0] == "indiserver" );
124 REQUIRE( clargs[1] == "-p" );
125 REQUIRE( clargs[2] == "2000" );
126 }
127
128 WHEN( "1 Option v provided with argument (-v)" )
129 {
130 std::vector<std::string> clargs;
131 xi_test.indiserver_v( xi, 1 );
132
133 rv = xi.constructIndiserverCommand( clargs );
134 REQUIRE( rv == 0 );
135 REQUIRE( clargs.size() == 2 );
136 REQUIRE( clargs[0] == "indiserver" );
137 REQUIRE( clargs[1] == "-v" );
138 }
139
140 WHEN( "2 Option v provided with argument (-vv)" )
141 {
142 std::vector<std::string> clargs;
143 xi_test.indiserver_v( xi, 2 );
144
145 rv = xi.constructIndiserverCommand( clargs );
146 REQUIRE( rv == 0 );
147 REQUIRE( clargs.size() == 2 );
148 REQUIRE( clargs[0] == "indiserver" );
149 REQUIRE( clargs[1] == "-vv" );
150 }
151
152 WHEN( "3 Option v provided with argument (3==>-vvv)" )
153 {
154 std::vector<std::string> clargs;
155 xi_test.indiserver_v( xi, 3 );
156
157 rv = xi.constructIndiserverCommand( clargs );
158 REQUIRE( rv == 0 );
159 REQUIRE( clargs.size() == 2 );
160 REQUIRE( clargs[0] == "indiserver" );
161 REQUIRE( clargs[1] == "-vvv" );
162 }
163
164 WHEN( "Option v provided with argument (4==>-vvv)" )
165 {
166 std::vector<std::string> clargs;
167 xi_test.indiserver_v( xi, 4 );
168
169 rv = xi.constructIndiserverCommand( clargs );
170 REQUIRE( rv == 0 );
171 REQUIRE( clargs.size() == 2 );
172 REQUIRE( clargs[0] == "indiserver" );
173 REQUIRE( clargs[1] == "-vvv" );
174 }
175
176 WHEN( "Option v provided with argument (0==>)" )
177 {
178 std::vector<std::string> clargs;
179 xi_test.indiserver_v( xi, 0 );
180
181 rv = xi.constructIndiserverCommand( clargs );
182 REQUIRE( rv == 0 );
183 REQUIRE( clargs.size() == 1 );
184 REQUIRE( clargs[0] == "indiserver" );
185 }
186
187 WHEN( "Option x provided" )
188 {
189 std::vector<std::string> clargs;
190 xi_test.indiserver_x( xi, true );
191
192 rv = xi.constructIndiserverCommand( clargs );
193 REQUIRE( rv == 0 );
194 REQUIRE( clargs.size() == 2 );
195 REQUIRE( clargs[0] == "indiserver" );
196 REQUIRE( clargs[1] == "-x" );
197 }
198
199 WHEN( "All options provided" )
200 {
201 std::vector<std::string> clargs;
202 xi_test.indiserver_m( xi, 100 );
203 xi_test.indiserver_n( xi, true );
204 xi_test.indiserver_p( xi, 2000 );
205 xi_test.indiserver_v( xi, 2 );
206 xi_test.indiserver_x( xi, true );
207
208 rv = xi.constructIndiserverCommand( clargs );
209 REQUIRE( rv == 0 );
210 REQUIRE( clargs.size() == 8 );
211 REQUIRE( clargs[0] == "indiserver" );
212 REQUIRE( clargs[1] == "-m" );
213 REQUIRE( clargs[2] == "100" );
214 REQUIRE( clargs[3] == "-n" );
215 REQUIRE( clargs[4] == "-p" );
216 REQUIRE( clargs[5] == "2000" );
217 REQUIRE( clargs[6] == "-vv" );
218 REQUIRE( clargs[7] == "-x" );
219 }
220 }
221}
222
223} // namespace xindiserverTest
224
225} // namespace libXWCTest
226
227SCENARIO( "xindiserver constructs local driver arguments", "[xindiserver]" )
228{
229 GIVEN( "A default constructed xindiserver" )
230 {
231 xindiserver xi;
232 xindiserver_test xi_test;
233
234 int rv;
235
236 WHEN( "Single local driver" )
237 {
238 std::vector<std::string> ml( { "driverX" } );
239 xi_test.m_local( xi, ml );
240
241 std::vector<std::string> clargs;
242 rv = xi.addLocalDrivers( clargs );
243 REQUIRE( rv == 0 );
244 REQUIRE( clargs.size() == 1 );
245 REQUIRE( clargs[0] == "/opt/MagAOX/drivers/driverX" );
246 }
247
248 WHEN( "Two local drivers" )
249 {
250 std::vector<std::string> ml( { "driverY", "driverZ" } );
251 xi_test.m_local( xi, ml );
252
253 std::vector<std::string> clargs;
254 rv = xi.addLocalDrivers( clargs );
255 REQUIRE( rv == 0 );
256 REQUIRE( clargs.size() == 2 );
257 REQUIRE( clargs[0] == "/opt/MagAOX/drivers/driverY" );
258 REQUIRE( clargs[1] == "/opt/MagAOX/drivers/driverZ" );
259 }
260
261 WHEN( "Three local drivers" )
262 {
263 std::vector<std::string> ml( { "driverX", "driverY", "driverZ" } );
264 xi_test.m_local( xi, ml );
265
266 std::vector<std::string> clargs;
267 rv = xi.addLocalDrivers( clargs );
268 REQUIRE( rv == 0 );
269 REQUIRE( clargs.size() == 3 );
270 REQUIRE( clargs[0] == "/opt/MagAOX/drivers/driverX" );
271 REQUIRE( clargs[1] == "/opt/MagAOX/drivers/driverY" );
272 REQUIRE( clargs[2] == "/opt/MagAOX/drivers/driverZ" );
273 }
274
275 WHEN( "Three local drivers, with an error (@)" )
276 {
277 std::vector<std::string> ml( { "driverX", "driver@Y", "driverZ" } );
278 xi_test.m_local( xi, ml );
279
280 std::vector<std::string> clargs;
281 rv = xi.addLocalDrivers( clargs );
282 REQUIRE( rv == XINDISERVER_E_BADDRIVERSPEC );
283 }
284
285 WHEN( "Three local drivers, with an error (/)" )
286 {
287 std::vector<std::string> ml( { "driver/X", "driverY", "driverZ" } );
288 xi_test.m_local( xi, ml );
289
290 std::vector<std::string> clargs;
291 rv = xi.addLocalDrivers( clargs );
292 REQUIRE( rv == XINDISERVER_E_BADDRIVERSPEC );
293 }
294
295 WHEN( "Three local drivers, with an error (:)" )
296 {
297 std::vector<std::string> ml( { "driverX", "driverY", "driver:Z" } );
298 xi_test.m_local( xi, ml );
299
300 std::vector<std::string> clargs;
301 rv = xi.addLocalDrivers( clargs );
302 REQUIRE( rv == XINDISERVER_E_BADDRIVERSPEC );
303 }
304
305 WHEN( "Three local drivers, duplicate" )
306 {
307 std::vector<std::string> ml( { "driverX", "driverY", "driverX" } );
308 xi_test.m_local( xi, ml );
309
310 std::vector<std::string> clargs;
311 rv = xi.addLocalDrivers( clargs );
312 REQUIRE( rv == XINDISERVER_E_DUPLICATEDRIVER );
313 }
314 }
315}
316
317SCENARIO( "xindiserver constructs remote driver arguments", "[xindiserver]" )
318{
319 GIVEN( "A default constructed xindiserver" )
320 {
321 xindiserver xi;
322 xindiserver_test xi_test;
323
324 int rv;
325
326 WHEN( "Single remote driver, single remote host" )
327 {
328 std::vector<std::string> mr( { "driverX@host1" } );
329 xi_test.m_remote( xi, mr );
330
331 mx::app::writeConfigFile( "/tmp/xindiserver_test.conf",
332 { "host1", "host1", "host1" },
333 { "remoteHost", "localPort", "remotePort" },
334 { "host1", "1000", "81" } );
335 mx::app::appConfigurator config;
336 config.readConfig( "/tmp/xindiserver_test.conf" );
337
338 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
339
340 std::vector<std::string> clargs;
341 rv = xi.addRemoteDrivers( clargs );
342 REQUIRE( rv == 0 );
343 REQUIRE( clargs.size() == 1 );
344 REQUIRE( clargs[0] == "driverX@localhost:1000" );
345 }
346
347 WHEN( "Two remote drivers, single remote host" )
348 {
349 std::vector<std::string> mr( { "driverX@host1", "driverY@host1" } );
350 xi_test.m_remote( xi, mr );
351
352 mx::app::writeConfigFile( "/tmp/xindiserver_test.conf",
353 { "host1", "host1", "host1" },
354 { "remoteHost", "localPort", "remotePort" },
355 { "host1", "1000", "81" } );
356 mx::app::appConfigurator config;
357 config.readConfig( "/tmp/xindiserver_test.conf" );
358
359 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
360 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
361
362 std::vector<std::string> clargs;
363 rv = xi.addRemoteDrivers( clargs );
364 REQUIRE( rv == 0 );
365 REQUIRE( clargs.size() == 2 );
366 REQUIRE( clargs[0] == "driverX@localhost:1000" );
367 REQUIRE( clargs[1] == "driverY@localhost:1000" );
368 }
369
370 WHEN( "Two remote drivers, two remote hosts" )
371 {
372 std::vector<std::string> mr( { "driverX@host1", "driverY@host2" } );
373 xi_test.m_remote( xi, mr );
374
375 mx::app::writeConfigFile(
376 "/tmp/xindiserver_test.conf",
377 { "host1", "host1", "host1", "host2", "host2", "host2" },
378 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
379 { "host1", "1000", "81", "host2", "1002", "86" } );
380 mx::app::appConfigurator config;
381 config.readConfig( "/tmp/xindiserver_test.conf" );
382
383 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
384 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
385
386 std::vector<std::string> clargs;
387 rv = xi.addRemoteDrivers( clargs );
388 REQUIRE( rv == 0 );
389 REQUIRE( clargs.size() == 2 );
390 REQUIRE( clargs[0] == "driverX@localhost:1000" );
391 REQUIRE( clargs[1] == "driverY@localhost:1002" );
392 }
393
394 WHEN( "Three remote drivers, two remote hosts, in order" )
395 {
396 std::vector<std::string> mr( { "driverX@host1", "driverZ@host1", "driverY@host2" } );
397 xi_test.m_remote( xi, mr );
398
399 mx::app::writeConfigFile(
400 "/tmp/xindiserver_test.conf",
401 { "host1", "host1", "host1", "host2", "host2", "host2" },
402 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
403 { "host1", "1000", "81", "host2", "1002", "86" } );
404
405 mx::app::appConfigurator config;
406 config.readConfig( "/tmp/xindiserver_test.conf" );
407
408 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
409 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
410
411 std::vector<std::string> clargs;
412 rv = xi.addRemoteDrivers( clargs );
413 REQUIRE( rv == 0 );
414 REQUIRE( clargs.size() == 3 );
415
416 REQUIRE( clargs[0] == "driverX@localhost:1000" );
417 REQUIRE( clargs[1] == "driverZ@localhost:1000" );
418 REQUIRE( clargs[2] == "driverY@localhost:1002" );
419 }
420
421 WHEN( "Three remote drivers, two remote hosts, arb order" )
422 {
423 std::vector<std::string> mr( { "driverX@host1", "driverZ@host2", "driverY@host1" } );
424 xi_test.m_remote( xi, mr );
425
426 mx::app::writeConfigFile(
427 "/tmp/xindiserver_test.conf",
428 { "host1", "host1", "host1", "host2", "host2", "host2" },
429 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
430 { "host1", "1000", "81", "host2", "1002", "86" } );
431
432 mx::app::appConfigurator config;
433 config.readConfig( "/tmp/xindiserver_test.conf" );
434
435 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
436 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
437
438 std::vector<std::string> clargs;
439 rv = xi.addRemoteDrivers( clargs );
440 REQUIRE( rv == 0 );
441 REQUIRE( clargs.size() == 3 );
442
443 REQUIRE( clargs[0] == "driverX@localhost:1000" );
444 REQUIRE( clargs[1] == "driverZ@localhost:1002" );
445 REQUIRE( clargs[2] == "driverY@localhost:1000" );
446 }
447
448 WHEN( "Three remote drivers, two remote hosts, error in host" )
449 {
450 std::vector<std::string> mr( { "driverX@host1", "driverZ@host2", "driverY@host1" } );
451 xi_test.m_remote( xi, mr );
452
453 mx::app::writeConfigFile( "/tmp/xindiserver_test.conf",
454 { "host1", "host1", "host1", "host2", "host2" },
455 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort" },
456 { "exao2", "1000", "81", "exao2", "1002" } );
457
458 mx::app::appConfigurator config;
459 config.readConfig( "/tmp/xindiserver_test.conf" );
460
461 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
462 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
463
464 std::vector<std::string> clargs;
465 rv = xi.addRemoteDrivers( clargs );
466 REQUIRE( rv == XINDISERVER_E_TUNNELNOTFOUND );
467 }
468
469 WHEN( "Three remote drivers, two remote hosts, error in driver" )
470 {
471 std::vector<std::string> mr( { "driverX", "driverZ@host2", "driverY@host1" } );
472 xi_test.m_remote( xi, mr );
473
474 mx::app::writeConfigFile(
475 "/tmp/xindiserver_test.conf",
476 { "host1", "host1", "host1", "host2", "host2", "host2" },
477 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
478 { "host1", "1000", "81", "host2", "1002", "86" } );
479
480 mx::app::appConfigurator config;
481 config.readConfig( "/tmp/xindiserver_test.conf" );
482
483 xi_test.tunnelMap( xi ).clear(); // make sure we don't hold over
484 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
485
486 std::vector<std::string> clargs;
487 rv = xi.addRemoteDrivers( clargs );
488 REQUIRE( rv == XINDISERVER_E_BADDRIVERSPEC );
489 }
490
491 WHEN( "Three remote drivers, two remote hosts, duplicate driver" )
492 {
493 std::vector<std::string> mr( { "driverX@host2", "driverX@host1", "driverY@host1" } );
494 xi_test.m_remote( xi, mr );
495
496 mx::app::writeConfigFile(
497 "/tmp/xindiserver_test.conf",
498 { "host1", "host1", "host1", "host2", "host2", "host2" },
499 { "remoteHost", "localPort", "remotePort", "remoteHost", "localPort", "remotePort" },
500 { "host1", "1000", "81", "host2", "1002", "86" } );
501
502 mx::app::appConfigurator config;
503 config.readConfig( "/tmp/xindiserver_test.conf" );
504 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
505
506 std::vector<std::string> clargs;
507 rv = xi.addRemoteDrivers( clargs );
508 REQUIRE( rv == XINDISERVER_E_DUPLICATEDRIVER );
509 }
510 }
511}
512
513SCENARIO( "xindiserver constructs both local and remote driver arguments", "[xindiserver]" )
514{
515 GIVEN( "A default constructed xindiserver" )
516 {
517 xindiserver xi;
518 xindiserver_test xi_test;
519
520 int rv;
521
522 WHEN( "single local driver, single remote driver, single remote host" )
523 {
524
525 std::vector<std::string> ml( { "driverX" } );
526 xi_test.m_local( xi, ml );
527
528 std::vector<std::string> mr( { "driverY@host1" } );
529 xi_test.m_remote( xi, mr );
530
531 mx::app::writeConfigFile( "/tmp/xindiserver_test.conf",
532 { "host1", "host1", "host1" },
533 { "remoteHost", "localPort", "remotePort" },
534 { "host1", "1000", "81" } );
535 mx::app::appConfigurator config;
536 config.readConfig( "/tmp/xindiserver_test.conf" );
537
538 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
539
540 std::vector<std::string> clargs;
541 rv = xi.addRemoteDrivers( clargs );
542 REQUIRE( rv == 0 );
543
544 rv = xi.addLocalDrivers( clargs );
545 REQUIRE( rv == 0 );
546
547 REQUIRE( clargs.size() == 2 );
548
549 REQUIRE( clargs[0] == "driverY@localhost:1000" );
550 REQUIRE( clargs[1] == "/opt/MagAOX/drivers/driverX" );
551 }
552
553 WHEN( "single local driver, single remote driver, single remote host -- duplicate driver" )
554 {
555
556 std::vector<std::string> ml( { "driverX" } );
557 xi_test.m_local( xi, ml );
558
559 std::vector<std::string> mr( { "driverX@host1" } );
560 xi_test.m_remote( xi, mr );
561
562 mx::app::writeConfigFile( "/tmp/xindiserver_test.conf",
563 { "host1", "host1", "host1" },
564 { "remoteHost", "localPort", "remotePort" },
565 { "host1", "1000", "81" } );
566 mx::app::appConfigurator config;
567 config.readConfig( "/tmp/xindiserver_test.conf" );
568
569 loadSSHTunnelConfigs( xi_test.tunnelMap( xi ), config );
570
571 std::vector<std::string> clargs;
572 rv = xi.addRemoteDrivers( clargs );
573 REQUIRE( rv == 0 );
574
575 rv = xi.addLocalDrivers( clargs );
576 REQUIRE( rv == XINDISERVER_E_DUPLICATEDRIVER );
577 }
578 }
579}
int indiserver_m
The indiserver MB behind setting (passed to indiserver)
int addRemoteDrivers(std::vector< std::string > &driverArgs)
Validate the remote driver entries, and append them to the indi server command line arguments.
std::vector< std::string > m_local
List of local drivers passed in by config.
bool indiserver_n
The indiserver ignore /tmp/noindi flag (passed to indiserver)
int addLocalDrivers(std::vector< std::string > &driverArgs)
Validate the local driver strings, and append them to the indi server command line arguments.
bool indiserver_x
The indiserver terminate after last exit flag (passed to indiserver)
std::vector< std::string > m_remote
List of remote drivers passed in by config.
tunnelMapT m_tunnels
Map of the ssh tunnels, used for processing the remote drivers in m_remote.
int indiserver_v
The indiserver verbosity (passed to indiserver)
int indiserver_p
The indiserver port (passed to indiserver)
int constructIndiserverCommand(std::vector< std::string > &indiserverCommand)
Construct the vector of indiserver arguments for exec.
SCENARIO("xindiserver constructs inserver options", "[xindiserver]")
Verify xindiserver builds command lines and tunnel-derived driver lists consistently.
std::unordered_map< std::string, sshTunnel > tunnelMapT
The map used to hold tunnel specifications.
int loadSSHTunnelConfigs(tunnelMapT &tmap, mx::app::appConfigurator &config)
Create the tunnel map from a configurator.
Namespace for all libXWC tests.
#define XINDISERVER_E_BADDRIVERSPEC
#define XINDISERVER_E_DUPLICATEDRIVER
#define XINDISERVER_E_TUNNELNOTFOUND
SCENARIO("xindiserver constructs local driver arguments", "[xindiserver]")