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