File indexing completed on 2024-03-24 15:18:36
0001 /* KStars UI tests 0002 SPDX-FileCopyrightText: 2020 Eric Dejouhanet <eric.dejouhanet@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef TESTEKOSFOCUS_H 0008 #define TESTEKOSFOCUS_H 0009 0010 #include "config-kstars.h" 0011 0012 #if defined(HAVE_INDI) 0013 0014 #include <QObject> 0015 #include <QPushButton> 0016 #include <QComboBox> 0017 #include <QDoubleSpinBox> 0018 #include <QSpinBox> 0019 #include <QCheckBox> 0020 #include <QTest> 0021 #include <QSystemTrayIcon> 0022 0023 /** @brief Helper to show the Focus tab 0024 */ 0025 #define KTRY_FOCUS_SHOW() do { \ 0026 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->focusModule() != nullptr, 5000); \ 0027 KTRY_EKOS_GADGET(QTabWidget, toolsWidget); \ 0028 QTRY_VERIFY_WITH_TIMEOUT(-1 != toolsWidget->indexOf(Ekos::Manager::Instance()->focusModule()), 5000); \ 0029 toolsWidget->setCurrentWidget(Ekos::Manager::Instance()->focusModule()); \ 0030 QTRY_COMPARE_WITH_TIMEOUT(toolsWidget->currentWidget(), Ekos::Manager::Instance()->focusModule(), 5000); \ 0031 QTRY_VERIFY_WITH_TIMEOUT(!Ekos::Manager::Instance()->focusModule()->focuser().isEmpty(), 5000); } while (false) 0032 0033 /** @brief Helper to retrieve a gadget in the Focus tab specifically. 0034 * @param klass is the class of the gadget to look for. 0035 * @param name is the gadget name to look for in the UI configuration. 0036 * @warning Fails the test if the gadget "name" of class "klass" does not exist in the Focus module 0037 */ 0038 #define KTRY_FOCUS_GADGET(klass, name) klass * const name = Ekos::Manager::Instance()->focusModule()->findChild<klass*>(#name); \ 0039 QVERIFY2(name != nullptr, QString(#klass " '%1' does not exist and cannot be used").arg(#name).toStdString().c_str()) 0040 0041 /** @brief Helper to click a button in the Focus tab specifically. 0042 * @param button is the gadget name of the button to look for in the UI configuration. 0043 * @warning Fails the test if the button is not currently enabled. 0044 */ 0045 #define KTRY_FOCUS_CLICK(button) do { \ 0046 static volatile bool clicked = false; \ 0047 QTimer::singleShot(100, Ekos::Manager::Instance(), [&]() { \ 0048 KTRY_FOCUS_GADGET(QPushButton, button); \ 0049 QVERIFY2(button->isEnabled(), qPrintable(QString("QPushButton '%1' is disabled and cannot be clicked").arg(#button))); \ 0050 QTest::mouseClick(button, Qt::LeftButton); \ 0051 clicked = true; }); \ 0052 QTRY_VERIFY_WITH_TIMEOUT(clicked, 5000); } while(false) 0053 0054 /** @brief Helper to set a string text into a QComboBox in the Focus module. 0055 * @param combobox is the gadget name of the QComboBox to look for in the UI configuration. 0056 * @param text is the string text to set in the gadget. 0057 * @note This is a contrived method to set a text into a QComboBox programmatically *and* emit the "activated" message. 0058 * @warning Fails the test if the name does not exist in the Focus UI or if the text cannot be set in the gadget. 0059 */ 0060 #define KTRY_FOCUS_COMBO_SET(combobox, text) do { \ 0061 KTRY_FOCUS_GADGET(QComboBox, combobox); \ 0062 int const cbIndex = combobox->findText(text); \ 0063 QVERIFY(0 <= cbIndex); \ 0064 combobox->setCurrentIndex(cbIndex); \ 0065 combobox->activated(cbIndex); \ 0066 QCOMPARE(combobox->currentText(), QString(text)); } while(false); 0067 0068 #define KTRY_FOCUS_CHECK_POSITION_WITH_TIMEOUT(pos, timeout) do { \ 0069 KTRY_FOCUS_GADGET(QLineEdit, absTicksLabel); \ 0070 QTRY_VERIFY2_WITH_TIMEOUT(pos == absTicksLabel->text().toInt(), \ 0071 QString("Focuser is at position %1 instead of last focus position %2") \ 0072 .arg(absTicksLabel->text()).arg(pos).toLocal8Bit(), timeout);} while(false); 0073 0074 /** @brief Helper for exposure. 0075 * @param exposure is the amount of seconds to expose for. 0076 * @param averaged is the number of frames the procedure should average before computation. 0077 * @note The Focus capture button is disabled during exposure. 0078 * @warning Fails the test if the exposure cannot be entered or if the capture button is 0079 * disabled or does not toggle during exposure or if the stop button is not the opposite of the capture button. 0080 */ 0081 /** @{ */ 0082 #define KTRY_FOCUS_EXPOSURE(exposure, gain) do { \ 0083 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusGain); \ 0084 focusGain->setValue(gain); \ 0085 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusExposure); \ 0086 focusExposure->setValue(exposure); } while (false) 0087 0088 #define KTRY_FOCUS_DETECT(exposure, averaged, gain) do { \ 0089 KTRY_FOCUS_EXPOSURE((exposure), (gain)); \ 0090 KTRY_FOCUS_GADGET(QSpinBox, focusFramesCount); \ 0091 focusFramesCount->setValue(averaged); \ 0092 KTRY_FOCUS_GADGET(QPushButton, captureB); \ 0093 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); \ 0094 QTRY_VERIFY_WITH_TIMEOUT(captureB->isEnabled(), 5000); \ 0095 QTRY_VERIFY(!stopFocusB->isEnabled()); \ 0096 KTRY_FOCUS_CLICK(captureB); \ 0097 QTRY_VERIFY_WITH_TIMEOUT(!captureB->isEnabled(), 5000); \ 0098 QVERIFY(stopFocusB->isEnabled()); \ 0099 QTest::qWait(ceil(exposure)*(averaged)*1000); \ 0100 QTRY_VERIFY_WITH_TIMEOUT(captureB->isEnabled(), 20000 + exposure*averaged*1000/5); \ 0101 QVERIFY(!stopFocusB->isEnabled()); } while (false) 0102 /** @} */ 0103 0104 /** brief Helper to configure main star detection parameters. 0105 * @param detection is the name of the star detection method to use. 0106 * @param algorithm is the name of the autofocus algorithm to use. 0107 * @param fieldin is the lower radius of the annulus filtering stars. 0108 * @param fieldout is the upper radius of the annulus filtering stars. 0109 * @warning Fails the test if detection, algorithm, full-field checkbox or annulus fields cannot be used. 0110 */ 0111 #define KTRY_FOCUS_CONFIGURE(detection, algorithm, fieldin, fieldout, tolerance) do { \ 0112 KTRY_FOCUS_GADGET(QCheckBox, focusUseFullField); \ 0113 focusUseFullField->setCheckState(fieldin < fieldout ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); \ 0114 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusFullFieldInnerRadius); \ 0115 focusFullFieldInnerRadius->setValue(fieldin); \ 0116 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusFullFieldOuterRadius); \ 0117 focusFullFieldOuterRadius->setValue(fieldout); \ 0118 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusTolerance); \ 0119 focusTolerance->setValue(tolerance); \ 0120 KTRY_FOCUS_COMBO_SET(focusDetection, detection); \ 0121 KTRY_FOCUS_COMBO_SET(focusAlgorithm, algorithm); \ 0122 KTRY_FOCUS_GADGET(QDoubleSpinBox, focusMaxTravel); \ 0123 focusMaxTravel->setValue(10000); } while (false) 0124 0125 /** @brief Helper to move the focuser. 0126 * @param steps is the absolute step value to set. 0127 */ 0128 #define KTRY_FOCUS_MOVETO(steps) do { \ 0129 KTRY_FOCUS_GADGET(QSpinBox, absTicksSpin); \ 0130 QTRY_VERIFY_WITH_TIMEOUT(absTicksSpin->isEnabled(), 500); \ 0131 absTicksSpin->setValue(steps); \ 0132 KTRY_FOCUS_GADGET(QPushButton, startGotoB); \ 0133 KTRY_FOCUS_CLICK(startGotoB); \ 0134 KTRY_FOCUS_GADGET(QLineEdit, absTicksLabel); \ 0135 QTRY_COMPARE_WITH_TIMEOUT(absTicksLabel->text().toInt(), steps, 10000); } while (false) 0136 0137 class TestEkosFocus : public QObject 0138 { 0139 Q_OBJECT 0140 0141 public: 0142 explicit TestEkosFocus(QObject *parent = nullptr); 0143 0144 private slots: 0145 void initTestCase(); 0146 void cleanupTestCase(); 0147 0148 void init(); 0149 void cleanup(); 0150 0151 void testCaptureStates(); 0152 void testDuplicateFocusRequest(); 0153 void testAutofocusSignalEmission(); 0154 void testFocusAbort(); 0155 void testGuidingSuspendWhileFocusing(); 0156 void testFocusWhenHFRChecking(); 0157 void testFocusFailure(); 0158 void testFocusWhenMountFlips(); 0159 0160 void testStarDetection_data(); 0161 void testStarDetection(); 0162 }; 0163 0164 #endif // HAVE_INDI 0165 #endif // TESTEKOSFOCUS_H