API
 
Loading...
Searching...
No Matches
MagAOXApp_test.cpp
Go to the documentation of this file.
1// #define CATCH_CONFIG_MAIN
2#include "../../../tests/catch2/catch.hpp"
3
4#include <filesystem>
5
6#include <mx/sys/timeUtils.hpp>
7
8#include "../MagAOXApp.hpp"
9#include "MagAOXApp_test.hpp"
10
11#undef app_MagAOXApp_hpp
12#undef app_tests_MagAOXApp_test_hpp
13#define XWCTEST_NAMESPACE XWCTEST_MAGAOXAPP_PID_LOCKED_ns
14#define XWCTEST_MAGAOXAPP_PID_LOCKED
15#include "../MagAOXApp.hpp"
16#include "MagAOXApp_test.hpp"
17#undef XWCTEST_NAMESPACE
18#undef XWCTEST_MAGAOXAPP_PID_LOCKED
19
20#undef app_MagAOXApp_hpp
21#undef app_tests_MagAOXApp_test_hpp
22#define XWCTEST_NAMESPACE XWCTEST_MAGAOXAPP_PID_WRITE_FAIL_ns
23#define XWCTEST_MAGAOXAPP_PID_WRITE_FAIL
24#include "../MagAOXApp.hpp"
25#include "MagAOXApp_test.hpp"
26#undef XWCTEST_NAMESPACE
27#undef XWCTEST_MAGAOXAPP_PID_WRITE_FAIL
28
29#undef app_MagAOXApp_hpp
30#undef app_tests_MagAOXApp_test_hpp
31#define XWCTEST_NAMESPACE XWCTEST_MAGAOXAPP_EXEC_NORM_ns
32#define XWCTEST_MAGAOXAPP_EXEC_NORM
33#include "../MagAOXApp.hpp"
34#include "MagAOXApp_test.hpp"
35#undef XWCTEST_NAMESPACE
36#undef XWCTEST_MAGAOXAPP_EXEC_NORM
37
38
39namespace libXWCTest
40{
41namespace appTest
42{
43
44/** \defgroup app_unit_test libXWC::app Unit Tests
45 * \ingroup unit_test
46*/
47
48/** \defgroup MagAOXApp_unit_test MagAOXApp Unit Tests
49 * \ingroup app_unit_test
50 */
51
52/// Namespace for XWC::app::MagAOXApp tests
53/** \ingroup MagAOXApp_unit_test
54 *
55 */
56namespace MagAOXAppTest
57{
58
59/// MagAOXApp 2nd instance
60/**
61 * \ingroup MagAOXApp_unit_test
62 */
63TEST_CASE( "MagAOXApp 2nd instance", "[app::MagAOXApp]" )
64{
65 SECTION( "test 2nd app" )
66 {
67 bool caught = false;
68
69 MagAOXApp_test app1;
70
71 try
72 {
73 MagAOXApp_test app2;
74 }
75 catch( const std::logic_error &e )
76 {
77 caught = true;
78 }
79
80 REQUIRE( caught == true );
81 }
82
83 #ifdef XWCTEST_DOXYGEN_REF_PROTECTED
84 MagAOX::app::MagAOXApp<true> app("", true);
85 #endif
86
87}
88
89/// MagAOXApp INDI NewProperty
90/**
91 * \ingroup MagAOXApp_unit_test
92 */
93SCENARIO( "MagAOXApp INDI NewProperty", "[app::MagAOXApp]" )
94{
95 GIVEN( "a new property request" )
96 {
97 WHEN( "a wrong device name" )
98 {
100
101 app.setConfigName( "test" );
102
103 REQUIRE( app.configName() == "test" );
104
105 pcf::IndiProperty prop;
106 app.registerIndiPropertyNew( prop,
107 "nprop",
108 pcf::IndiProperty::Number,
109 pcf::IndiProperty::ReadWrite,
110 pcf::IndiProperty::Idle,
111 callback );
112
113 pcf::IndiProperty nprop;
114
115 // First test the right device name
116 nprop.setDevice( "test" );
117 nprop.setName( "nprop" );
118
119 app.handleNewProperty( nprop );
120
121 REQUIRE( app.called_back == 1 );
122
123 app.called_back = 0;
124
125 // Now test the wrong device name
126 nprop.setDevice( "wrong" );
127
128 app.handleNewProperty( nprop );
129
130 REQUIRE( app.called_back == 0 );
131 }
132 }
133
134 #ifdef XWCTEST_DOXYGEN_REF_PROTECTED
135 MagAOX::app::MagAOXApp<true> app("", true);
136 app.configName();
137 pcf::IndiProperty prop;
138 app.registerIndiPropertyNew( prop,
139 "nprop",
140 pcf::IndiProperty::Number,
141 pcf::IndiProperty::ReadWrite,
142 pcf::IndiProperty::Idle,
143 callback );
144 app.handleNewProperty(prop);
145 #endif
146}
147
148/// Setting defaults
149/**
150 * \ingroup MagAOXApp_unit_test
151 */
152TEST_CASE( "Setting defaults", "[app::MagAOXApp]" )
153{
154 SECTION( "using default paths, configname is invoked name" )
155 {
156 std::vector<std::string> argvstr( { "./execname" } );
157
158 std::vector<const char *> argv( argvstr.size() + 1, NULL );
159 for( size_t index = 0; index < argvstr.size(); ++index )
160 {
161 argv[index] = argvstr[index].c_str();
162 }
163
164 MagAOXApp_test app;
165
166 app.invokedName() = argv[0];
167 REQUIRE( app.doHelp() == false );
168 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
169 REQUIRE( app.doHelp() == true );
170
171 app.basePath(); // make lcov records this call
172 REQUIRE( app.basePath() == MAGAOX_path );
173 app.configDir(); // make lcov records this call
174 REQUIRE( app.configDir() == app.basePath() + '/' + MAGAOX_configRelPath );
175 REQUIRE( app.configPathGlobal() == app.configDir() + "/magaox.conf" );
176 app.calibDir(); // make lcov records this call
177 REQUIRE( app.calibDir() == app.basePath() + '/' + MAGAOX_calibRelPath );
178 REQUIRE( app.m_log.logPath() == app.basePath() + '/' + MAGAOX_logRelPath );
179 app.sysPath(); // make lcov records this call
180 REQUIRE( app.sysPath() == app.basePath() + '/' + MAGAOX_sysRelPath );
181 app.secretsPath(); // make lcov records this call
182 REQUIRE( app.secretsPath() == app.basePath() + '/' + MAGAOX_secretsRelPath );
183 app.cpusetPath(); // make lcov records this call
184 REQUIRE( app.cpusetPath() == MAGAOX_cpusetPath );
185 app.configBase(); // make lcov records this call
186 REQUIRE( app.configBase() == "" );
187 REQUIRE( app.configPathUser() == "" );
188 REQUIRE( app.configName() == "execname" );
189 REQUIRE( app.configPathLocal() == app.configDir() + "/execname.conf" );
190
191 REQUIRE( app.doHelp() == true );
192 }
193
194 SECTION( "using default paths, with config-ed name" )
195 {
196 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
197
198 std::vector<const char *> argv( argvstr.size() + 1, NULL );
199 for( size_t index = 0; index < argvstr.size(); ++index )
200 {
201 argv[index] = argvstr[index].c_str();
202 }
203
204 MagAOXApp_test app;
205 app.invokedName() = argv[0];
206
207 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
208
209 REQUIRE( app.basePath() == MAGAOX_path );
210 REQUIRE( app.configDir() == app.basePath() + '/' + MAGAOX_configRelPath );
211 REQUIRE( app.configPathGlobal() == app.configDir() + "/magaox.conf" );
212 REQUIRE( app.calibDir() == app.basePath() + '/' + MAGAOX_calibRelPath );
213 REQUIRE( app.m_log.logPath() == app.basePath() + '/' + MAGAOX_logRelPath );
214
215 REQUIRE( app.sysPath() == app.basePath() + '/' + MAGAOX_sysRelPath );
216 REQUIRE( app.secretsPath() == app.basePath() + '/' + MAGAOX_secretsRelPath );
217 REQUIRE( app.cpusetPath() == MAGAOX_cpusetPath );
218 REQUIRE( app.configBase() == "" );
219 REQUIRE( app.configPathUser() == "" );
220 REQUIRE( app.configName() == "testapp" );
221 REQUIRE( app.configPathLocal() == app.configDir() + "/testapp.conf" );
222 REQUIRE( app.doHelp() == false );
223 }
224
225 // Something goes wrong here, third time is the charm.
226 // Hangs on config.parseCommandLine
227 SECTION( "using environment paths, with config-ed name" )
228 {
229 std::vector<const char *> argv;
230 std::vector<std::string> argvstr( { "./execname", "--name", "testapp2" } );
231
232 argv.resize( argvstr.size() + 1, NULL );
233 for( size_t index = 0; index < argvstr.size(); ++index )
234 {
235 argv[index] = argvstr[index].c_str();
236 }
237
238 char ppath[1024];
239 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
240 putenv( ppath );
241
242 char cpath[1024];
243 snprintf( cpath, sizeof( cpath ), "%s=config2", MAGAOX_env_config );
244 putenv( cpath );
245
246 char cbpath[1024];
247 snprintf( cbpath, sizeof( cbpath ), "%s=calib2", MAGAOX_env_calib );
248 putenv( cbpath );
249
250 char lpath[1024];
251 snprintf( lpath, sizeof( lpath ), "%s=logs2", MAGAOX_env_log );
252 putenv( lpath );
253
254 char syspath[1024];
255 snprintf( syspath, sizeof( syspath ), "%s=sys2", MAGAOX_env_sys );
256 putenv( syspath );
257
258 char secretspath[1024];
259 snprintf( secretspath, sizeof( secretspath ), "%s=secrets2", MAGAOX_env_secrets );
260 putenv( secretspath );
261
262 char cpupath[1024];
263 snprintf( cpupath, sizeof( cpupath ), "%s=/tmp/MagAOX/cpuset", MAGAOX_env_cpuset );
264 putenv( cpupath );
265
266 MagAOXApp_test app;
267
268 app.invokedName() = argv[0];
269 app.setConfigBase( "cbase" );
270
271 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
272
273 REQUIRE( app.basePath() == "/tmp/MagAOXApp_test" );
274 REQUIRE( app.configDir() == app.basePath() + '/' + "config2" );
275 REQUIRE( app.configPathGlobal() == app.configDir() + "/magaox.conf" );
276 REQUIRE( app.calibDir() == app.basePath() + '/' + "calib2" );
277 REQUIRE( app.m_log.logPath() == app.basePath() + '/' + "logs2" );
278 REQUIRE( app.sysPath() == app.basePath() + '/' + "sys2" );
279 REQUIRE( app.secretsPath() == app.basePath() + '/' + "secrets2" );
280 REQUIRE( app.cpusetPath() == "/tmp/MagAOX/cpuset" );
281 REQUIRE( app.configBase() == "cbase" );
282 REQUIRE( app.configPathUser() == app.configDir() + "/cbase.conf" );
283 REQUIRE( app.configName() == "testapp2" );
284 REQUIRE( app.configPathLocal() == app.configDir() + "/testapp2.conf" );
285 REQUIRE( app.doHelp() == false );
286 }
287}
288
289/// Configuring MagAOXApp
290/**
291 * \ingroup MagAOXApp_unit_test
292 */
293TEST_CASE( "Configuring MagAOXApp", "[app::MagAOXApp]" )
294{
295 SECTION( "setup basic config" )
296 {
297 MagAOXApp_test app;
298 app.setPowerMgtEnabled( true );
299
300 app.setupBasicConfig();
301
302 REQUIRE( app.shutdown() == false );
303 }
304
305 SECTION( "load basic config w all defaults w/out pwr management" )
306 {
307 MagAOXApp_test app;
308 app.setPowerMgtEnabled( false );
309
310 app.setupBasicConfig();
311
312 app.loadBasicConfig();
313
314 app.checkConfig();
315
316 REQUIRE( app.stateAlert() == false );
317 REQUIRE( app.gitAlert() == false );
318 REQUIRE( app.shutdown() == false );
319 }
320
321 SECTION( "load basic config w all defaults w/out pwr management, setting state and clearing alerts" )
322 {
323 std::vector<const char *> argv;
324 std::vector<std::string> argvstr( { "./execname", "--name", "testapp" } );
325
326 argv.resize( argvstr.size() + 1, NULL );
327 for( size_t index = 0; index < argvstr.size(); ++index )
328 {
329 argv[index] = argvstr[index].c_str();
330 }
331
332 MagAOXApp_test app( true );
333 app.setPowerMgtEnabled( false );
334
335 app.setupBasicConfig();
336
337 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
338
339 app.loadBasicConfig();
340
341 app.checkConfig();
342
343 REQUIRE( app.stateAlert() == true );
344 REQUIRE( app.gitAlert() == true );
345 REQUIRE( app.shutdown() == false );
346
347 app.doFSMClearAlert();
348 REQUIRE( app.stateAlert() == false );
349 REQUIRE( app.gitAlert() == true );
350 REQUIRE( app.shutdown() == false );
351
352 app.doFSMClearAlert(); // calls an immediate return of clearFSMAlert
353
354 // Now test each path out of clearFSMAlert
356 REQUIRE( app.state() == MagAOX::app::stateCodes::READY );
357
358 REQUIRE( app.stateLogged() == 0 );
359 REQUIRE( app.stateLogged() == 1 );
360
361 app.setAlert();
362 REQUIRE( app.stateAlert() == true );
363
364 app.doFSMClearAlert();
365 REQUIRE( app.stateAlert() == false );
366
368 REQUIRE( app.state() == MagAOX::app::stateCodes::HOMING );
369
370 app.setAlert();
371 REQUIRE( app.stateAlert() == true );
372
373 app.doFSMClearAlert();
374 REQUIRE( app.stateAlert() == false );
375
377 REQUIRE( app.state() == MagAOX::app::stateCodes::NODEVICE );
378
379 app.setAlert();
380 REQUIRE( app.stateAlert() == true );
381
382 app.doFSMClearAlert();
383 REQUIRE( app.stateAlert() == false );
384
386 REQUIRE( app.state() == MagAOX::app::stateCodes::LOGGEDIN );
387
388 app.setAlert();
389 REQUIRE( app.stateAlert() == true );
390
391 app.doFSMClearAlert();
392 REQUIRE( app.stateAlert() == false );
393
395 REQUIRE( app.state() == MagAOX::app::stateCodes::NODEVICE );
396
397 app.setAlert();
398 REQUIRE( app.stateAlert() == true );
399
400 app.doFSMClearAlert();
401 REQUIRE( app.stateAlert() == false );
402
404 REQUIRE( app.state() == MagAOX::app::stateCodes::NOTHOMED );
405
406 app.setAlert();
407 REQUIRE( app.stateAlert() == true );
408
409 app.doFSMClearAlert();
410 REQUIRE( app.stateAlert() == false );
411 }
412
413 SECTION( "load basic config w all defaults w unconfigured pwr management" )
414 {
415 MagAOXApp_test app;
416 app.setPowerMgtEnabled( true );
417
418 app.setupBasicConfig();
419
420 app.loadBasicConfig();
421
422 REQUIRE( app.shutdown() == true );
423
424 app.checkConfig();
425
426 REQUIRE( app.stateAlert() == false );
427 REQUIRE( app.gitAlert() == false );
428 REQUIRE( app.shutdown() == true );
429 }
430
431 SECTION( "load a full config" )
432 {
433 std::vector<const char *> argv;
434 std::vector<std::string> argvstr( { "./execname", "-n", "testapp", "--config.validate" } );
435
436 argv.resize( argvstr.size() + 1, NULL );
437 for( size_t index = 0; index < argvstr.size(); ++index )
438 {
439 argv[index] = argvstr[index].c_str();
440 }
441
442 char ppath[1024];
443 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
444 putenv( ppath );
445
446 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
447
448 std::ofstream fout;
449 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
450 fout.close();
451
452 mx::app::writeConfigFile( "/tmp/MagAOXApp_test/config/testapp.conf",
453 { "", "power", "power", "power", "power", "power" },
454 { "loopPause", "device", "channel", "element", "targetElement", "powerOnWait" },
455 { "2500", "pdu9", "thisch", "thisel", "thistgtel", "500000" } );
456
457 MagAOXApp_test app( true );
458 app.setPowerMgtEnabled( true );
459
460 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
461
462 REQUIRE( app.stateAlert() == true ); // due to git
463 REQUIRE( app.configOnly() == true );
464 REQUIRE( app.loopPause() == 2500 );
465 REQUIRE( app.powerDevice() == "pdu9" );
466 REQUIRE( app.powerChannel() == "thisch" );
467 REQUIRE( app.powerElement() == "thisel" );
468 REQUIRE( app.powerTargetElement() == "thistgtel" );
469 REQUIRE( app.powerOnWait() == 0 );
470
471 REQUIRE( app.shutdown() == false );
472 }
473
474 SECTION( "load a full config w unknown config in file, do help" )
475 {
476 std::vector<const char *> argv;
477 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
478
479 argv.resize( argvstr.size() + 1, NULL );
480 for( size_t index = 0; index < argvstr.size(); ++index )
481 {
482 argv[index] = argvstr[index].c_str();
483 }
484
485 char ppath[1024];
486 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
487 putenv( ppath );
488
489 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
490
491 std::ofstream fout;
492 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
493 fout.close();
494
495 // this adds unknown=value
496 mx::app::writeConfigFile(
497 "/tmp/MagAOXApp_test/config/testapp.conf",
498 { "", "power", "power", "power", "power", "power", "" },
499 { "loopPause", "device", "channel", "element", "targetElement", "powerOnWait", "unknown" },
500 { "2500", "pdu9", "thisch", "thisel", "thistgtel", "500", "value" } );
501
502 MagAOXApp_test app( false );
503 app.setPowerMgtEnabled( true );
504
505 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
506
507 REQUIRE( app.stateAlert() == false );
508 REQUIRE( app.configOnly() == false );
509 REQUIRE( app.loopPause() == 2500 );
510 REQUIRE( app.powerDevice() == "pdu9" );
511 REQUIRE( app.powerChannel() == "thisch" );
512 REQUIRE( app.powerElement() == "thisel" );
513 REQUIRE( app.powerTargetElement() == "thistgtel" );
514 REQUIRE( app.powerOnWait() == 500 );
515
516 REQUIRE( app.doHelp() == true );
517 REQUIRE( app.shutdown() == true );
518 }
519
520 SECTION( "load a full config w unknown config in file, validate" )
521 {
522 std::vector<const char *> argv;
523 std::vector<std::string> argvstr( { "./execname", "-n", "testapp", "--config.validate" } );
524
525 argv.resize( argvstr.size() + 1, NULL );
526 for( size_t index = 0; index < argvstr.size(); ++index )
527 {
528 argv[index] = argvstr[index].c_str();
529 }
530
531 char ppath[1024];
532 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
533 putenv( ppath );
534
535 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
536
537 std::ofstream fout;
538 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
539 fout.close();
540
541 // this adds unknown=value
542 mx::app::writeConfigFile(
543 "/tmp/MagAOXApp_test/config/testapp.conf",
544 { "", "power", "power", "power", "power", "power", "" },
545 { "loopPause", "device", "channel", "element", "targetElement", "powerOnWait", "unknown" },
546 { "2500", "pdu9", "thisch", "thisel", "thistgtel", "500000", "value" } );
547
548 MagAOXApp_test app( true );
549 app.setPowerMgtEnabled( true );
550
551 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
552
553 REQUIRE( app.stateAlert() == true ); // due to git
554 REQUIRE( app.configOnly() == true );
555 REQUIRE( app.loopPause() == 2500 );
556 REQUIRE( app.powerDevice() == "pdu9" );
557 REQUIRE( app.powerChannel() == "thisch" );
558 REQUIRE( app.powerElement() == "thisel" );
559 REQUIRE( app.powerTargetElement() == "thistgtel" );
560 REQUIRE( app.powerOnWait() == 0 );
561
562 REQUIRE( app.doHelp() == false );
563 REQUIRE( app.shutdown() == true );
564 }
565
566 SECTION( "load a full config w non-option clopt" )
567 {
568 std::vector<const char *> argv;
569 std::vector<std::string> argvstr( { "./execname", "-n", "testapp", "straylight" } );
570
571 argv.resize( argvstr.size() + 1, NULL );
572 for( size_t index = 0; index < argvstr.size(); ++index )
573 {
574 argv[index] = argvstr[index].c_str();
575 }
576
577 char ppath[1024];
578 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
579 putenv( ppath );
580
581 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
582
583 std::ofstream fout;
584 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
585 fout.close();
586
587 mx::app::writeConfigFile( "/tmp/MagAOXApp_test/config/testapp.conf",
588 { "", "power", "power", "power", "power", "power" },
589 { "loopPause", "device", "channel", "element", "targetElement", "powerOnWait" },
590 { "2500", "pdu9", "thisch", "thisel", "thistgtel", "500000" } );
591
592 MagAOXApp_test app( false );
593 app.setPowerMgtEnabled( true );
594
595 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
596
597 REQUIRE( app.stateAlert() == false ); // due to git
598 REQUIRE( app.configOnly() == false );
599 REQUIRE( app.loopPause() == 2500 );
600 REQUIRE( app.powerDevice() == "pdu9" );
601 REQUIRE( app.powerChannel() == "thisch" );
602 REQUIRE( app.powerElement() == "thisel" );
603 REQUIRE( app.powerTargetElement() == "thistgtel" );
604 REQUIRE( app.powerOnWait() == 0 );
605
606 REQUIRE( app.doHelp() == true );
607 REQUIRE( app.shutdown() == true );
608 }
609
610 SECTION( "load a full config w no power mgt opts" )
611 {
612 std::vector<const char *> argv;
613 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
614
615 argv.resize( argvstr.size() + 1, NULL );
616 for( size_t index = 0; index < argvstr.size(); ++index )
617 {
618 argv[index] = argvstr[index].c_str();
619 }
620
621 char ppath[1024];
622 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
623 putenv( ppath );
624
625 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
626
627 std::ofstream fout;
628 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
629 fout.close();
630
631 mx::app::writeConfigFile( "/tmp/MagAOXApp_test/config/testapp.conf", { "" }, { "loopPause" }, { "2500" } );
632
633 MagAOXApp_test app( false );
634 app.setPowerMgtEnabled( true );
635
636 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
637
638 REQUIRE( app.stateAlert() == false ); // due to git
639 REQUIRE( app.configOnly() == false );
640 REQUIRE( app.loopPause() == 2500 );
641 REQUIRE( app.powerDevice() == "" );
642 REQUIRE( app.powerChannel() == "" );
643 REQUIRE( app.powerElement() == "state" );
644 REQUIRE( app.powerTargetElement() == "target" );
645 REQUIRE( app.powerOnWait() == 0 );
646
647 REQUIRE( app.doHelp() == true );
648 REQUIRE( app.shutdown() == true );
649 }
650
651 SECTION( "load a full config w unused config options" )
652 {
653 std::vector<const char *> argv;
654 std::vector<std::string> argvstr( { "./execname", "-n", "testapp", "--config.validate" } );
655
656 argv.resize( argvstr.size() + 1, NULL );
657 for( size_t index = 0; index < argvstr.size(); ++index )
658 {
659 argv[index] = argvstr[index].c_str();
660 }
661
662 char ppath[1024];
663 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
664 putenv( ppath );
665
666 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/config" );
667
668 std::ofstream fout;
669 fout.open( "/tmp/MagAOXApp_test/config/magaox.conf" );
670 fout.close();
671
672 // this adds unknown=value
673 mx::app::writeConfigFile( "/tmp/MagAOXApp_test/config/testapp.conf",
674 { "", "power", "power", "power", "power", "power" },
675 { "loopPause", "device", "channel", "element", "targetElement", "powerOnWait" },
676 { "2500", "pdu9", "thisch", "thisel", "thistgtel", "500000" } );
677
678 MagAOXApp_test app( true );
679 app.setPowerMgtEnabled( true );
680
681 app.addUnusedConfig();
682
683 app.setup( argv.size() - 1, const_cast<char **>( argv.data() ) );
684
685 REQUIRE( app.stateAlert() == true ); // due to git
686 REQUIRE( app.configOnly() == true );
687 REQUIRE( app.loopPause() == 2500 );
688 REQUIRE( app.powerDevice() == "pdu9" );
689 REQUIRE( app.powerChannel() == "thisch" );
690 REQUIRE( app.powerElement() == "thisel" );
691 REQUIRE( app.powerTargetElement() == "thistgtel" );
692 REQUIRE( app.powerOnWait() == 0 );
693
694 REQUIRE( app.doHelp() == false );
695 REQUIRE( app.shutdown() == false );
696 }
697}
698
699/// PID Locking
700/**
701 * \ingroup MagAOXApp_unit_test
702 */
703TEST_CASE( "PID Locking", "[app::MagAOXApp]" )
704{
705 SECTION( "Basic PID Lock" )
706 {
707 std::vector<const char *> argv;
708 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
709
710 argv.resize( argvstr.size() + 1, NULL );
711 for( size_t index = 0; index < argvstr.size(); ++index )
712 {
713 argv[index] = argvstr[index].c_str();
714 }
715
716 char ppath[1024];
717 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
718 putenv( ppath );
719
720 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/sys/" );
721
722 // First delete the directory and files in case this is a repeat call
723 std::filesystem::remove_all( "/tmp/MagAOXApp_test/sys/testapp" );
724
725 MagAOXApp_test app;
726 app.invokedName() = argv[0];
727 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
728
729 REQUIRE( !std::filesystem::exists( "/tmp/MagAOXApp_test/sys/testapp/pid" ) );
730
731 int rv = app.lockPID();
732 REQUIRE( rv == 0 );
733 REQUIRE( std::filesystem::exists( "/tmp/MagAOXApp_test/sys/testapp/pid" ) );
734
735 rv = app.unlockPID();
736 REQUIRE( rv == 0 );
737 REQUIRE( !std::filesystem::exists( "/tmp/MagAOXApp_test/sys/testapp/pid" ) );
738 }
739
740 SECTION( "PID Lock, app directory creation error" )
741 {
742 std::vector<const char *> argv;
743 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
744
745 argv.resize( argvstr.size() + 1, NULL );
746 for( size_t index = 0; index < argvstr.size(); ++index )
747 {
748 argv[index] = argvstr[index].c_str();
749 }
750
751 char ppath[1024];
752 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
753 putenv( ppath );
754
755 // First delete the directory and files in case this is a repeat call
756 std::filesystem::remove_all( "/tmp/MagAOXApp_test" );
757
758 MagAOXApp_test app;
759 app.invokedName() = argv[0];
760 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
761
762 int rv = app.lockPID();
763 REQUIRE( rv == -1 );
764
765 rv = app.unlockPID();
766 REQUIRE( rv == -1 );
767 }
768
769 SECTION( "Stale lock" )
770 {
771 std::vector<const char *> argv;
772 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
773
774 argv.resize( argvstr.size() + 1, NULL );
775 for( size_t index = 0; index < argvstr.size(); ++index )
776 {
777 argv[index] = argvstr[index].c_str();
778 }
779
780 char ppath[1024];
781 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
782 putenv( ppath );
783
784 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/sys/testapp" );
785
786 std::ofstream fout;
787 fout.open( "/tmp/MagAOXApp_test/sys/testapp/pid" );
788 fout << 1;
789 fout.close();
790
791 MagAOXApp_test app;
792 app.invokedName() = argv[0];
793 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
794
795 int rv = app.lockPID();
796 REQUIRE( rv == 0 );
797 REQUIRE( std::filesystem::exists( "/tmp/MagAOXApp_test/sys/testapp/pid" ) );
798
799 rv = app.unlockPID();
800 REQUIRE( rv == 0 );
801 REQUIRE( !std::filesystem::exists( "/tmp/MagAOXApp_test/sys/testapp/pid" ) );
802 }
803
804 SECTION( "already locked" )
805 {
806 std::vector<const char *> argv;
807 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
808
809 argv.resize( argvstr.size() + 1, NULL );
810 for( size_t index = 0; index < argvstr.size(); ++index )
811 {
812 argv[index] = argvstr[index].c_str();
813 }
814
815 char ppath[1024];
816 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
817 putenv( ppath );
818
819 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/sys/testapp" );
820
821 std::ofstream fout;
822 fout.open( "/tmp/MagAOXApp_test/sys/testapp/pid" );
823 fout << 1;
824 fout.close();
825
826 XWCTEST_MAGAOXAPP_PID_LOCKED_ns::MagAOXApp_test app;
827 app.invokedName() = argv[0];
828 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
829
830 int rv = app.lockPID();
831 REQUIRE( rv == -1 );
832 }
833
834 SECTION( "write fails" )
835 {
836 std::vector<const char *> argv;
837 std::vector<std::string> argvstr( { "./execname", "-n", "testapp" } );
838
839 argv.resize( argvstr.size() + 1, NULL );
840 for( size_t index = 0; index < argvstr.size(); ++index )
841 {
842 argv[index] = argvstr[index].c_str();
843 }
844
845 char ppath[1024];
846 snprintf( ppath, sizeof( ppath ), "%s=/tmp/MagAOXApp_test", MAGAOX_env_path );
847 putenv( ppath );
848
849 mx::ioutils::createDirectories( "/tmp/MagAOXApp_test/sys/testapp" );
850
851 std::ofstream fout;
852 fout.open( "/tmp/MagAOXApp_test/sys/testapp/pid" );
853 fout << 1;
854 fout.close();
855
856 XWCTEST_MAGAOXAPP_PID_WRITE_FAIL_ns::MagAOXApp_test app;
857 app.invokedName() = argv[0];
858 app.setDefaults( argv.size() - 1, const_cast<char **>( argv.data() ) );
859
860 int rv = app.lockPID();
861 REQUIRE( rv == -1 );
862 }
863}
864
865/// MagAOXApp Power Management Logic Outside of Execute
866/**
867 * \ingroup MagAOXApp_unit_test
868 */
869TEST_CASE( "MagAOXApp Power Management Logic Outside of Execute", "[app::MagAOXApp]" )
870{
871 SECTION( "Power Management Not Configured" )
872 {
873 MagAOXApp_test app( true );
874 app.setPowerMgtEnabled( false );
875
876 REQUIRE( app.onPowerOff() == 0 );
877 REQUIRE( app.whilePowerOff() == 0 );
878 REQUIRE( app.powerOnWaitElapsed() == true );
879 REQUIRE( app.powerState() == 1 );
880 REQUIRE( app.powerStateTarget() == 1 );
881 }
882
883 SECTION( "Power Management Configured" )
884 {
885 MagAOXApp_test app( true );
886 app.setPowerMgtEnabled( true );
887 app.configurePowerManagement( "pdu", "test" );
888
889 REQUIRE( app.onPowerOff() == 0 );
890 REQUIRE( app.whilePowerOff() == 0 );
891 REQUIRE( app.powerOnWaitElapsed() == true );
892
893 // Comes up unknown
894 REQUIRE( app.powerState() == -1 );
895 REQUIRE( app.powerStateTarget() == -1 );
896
897 app.setPowerState( "Off", "Off" );
898 REQUIRE( app.powerState() == 0 );
899 REQUIRE( app.powerStateTarget() == 0 );
900
901 app.setPowerState( "Int", "Int" );
902 REQUIRE( app.powerState() == -1 );
903 REQUIRE( app.powerStateTarget() == -1 );
904
905 app.setPowerState( "Off", "On" );
906 REQUIRE( app.powerState() == 0 );
907 REQUIRE( app.powerStateTarget() == 1 );
908
909 app.configurePowerOnWait( 10, 0, 1e9 );
910 REQUIRE( app.loopPause() == 1e9 );
911
912 // 10 checks, then true on 11th
913 REQUIRE( app.powerOnWaitElapsed() == false );
914 REQUIRE( app.powerOnWaitElapsed() == false );
915 REQUIRE( app.powerOnWaitElapsed() == false );
916 REQUIRE( app.powerOnWaitElapsed() == false );
917 REQUIRE( app.powerOnWaitElapsed() == false );
918 REQUIRE( app.powerOnWaitElapsed() == false );
919 REQUIRE( app.powerOnWaitElapsed() == false );
920 REQUIRE( app.powerOnWaitElapsed() == false );
921 REQUIRE( app.powerOnWaitElapsed() == false );
922 REQUIRE( app.powerOnWaitElapsed() == false );
923 REQUIRE( app.powerOnWaitElapsed() == false );
924 REQUIRE( app.powerOnWaitElapsed() == true );
925
926 app.setPowerState( "On", "On" );
927 REQUIRE( app.powerState() == 1 );
928 REQUIRE( app.powerStateTarget() == 1 );
929
930 app.setPowerState( "On", "Off" );
931 REQUIRE( app.powerState() == 1 );
932 REQUIRE( app.powerStateTarget() == 0 );
933
934 app.setPowerState( "Off", "Off" );
935 REQUIRE( app.powerState() == 0 );
936 REQUIRE( app.powerStateTarget() == 0 );
937 }
938}
939
940/// INDI preperty creation utilities
941/**
942 * \ingroup MagAOXApp_unit_test
943 */
944TEST_CASE( "INDI preperty creation utilities", "[app::MagAOXApp]" )
945{
946 SECTION( "createStandardIndiText" )
947 {
948 MagAOXApp_test app;
949 app.setConfigName( "test" );
950
951 pcf::IndiProperty ip;
952
953 app.createStandardIndiText( ip, "tprop", "tlabel", "tgroup" );
954
955 REQUIRE( ip.getType() == pcf::IndiProperty::Text );
956 REQUIRE( ip.getDevice() == "test" );
957 REQUIRE( ip.getName() == "tprop" );
958 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
959 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
960 REQUIRE( ip.find( "current" ) == true );
961 REQUIRE( ip.find( "target" ) == true );
962 REQUIRE( ip.getLabel() == "tlabel" );
963 REQUIRE( ip.getGroup() == "tgroup" );
964 }
965
966 SECTION( "createROIndiText" )
967 {
968 MagAOXApp_test app;
969 app.setConfigName( "test" );
970
971 pcf::IndiProperty ip;
972
973 app.createROIndiText( ip, "tprop", "tel", "tlabel", "tgroup", "ellabel" );
974
975 REQUIRE( ip.getType() == pcf::IndiProperty::Text );
976 REQUIRE( ip.getDevice() == "test" );
977 REQUIRE( ip.getName() == "tprop" );
978 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadOnly );
979 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
980 REQUIRE( ip.getLabel() == "tlabel" );
981 REQUIRE( ip.getGroup() == "tgroup" );
982
983 REQUIRE( ip.find( "tel" ) == true );
984 REQUIRE( ip["tel"].getLabel() == "ellabel" );
985 }
986
987 SECTION( "createStandardIndiNumber" )
988 {
989 MagAOXApp_test app;
990 app.setConfigName( "test" );
991
992 pcf::IndiProperty ip;
993
994 app.createStandardIndiNumber<double>( ip, "tprop", 0.001, 1, 0.002, "%0.23g", "tlabel", "tgroup" );
995
996 REQUIRE( ip.getType() == pcf::IndiProperty::Number );
997 REQUIRE( ip.getDevice() == "test" );
998 REQUIRE( ip.getName() == "tprop" );
999 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
1000 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1001
1002 REQUIRE( ip.find( "current" ) == true );
1003 REQUIRE( ip["current"].getMin() == "0.001" );
1004 REQUIRE( ip["current"].getMax() == "1" );
1005 REQUIRE( ip["current"].getStep() == "0.002" );
1006 REQUIRE( ip["current"].getFormat() == "%0.23g" );
1007
1008 REQUIRE( ip.find( "target" ) == true );
1009 REQUIRE( ip["target"].getMin() == "0.001" );
1010 REQUIRE( ip["target"].getMax() == "1" );
1011 REQUIRE( ip["target"].getStep() == "0.002" );
1012 REQUIRE( ip["target"].getFormat() == "%0.23g" );
1013
1014 REQUIRE( ip.getLabel() == "tlabel" );
1015 REQUIRE( ip.getGroup() == "tgroup" );
1016 }
1017
1018 SECTION( "createROIndiNumber" )
1019 {
1020 MagAOXApp_test app;
1021 app.setConfigName( "test" );
1022
1023 pcf::IndiProperty ip;
1024
1025 app.createROIndiNumber( ip, "tprop", "tlabel", "tgroup" );
1026
1027 REQUIRE( ip.getType() == pcf::IndiProperty::Number );
1028 REQUIRE( ip.getDevice() == "test" );
1029 REQUIRE( ip.getName() == "tprop" );
1030 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadOnly );
1031 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1032 REQUIRE( ip.getLabel() == "tlabel" );
1033 REQUIRE( ip.getGroup() == "tgroup" );
1034 }
1035
1036 SECTION( "createStandardIndiToggleSw" )
1037 {
1038 MagAOXApp_test app;
1039 app.setConfigName( "testz" );
1040
1041 pcf::IndiProperty ip;
1042
1043 app.createStandardIndiToggleSw( ip, "tpropz", "tlabelz", "tgroupz" );
1044
1045 REQUIRE( ip.getType() == pcf::IndiProperty::Switch );
1046 REQUIRE( ip.getDevice() == "testz" );
1047 REQUIRE( ip.getName() == "tpropz" );
1048 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
1049 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1050 REQUIRE( ip.getRule() == pcf::IndiProperty::AtMostOne );
1051
1052 REQUIRE( ip.getNumElements() == 1 );
1053 REQUIRE( ip.find( "toggle" ) == true );
1054 REQUIRE( ip["toggle"].getSwitchState() == pcf::IndiElement::Off );
1055 REQUIRE( ip.getLabel() == "tlabelz" );
1056 REQUIRE( ip.getGroup() == "tgroupz" );
1057 }
1058
1059 SECTION( "createStandardIndiRequestSw" )
1060 {
1061 MagAOXApp_test app;
1062 app.setConfigName( "testz" );
1063
1064 pcf::IndiProperty ip;
1065
1066 app.createStandardIndiRequestSw( ip, "tpropz", "tlabelz", "tgroupz" );
1067
1068 REQUIRE( ip.getType() == pcf::IndiProperty::Switch );
1069 REQUIRE( ip.getDevice() == "testz" );
1070 REQUIRE( ip.getName() == "tpropz" );
1071 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
1072 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1073 REQUIRE( ip.getRule() == pcf::IndiProperty::AtMostOne );
1074
1075 REQUIRE( ip.getNumElements() == 1 );
1076 REQUIRE( ip.find( "request" ) == true );
1077 REQUIRE( ip["request"].getSwitchState() == pcf::IndiElement::Off );
1078 REQUIRE( ip.getLabel() == "tlabelz" );
1079 REQUIRE( ip.getGroup() == "tgroupz" );
1080 }
1081
1082 SECTION( "createStandardIndiSelectionSw, w/ labels" )
1083 {
1084 MagAOXApp_test app;
1085 app.setConfigName( "testy" );
1086
1087 pcf::IndiProperty ip;
1088
1089 std::vector<std::string> els( { "el1", "el2", "el3" } );
1090 std::vector<std::string> labs( { "l1", "", "l3" } );
1091
1092 app.createStandardIndiSelectionSw( ip, "tpropy", els, labs, "tlabely", "tgroupy" );
1093
1094 REQUIRE( ip.getType() == pcf::IndiProperty::Switch );
1095 REQUIRE( ip.getDevice() == "testy" );
1096 REQUIRE( ip.getName() == "tpropy" );
1097 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
1098 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1099 REQUIRE( ip.getRule() == pcf::IndiProperty::OneOfMany );
1100
1101 REQUIRE( ip.getNumElements() == 3 );
1102 REQUIRE( ip.find( "el1" ) == true );
1103 REQUIRE( ip["el1"].getSwitchState() == pcf::IndiElement::Off );
1104 REQUIRE( ip["el1"].getLabel() == "l1" );
1105
1106 REQUIRE( ip.find( "el2" ) == true );
1107 REQUIRE( ip["el2"].getSwitchState() == pcf::IndiElement::Off );
1108 REQUIRE( ip["el2"].getLabel() == "" );
1109
1110 REQUIRE( ip.find( "el3" ) == true );
1111 REQUIRE( ip["el3"].getSwitchState() == pcf::IndiElement::Off );
1112 REQUIRE( ip["el3"].getLabel() == "l3" );
1113
1114 REQUIRE( ip.getLabel() == "tlabely" );
1115 REQUIRE( ip.getGroup() == "tgroupy" );
1116 }
1117
1118 SECTION( "createStandardIndiSelectionSw, no labels" )
1119 {
1120 MagAOXApp_test app;
1121 app.setConfigName( "testy" );
1122
1123 pcf::IndiProperty ip;
1124
1125 std::vector<std::string> els( { "el1", "el2", "el3" } );
1126
1127 app.createStandardIndiSelectionSw( ip, "tpropy", els, "tlabely", "tgroupy" );
1128
1129 REQUIRE( ip.getType() == pcf::IndiProperty::Switch );
1130 REQUIRE( ip.getDevice() == "testy" );
1131 REQUIRE( ip.getName() == "tpropy" );
1132 REQUIRE( ip.getPerm() == pcf::IndiProperty::ReadWrite );
1133 REQUIRE( ip.getState() == pcf::IndiProperty::Idle );
1134 REQUIRE( ip.getRule() == pcf::IndiProperty::OneOfMany );
1135
1136 REQUIRE( ip.getNumElements() == 3 );
1137 REQUIRE( ip.find( "el1" ) == true );
1138 REQUIRE( ip["el1"].getSwitchState() == pcf::IndiElement::Off );
1139 REQUIRE( ip["el1"].getLabel() == "el1" );
1140
1141 REQUIRE( ip.find( "el2" ) == true );
1142 REQUIRE( ip["el2"].getSwitchState() == pcf::IndiElement::Off );
1143 REQUIRE( ip["el2"].getLabel() == "el2" );
1144
1145 REQUIRE( ip.find( "el3" ) == true );
1146 REQUIRE( ip["el3"].getSwitchState() == pcf::IndiElement::Off );
1147 REQUIRE( ip["el3"].getLabel() == "el3" );
1148
1149 REQUIRE( ip.getLabel() == "tlabely" );
1150 REQUIRE( ip.getGroup() == "tgroupy" );
1151 }
1152}
1153
1154/// Signal Handlers
1155/**
1156 * \ingroup MagAOXApp_unit_test
1157 */
1158TEST_CASE( "Signal Handlers", "[app::MagAOXApp]" )
1159{
1160 SECTION( "Setting and calling signal handler: SIGTERM" )
1161 {
1162
1163 MagAOXApp_test app;
1164
1165 // this is just to touch this function
1166 REQUIRE( app.setSigTermHandler() == 0 );
1167
1168 REQUIRE( app.shutdown() == 0 );
1169 app._handlerSigTerm( SIGTERM, nullptr, nullptr );
1170 REQUIRE( app.shutdown() == 1 );
1171 }
1172
1173 SECTION( "Setting and calling signal handler: SIGINT" )
1174 {
1175
1176 MagAOXApp_test app;
1177
1178 // this is just to touch this function
1179 REQUIRE( app.setSigTermHandler() == 0 );
1180
1181 REQUIRE( app.shutdown() == 0 );
1182 app._handlerSigTerm( SIGINT, nullptr, nullptr );
1183 REQUIRE( app.shutdown() == 1 );
1184 }
1185
1186 SECTION( "Setting and calling signal handler: SIGQUIT" )
1187 {
1188
1189 MagAOXApp_test app;
1190
1191 // this is just to touch this function
1192 REQUIRE( app.setSigTermHandler() == 0 );
1193
1194 REQUIRE( app.shutdown() == 0 );
1195 app._handlerSigTerm( SIGQUIT, nullptr, nullptr );
1196 REQUIRE( app.shutdown() == 1 );
1197 }
1198
1199 SECTION( "Setting and calling signal handler: SIGHUP" )
1200 {
1201
1202 MagAOXApp_test app;
1203
1204 // this is just to touch this function
1205 REQUIRE( app.setSigTermHandler() == 0 );
1206
1207 REQUIRE( app.shutdown() == 0 );
1208 app._handlerSigTerm( SIGHUP, nullptr, nullptr );
1209 REQUIRE( app.shutdown() == 1 );
1210 }
1211}
1212
1213/// Setting Euid
1214/**
1215 * \ingroup MagAOXApp_unit_test
1216 */
1217TEST_CASE( "Setting Euid", "[app::MagAOXApp]" )
1218{
1219
1220 MagAOXApp_test app;
1221
1222 REQUIRE( app.setEuidReal() == 0 );
1223
1224 REQUIRE( app.setEuidCalled() == 0 );
1225
1226 REQUIRE( app.setEuidReal( 0 ) == -1 );
1227 REQUIRE( app.setEuidCalled( 0 ) == -1 );
1228}
1229
1230
1231
1232/// Tests of utilities in cpp
1233/**
1234 * \ingroup MagAOXApp_unit_test
1235 */
1236TEST_CASE( "Tests of utilities in cpp", "[app::MagAOXApp]" )
1237{
1238 SECTION( "sigusr1 handler" )
1239 {
1240 // this is just to touch this function
1241 MagAOX::app::sigUsr1Handler( 0, nullptr, nullptr );
1242
1243 REQUIRE( true );
1244 }
1245}
1246
1247} // namespace MagAOXAppTest
1248} // namespace appTest
1249} // namespace libXWCTest
The base-class for XWCTk applications.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
void handleNewProperty(const pcf::IndiProperty &ipRecv)
Handler for the new INDI property request.
std::string configName()
Get the config name.
TEST_CASE("MagAOXApp 2nd instance", "[app::MagAOXApp]")
MagAOXApp 2nd instance.
SCENARIO("MagAOXApp INDI NewProperty", "[app::MagAOXApp]")
MagAOXApp INDI NewProperty.
#define MAGAOX_calibRelPath
The relative path to the calibration files.
Definition paths.hpp:36
#define MAGAOX_configRelPath
The relative path to the configuration files.
Definition paths.hpp:29
#define MAGAOX_logRelPath
The relative path to the log directory.
Definition paths.hpp:50
#define MAGAOX_sysRelPath
The relative path to the system directory.
Definition paths.hpp:64
#define MAGAOX_path
The path to the MagAO-X system files.
Definition paths.hpp:22
#define MAGAOX_secretsRelPath
The relative path to the secrets directory. Used for storing passwords, etc.
Definition paths.hpp:71
#define MAGAOX_cpusetPath
The absolute path to the cpuset mount point.
Definition paths.hpp:99
#define MAGAOX_env_sys
Environment variable setting the relative system directory path.
#define MAGAOX_env_path
Environment variable setting the MagAO-X path.
#define MAGAOX_env_log
Environment variable setting the relative log path.
#define MAGAOX_env_calib
Environment variable setting the relative calib path.
#define MAGAOX_env_secrets
Environment variable setting the relative secrets path.
#define MAGAOX_env_config
Environment variable setting the relative config path.
#define MAGAOX_env_cpuset
Environment variable setting the cpu set path.
@ NODEVICE
No device exists for the application to control.
@ NOTHOMED
The device has not been homed.
@ HOMING
The device is homing.
@ READY
The device is ready for operation, but is not operating.
@ LOGGEDIN
The application has logged into the device or service.
void sigUsr1Handler(int signum, siginfo_t *siginf, void *ucont)
Empty signal handler. SIGUSR1 is used to interrupt sleep in various threads.
Definition MagAOXApp.cpp:18
int callback(void *app, const pcf::IndiProperty &ipRecv)
Namespace for all libXWC tests.
Definition MagAOXApp.hpp:49
void _handlerSigTerm(int signum, siginfo_t *siginf, void *ucont)
void configurePowerManagement(const std::string &device, const std::string &channel)
void configurePowerOnWait(unsigned long powerOnWait, int powerOnCounter, int loopPause)
int setPowerState(const std::string &state, const std::string target)