File indexing completed on 2024-04-21 14:47:23
0001 /* 0002 KStars UI tests for capture workflows (re-focus, dithering, guiding, ...) 0003 0004 SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "test_ekos_capture_workflow.h" 0010 0011 #include "kstars_ui_tests.h" 0012 #include "ui_calibrationoptions.h" 0013 #include "indicom.h" 0014 #include "Options.h" 0015 #include "skymapcomposite.h" 0016 #include "ekos/capture/sequencejobstate.h" 0017 #include "ekos/capture/capture.h" 0018 0019 #define SHUTTER_UNKNOWN -1 0020 #define SHUTTER_NO 0 0021 #define SHUTTER_YES 1 0022 0023 0024 TestEkosCaptureWorkflow::TestEkosCaptureWorkflow(QObject *parent) : 0025 TestEkosCaptureWorkflow::TestEkosCaptureWorkflow("Internal", parent) {} 0026 0027 TestEkosCaptureWorkflow::TestEkosCaptureWorkflow(QString guider, QObject *parent) : QObject(parent) 0028 { 0029 m_CaptureHelper = new TestEkosCaptureHelper(guider); 0030 m_CaptureHelper->m_GuiderDevice = "CCD Simulator"; 0031 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0032 } 0033 0034 void TestEkosCaptureWorkflow::testCaptureRefocusDelay() 0035 { 0036 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0037 // default initialization 0038 QVERIFY(prepareTestCase()); 0039 0040 Ekos::Manager *manager = Ekos::Manager::Instance(); 0041 QVERIFY(prepareCapture(1)); 0042 QVERIFY(m_CaptureHelper->executeFocusing()); 0043 0044 // start capturing, expect focus after first captured frame 0045 Ekos::Capture *capture = manager->captureModule(); 0046 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0047 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0048 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_FOCUSING); 0049 KTRY_CLICK(capture, startB); 0050 // focusing must have started 60 secs + exposure time + 10 secs delay 0051 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 0052 60000 + 10000 + 1000 * capture->captureExposureN->value()); 0053 } 0054 0055 void TestEkosCaptureWorkflow::testCaptureRefocusHFR() 0056 { 0057 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0058 // default initialization 0059 QVERIFY(prepareTestCase()); 0060 0061 Ekos::Manager *manager = Ekos::Manager::Instance(); 0062 QVERIFY(prepareCapture(0, 1.2)); 0063 QVERIFY(m_CaptureHelper->executeFocusing()); 0064 0065 // start capturing 0066 Ekos::Capture *capture = manager->captureModule(); 0067 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0068 m_CaptureHelper->expectedFocusStates.append(Ekos::FOCUS_PROGRESS); 0069 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0070 KTRY_CLICK(capture, startB); 0071 // wait for one frame has been captured: exposure time + 10 secs delay 0072 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 0073 10000 + 1000 * capture->captureExposureN->value()); 0074 // now move the focuser twice to increase the HFR 0075 KTRY_CLICK(manager->focusModule(), focusOutB); 0076 KTRY_CLICK(manager->focusModule(), focusOutB); 0077 // check if focusing has started, latest after two more frames 0078 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedFocusStates, 0079 10000 + 2 * 1000 * capture->captureExposureN->value()); 0080 } 0081 0082 0083 void TestEkosCaptureWorkflow::testCaptureRefocusTemperature() 0084 { 0085 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0086 // default initialization 0087 QVERIFY(prepareTestCase()); 0088 0089 Ekos::Manager *manager = Ekos::Manager::Instance(); 0090 Ekos::Capture *capture = manager->captureModule(); 0091 // select temperature threshold 0092 double deltaT = 2.0; 0093 QVERIFY(prepareCapture(0, 0, deltaT)); 0094 // set the focuser temperature 0095 SET_INDI_VALUE_DOUBLE(m_CaptureHelper->m_FocuserDevice, "FOCUS_TEMPERATURE", "TEMPERATURE", 0); 0096 // select the focuser as temperature source 0097 KTRY_SET_COMBO(manager->focusModule(), defaultFocusTemperatureSource, m_CaptureHelper->m_FocuserDevice); 0098 0099 QVERIFY(m_CaptureHelper->executeFocusing()); 0100 0101 // start capturing 0102 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0103 m_CaptureHelper->expectedFocusStates.append(Ekos::FOCUS_PROGRESS); 0104 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0105 KTRY_CLICK(capture, startB); 0106 // wait for one frame has been captured: exposure time + 10 secs delay 0107 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 0108 10000 + 1000 * capture->captureExposureN->value()); 0109 // now change the temperature on the focuser 0110 SET_INDI_VALUE_DOUBLE(m_CaptureHelper->m_FocuserDevice, "FOCUS_TEMPERATURE", "TEMPERATURE", -2 * deltaT); 0111 0112 KTRY_CLICK(manager->focusModule(), focusOutB); 0113 KTRY_CLICK(manager->focusModule(), focusOutB); 0114 // check if focusing has started, latest after two more frames 0115 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedFocusStates, 0116 10000 + 2 * 1000 * capture->captureExposureN->value()); 0117 0118 } 0119 0120 0121 void TestEkosCaptureWorkflow::testCaptureRefocusAbort() 0122 { 0123 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0124 // default initialization 0125 QVERIFY(prepareTestCase()); 0126 0127 Ekos::Manager *manager = Ekos::Manager::Instance(); 0128 QVERIFY(prepareCapture(1)); 0129 QVERIFY(m_CaptureHelper->executeFocusing()); 0130 0131 // start capturing, expect focus after first captured frame 0132 Ekos::Capture *capture = manager->captureModule(); 0133 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0134 m_CaptureHelper->expectedFocusStates.append(Ekos::FOCUS_PROGRESS); 0135 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_FOCUSING); 0136 KTRY_CLICK(capture, startB); 0137 // focusing must have started 60 secs + exposure time + 10 secs delay 0138 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedFocusStates, 0139 60000 + 10000 + 1000 * capture->captureExposureN->value()); 0140 // the capture module must change to focusing subsequently 0141 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 5000); 0142 // now abort capturing 0143 m_CaptureHelper->expectedFocusStates.append(Ekos::FOCUS_ABORTED); 0144 capture->abort(); 0145 // expect that focusing aborts 0146 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedFocusStates, 10000); 0147 } 0148 0149 void TestEkosCaptureWorkflow::testCaptureScriptsExecution() 0150 { 0151 // default initialization 0152 QVERIFY(prepareTestCase()); 0153 0154 QFETCH(bool, pausing); 0155 // static test with three exposures 0156 int count = 3; 0157 // switch to capture module 0158 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0159 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0160 0161 // add target to path to emulate the behavior of the scheduler 0162 QString imagepath = getImageLocation()->path() + "/test"; 0163 0164 // create executable scripts 0165 m_CaptureHelper->createAllCaptureScripts(destination); 0166 0167 // setup scripts - starts as thread since clicking on capture blocks 0168 bool success = false; 0169 QTimer::singleShot(1000, capture, [&] {success = m_CaptureHelper->fillScriptManagerDialog(m_CaptureHelper->getScripts());}); 0170 // open script manager 0171 KTRY_CLICK(capture, scriptManagerB); 0172 // verify if script configuration succeeded 0173 QVERIFY2(success, "Scripts set up failed!"); 0174 0175 // create capture sequences 0176 KTRY_CAPTURE_CONFIGURE_LIGHT(2.0, count, 0.0, "Luminance", "test", imagepath); 0177 KTRY_CAPTURE_CLICK(addToQueueB); 0178 KTRY_CAPTURE_CONFIGURE_LIGHT(2.0, count, 0.0, "Red", "test", imagepath); 0179 KTRY_CAPTURE_CLICK(addToQueueB); 0180 // check if row has been added 0181 KTRY_CAPTURE_GADGET(QTableWidget, queueTable); 0182 QTRY_VERIFY_WITH_TIMEOUT(queueTable->rowCount() == 2, 1000); 0183 // wait to pause when second frame is running 0184 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0185 // start capture 0186 KTRY_CLICK(capture, startB); 0187 if (pausing) 0188 { 0189 // wait for first frame to be completed 0190 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 15000); 0191 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_PAUSED); 0192 QTest::qWait(1500); 0193 // press pause 0194 KTRY_CLICK(capture, pauseB); 0195 // wait until paused 0196 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 15000); 0197 // prepare next stage 0198 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0199 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_PAUSED); 0200 QTest::qWait(3000); 0201 // press continue 0202 KTRY_CLICK(capture, startB); 0203 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.size() <= 1, 15000); 0204 QTest::qWait(500); 0205 // press pause 0206 KTRY_CLICK(capture, pauseB); 0207 // wait until paused 0208 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 15000); 0209 // press continue 0210 QTest::qWait(3000); 0211 KTRY_CLICK(capture, startB); 0212 } 0213 // wait until completed 0214 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0215 // wait that all frames have been taken 0216 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 30000); 0217 0218 // check the log file if it holds the expected number 0219 QVERIFY(m_CaptureHelper->checkScriptRuns(count, 2)); 0220 } 0221 0222 void TestEkosCaptureWorkflow::testGuidingDeviationSuspendingCapture() 0223 { 0224 // default initialization 0225 QVERIFY(prepareTestCase()); 0226 0227 const double deviation_limit = 2.0; 0228 // switch to capture module 0229 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0230 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0231 // set guide deviation guard to < 2" 0232 KTRY_SET_CHECKBOX(capture, limitGuideDeviationS, true); 0233 KTRY_SET_DOUBLESPINBOX(capture, limitGuideDeviationN, deviation_limit); 0234 0235 // add target to path to emulate the behavior of the scheduler 0236 QString imagepath = getImageLocation()->path() + "/test"; 0237 // build a LRGB sequence 0238 KTRY_CAPTURE_ADD_LIGHT(30.0, 1, 5.0, "Luminance", "test", imagepath); 0239 KTRY_CAPTURE_ADD_LIGHT(30.0, 1, 5.0, "Red", "test", imagepath); 0240 KTRY_CAPTURE_ADD_LIGHT(30.0, 1, 5.0, "Green", "test", imagepath); 0241 KTRY_CAPTURE_ADD_LIGHT(30.0, 1, 5.0, "Blue", "test", imagepath); 0242 0243 // set a position in the west 0244 SkyPoint *target = new SkyPoint(); 0245 target->setAz(270.0); 0246 target->setAlt(KStarsData::Instance()->geo()->lat()->Degrees() / 2.0); 0247 // translate to equatorial coordinates 0248 const dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst()); 0249 const dms *lat = KStarsData::Instance()->geo()->lat(); 0250 target->HorizontalToEquatorial(&lst, lat); 0251 0252 m_CaptureHelper->slewTo(target->ra().Hours(), target->dec().Degrees(), true); 0253 0254 // clear calibration to ensure proper guiding 0255 KTRY_CLICK(Ekos::Manager::Instance()->guideModule(), clearCalibrationB); 0256 0257 // start guiding 0258 m_CaptureHelper->startGuiding(2.0); 0259 0260 // start capture 0261 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0262 KTRY_CLICK(capture, startB); 0263 // wait until capturing starts 0264 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 10000); 0265 // wait for settling 0266 QTest::qWait(2000); 0267 // create a guide drift 0268 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_SUSPENDED); 0269 Ekos::Manager::Instance()->mountModule()->doPulse(RA_INC_DIR, 2000, DEC_INC_DIR, 2000); 0270 qCInfo(KSTARS_EKOS_TEST()) << "Sent 2000ms RA+DEC guiding pulses."; 0271 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0272 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 30000); 0273 // expect that capturing continues 0274 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_CAPTURING, 60000); 0275 // verify that capture starts only once 0276 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_PROGRESS); 0277 QTest::qWait(20000); 0278 QVERIFY2(m_CaptureHelper->expectedCaptureStates.size() > 0, "Multiple capture starts."); 0279 } 0280 0281 void TestEkosCaptureWorkflow::testGuidingDeviationAbortCapture() 0282 { 0283 // default initialization 0284 QVERIFY(prepareTestCase()); 0285 0286 const double deviation_limit = 2.0; 0287 // switch to capture module 0288 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0289 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0290 // set guide deviation guard to < 2" 0291 KTRY_SET_CHECKBOX(capture, limitGuideDeviationS, true); 0292 KTRY_SET_DOUBLESPINBOX(capture, limitGuideDeviationN, deviation_limit); 0293 0294 // add target to path to emulate the behavior of the scheduler 0295 QString imagepath = getImageLocation()->path() + "/test"; 0296 // build a simple 5xL sequence 0297 KTRY_CAPTURE_ADD_LIGHT(45.0, 5, 5.0, "Luminance", "", imagepath); 0298 // set Dubhe as target and slew there 0299 SkyObject *target = KStars::Instance()->data()->skyComposite()->findByName("Dubhe"); 0300 m_CaptureHelper->slewTo(target->ra().Hours(), target->dec().Degrees(), true); 0301 0302 // clear calibration to ensure proper guiding 0303 KTRY_CLICK(Ekos::Manager::Instance()->guideModule(), clearCalibrationB); 0304 0305 // start guiding 0306 m_CaptureHelper->startGuiding(2.0); 0307 0308 // start capture 0309 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0310 KTRY_CLICK(capture, startB); 0311 // wait until capturing starts 0312 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 10000); 0313 // wait for settling 0314 QTest::qWait(2000); 0315 // create a guide drift 0316 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_SUSPENDED); 0317 Ekos::Manager::Instance()->mountModule()->doPulse(RA_INC_DIR, 2000, DEC_INC_DIR, 2000); 0318 qCInfo(KSTARS_EKOS_TEST()) << "Sent 2000ms RA+DEC guiding pulses."; 0319 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0320 // wait that capturing gets suspended 0321 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 15000); 0322 // abort capturing 0323 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_ABORTED); 0324 KTRY_CLICK(capture, startB); 0325 // check that it has been aborted 0326 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 10000); 0327 // wait that the guiding deviation is below the limit and 0328 // verify that capture does not start 0329 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_PROGRESS); 0330 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuideDeviation() < deviation_limit, 60000); 0331 0332 QTest::qWait(20000); 0333 QVERIFY2(m_CaptureHelper->expectedCaptureStates.size() > 0, "Capture has been restarted although aborted."); 0334 } 0335 0336 void TestEkosCaptureWorkflow::testInitialGuidingLimitCapture() 0337 { 0338 // default initialization 0339 QVERIFY(prepareTestCase()); 0340 0341 const double deviation_limit = 2.0; 0342 QFETCH(double, exptime); 0343 // switch to capture module 0344 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0345 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0346 // set start guide deviation guard to < 2" but disable the other one 0347 KTRY_SET_CHECKBOX(capture, startGuiderDriftS, true); 0348 KTRY_SET_DOUBLESPINBOX(capture, startGuiderDriftN, deviation_limit); 0349 // create sequence with 10 sec delay 0350 QVERIFY(prepareCapture(0, 0, 0, 10)); 0351 // set Dubhe as target and slew there 0352 SkyObject *target = KStars::Instance()->data()->skyComposite()->findByName("Dubhe"); 0353 m_CaptureHelper->slewTo(target->ra().Hours(), target->dec().Degrees(), true); 0354 0355 // start guiding 0356 m_CaptureHelper->startGuiding(2.0); 0357 0358 for (int i = 1; i <= 2; i++) 0359 { 0360 // wait intially 5 seconds 0361 if (i == 1) 0362 QTest::qWait(5000); 0363 0364 // prepare to expect that capturing will start 0365 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0366 0367 // ensure that guiding is running 0368 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuidingStatus() == Ekos::GUIDE_GUIDING, 10000); 0369 0370 // create a guide drift 0371 Ekos::Manager::Instance()->mountModule()->doPulse(RA_INC_DIR, 2000, DEC_INC_DIR, 2000); 0372 qCInfo(KSTARS_EKOS_TEST()) << "Sent 2000ms RA+DEC guiding pulses."; 0373 0374 // wait until guide deviation is present 0375 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuideDeviation() > deviation_limit, 15000); 0376 0377 if (i == 1) 0378 { 0379 // start capture but expect it being suspended first 0380 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0381 KTRY_CLICK(capture, startB); 0382 } 0383 // verify that capturing does not start before the guide deviation is below the limit 0384 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuideDeviation() >= deviation_limit, 60000); 0385 // wait 3 seconds and then ensure that capture did not start 0386 QTest::qWait(3000); 0387 QTRY_VERIFY(m_CaptureHelper->expectedCaptureStates.size() > 0); 0388 // wait until guiding deviation is below the limit 0389 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuideDeviation() < deviation_limit, 60000); 0390 // wait until capturing starts 0391 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 30000); 0392 if (i < 2) 0393 { 0394 // in the first iteration wait until the capture completes 0395 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0396 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 1500 * exptime); 0397 } 0398 } 0399 } 0400 0401 void TestEkosCaptureWorkflow::testCaptureWaitingForTemperature() 0402 { 0403 // default initialization 0404 QVERIFY(prepareTestCase()); 0405 0406 // switch to capture module 0407 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0408 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0409 0410 // initial and target temperature 0411 QFETCH(double, initTemp); 0412 QFETCH(double, targetTemp); 0413 0414 // initialize the CCD temperature and wait until it is reached 0415 SET_INDI_VALUE_DOUBLE(m_CaptureHelper->m_CCDDevice, "CCD_TEMPERATURE", "CCD_TEMPERATURE_VALUE", initTemp); 0416 QTRY_VERIFY_WITH_TIMEOUT(std::abs(capture->temperatureOUT->text().toDouble()) <= Options::maxTemperatureDiff(), 60000); 0417 0418 // set target temperature 0419 KTRY_SET_DOUBLESPINBOX(capture, cameraTemperatureN, targetTemp); 0420 KTRY_SET_CHECKBOX(capture, cameraTemperatureS, true); 0421 0422 // build a simple 1xL sequence 0423 KTRY_CAPTURE_ADD_LIGHT(10.0, 5, 5.0, "Luminance", "test", getImageLocation()->path() + " / test"); 0424 // expect capturing state 0425 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0426 0427 // start capturing 0428 KTRY_CLICK(capture, startB); 0429 // check if capturing has started 0430 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0431 // check if the temperature is at the expected level 0432 QTRY_VERIFY2(std::abs(capture->temperatureOUT->text().toDouble() - targetTemp) <= Options::maxTemperatureDiff(), 0433 QString("Temperature %1°C not at the expected level of %2°C").arg(capture->temperatureOUT->text()).arg( 0434 targetTemp).toLocal8Bit()); 0435 0436 // stop capturing 0437 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_ABORTED); 0438 KTRY_CLICK(capture, startB); 0439 // check if capturing has stopped 0440 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 10000); 0441 0442 // restart again to check whether an already reached temperature is handled properly 0443 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0444 KTRY_CLICK(capture, startB); 0445 // check if capturing has started 0446 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 20000); 0447 // check if the temperature is at the expected level 0448 QTRY_VERIFY2(std::abs(capture->temperatureOUT->text().toDouble() - targetTemp) <= Options::maxTemperatureDiff(), 0449 QString("Temperature %1°C not at the expected level of %2°C").arg(capture->temperatureOUT->text()).arg( 0450 targetTemp).toLocal8Bit()); 0451 0452 // stop capturing 0453 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_ABORTED); 0454 KTRY_CLICK(capture, startB); 0455 // check if capturing has stopped 0456 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 10000); 0457 0458 // change temperature back to initial value 0459 SET_INDI_VALUE_DOUBLE(m_CaptureHelper->m_CCDDevice, "CCD_TEMPERATURE", "CCD_TEMPERATURE_VALUE", initTemp); 0460 QTRY_VERIFY_WITH_TIMEOUT(std::abs(capture->temperatureOUT->text().toDouble()) <= Options::maxTemperatureDiff(), 60000); 0461 0462 // start capturing for a second time 0463 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0464 KTRY_CLICK(capture, startB); 0465 // check if capturing has started 0466 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0467 // check if the temperature is at the expected level 0468 QTRY_VERIFY2(std::abs(capture->temperatureOUT->text().toDouble() - targetTemp) <= Options::maxTemperatureDiff(), 0469 QString("Temperature %1°C not at the expected level of %2°C").arg(capture->temperatureOUT->text()).arg( 0470 targetTemp).toLocal8Bit()); 0471 0472 } 0473 0474 void TestEkosCaptureWorkflow::testCaptureWaitingForRotator() 0475 { 0476 // use the rotator simulator 0477 m_CaptureHelper->m_RotatorDevice = "Rotator Simulator"; 0478 0479 // default initialization 0480 QVERIFY(prepareTestCase()); 0481 QSKIP("Skipping test after UI rework"); 0482 0483 // switch to capture module 0484 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0485 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0486 0487 // open the rotator dialog 0488 KTRY_CLICK(capture, rotatorB); 0489 0490 // ensure that the rotator dialog appears 0491 QWidget *rotatorDialog = nullptr; 0492 QTRY_VERIFY_WITH_TIMEOUT((rotatorDialog = Ekos::Manager::Instance()->findChild<QWidget *>("RotatorDialog")) != nullptr, 0493 10000); 0494 0495 // target angle rotation 0496 double targetAngle = 90.0; 0497 // set the target rotation angle 0498 KTRY_SET_DOUBLESPINBOX(rotatorDialog, CameraPA, targetAngle); 0499 // save it to the sequence job 0500 KTRY_SET_CHECKBOX(rotatorDialog, enforceJobPA, true); 0501 0502 // build a simple 1xL sequence 0503 KTRY_CAPTURE_ADD_LIGHT(30.0, 1, 5.0, "Luminance", "test", getImageLocation()->path() + "/test"); 0504 // expect capturing state 0505 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0506 0507 // set the rotation angle back 0508 CameraPA->setValue(0); 0509 // let the rotator rotate back for at least 3sec 0510 QTest::qWait(3000); 0511 0512 // start capturing 0513 KTRY_CLICK(capture, startB); 0514 // check if capturing has started 0515 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0516 0517 // KTRY_GADGET(rotatorDialog, QLineEdit, rawAngleOut); 0518 // QTRY_VERIFY2(fabs(rawAngleOut->text().toDouble() - targetAngle) * 60 <= Options::astrometryRotatorThreshold(), 0519 // QString("Rotator angle %1° not at the expected value of %2°").arg(rawAngleOut->text()).arg(targetAngle).toLocal8Bit()); 0520 QWARN("Since the rotator interface has changed, the correct rotator angle cannot be checked from the test case."); 0521 } 0522 0523 void TestEkosCaptureWorkflow::testFlatManualSource() 0524 { 0525 // default initialization 0526 QVERIFY(prepareTestCase()); 0527 0528 // switch to capture module 0529 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0530 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0531 0532 // use a test directory 0533 QString imagepath = getImageLocation()->path() + "/test"; 0534 0535 // switch capture type to flat so that we can set the calibration 0536 KTRY_SET_COMBO(capture, captureTypeS, "Flat"); 0537 // ensure that the filter wheel is configured 0538 KTRY_CAPTURE_GADGET(QComboBox, FilterPosCombo); 0539 // wait until filter combo box is filled 0540 QTRY_VERIFY_WITH_TIMEOUT(FilterPosCombo->count() > 0, 60000); 0541 // build a simple 1xL flat sequence 0542 KTRY_CAPTURE_ADD_FRAME("Flat", 1, 1, 0.0, "Luminance", "test", imagepath); 0543 // build a simple 1xL light sequence 0544 KTRY_CAPTURE_ADD_LIGHT(1, 1, 0.0, "Red", "test", imagepath); 0545 // click OK or Cancel? 0546 QFETCH(bool, clickModalOK); 0547 QFETCH(bool, clickModal2OK); 0548 if (clickModalOK) 0549 { 0550 // Expect a capture sequence 0551 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0552 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0553 KTRY_CLICK(capture, startB); 0554 // click OK in the modal dialog for covering the telescope 0555 CLOSE_MODAL_DIALOG(0); 0556 // check if one single frame is captured 0557 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0558 if (clickModal2OK) 0559 { 0560 // expect the light sequence 0561 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0562 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0563 // click OK in the modal dialog for uncovering the telescope 0564 CLOSE_MODAL_DIALOG(0); 0565 // check if one single light is captured 0566 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0567 } 0568 else 0569 { 0570 // this must not happen 0571 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0572 // click Cancel in the modal dialog for uncovering the telescope 0573 CLOSE_MODAL_DIALOG(1); 0574 // check if capturing has not been started 0575 KTRY_CAPTURE_GADGET(QPushButton, startB); 0576 // within 5 secs the job must be stopped ... 0577 QTRY_VERIFY_WITH_TIMEOUT(startB->icon().name() == QString("media-playback-start"), 5000); 0578 // ... and capturing has not been started 0579 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.size() > 0, 5000); 0580 } 0581 } 0582 else 0583 { 0584 // this must not happen 0585 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0586 // start flats capturing 0587 KTRY_CLICK(capture, startB); 0588 // click Cancel in the modal dialog for covering the telescope 0589 CLOSE_MODAL_DIALOG(1); 0590 // check if capturing has not been started 0591 KTRY_CAPTURE_GADGET(QPushButton, startB); 0592 // within 5 secs the job mus be stopped ... 0593 QTRY_VERIFY_WITH_TIMEOUT(startB->icon().name() == QString("media-playback-start"), 5000); 0594 // ... and capturing has not been started 0595 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.size() > 0, 5000); 0596 } 0597 } 0598 0599 0600 void TestEkosCaptureWorkflow::testLightPanelSource() 0601 { 0602 // use the light panel simulator 0603 m_CaptureHelper->m_LightPanelDevice = "Light Panel Simulator"; 0604 // default initialization 0605 QVERIFY(prepareTestCase()); 0606 0607 // switch to capture module 0608 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0609 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0610 0611 // use a test directory for flats 0612 QString imagepath = getImageLocation()->path() + "/test"; 0613 0614 // switch capture type to the selected type so that we can set the calibration 0615 QFETCH(QString, frametype); 0616 KTRY_SET_COMBO(capture, captureTypeS, frametype); 0617 0618 // select internal or external flat light 0619 // build a simple 1xL sequence 0620 KTRY_CAPTURE_ADD_FRAME(frametype, 1, 1, 0.0, "Luminance", "test", imagepath); 0621 // build a simple 1xL light sequence 0622 KTRY_CAPTURE_ADD_LIGHT(1, 1, 0.0, "Red", "test", imagepath); 0623 0624 // start the sequence 0625 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0626 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0627 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0628 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0629 KTRY_CLICK(capture, startB); 0630 // check if one single flat is captured 0631 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0632 } 0633 0634 0635 void TestEkosCaptureWorkflow::testDustcapSource() 0636 { 0637 // use the Flip Flat in simulator mode both as light source and as dust cap 0638 m_CaptureHelper->m_DustCapDevice = "Flip Flat"; 0639 m_CaptureHelper->m_LightPanelDevice = "Flip Flat"; 0640 0641 Ekos::Manager * const ekos = Ekos::Manager::Instance(); 0642 0643 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(ekos->setupTab, 1000); 0644 QVERIFY(m_CaptureHelper->setupEkosProfile("Simulators", false)); 0645 // start the profile 0646 KTRY_EKOS_CLICK(processINDIB); 0647 0648 // wait until the disconnect button is enabled which shows that INDI has started 0649 KTRY_GADGET(ekos, QAbstractButton, disconnectB); 0650 QTRY_VERIFY_WITH_TIMEOUT(disconnectB->isEnabled(), 10000); 0651 0652 // enable simulation 0653 SET_INDI_VALUE_SWITCH("Flip Flat", "SIMULATION", "ENABLE", true); 0654 // connect 0655 SET_INDI_VALUE_SWITCH("Flip Flat", "CONNECTION", "CONNECT", true); 0656 // park 0657 SET_INDI_VALUE_SWITCH("Flip Flat", "CAP_PARK", "PARK", true); 0658 // turn light off 0659 SET_INDI_VALUE_SWITCH("Flip Flat", "FLAT_LIGHT_CONTROL", "FLAT_LIGHT_OFF", true); 0660 0661 // Now all devices should be up and running 0662 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->indiStatus() == Ekos::Success, 10000); 0663 0664 // init the helper 0665 m_CaptureHelper->init(); 0666 0667 // prepare optical trains for testing 0668 m_CaptureHelper->prepareOpticalTrains(); 0669 0670 // receive status updates from all devices 0671 m_CaptureHelper->connectModules(); 0672 0673 // switch to capture module 0674 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0675 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0676 0677 // use a test directory for flats 0678 QString imagepath = getImageLocation()->path() + "/test"; 0679 0680 // switch capture type to flat so that we can set the calibration 0681 KTRY_SET_COMBO(capture, captureTypeS, "Flat"); 0682 QTRY_VERIFY_WITH_TIMEOUT(captureTypeS->findText("Flat", Qt::MatchExactly) >= 0, 5000); 0683 0684 // select frame type and internal or external flat light 0685 QFETCH(QString, frametype); 0686 0687 // build a simple 1xL sequence 0688 KTRY_CAPTURE_ADD_FRAME(frametype, 1, 1, 0.0, "Luminance", "test", imagepath); 0689 // build a simple 1xL light sequence 0690 KTRY_CAPTURE_ADD_LIGHT(1, 1, 0.0, "Red", "test", imagepath); 0691 0692 // start the sequence 0693 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0694 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0695 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0696 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0697 KTRY_CLICK(capture, startB); 0698 // check if one single flat is captured 0699 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0700 } 0701 0702 0703 void TestEkosCaptureWorkflow::testWallSource() 0704 { 0705 // use the light panel simulator 0706 m_CaptureHelper->m_LightPanelDevice = "Light Panel Simulator"; 0707 // default initialization 0708 QVERIFY(prepareTestCase()); 0709 0710 // switch to capture module 0711 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0712 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0713 0714 // use a test directory for flats 0715 QString imagepath = getImageLocation()->path() + "/test"; 0716 0717 // switch capture type to flat so that we can set the calibration 0718 KTRY_SET_COMBO(capture, captureTypeS, "Flat"); 0719 0720 // select the wall as flat light source (az=90°, alt=0) 0721 KTRY_SELECT_FLAT_WALL(capture, "90", "0"); 0722 0723 // determine frame type 0724 QFETCH(QString, frametype); 0725 // build a simple 1xL sequence 0726 KTRY_CAPTURE_ADD_FRAME(frametype, 2, 1, 2.0, "Luminance", "test", imagepath); 0727 // build a simple 1xL light sequence 0728 KTRY_CAPTURE_ADD_LIGHT(1, 1, 0.0, "Red", "test", imagepath); 0729 // switch capture type to flat so that we can set the calibration 0730 captureTypeS->setCurrentText("Flat"); 0731 // add another sequence to check if wall source may be used twice 0732 // select another wall position as flat light source (az=0°, alt=0) 0733 KTRY_SELECT_FLAT_WALL(capture, "0", "0"); 0734 KTRY_CAPTURE_ADD_FRAME(frametype, 2, 1, 2.0, "Luminance", "test", imagepath); 0735 0736 // start the sequence 0737 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0738 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0739 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0740 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0741 m_CaptureHelper->expectedMountStates.append(ISD::Mount::MOUNT_SLEWING); 0742 m_CaptureHelper->expectedMountStates.append(ISD::Mount::MOUNT_IDLE); 0743 KTRY_CLICK(capture, startB); 0744 // check if mount has reached the expected position 0745 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedMountStates, 60000); 0746 // check if one single flat and one red frame is captured 0747 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0748 0749 // reset the sequence 0750 KTRY_CLICK(capture, resetB); 0751 // restart the sequence 0752 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0753 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0754 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0755 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0756 m_CaptureHelper->expectedMountStates.append(ISD::Mount::MOUNT_SLEWING); 0757 m_CaptureHelper->expectedMountStates.append(ISD::Mount::MOUNT_IDLE); 0758 KTRY_CLICK(capture, startB); 0759 // check if mount has reached the expected position 0760 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedMountStates, 60000); 0761 // check if one single flat and one red frame is captured 0762 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0763 0764 } 0765 0766 0767 //void TestEkosCaptureWorkflow::testPreMountAndDomePark() 0768 //{ 0769 // // use the light panel simulator 0770 // m_CaptureHelper->m_LightPanelDevice = "Light Panel Simulator"; 0771 // // use the dome simulator 0772 // m_CaptureHelper->m_DomeDevice = "Dome Simulator"; 0773 // // default initialization 0774 // QVERIFY(prepareTestCase()); 0775 0776 // // QSKIP("Observatory refactoring needs to be completed until this test can be activated."); 0777 0778 // // switch to capture module 0779 // Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0780 // KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0781 0782 // // use a test directory for flats 0783 // QString imagepath = getImageLocation()->path() + "/test"; 0784 0785 // // switch capture type to flat so that we can set the calibration 0786 // KTRY_SET_COMBO(capture, captureTypeS, "Flat"); 0787 0788 // // select internal flat light, pre-mount and but not pre-dome park 0789 // KTRY_SELECT_FLAT_METHOD(flatDeviceSourceC, true, false); 0790 // // determine frame type 0791 // QFETCH(QString, frametype); 0792 // // build a simple 1xL sequence 0793 // KTRY_CAPTURE_ADD_FRAME(frametype, 2, 1, 2.0, "Luminance", imagepath); 0794 0795 // // start the sequence 0796 // // m_CaptureHelper->expectedDomeStates.append(ISD::Dome::DOME_PARKED); 0797 // m_CaptureHelper->expectedMountStates.append(ISD::Mount::MOUNT_PARKED); 0798 // m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0799 // m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0800 // KTRY_CLICK(capture, startB); 0801 // // check if mount has reached the expected position 0802 // KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedMountStates, 30000); 0803 // // check if dome has reached the expected position 0804 // KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedDomeStates, 30000); 0805 // // check if one single flat is captured 0806 // KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0807 //} 0808 0809 void TestEkosCaptureWorkflow::testFlatSyncFocus() 0810 { 0811 // use the light panel simulator and focuser simulator 0812 m_CaptureHelper->m_LightPanelDevice = "Light Panel Simulator"; 0813 m_CaptureHelper->m_FocuserDevice = "Focuser Simulator"; 0814 // default initialization 0815 QVERIFY(prepareTestCase()); 0816 // set flat sync 0817 Options::setFlatSyncFocus(true); 0818 // run autofocus 0819 QVERIFY(m_CaptureHelper->executeFocusing()); 0820 0821 Ekos::Focus *focus = Ekos::Manager::Instance()->focusModule(); 0822 // update the initial focuser position 0823 KTRY_GADGET(Ekos::Manager::Instance()->focusModule(), QLineEdit, absTicksLabel); 0824 int focusPosition = absTicksLabel->text().toInt(); 0825 // move the focuser 100 steps out 0826 KTRY_SET_SPINBOX(focus, absTicksSpin, focusPosition + 100); 0827 // click goto 0828 KTRY_CLICK(focus, startGotoB); 0829 // check if new position has been reached 0830 QTRY_VERIFY_WITH_TIMEOUT(absTicksLabel->text().toInt() == focusPosition + 100, 5000); 0831 0832 // capture flats with light panel source (simplest way to test) 0833 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0834 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0835 0836 // use a test directory for flats 0837 QString imagepath = getImageLocation()->path() + "/test"; 0838 0839 // switch capture type to flat so that we can set the calibration 0840 KTRY_SET_COMBO(capture, captureTypeS, "Flat"); 0841 0842 // build a simple 5xL sequence 0843 KTRY_CAPTURE_CONFIGURE_FLAT(2, 1, 2.0, "Luminance", imagepath); 0844 0845 // start the sequence 0846 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0847 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0848 KTRY_CLICK(capture, startB); 0849 // check if one single flat is captured 0850 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0851 // check if the focuser is at the determined focus position 0852 QTRY_VERIFY_WITH_TIMEOUT(absTicksLabel->text().toInt() == focusPosition, 5000); 0853 } 0854 0855 void TestEkosCaptureWorkflow::testDarkManualCovering() 0856 { 0857 // default initialization 0858 QVERIFY(prepareTestCase()); 0859 0860 // switch to capture module 0861 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0862 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0863 0864 // use a test directory for darks 0865 QString imagepath = getImageLocation()->path() + "/test"; 0866 0867 // switch capture type to flat so that we can set the calibration 0868 KTRY_CAPTURE_GADGET(QComboBox, captureTypeS); 0869 KTRY_CAPTURE_COMBO_SET(captureTypeS, "Dark"); 0870 0871 // build a simple 1xBlue dark sequence 0872 KTRY_CAPTURE_ADD_FRAME("Dark", 1, 1, 0.0, "Blue", "test", imagepath); 0873 // build a simple 1xL light sequence 0874 KTRY_CAPTURE_ADD_LIGHT(1, 1, 0.0, "Red", "test", imagepath); 0875 // shutter type 0876 QFETCH(int, shutter); 0877 // click OK or Cancel? 0878 QFETCH(bool, clickModalOK); 0879 QFETCH(bool, clickModal2OK); 0880 0881 // prepare shutter settings 0882 QStringList shutterfulCCDs; 0883 QStringList shutterlessCCDs; 0884 if (shutter == SHUTTER_NO) 0885 shutterlessCCDs.append(m_CaptureHelper->m_CCDDevice); 0886 else if (shutter == SHUTTER_YES) 0887 shutterfulCCDs.append(m_CaptureHelper->m_CCDDevice); 0888 // set the option values 0889 Options::setShutterfulCCDs(shutterfulCCDs); 0890 Options::setShutterlessCCDs(shutterlessCCDs); 0891 0892 // if the camera has a shutter, no manual cover is required 0893 if (clickModalOK) 0894 { 0895 // start the flat sequence 0896 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0897 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IDLE); 0898 KTRY_CLICK(capture, startB); 0899 // if shutter type unknown, answer the the modal dialog with "No" 0900 if (shutter == SHUTTER_UNKNOWN) 0901 CLOSE_MODAL_DIALOG(1); 0902 // click OK in the modal dialog for covering the telescope if camera has no shutter 0903 if (shutter != SHUTTER_YES) 0904 CLOSE_MODAL_DIALOG(0); 0905 // check if one single flat is captured 0906 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0907 if (clickModal2OK) 0908 { 0909 // expect the light sequence 0910 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0911 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0912 // click OK in the modal dialog for uncovering the telescope 0913 CLOSE_MODAL_DIALOG(0); 0914 // check if one single light is captured 0915 KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 60000); 0916 } 0917 else 0918 { 0919 // this must not happen 0920 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0921 // click Cancel in the modal dialog for uncovering the telescope 0922 CLOSE_MODAL_DIALOG(1); 0923 // check if capturing has not been started 0924 KTRY_CAPTURE_GADGET(QPushButton, startB); 0925 // within 5 secs the job must be stopped ... 0926 QTRY_VERIFY_WITH_TIMEOUT(startB->icon().name() == QString("media-playback-start"), 5000); 0927 // ... and capturing has not been started 0928 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.size() > 0, 5000); 0929 } 0930 } 0931 else 0932 { 0933 // this must not happen 0934 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_CAPTURING); 0935 // start flats capturing 0936 KTRY_CLICK(capture, startB); 0937 // click Cancel in the modal dialog for covering the telescope 0938 CLOSE_MODAL_DIALOG(1); 0939 // check if capturing has not been started 0940 KTRY_CAPTURE_GADGET(QPushButton, startB); 0941 // within 5 secs the job mus be stopped ... 0942 QTRY_VERIFY_WITH_TIMEOUT(startB->icon().name() == QString("media-playback-start"), 5000); 0943 // ... and capturing has not been started 0944 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.size() > 0, 5000); 0945 } 0946 } 0947 0948 0949 void TestEkosCaptureWorkflow::testDarksLibrary() 0950 { 0951 // default initialization 0952 QVERIFY(prepareTestCase()); 0953 0954 // ensure that we know that the CCD has a shutter 0955 m_CaptureHelper->ensureCCDShutter(true); 0956 0957 // switch to capture module 0958 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0959 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0960 0961 // open the darks library dialog 0962 KTRY_CLICK(capture, darkLibraryB); 0963 QWidget *darkLibraryDialog = nullptr; 0964 QTRY_VERIFY_WITH_TIMEOUT(darkLibraryDialog = Ekos::Manager::Instance()->findChild<QWidget *>("DarkLibrary"), 2000); 0965 0966 // select the primary train for darks capturing 0967 KTRY_SET_COMBO(darkLibraryDialog, opticalTrainCombo, m_CaptureHelper->m_primaryTrain); 0968 0969 // set dark library values to 3x1s darks 0970 KTRY_SET_DOUBLESPINBOX(darkLibraryDialog, maxExposureSpin, 1); 0971 KTRY_SET_SPINBOX(darkLibraryDialog, countSpin, 3); 0972 // expect exactly 3 frames 0973 for (int i = 0; i < 3; i++) 0974 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_IMAGE_RECEIVED); 0975 m_CaptureHelper->expectedCaptureStates.append(Ekos::CAPTURE_COMPLETE); 0976 // start 0977 KTRY_CLICK(darkLibraryDialog, startB); 0978 // wait until completion 0979 QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates.isEmpty(), 10000); 0980 // check if master frame has been created 0981 QFileInfo destinationInfo(QStandardPaths::writableLocation(QStandardPaths::DataLocation), "darks"); 0982 QDir destination(destinationInfo.absoluteFilePath()); 0983 QVERIFY(m_CaptureHelper->searchFITS(destination).size() == 1); 0984 } 0985 0986 void TestEkosCaptureWorkflow::testLoadEsqFileGeneral() 0987 { 0988 // default initialization 0989 QVERIFY(prepareTestCase()); 0990 0991 // switch to capture module 0992 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 0993 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 0994 0995 // initialize the capture settings 0996 QFETCH(uint, esqVersion); 0997 QFETCH(QString, observer); 0998 QFETCH(bool, guideDeviation); 0999 QFETCH(bool, startGuideDeviation); 1000 QFETCH(bool, inSequenceFocus); 1001 QFETCH(bool, autofocusOnTemperature); 1002 QFETCH(bool, refocusEveryN); 1003 QFETCH(bool, refocusAfterMeridianFlip); 1004 TestEkosCaptureHelper::CaptureSettings settings; 1005 settings.observer = observer; 1006 settings.guideDeviation = {guideDeviation, 2.0}; 1007 settings.startGuideDeviation = {startGuideDeviation, 1.0}; 1008 settings.inSequenceFocus = {inSequenceFocus, 1.5}; 1009 settings.autofocusOnTemperature = {autofocusOnTemperature, 3.3}; 1010 settings.refocusEveryN = {refocusEveryN, 5}; 1011 settings.refocusAfterMeridianFlip = refocusAfterMeridianFlip; 1012 1013 // clear current values to ensure that we observe a change 1014 QString oldObserver("unknown"); 1015 capture->setObserverName(oldObserver); 1016 KTRY_SET_DOUBLESPINBOX(capture, limitGuideDeviationN, 0.0); 1017 KTRY_SET_CHECKBOX(capture, limitGuideDeviationS, !settings.guideDeviation.enabled); 1018 KTRY_SET_DOUBLESPINBOX(capture, startGuiderDriftN, 0.0); 1019 KTRY_SET_CHECKBOX(capture, startGuiderDriftS, !settings.startGuideDeviation.enabled); 1020 KTRY_SET_DOUBLESPINBOX(capture, limitFocusHFRN, 0.1); 1021 KTRY_SET_CHECKBOX(capture, limitFocusHFRS, !settings.guideDeviation.enabled); 1022 KTRY_SET_DOUBLESPINBOX(capture, limitFocusDeltaTN, 0.2); 1023 KTRY_SET_CHECKBOX(capture, limitFocusDeltaTS, !settings.autofocusOnTemperature.enabled); 1024 KTRY_SET_SPINBOX(capture, limitRefocusN, 100); 1025 KTRY_SET_CHECKBOX(capture, limitRefocusS, !settings.refocusEveryN.enabled); 1026 KTRY_SET_CHECKBOX(capture, meridianRefocusS, !settings.refocusAfterMeridianFlip); 1027 1028 // create capture sequence file 1029 TestEkosCaptureHelper::SimpleCaptureLightsJob job; 1030 QVector<TestEkosCaptureHelper::SimpleCaptureLightsJob> jobs; 1031 jobs.append(job); 1032 QStringList content = m_CaptureHelper->getSimpleEsqContent(settings, jobs, 1033 static_cast<TestEkosCaptureHelper::ESQVersion>(esqVersion)); 1034 QString esqFilename = destination->filePath("test.esq"); 1035 qCInfo(KSTARS_EKOS_TEST) << "Sequence file name: " << esqFilename; 1036 m_CaptureHelper->writeFile(esqFilename, content); 1037 1038 // load the capture sequence file 1039 QVERIFY2(capture->loadSequenceQueue(esqFilename), "Loading capture sequence file failed!"); 1040 1041 // Verify the results 1042 QCOMPARE(capture->getObserverName(), settings.observer); 1043 QCOMPARE(limitGuideDeviationS->isChecked(), settings.guideDeviation.enabled); 1044 QCOMPARE(limitGuideDeviationN->value(), settings.guideDeviation.value); 1045 QCOMPARE(startGuiderDriftS->isChecked(), settings.startGuideDeviation.enabled); 1046 QCOMPARE(startGuiderDriftN->value(), settings.startGuideDeviation.value); 1047 QCOMPARE(limitFocusHFRS->isChecked(), settings.inSequenceFocus.enabled); 1048 QCOMPARE(limitFocusHFRN->value(), settings.inSequenceFocus.value); 1049 QCOMPARE(limitFocusDeltaTS->isChecked(), settings.autofocusOnTemperature.enabled); 1050 QCOMPARE(limitFocusDeltaTN->value(), settings.autofocusOnTemperature.value); 1051 QCOMPARE(limitRefocusS->isChecked(), settings.refocusEveryN.enabled); 1052 QCOMPARE(limitRefocusN->value(), settings.refocusEveryN.value); 1053 QCOMPARE(meridianRefocusS->isChecked(), settings.refocusAfterMeridianFlip); 1054 } 1055 1056 void TestEkosCaptureWorkflow::testLoadEsqFileBasicJobSettings() 1057 { 1058 // default initialization 1059 QVERIFY(prepareTestCase()); 1060 1061 // switch to capture module 1062 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 1063 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 1064 1065 // initialize default settings 1066 TestEkosCaptureHelper::CaptureSettings settings = {"Test Observer", {true, 2.0}, {true, 1.0}, {false, 1.5}, {true, 1.0}, {false, 5}, false}; 1067 1068 // clear the UI settings 1069 KTRY_SET_DOUBLESPINBOX(capture, captureExposureN, 1.0); 1070 KTRY_SET_SPINBOX(capture, captureCountN, 1); 1071 KTRY_SET_SPINBOX(capture, captureDelayN, 0); 1072 KTRY_SET_SPINBOX(capture, captureBinHN, 1); 1073 KTRY_SET_SPINBOX(capture, captureBinVN, 1); 1074 KTRY_SET_SPINBOX(capture, captureFrameXN, 0); 1075 KTRY_SET_SPINBOX(capture, captureFrameYN, 0); 1076 KTRY_SET_SPINBOX(capture, captureFrameWN, 500); 1077 KTRY_SET_SPINBOX(capture, captureFrameHN, 500); 1078 KTRY_SET_COMBO(capture, FilterPosCombo, "Blue"); 1079 KTRY_SET_COMBO(capture, captureEncodingS, "FITS"); 1080 KTRY_SET_COMBO(capture, captureTypeS, "Dark"); 1081 KTRY_SET_LINEEDIT(capture, targetNameT, "nothing"); 1082 KTRY_SET_LINEEDIT(capture, fileDirectoryT, "/home/pi"); 1083 KTRY_SET_LINEEDIT(capture, placeholderFormatT, "/%T"); 1084 KTRY_SET_SPINBOX(capture, formatSuffixN, 1); 1085 KTRY_SET_DOUBLESPINBOX(capture, cameraTemperatureN, 10.0); 1086 KTRY_SET_CHECKBOX(capture, cameraTemperatureS, false); 1087 KTRY_SET_COMBO_INDEX(capture, fileUploadModeS, 1); 1088 1089 // create the job 1090 TestEkosCaptureHelper::SimpleCaptureLightsJob job; 1091 QFETCH(uint, esqVersion); 1092 job.version = static_cast<TestEkosCaptureHelper::ESQVersion>(esqVersion); 1093 QFETCH(double, exposureTime); 1094 job.exposureTime = exposureTime; 1095 QFETCH(QString, targetName); 1096 job.targetName = targetName; 1097 QFETCH(int, count); 1098 job.count = count; 1099 QFETCH(int, delay); 1100 job.delayMS = delay; 1101 QFETCH(int, binX); 1102 job.binX = binX; 1103 QFETCH(int, binY); 1104 job.binY = binY; 1105 QFETCH(int, x); 1106 job.x = x; 1107 QFETCH(int, y); 1108 job.y = y; 1109 QFETCH(int, w); 1110 job.w = w; 1111 QFETCH(int, h); 1112 job.h = h; 1113 QFETCH(QString, filter); 1114 job.filterName = filter; 1115 QFETCH(QString, type); 1116 job.type = type; 1117 QFETCH(QString, encoding); 1118 job.encoding = encoding; 1119 QFETCH(QString, fitsDirectory); 1120 job.fitsDirectory = fitsDirectory; 1121 QFETCH(int, formatSuffix); 1122 job.formatSuffix = formatSuffix; 1123 QFETCH(QString, placeholderFormat); 1124 job.placeholderFormat = placeholderFormat; 1125 QFETCH(double, cameraTemperature); 1126 job.cameraTemperature.value = cameraTemperature; 1127 QFETCH(bool, cameraCooling); 1128 job.cameraTemperature.enabled = cameraCooling; 1129 QFETCH(int, fileUploadMode); 1130 job.uploadMode = fileUploadMode; 1131 1132 QVector<TestEkosCaptureHelper::SimpleCaptureLightsJob> jobs; 1133 jobs.append(job); 1134 // create capture sequence file 1135 QStringList content = m_CaptureHelper->getSimpleEsqContent(settings, jobs); 1136 QString esqFilename = destination->filePath("test.esq"); 1137 qCInfo(KSTARS_EKOS_TEST) << "Sequence file name: " << esqFilename; 1138 m_CaptureHelper->writeFile(esqFilename, content); 1139 1140 // load the capture sequence file 1141 QVERIFY2(capture->loadSequenceQueue(esqFilename), "Loading capture sequence file failed!"); 1142 1143 // Verify the results 1144 QTRY_COMPARE(captureExposureN->value(), exposureTime); 1145 QTRY_COMPARE(captureCountN->value(), count); 1146 QTRY_COMPARE(captureDelayN->value(), delay / 1000); 1147 QTRY_COMPARE(captureBinHN->value(), binX); 1148 QTRY_COMPARE(captureBinVN->value(), binY); 1149 QTRY_COMPARE(captureFrameXN->value(), x); 1150 QTRY_COMPARE(captureFrameYN->value(), y); 1151 QTRY_COMPARE(captureFrameWN->value(), w); 1152 QTRY_COMPARE(captureFrameHN->value(), h); 1153 QTRY_COMPARE(FilterPosCombo->currentText(), filter); 1154 QTRY_COMPARE(captureTypeS->currentText(), type); 1155 QTRY_COMPARE(captureEncodingS->currentText(), encoding); 1156 QTRY_COMPARE(targetNameT->text(), esqVersion == TestEkosCaptureHelper::ESQ_VERSION_2_5 ? "Test Target" : targetName); 1157 QTRY_COMPARE(fileDirectoryT->text(), fitsDirectory); 1158 QTRY_COMPARE(placeholderFormatT->text(), placeholderFormat); 1159 QTRY_COMPARE(formatSuffixN->value(), formatSuffix); 1160 QTRY_COMPARE(cameraTemperatureN->value(), cameraTemperature); 1161 QTRY_COMPARE(cameraTemperatureS->isChecked(), cameraCooling); 1162 QTRY_COMPARE(fileUploadModeS->currentIndex(), fileUploadMode); 1163 } 1164 1165 1166 void TestEkosCaptureWorkflow::testLoadEsqFileCalibrationSettings() 1167 { 1168 // default initialization 1169 QVERIFY(prepareTestCase()); 1170 1171 // switch to capture module 1172 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 1173 KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000); 1174 1175 // initialize default settings 1176 TestEkosCaptureHelper::CaptureSettings settings = {"Test Observer", {true, 2.0}, {true, 1.0}, {false, 1.5}, {true, 1.0}, {false, 5}, false}; 1177 1178 // retrieve test data 1179 QFETCH(uint, esqVersion); 1180 QFETCH(double, exposureTime); 1181 QFETCH(int, count); 1182 QFETCH(QString, type); 1183 QFETCH(uint, pre_action); 1184 QFETCH(double, wall_az); 1185 QFETCH(double, wall_alt); 1186 QFETCH(bool, duration_manual); 1187 QFETCH(bool, duration_adu); 1188 QFETCH(int, adu); 1189 QFETCH(int, tolerance); 1190 1191 // clear the UI settings 1192 KTRY_SET_DOUBLESPINBOX(capture, captureExposureN, 5.4); 1193 KTRY_SET_COMBO(capture, captureTypeS, (type == "Flat" ? "Dark" : "Flat")); 1194 KTRY_SET_SPINBOX(capture, captureCountN, 2 + count); 1195 1196 // create the job 1197 TestEkosCaptureHelper::SimpleCaptureCalibratingJob job; 1198 job.version = static_cast<TestEkosCaptureHelper::ESQVersion>(esqVersion); 1199 job.exposureTime = exposureTime; 1200 job.type = type; 1201 job.count = count; 1202 job.preAction = pre_action; 1203 job.wall_az = wall_az; 1204 job.wall_alt = wall_alt; 1205 job.duration_manual = duration_manual; 1206 job.duration_adu = duration_adu; 1207 job.adu = adu; 1208 job.tolerance = tolerance; 1209 1210 QVector<TestEkosCaptureHelper::SimpleCaptureCalibratingJob> jobs; 1211 jobs.append(job); 1212 // create capture sequence file 1213 QStringList content = m_CaptureHelper->getSimpleEsqContent(settings, jobs, 1214 static_cast<TestEkosCaptureHelper::ESQVersion>(esqVersion)); 1215 QString esqFilename = destination->filePath("test.esq"); 1216 qCInfo(KSTARS_EKOS_TEST) << "Sequence file name: " << esqFilename; 1217 m_CaptureHelper->writeFile(esqFilename, content); 1218 1219 // load the capture sequence file 1220 QVERIFY2(capture->loadSequenceQueue(esqFilename), "Loading capture sequence file failed!"); 1221 1222 // Verify the results on the main tab 1223 QTRY_COMPARE(captureExposureN->value(), exposureTime); 1224 QTRY_COMPARE(captureCountN->value(), count); 1225 QTRY_COMPARE(captureTypeS->currentText(), type); 1226 1227 // Verify the results on the calibration dialog 1228 bool success = false; 1229 QTimer::singleShot(1000, capture, [&] { success = verifyCalibrationSettings(); }); 1230 KTRY_CLICK(capture, calibrationB); 1231 1232 QTRY_VERIFY_WITH_TIMEOUT(success, 10000); 1233 } 1234 1235 bool TestEkosCaptureWorkflow::verifyCalibrationSettings() 1236 { 1237 bool passed = false; 1238 QDialog *calibrationDialog = nullptr; 1239 KTRY_VERIFY_WITH_TIMEOUT_SUB(calibrationDialog = Ekos::Manager::Instance()->findChild<QDialog *>("calibrationOptions"), 1240 2000); 1241 // ensure that the cancel button is pressed in any case 1242 [&]() 1243 { 1244 QFETCH(uint, pre_action); 1245 QFETCH(double, wall_az); 1246 QFETCH(double, wall_alt); 1247 QFETCH(bool, duration_manual); 1248 QFETCH(bool, duration_adu); 1249 QFETCH(int, adu); 1250 QFETCH(int, tolerance); 1251 KTRY_GADGET(calibrationDialog, QCheckBox, gotoWallC); 1252 KTRY_GADGET(calibrationDialog, QCheckBox, parkMountC); 1253 KTRY_GADGET(calibrationDialog, QCheckBox, parkDomeC); 1254 KTRY_GADGET(calibrationDialog, dmsBox, azBox); 1255 KTRY_GADGET(calibrationDialog, dmsBox, altBox); 1256 KTRY_GADGET(calibrationDialog, QRadioButton, manualDurationC); 1257 KTRY_GADGET(calibrationDialog, QRadioButton, ADUC); 1258 KTRY_GADGET(calibrationDialog, QSpinBox, ADUValue); 1259 KTRY_GADGET(calibrationDialog, QSpinBox, ADUTolerance); 1260 QTRY_COMPARE(gotoWallC->isChecked(), (pre_action & ACTION_WALL) > 0); 1261 QTRY_COMPARE(parkMountC->isChecked(), (pre_action & ACTION_PARK_MOUNT) > 0); 1262 QTRY_COMPARE(parkDomeC->isChecked(), (pre_action & ACTION_PARK_DOME) > 0); 1263 1264 if (pre_action & ACTION_WALL) 1265 { 1266 dms wallAz, wallAlt; 1267 bool azOk = false, altOk = false; 1268 1269 wallAz = azBox->createDms(&azOk); 1270 wallAlt = altBox->createDms(&altOk); 1271 1272 QTRY_COMPARE(wallAz.Degrees(), wall_az); 1273 QTRY_COMPARE(wallAlt.Degrees(), wall_alt); 1274 } 1275 QTRY_COMPARE(manualDurationC->isChecked(), duration_manual); 1276 QTRY_COMPARE(ADUC->isChecked(), duration_adu); 1277 if (duration_adu) 1278 { 1279 QTRY_COMPARE(ADUValue->value(), adu); 1280 QTRY_COMPARE(ADUTolerance->value(), tolerance); 1281 } 1282 passed = true; 1283 } 1284 (); 1285 // cancel the dialog 1286 calibrationDialog->done(QDialog::Rejected); 1287 1288 return passed; 1289 } 1290 1291 1292 /* ********************************************************************************* 1293 * 1294 * Test data 1295 * 1296 * ********************************************************************************* */ 1297 1298 void TestEkosCaptureWorkflow::testCaptureRefocusDelay_data() 1299 { 1300 prepareTestData(31.0, {"Luminance:3"}); 1301 } 1302 1303 void TestEkosCaptureWorkflow::testCaptureRefocusHFR_data() 1304 { 1305 prepareTestData(10.0, {"Luminance:6"}); 1306 } 1307 1308 void TestEkosCaptureWorkflow::testCaptureRefocusTemperature_data() 1309 { 1310 prepareTestData(10.0, {"Luminance:6"}); 1311 } 1312 1313 void TestEkosCaptureWorkflow::testCaptureRefocusAbort_data() 1314 { 1315 prepareTestData(31.0, {"Luminance:3"}); 1316 } 1317 1318 void TestEkosCaptureWorkflow::testCaptureScriptsExecution_data() 1319 { 1320 QTest::addColumn<bool>("pausing"); /*!< pause between capturing */ 1321 QTest::newRow("pausing=false") << false; 1322 QTest::newRow("pausing=true") << true; 1323 } 1324 1325 void TestEkosCaptureWorkflow::testInitialGuidingLimitCapture_data() 1326 { 1327 prepareTestData(20.0, {"Luminance:5"}); 1328 } 1329 1330 void TestEkosCaptureWorkflow::testFlatManualSource_data() 1331 { 1332 QTest::addColumn<bool>("clickModalOK"); /*!< click "OK" on the modal dialog */ 1333 QTest::addColumn<bool>("clickModal2OK"); /*!< click "OK" on the second modal dialog */ 1334 1335 // both variants for second click: click OK and click Cancel 1336 QTest::newRow("Flat, modal=true/true") << true << true; 1337 QTest::newRow("Flat, modal=true/false") << true << false; 1338 // first click Cancel 1339 QTest::newRow("Flat, modal=false") << false << true; 1340 } 1341 1342 void TestEkosCaptureWorkflow::testLightPanelSource_data() 1343 { 1344 QTest::addColumn<QString>("frametype"); /*!< frame type (Bias, Dark, Flat) */ 1345 QTest::addColumn<bool>("internalLight"); /*!< use internal or external flat light */ 1346 1347 for (auto frametype : 1348 { 1349 "Flat", "Dark", "Bias" 1350 }) 1351 for (auto internalLight : // light source integrated into the light panel? 1352 { 1353 true, false 1354 }) 1355 QTest::newRow(QString("%1, light=%2").arg(frametype).arg(internalLight ? "internal" : "external").toLatin1()) 1356 << frametype << internalLight; 1357 } 1358 1359 void TestEkosCaptureWorkflow::testDustcapSource_data() 1360 { 1361 QTest::addColumn<QString>("frametype"); /*!< frame type (Dark or Flat) */ 1362 1363 // QTest::newRow("Flat, light=internal") << "Flat" << true; // flat + light source integrated into the light panel 1364 QTest::newRow("Flat, light=internal") << "Flat"; // flat + internal light source used 1365 QTest::newRow("Dark, light=internal") << "Dark"; // dark + external light source turned off 1366 QTest::newRow("Bias, light=internal") << "Bias"; // dark + external light source turned off 1367 // QTest::newRow("Dark") << "Dark" << false; // dark 1368 } 1369 1370 void TestEkosCaptureWorkflow::testWallSource_data() 1371 { 1372 QTest::addColumn<QString>("frametype"); /*!< frame type (Dark, Flat or bias) */ 1373 1374 QTest::newRow("Flat") << "Flat"; 1375 QTest::newRow("Dark") << "Dark"; 1376 QTest::newRow("Bias") << "Bias"; 1377 } 1378 1379 1380 //void TestEkosCaptureWorkflow::testPreMountAndDomePark_data() 1381 //{ 1382 // testWallSource_data(); 1383 //} 1384 1385 void TestEkosCaptureWorkflow::testDarkManualCovering_data() 1386 { 1387 QTest::addColumn<int>("shutter"); /*!< does the CCD have a shutter? */ 1388 QTest::addColumn<bool>("clickModalOK"); /*!< click "OK" on the modal dialog */ 1389 QTest::addColumn<bool>("clickModal2OK"); /*!< click "OK" on the second modal dialog */ 1390 1391 // all shutter types plus both variants: click OK and click Cancel 1392 QTest::newRow("shutter=? modal=true") << SHUTTER_UNKNOWN << true << true; 1393 QTest::newRow("shutter=yes modal=true") << SHUTTER_YES << true << true; 1394 QTest::newRow("shutter=no modal=true") << SHUTTER_NO << true << true; 1395 QTest::newRow("modal=true") << SHUTTER_NO << true << false; 1396 QTest::newRow("modal=false") << SHUTTER_NO << false << true; 1397 } 1398 1399 void TestEkosCaptureWorkflow::testCaptureWaitingForTemperature_data() 1400 { 1401 QTest::addColumn<double>("initTemp"); /*!< Initial temperature value */ 1402 QTest::addColumn<double>("targetTemp"); /*!< Target temperature value */ 1403 1404 QTest::newRow("init=0 target=-5") << 0.0 << -5.0; 1405 QTest::newRow("init=0 target=0") << 0.0 << 0.0; 1406 } 1407 1408 void TestEkosCaptureWorkflow::testLoadEsqFileGeneral_data() 1409 { 1410 QTest::addColumn<uint>("esqVersion"); /*!< ESQ XML version */ 1411 QTest::addColumn<QString>("observer"); /*!< Set the observer value */ 1412 QTest::addColumn<bool>("guideDeviation"); /*!< Enable guide deviation */ 1413 QTest::addColumn<bool>("startGuideDeviation"); /*!< Enable starting guide deviation */ 1414 QTest::addColumn<bool>("inSequenceFocus"); /*!< Enable in sequence focusing (HFR based) */ 1415 QTest::addColumn<bool>("autofocusOnTemperature"); /*!< Enable temperature based autofocus */ 1416 QTest::addColumn<bool>("refocusEveryN"); /*!< Enable focusing after every n capture */ 1417 QTest::addColumn<bool>("refocusAfterMeridianFlip"); /*!< Enable refocus after a meridian flip */ 1418 1419 uint version = TestEkosCaptureHelper::ESQ_VERSION_2_6; 1420 QTest::newRow(QString("observer v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) 1421 << version << "KStars Freak" << false << false << false << false << false << false; 1422 QTest::newRow(QString("guideDeviation v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << version << 1423 "KStars Freak" << true << false << false << false << false << false; 1424 QTest::newRow(QString("startGuideDeviation v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << version 1425 << "KStars Freak" << false << true << false << false << false << false; 1426 QTest::newRow(QString("inSequenceFocus v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << version << 1427 "KStars Freak" << false << false << true << false << false << false; 1428 QTest::newRow(QString("autofocusOnTemperature v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << 1429 version << "KStars Freak" << false << false << false << true << false << false; 1430 QTest::newRow(QString("refocusEveryN v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << version << 1431 "KStars Freak" << false << false << false << false << true << false; 1432 QTest::newRow(QString("refocusAfterMeridianFlip v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << 1433 version << "KStars Freak" << false << false << false << false << false << true; 1434 } 1435 1436 void TestEkosCaptureWorkflow::testLoadEsqFileBasicJobSettings_data() 1437 { 1438 QTest::addColumn<uint>("esqVersion"); /*!< ESQ XML version */ 1439 QTest::addColumn<double>("exposureTime"); /*!< Exposure time */ 1440 QTest::addColumn<QString>("targetName"); /*!< Capture target */ 1441 QTest::addColumn<int>("count"); /*!< Number of frames */ 1442 QTest::addColumn<int>("delay"); /*!< Delay between captures */ 1443 QTest::addColumn<QString>("filter"); /*!< Filter name */ 1444 QTest::addColumn<QString>("type"); /*!< Frame type (Light etc.) */ 1445 QTest::addColumn<QString>("encoding"); /*!< Encoding (FITS etc.) */ 1446 QTest::addColumn<int>("binX"); /*!< Binning (X value) */ 1447 QTest::addColumn<int>("binY"); /*!< Binning (Y value) */ 1448 QTest::addColumn<int>("x"); /*!< ROI left */ 1449 QTest::addColumn<int>("y"); /*!< ROI top */ 1450 QTest::addColumn<int>("w"); /*!< ROI width */ 1451 QTest::addColumn<int>("h"); /*!< ROI height */ 1452 QTest::addColumn<QString>("fitsDirectory"); /*!< Base directory for frames */ 1453 QTest::addColumn<QString>("placeholderFormat"); /*!< Placeholder format string */ 1454 QTest::addColumn<int>("formatSuffix"); /*!< Digits of the number suffix */ 1455 QTest::addColumn<double>("cameraTemperature"); /*!< Cooling temperature */ 1456 QTest::addColumn<bool>("cameraCooling"); /*!< Cooling necessary */ 1457 QTest::addColumn<int>("fileUploadMode"); /*!< Upload mode (local/remote) */ 1458 1459 double exposureTime = 2.0, cameraTemperature = -20.0; 1460 int count = 2, delay = 5000, binX = 2, binY = 2; 1461 int x = 10, y = 10, w = 480, h = 360; 1462 int formatSuffix = 4, fileUploadMode = 2; 1463 bool cameraCooling = true; 1464 QString target("Test Target"); 1465 QString filter("Green"); 1466 QString type("Light"); 1467 QString encoding("Native"); 1468 QString fitsDirectory("/home/astro"); 1469 QString placeholderFormat("/%t/%T/%T_%t_%e"); 1470 1471 for (uint version : 1472 { 1473 TestEkosCaptureHelper::ESQ_VERSION_2_4, TestEkosCaptureHelper::ESQ_VERSION_2_5, TestEkosCaptureHelper::ESQ_VERSION_2_6 1474 }) 1475 { 1476 QTest::newRow(QString("%2x %5 %3 %1s bin=%6x%7 dir=%4 v=%8").arg(exposureTime).arg(count).arg(filter) 1477 .arg(fitsDirectory).arg(type).arg(binX).arg(binY).arg(m_CaptureHelper->esqVersionNames[version]).toLatin1()) 1478 << version << exposureTime << target << count << delay << filter << type << encoding << binX << binY << x << y << w << h << 1479 fitsDirectory << placeholderFormat << formatSuffix << cameraTemperature << cameraCooling << fileUploadMode; 1480 } 1481 } 1482 1483 void TestEkosCaptureWorkflow::testLoadEsqFileCalibrationSettings_data() 1484 { 1485 QTest::addColumn<uint>("esqVersion"); /*!< ESQ XML version */ 1486 QTest::addColumn<double>("exposureTime"); /*!< Exposure time */ 1487 QTest::addColumn<int>("count"); /*!< Number of frames */ 1488 QTest::addColumn<QString>("type"); /*!< Frame type (Flat etc.) */ 1489 QTest::addColumn<uint>("pre_action"); /*!< Calibration Pre-Actions */ 1490 QTest::addColumn<double>("wall_az"); /*!< Az position for wall source */ 1491 QTest::addColumn<double>("wall_alt"); /*!< Alt position for wall source */ 1492 QTest::addColumn<bool>("duration_manual"); /*!< Manual exposure time */ 1493 QTest::addColumn<bool>("duration_adu"); /*!< ADU based exposure */ 1494 QTest::addColumn<int>("adu"); /*!< Target ADU */ 1495 QTest::addColumn<int>("tolerance"); /*!< ADU tolerance */ 1496 1497 for (uint version : 1498 { 1499 TestEkosCaptureHelper::ESQ_VERSION_2_5, TestEkosCaptureHelper::ESQ_VERSION_2_6 1500 }) 1501 { 1502 QTest::newRow(QString("Flat pre_action=wall adu=manual v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) 1503 << version << 1.0 << 2 << 1504 "Flat" << static_cast<uint>(ACTION_WALL) << 180.0 << 85.0 << true << false << 12345 << 1234; 1505 QTest::newRow(QString("Dark pre_action=none adu=automatic v=%1").arg( 1506 m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << version << 1.0 << 2 << "Dark" << 1507 static_cast<uint>(ACTION_NONE) << 180.0 << 85.0 << false << true << 12345 << 1234; 1508 QTest::newRow(QString("Bias pre_action=park_mount v=%1").arg(m_CaptureHelper->esqVersionNames[version]).toLocal8Bit()) << 1509 version << 1.0 << 2 << "Bias" << static_cast<uint>(ACTION_PARK_MOUNT) << 180.0 << 85.0 << false << true << 12345 << 1234; 1510 } 1511 } 1512 1513 /* ********************************************************************************* 1514 * 1515 * Test infrastructure 1516 * 1517 * ********************************************************************************* */ 1518 1519 void TestEkosCaptureWorkflow::initTestCase() 1520 { 1521 KVERIFY_EKOS_IS_HIDDEN(); 1522 // limit guiding pulses to ensure that guiding deviations lead to aborted capture 1523 Options::setRAMaximumPulseArcSec(5.0); 1524 Options::setDECMaximumPulseArcSec(5.0); 1525 1526 QStandardPaths::setTestModeEnabled(true); 1527 1528 QFileInfo test_dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation), "test"); 1529 destination = new QTemporaryDir(test_dir.absolutePath()); 1530 QVERIFY(destination->isValid()); 1531 QVERIFY(destination->autoRemove()); 1532 } 1533 1534 void TestEkosCaptureWorkflow::cleanupTestCase() 1535 { 1536 // nothing to do since we start the INDI service for each test case 1537 } 1538 1539 bool TestEkosCaptureWorkflow::prepareTestCase() 1540 { 1541 // set logging defaults for alignment 1542 Options::setVerboseLogging(false); 1543 Options::setLogToFile(false); 1544 1545 // turn off altitude limits 1546 Options::setEnableAltitudeLimits(false); 1547 1548 // use the helper to start the profile 1549 KVERIFY_SUB(m_CaptureHelper->startEkosProfile()); 1550 // prepare optical trains for testing 1551 m_CaptureHelper->prepareOpticalTrains(); 1552 // prepare the mount module for testing with OAG guiding 1553 m_CaptureHelper->prepareMountModule(TestEkosCaptureHelper::SCOPE_FSQ85, TestEkosCaptureHelper::SCOPE_FSQ85); 1554 // prepare for focusing tests 1555 m_CaptureHelper->prepareFocusModule(); 1556 // prepare for alignment tests 1557 m_CaptureHelper->prepareAlignmentModule(); 1558 // prepare for guiding tests 1559 m_CaptureHelper->prepareGuidingModule(); 1560 // prepare for capturing tests 1561 m_CaptureHelper->prepareCaptureModule(); 1562 1563 m_CaptureHelper->init(); 1564 1565 // clear image directory 1566 KVERIFY_SUB(m_CaptureHelper->getImageLocation()->removeRecursively()); 1567 1568 // ensure that the scope is unparked 1569 Ekos::Mount *mount = Ekos::Manager::Instance()->mountModule(); 1570 if (mount->parkStatus() == ISD::PARK_PARKED) 1571 mount->unpark(); 1572 KTRY_VERIFY_WITH_TIMEOUT_SUB(mount->parkStatus() == ISD::PARK_UNPARKED, 30000); 1573 1574 // ensure that the dome is unparked 1575 // if (m_CaptureHelper->m_DomeDevice != nullptr) 1576 // { 1577 // Ekos::Dome *dome = Ekos::Manager::Instance()->domeModule(); 1578 // KVERIFY_SUB(dome != nullptr); 1579 // if (dome->parkStatus() == ISD::PARK_PARKED) 1580 // dome->unpark(); 1581 // KTRY_VERIFY_WITH_TIMEOUT_SUB(dome->parkStatus() == ISD::PARK_UNPARKED, 30000); 1582 // } 1583 1584 // preparation successful 1585 return true; 1586 } 1587 1588 void TestEkosCaptureWorkflow::init() 1589 { 1590 // reset counters 1591 image_count = 0; 1592 // reset calibration 1593 Options::setCalibrationPreActionIndex(ACTION_NONE); 1594 1595 KTRY_OPEN_EKOS(); 1596 KVERIFY_EKOS_IS_OPENED(); 1597 // clear light panel 1598 m_CaptureHelper->m_LightPanelDevice = nullptr; 1599 // clear rotator 1600 m_CaptureHelper->m_RotatorDevice = nullptr; 1601 // disable reset jobs warning 1602 KMessageBox::saveDontShowAgainYesNo("reset_job_status_warning", KMessageBox::ButtonCode::No); 1603 } 1604 1605 void TestEkosCaptureWorkflow::cleanup() 1606 { 1607 if (Ekos::Manager::Instance()->focusModule() != nullptr) 1608 Ekos::Manager::Instance()->focusModule()->abort(); 1609 1610 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 1611 if (capture != nullptr) 1612 { 1613 capture->abort(); 1614 capture->clearSequenceQueue(); 1615 KTRY_SET_CHECKBOX(capture, limitRefocusS, false); 1616 } 1617 1618 m_CaptureHelper->cleanup(); 1619 QVERIFY(m_CaptureHelper->shutdownEkosProfile()); 1620 KTRY_CLOSE_EKOS(); 1621 KVERIFY_EKOS_IS_HIDDEN(); 1622 } 1623 1624 1625 bool TestEkosCaptureWorkflow::prepareCapture(int refocusLimitTime, double refocusHFR, double refocusTemp, int delay) 1626 { 1627 QFETCH(double, exptime); 1628 QFETCH(QString, sequence); 1629 // test data 1630 // switch to capture module 1631 Ekos::Capture *capture = Ekos::Manager::Instance()->captureModule(); 1632 KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(capture, 1000)); 1633 1634 // add target to path to emulate the behavior of the scheduler 1635 QString imagepath = getImageLocation()->path() + "/test"; 1636 1637 // create the destination for images 1638 qCInfo(KSTARS_EKOS_TEST) << "FITS path: " << imagepath; 1639 1640 // set refocusing limits 1641 KTRY_SET_CHECKBOX_SUB(capture, limitRefocusS, (refocusLimitTime > 0)); 1642 if (refocusLimitTime > 0) 1643 KTRY_SET_SPINBOX_SUB(capture, limitRefocusN, refocusLimitTime); 1644 1645 KTRY_SET_CHECKBOX_SUB(capture, limitFocusHFRS, (refocusHFR > 0)); 1646 if (refocusHFR > 0) 1647 KTRY_SET_DOUBLESPINBOX_SUB(capture, limitFocusHFRN, refocusHFR); 1648 1649 KTRY_SET_CHECKBOX_SUB(capture, limitFocusDeltaTS, (refocusTemp > 0)); 1650 if (refocusTemp > 0) 1651 KTRY_SET_DOUBLESPINBOX_SUB(capture, limitFocusDeltaTN, refocusTemp); 1652 1653 // create capture sequences 1654 KVERIFY_SUB(m_CaptureHelper->fillCaptureSequences(target, sequence, exptime, imagepath, delay)); 1655 1656 // everything successfully completed 1657 return true; 1658 } 1659 1660 void TestEkosCaptureWorkflow::prepareTestData(double exptime, QList<QString> sequenceList) 1661 { 1662 #if QT_VERSION < QT_VERSION_CHECK(5,9,0) 1663 QSKIP("Bypassing fixture test on old Qt"); 1664 Q_UNUSED(exptime) 1665 Q_UNUSED(sequence) 1666 #else 1667 QTest::addColumn<double>("exptime"); /*!< exposure time */ 1668 QTest::addColumn<QString>("sequence"); /*!< list of filters */ 1669 1670 for (QString sequence : sequenceList) 1671 QTest::newRow(QString("seq=%2, exp=%1").arg(exptime).arg(sequence).toStdString().c_str()) << exptime << sequence; 1672 #endif 1673 } 1674 1675 QDir *TestEkosCaptureWorkflow::getImageLocation() 1676 { 1677 if (imageLocation == nullptr || imageLocation->exists()) 1678 imageLocation = new QDir(destination->path() + "/images"); 1679 1680 return imageLocation; 1681 } 1682 1683 /* ********************************************************************************* 1684 * 1685 * Main function 1686 * 1687 * ********************************************************************************* */ 1688 1689 QTEST_KSTARS_WITH_GUIDER_MAIN(TestEkosCaptureWorkflow)