35namespace zaberLowLevelBinaryTest
43 zaberLowLevelBinary_test(
const std::string &device )
45 m_configName = device;
56 int setupPowerOffSnapshot(
const std::string &stageName,
long rawPos,
bool parked,
long maxPos, time_t lastHomed )
60 m_testRoot = std::filesystem::temp_directory_path() / (
"zaberLowLevelBinary_test_" + m_configName );
61 std::filesystem::remove_all( m_testRoot, ec );
63 m_basePath = m_testRoot.string();
64 m_sysPath = ( m_testRoot /
"sys" ).
string();
67 std::filesystem::create_directories( std::filesystem::path( m_sysPath ) / m_configName );
69 m_stages.emplace_back(
this );
70 m_stages.back().name( stageName );
71 m_stages.back().serial(
"serial0" );
74 std::ofstream stateOut( std::filesystem::path( m_sysPath ) / m_configName / stageName );
75 stateOut << rawPos <<
'\n' << parked <<
'\n' << maxPos <<
'\n' << lastHomed <<
'\n';
78 if( appStartup() < 0 )
83 if( createINDIFIFOS() < 0 )
90 return ( m_indiDriver && m_indiDriver->good() ) ? 0 : -1;
94 int addConfiguredStage(
const std::string &stageName,
const std::string &serial,
int deviceAddress = -1 )
96 m_stages.emplace_back(
this );
97 m_stages.back().name( stageName );
98 m_stages.back().serial( serial );
99 m_stages.back().deviceAddress( deviceAddress );
101 const size_t idx = m_stages.size() - 1;
103 m_stageName.insert( { stageName, idx } );
104 m_stageSerial.insert( { serial, idx } );
110 int loadDiscoverySnapshot(
const std::vector<int> &addresses,
const std::vector<std::string> &serials )
112 return loadStages( addresses, serials );
116 int setDeviceAddressFor(
size_t stageIndex,
int deviceAddress )
118 m_stages.at( stageIndex ).deviceAddress( deviceAddress );
123 int deviceAddressFor(
size_t stageIndex )
const
125 return m_stages.at( stageIndex ).deviceAddress();
129 int recoverTransportError(
bool devicePresent )
131 return recoverFromError( devicePresent );
148 std::string propertyValue(
const pcf::IndiProperty &property,
const std::string &element )
const
150 return property[element].getValue();
154 std::string currPosValue(
const std::string &stageName )
const
156 return propertyValue( m_indiP_curr_pos, stageName );
160 std::string tgtPosValue(
const std::string &stageName )
const
162 return propertyValue( m_indiP_tgt_pos, stageName );
166 std::string parkedValue(
const std::string &stageName )
const
168 return propertyValue( m_indiP_parked, stageName );
172 std::string lastHomedValue(
const std::string &stageName )
const
174 return propertyValue( m_indiP_lastHomed, stageName );
178 std::string maxPosValue(
const std::string &stageName )
const
180 return propertyValue( m_indiP_max_pos, stageName );
184 std::string currStateValue(
const std::string &stageName )
const
186 return propertyValue( m_indiP_curr_state, stageName );
190 std::string warnValue(
const std::string &stageName )
const
192 return propertyValue( m_indiP_warn, stageName );
201 ~zaberLowLevelBinary_test()
noexcept
206 m_indiDriver =
nullptr;
207 std::filesystem::remove_all( m_testRoot, ec );
211 std::filesystem::path m_testRoot;
214class zaberBinaryStage_test :
public zaberBinaryStage<zaberLowLevelBinary_test>
223 void setHomeState(
bool homing,
bool warnWR,
long tgtPos,
long rawPos, time_t lastHomed )
229 m_lastHomed.tv_sec = lastHomed;
230 m_lastHomed.tv_nsec = 0;
234 int refreshLastHomed(
bool wasHoming )
236 return updateLastHomed( wasHoming );
240 time_t lastHomedSec()
const
242 return m_lastHomed.tv_sec;
251SCENARIO(
"INDI Callbacks",
"[zaberLowLevelBinary]" )
254 #ifdef ZABERLOWLEVELBINARY_TEST_DOXYGEN_REF
255 zaberLowLevelBinary::newCallBack_m_indiP_tgt_pos( pcf::IndiProperty() );
268SCENARIO(
"Power-off INDI snapshot retains stage state",
"[zaberLowLevelBinary]" )
270 zaberLowLevelBinary_test zllbt(
"zllbtest" );
272 REQUIRE( zllbt.setupPowerOffSnapshot(
"stageA", 12345,
true, 54321, 77 ) == 0 );
274 REQUIRE( zllbt.doOnPowerOff() == 0 );
276 REQUIRE( zllbt.currPosValue(
"stageA" ) ==
"12345" );
277 REQUIRE( zllbt.tgtPosValue(
"stageA" ) ==
"12345" );
278 REQUIRE( zllbt.parkedValue(
"stageA" ) ==
"1" );
279 REQUIRE( zllbt.lastHomedValue(
"stageA" ) ==
"77" );
280 REQUIRE( zllbt.maxPosValue(
"stageA" ) ==
"54321" );
281 REQUIRE( zllbt.currStateValue(
"stageA" ) ==
"POWEROFF" );
282 REQUIRE( zllbt.warnValue(
"stageA" ) ==
"Off" );
285SCENARIO(
"Binary last-home timestamps refresh after homing completes",
"[zaberLowLevelBinary]" )
287 zaberLowLevelBinary_test zllbt(
"zllbtest" );
288 zaberBinaryStage_test stage( &zllbt );
290 WHEN(
"a homing sequence completes with a stale stored timestamp" )
292 stage.setHomeState(
false,
false, 0, 0, 77 );
294 REQUIRE( stage.refreshLastHomed(
true ) == 0 );
295 REQUIRE( stage.lastHomedSec() != 77 );
298 WHEN(
"the stage is merely idle at home with an existing timestamp" )
300 stage.setHomeState(
false,
false, 0, 0, 77 );
302 REQUIRE( stage.refreshLastHomed(
false ) == 0 );
303 REQUIRE( stage.lastHomedSec() == 77 );
311SCENARIO(
"Binary discovery resets stale device addresses",
"[zaberLowLevelBinary]" )
314 #ifdef ZABERLOWLEVELBINARY_TEST_DOXYGEN_REF
319 zaberLowLevelBinary_test zllbt(
"zllbtest" );
321 REQUIRE( zllbt.addConfiguredStage(
"stagebs",
"64040", 1 ) == 0 );
322 REQUIRE( zllbt.addConfiguredStage(
"stageirf",
"122400", 2 ) == 0 );
324 REQUIRE( zllbt.loadDiscoverySnapshot( { 1 }, {
"64040" } ) ==
ZBC_CONNECTED );
325 REQUIRE( zllbt.deviceAddressFor( 0 ) == 1 );
326 REQUIRE( zllbt.deviceAddressFor( 1 ) < 1 );
333SCENARIO(
"Binary discovery can find devices that appear later",
"[zaberLowLevelBinary]" )
335 zaberLowLevelBinary_test zllbt(
"zllbtest_rediscover" );
337 REQUIRE( zllbt.addConfiguredStage(
"stagebs",
"64040" ) == 0 );
338 REQUIRE( zllbt.addConfiguredStage(
"stageirf",
"122400" ) == 0 );
340 REQUIRE( zllbt.loadDiscoverySnapshot( { 1 }, {
"64040" } ) ==
ZBC_CONNECTED );
341 REQUIRE( zllbt.deviceAddressFor( 0 ) == 1 );
342 REQUIRE( zllbt.deviceAddressFor( 1 ) < 1 );
344 REQUIRE( zllbt.loadDiscoverySnapshot( { 1, 2 }, {
"64040",
"122400" } ) ==
ZBC_CONNECTED );
345 REQUIRE( zllbt.deviceAddressFor( 0 ) == 1 );
346 REQUIRE( zllbt.deviceAddressFor( 1 ) == 2 );
353SCENARIO(
"Recoverable binary transport errors transition to reconnect states",
"[zaberLowLevelBinary]" )
356 #ifdef ZABERLOWLEVELBINARY_TEST_DOXYGEN_REF
362 SECTION(
"A present tty returns the app to NOTCONNECTED" )
364 zaberLowLevelBinary_test zllbt(
"zllbtest_present" );
366 REQUIRE( zllbt.setupPowerOffSnapshot(
"stageA", 12345,
true, 54321, 77 ) == 0 );
367 REQUIRE( zllbt.setDeviceAddressFor( 0, 1 ) == 0 );
370 REQUIRE( zllbt.recoverTransportError(
true ) == 0 );
372 REQUIRE( zllbt.currStateValue(
"stageA" ) ==
"NOTCONNECTED" );
375 SECTION(
"A missing tty returns the app to NODEVICE" )
377 zaberLowLevelBinary_test zllbt(
"zllbtest_missing" );
379 REQUIRE( zllbt.setupPowerOffSnapshot(
"stageA", 12345,
true, 54321, 77 ) == 0 );
380 REQUIRE( zllbt.setDeviceAddressFor( 0, 1 ) == 0 );
383 REQUIRE( zllbt.recoverTransportError(
false ) == 0 );
385 REQUIRE( zllbt.currStateValue(
"stageA" ) ==
"NODEVICE" );