File indexing completed on 2024-04-21 14:47:26

0001 /*  KStars UI tests
0002     SPDX-FileCopyrightText: 2020 Eric Dejouhanet <eric.dejouhanet@gmail.com>
0003     SPDX-FileCopyrightText: Fabrizio Pollastri <mxgbot@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 /* FP2020830
0009  * For now, tests covers only my changes to Mount Control.
0010  */
0011 
0012 #include "test_ekos_mount.h"
0013 
0014 #if defined(HAVE_INDI)
0015 
0016 #include "kstars_ui_tests.h"
0017 #include "test_ekos.h"
0018 #include "test_ekos_simulator.h"
0019 #include "ekos/mount/mount.h"
0020 
0021 TestEkosMount::TestEkosMount(QObject *parent) : QObject(parent)
0022 {
0023 }
0024 
0025 void TestEkosMount::initTestCase()
0026 {
0027     if (!qgetenv("CI").isEmpty())
0028         QSKIP("Skipping mount control test until QML/GL mixed window issue is resolved under EGLFS.");
0029 
0030     KVERIFY_EKOS_IS_HIDDEN();
0031     KTRY_OPEN_EKOS();
0032     KVERIFY_EKOS_IS_OPENED();
0033     KTRY_EKOS_START_SIMULATORS();
0034 
0035     ekos = Ekos::Manager::Instance();
0036 
0037     // HACK: Reset clock to initial conditions
0038     KHACK_RESET_EKOS_TIME();
0039 
0040     // Wait for Mount to come up, switch to Mount tab
0041     QTRY_VERIFY_WITH_TIMEOUT(ekos->mountModule() != nullptr, 5000);
0042     KTRY_EKOS_GADGET(QTabWidget, toolsWidget);
0043     toolsWidget->setCurrentWidget(ekos->mountModule());
0044     QTRY_COMPARE_WITH_TIMEOUT(toolsWidget->currentWidget(), ekos->mountModule(), 1000);
0045 
0046     // Open Mount Control window
0047     KTRY_MOUNT_GADGET(QPushButton, mountToolBoxB);
0048     KTRY_MOUNT_CLICK(mountToolBoxB);
0049 
0050     // Get Mount Control window object
0051     QWindow *mountControl = nullptr;
0052     for (QWindow *window : qApp->topLevelWindows())
0053     {
0054         if (window->title() != "Mount Control")
0055             mountControl = nullptr;
0056         else
0057         {
0058             mountControl = window;
0059             break;
0060         }
0061     }
0062     QVERIFY(mountControl != nullptr);
0063     QTRY_VERIFY_WITH_TIMEOUT(mountControl->isVisible(), 1000);
0064 
0065     // get access to Mount Control widgets
0066 
0067     raLabel = mountControl->findChild<QObject*>("targetRALabelObject");
0068     QVERIFY(raLabel != nullptr);
0069     deLabel = mountControl->findChild<QObject*>("targetDELabelObject");
0070     QVERIFY(deLabel != nullptr);
0071 
0072     coordRaDe = mountControl->findChild<QObject*>("equatorialCheckObject");
0073     QVERIFY(coordRaDe != nullptr);
0074     coordAzAl = mountControl->findChild<QObject*>("horizontalCheckObject");
0075     QVERIFY(coordAzAl != nullptr);
0076     coordHaDe = mountControl->findChild<QObject*>("haEquatorialCheckObject");
0077     QVERIFY(coordHaDe != nullptr);
0078 
0079     raText = mountControl->findChild<QObject*>("targetRATextObject");
0080     QVERIFY(raText != nullptr);
0081     deText = mountControl->findChild<QObject*>("targetDETextObject");
0082     QVERIFY(deText != nullptr);
0083 
0084     raValue = mountControl->findChild<QObject*>("raValueObject");
0085     QVERIFY(raValue != nullptr);
0086     deValue = mountControl->findChild<QObject*>("deValueObject");
0087     QVERIFY(deValue != nullptr);
0088     azValue = mountControl->findChild<QObject*>("azValueObject");
0089     QVERIFY(azValue != nullptr);
0090     altValue = mountControl->findChild<QObject*>("altValueObject");
0091     QVERIFY(altValue != nullptr);
0092     haValue = mountControl->findChild<QObject*>("haValueObject");
0093     QVERIFY(haValue != nullptr);
0094     zaValue = mountControl->findChild<QObject*>("zaValueObject");
0095     QVERIFY(zaValue != nullptr);
0096     gotoButton = mountControl->findChild<QObject*>("gotoButtonObject");
0097     QVERIFY(gotoButton != nullptr);
0098     syncButton = mountControl->findChild<QObject*>("syncButtonObject");
0099     QVERIFY(syncButton != nullptr);
0100 
0101 }
0102 
0103 void TestEkosMount::cleanupTestCase()
0104 {
0105     KTRY_EKOS_STOP_SIMULATORS();
0106     KTRY_CLOSE_EKOS();
0107     KVERIFY_EKOS_IS_HIDDEN();
0108 }
0109 
0110 void TestEkosMount::init()
0111 {
0112 }
0113 
0114 void TestEkosMount::cleanup()
0115 {
0116 }
0117 
0118 void TestEkosMount::testMountCtrlCoordLabels()
0119 {
0120 #if QT_VERSION < 0x050900
0121     QSKIP("Skipping fixture-based test on old QT version.");
0122 #else
0123     // Test proper setting of input coord label widget according to
0124     // type radio button selection
0125 
0126     // check initial setting RA/DE
0127     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("RA:"), 1000);
0128     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("DE:"), 1000);
0129 
0130     return;
0131     // check transition RA/DE -> AZ/ALT
0132     coordAzAl->setProperty("checked", true);
0133     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("AZ:"), 1000);
0134     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("AL:"), 1000);
0135 
0136     // check transition AZ/ALT -> HA/DE
0137     coordHaDe->setProperty("checked", true);
0138     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("HA:"), 1000);
0139     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("DE:"), 1000);
0140 
0141     // check transition HA/DE -> RA/DE
0142     coordRaDe->setProperty("checked", true);
0143     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("RA:"), 1000);
0144     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("DE:"), 1000);
0145 
0146     // check transition RA/DE -> HA/DE
0147     coordHaDe->setProperty("checked", true);
0148     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("HA:"), 1000);
0149     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("DE:"), 1000);
0150 
0151     // check transition HA/DE -> AZ/AL
0152     coordAzAl->setProperty("checked", true);
0153     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("AZ:"), 1000);
0154     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("AL:"), 1000);
0155 
0156     // check transition AZ/AL -> RA/DE
0157     coordRaDe->setProperty("checked", true);
0158     QTRY_COMPARE_WITH_TIMEOUT(raLabel->property("text"), QVariant("RA:"), 1000);
0159     QTRY_COMPARE_WITH_TIMEOUT(deLabel->property("text"), QVariant("DE:"), 1000);
0160 }
0161 
0162 void TestEkosMount::testMountCtrlCoordConversion()
0163 {
0164     //  Test coord calculator with cyclic transform chain driven by
0165     //  cyclic changes of selection of coord type radiobutton
0166 
0167     dms RA, Dec;
0168     srand(1);
0169     int i;
0170 
0171     // montecarlo test with cyclic coords trasforms among all coord types
0172     for (i = 0; i < 10; i++)
0173     {
0174         // random coordinates: everywhere on the celestial sphere.
0175         RA.setD(rand() * 23.999999999 / RAND_MAX);
0176         Dec.setD(rand() * 180.0 / RAND_MAX - 90.);
0177 
0178         // random UTC range 2000-1-1 -> 2020-12-31
0179         KStarsDateTime JD(rand() * 7670.0 / RAND_MAX + 2451544.0);
0180         if (KStars::Instance() != nullptr) \
0181             if (KStars::Instance()->data() != nullptr) \
0182                 KStars::Instance()->data()->clock()->setUTC(JD);
0183 
0184         // set coord input text boxes to random coord
0185         coordRaDe->setProperty("checked", true);
0186         raText->setProperty("text", QVariant(RA.toHMSString()));
0187         deText->setProperty("text", QVariant(Dec.toDMSString()));
0188 
0189         // forward chain RA/Dec -> Az/Alt -> HA/Dec -> RA/Dec
0190 
0191         // RA/Dec -> Az/Alt
0192         QVariant RAText = raText->property("text");
0193         QVariant DEText = raText->property("text");
0194         coordAzAl->setProperty("checked", true);
0195         QTest::qWait(20);
0196         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0197         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0198 
0199         // Az/Alt -> HA/Dec
0200         RAText = raText->property("text");
0201         DEText = raText->property("text");
0202         coordHaDe->setProperty("checked", true);
0203         QTest::qWait(20);
0204         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0205         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0206 
0207         // HA/Dec -> RA/Dec
0208         coordRaDe->setProperty("checked", true);
0209         QTest::qWait(20);
0210         QTRY_VERIFY_WITH_TIMEOUT(fabs(RA.Hours() -  dms::fromString(raText->property("text").toString(),
0211                                       false).Hours()) < hourPrecision, 1000);
0212         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deText->property("text").toString(),
0213                                       true).Degrees()) < degreePrecision, 1000);
0214 
0215         // backward chain RA/Dec -> HA/Dec -> Az/Alt -> RA/Dec
0216 
0217         // RA/Dec -> HA/Dec
0218         RAText = raText->property("text");
0219         DEText = raText->property("text");
0220         coordHaDe->setProperty("checked", true);
0221         QTest::qWait(20);
0222         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0223         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0224 
0225         // HA/Dec -> Az/Alt
0226         RAText = raText->property("text");
0227         DEText = raText->property("text");
0228         coordAzAl->setProperty("checked", true);
0229         QTest::qWait(20);
0230         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0231         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0232 
0233         // Az/Alt -> RA/Dec
0234         RAText = raText->property("text");
0235         DEText = raText->property("text");
0236         coordRaDe->setProperty("checked", true);
0237         QTest::qWait(20);
0238         QTRY_VERIFY_WITH_TIMEOUT(fabs(RA.Hours() -  dms::fromString(raText->property("text").toString(),
0239                                       false).Hours()) < hourPrecision, 1000);
0240         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deText->property("text").toString(),
0241                                       true).Degrees()) < degreePrecision, 1000);
0242     }
0243 }
0244 
0245 void TestEkosMount::testMountCtrlGoto()
0246 {
0247     int i;
0248 
0249     // montecarlo test of GOTO with RA/Dec coordinate
0250     srand(1);
0251     coordRaDe->setProperty("checked", true);
0252     for (i = 0; i < 3; i++)
0253     {
0254         // random coordinates above horizon
0255         dms Az(rand() * 359.999999999 / RAND_MAX);
0256         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0257 
0258         // random UTC range 2000-1-1 -> 2020-12-31
0259         KStarsDateTime JD(rand() * 7670.0 / RAND_MAX + 2451544.0);
0260         if (KStars::Instance() != nullptr) \
0261             if (KStars::Instance()->data() != nullptr) \
0262                 KStars::Instance()->data()->clock()->setUTC(JD);
0263 
0264         // convert Az/Alt -> RA/Dec
0265         SkyPoint sp;
0266         sp.setAz(Az);
0267         sp.setAlt(Alt);
0268         sp.HorizontalToEquatorial(KStars::Instance()->data()->lst(), KStars::Instance()->data()->geo()->lat());
0269         dms RA  = sp.ra();
0270         dms Dec = sp.dec();
0271 
0272         // set coord input text boxes to random coord
0273         QTest::qWait(20);
0274         QVariant RAText = raText->property("text");
0275         QVariant DEText = raText->property("text");
0276         raText->setProperty("text", QVariant(RA.toHMSString()));
0277         deText->setProperty("text", QVariant(Dec.toDMSString()));
0278         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0279         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0280 
0281         // check GOTO RA/Dec
0282         ekos->mountModule()->slew(raText->property("text").toString(), deText->property("text").toString());
0283         QTRY_VERIFY_WITH_TIMEOUT(fabs(RA.Hours() -  dms::fromString(raValue->property("text").toString(),
0284                                       false).Hours()) < hourPrecision, 30000);
0285         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deValue->property("text").toString(),
0286                                       true).Degrees()) < degreePrecision, 30000);
0287     }
0288 
0289     // montecarlo test of GOTO with Az/alt coordinate
0290     srand(1);
0291     coordAzAl->setProperty("checked", true);
0292     for (i = 0; i < 3; i++)
0293     {
0294         // random coordinates above horizon
0295         dms Az(rand() * 359.999999999 / RAND_MAX);
0296         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0297 
0298         // set coord input text boxes to random coord
0299         QTest::qWait(20);
0300         raText->setProperty("text", QVariant(Az.toDMSString()));
0301         deText->setProperty("text", QVariant(Alt.toDMSString()));
0302 
0303         // check GOTO Az/Alt
0304         ekos->mountModule()->slew(raText->property("text").toString(), deText->property("text").toString());
0305         QTRY_VERIFY_WITH_TIMEOUT(fabs(Az.Degrees() -  dms::fromString(azValue->property("text").toString(),
0306                                       true).Degrees()) < degreePrecision * 120.0, 30000);
0307         QTRY_VERIFY_WITH_TIMEOUT(fabs(Alt.Degrees() -  dms::fromString(altValue->property("text").toString(),
0308                                       true).Degrees()) < degreePrecision * 120.0, 30000);
0309     }
0310 
0311     // montecarlo test of GOTO with HA/Dec coordinate
0312     srand(1);
0313     coordHaDe->setProperty("checked", true);
0314     for (i = 0; i < 3; i++)
0315     {
0316         // random coordinates above horizon
0317         dms Az(rand() * 359.999999999 / RAND_MAX);
0318         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0319 
0320         // convert Az/Alt -> HA/Dec
0321         SkyPoint sp;
0322         sp.setAz(Az);
0323         sp.setAlt(Alt);
0324         dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
0325         sp.HorizontalToEquatorial(&lst, KStars::Instance()->data()->geo()->lat());
0326         dms RA  = sp.ra();
0327         dms HA = (lst - RA + dms(360.0)).reduce();
0328         dms Dec = sp.dec();
0329 
0330         // set coord input text boxes to random coord
0331         QTest::qWait(20);
0332         QVariant RAText = raText->property("text");
0333         QVariant DEText = raText->property("text");
0334         QChar sgn('+');
0335         if (HA.Hours() > 12.0)
0336         {
0337             HA.setH(24.0 - HA.Hours());
0338             sgn = '-';
0339         }
0340         raText->setProperty("text", QString("%1%2").arg(sgn).arg(HA.toHMSString()));
0341         deText->setProperty("text", QVariant(Dec.toDMSString()));
0342         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0343         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0344 
0345         // check GOTO RA/Dec
0346         ekos->mountModule()->slew(raText->property("text").toString(), deText->property("text").toString());
0347         QTRY_VERIFY_WITH_TIMEOUT(fabs(HA.Hours() -  dms::fromString(haValue->property("text").toString(),
0348                                       false).Hours()) < hourPrecision * 120, 30000);
0349         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deValue->property("text").toString(),
0350                                       true).Degrees()) < degreePrecision, 30000);
0351     }
0352 }
0353 
0354 void TestEkosMount::testMountCtrlSync()
0355 {
0356     int i;
0357 
0358     // montecarlo test of SYNC with RA/Dec coordinate
0359     srand(1);
0360     coordRaDe->setProperty("checked", true);
0361     for (i = 0; i < 3; i++)
0362     {
0363         // random coordinates above horizon
0364         dms Az(rand() * 359.999999999 / RAND_MAX);
0365         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0366 
0367         // random UTC range 2000-1-1 -> 2020-12-31
0368         KStarsDateTime JD(rand() * 7670.0 / RAND_MAX + 2451544.0);
0369         if (KStars::Instance() != nullptr) \
0370             if (KStars::Instance()->data() != nullptr) \
0371                 KStars::Instance()->data()->clock()->setUTC(JD);
0372 
0373         // convert Az/Alt -> RA/Dec
0374         SkyPoint sp;
0375         sp.setAz(Az);
0376         sp.setAlt(Alt);
0377         sp.HorizontalToEquatorial(KStars::Instance()->data()->lst(), KStars::Instance()->data()->geo()->lat());
0378         dms RA  = sp.ra();
0379         dms Dec = sp.dec();
0380 
0381         // set coord input text boxes to random coord
0382         QTest::qWait(20);
0383         QVariant RAText = raText->property("text");
0384         QVariant DEText = raText->property("text");
0385         raText->setProperty("text", QVariant(RA.toHMSString()));
0386         deText->setProperty("text", QVariant(Dec.toDMSString()));
0387         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0388         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0389 
0390         // check SYNC RA/Dec
0391         ekos->mountModule()->sync(raText->property("text").toString(), deText->property("text").toString());
0392         QTRY_VERIFY_WITH_TIMEOUT(fabs(RA.Hours() -  dms::fromString(raValue->property("text").toString(),
0393                                       false).Hours()) < hourPrecision, 30000);
0394         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deValue->property("text").toString(),
0395                                       true).Degrees()) < degreePrecision, 30000);
0396     }
0397 
0398     // montecarlo test of SYNC with Az/alt coordinate
0399     srand(1);
0400     coordAzAl->setProperty("checked", true);
0401     for (i = 0; i < 3; i++)
0402     {
0403         // random coordinates above horizon
0404         dms Az(rand() * 359.999999999 / RAND_MAX);
0405         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0406 
0407         // set coord input text boxes to random coord
0408         QTest::qWait(20);
0409         raText->setProperty("text", QVariant(Az.toDMSString()));
0410         deText->setProperty("text", QVariant(Alt.toDMSString()));
0411 
0412         // check SYNC Az/Alt
0413         ekos->mountModule()->sync(raText->property("text").toString(), deText->property("text").toString());
0414         QTRY_VERIFY_WITH_TIMEOUT(fabs(Az.Degrees() -  dms::fromString(azValue->property("text").toString(),
0415                                       true).Degrees()) < degreePrecision * 20, 20000);
0416         QTRY_VERIFY_WITH_TIMEOUT(fabs(Alt.Degrees() -  dms::fromString(altValue->property("text").toString(),
0417                                       true).Degrees()) < degreePrecision * 20, 20000);
0418     }
0419 
0420     // montecarlo test of SYNC with HA/Dec coordinate
0421     srand(1);
0422     coordHaDe->setProperty("checked", true);
0423     for (i = 0; i < 3; i++)
0424     {
0425         // random coordinates above horizon
0426         dms Az(rand() * 359.999999999 / RAND_MAX);
0427         dms Alt(rand() * 89.0 / RAND_MAX + 1.0);
0428 
0429         // convert Az/Alt -> HA/Dec
0430         SkyPoint sp;
0431         sp.setAz(Az);
0432         sp.setAlt(Alt);
0433         dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
0434         sp.HorizontalToEquatorial(&lst, KStars::Instance()->data()->geo()->lat());
0435         dms RA  = sp.ra();
0436         dms HA = (lst - RA + dms(360.0)).reduce();
0437         dms Dec = sp.dec();
0438 
0439         // set coord input text boxes to random coord
0440         QTest::qWait(20);
0441         QVariant RAText = raText->property("text");
0442         QVariant DEText = raText->property("text");
0443         QChar sgn('+');
0444         if (HA.Hours() > 12.0)
0445         {
0446             HA.setH(24.0 - HA.Hours());
0447             sgn = '-';
0448         }
0449         raText->setProperty("text", QString("%1%2").arg(sgn).arg(HA.toHMSString()));
0450         deText->setProperty("text", QVariant(Dec.toDMSString()));
0451         QTRY_VERIFY_WITH_TIMEOUT(RAText != raText->property("text"), 1000);
0452         QTRY_VERIFY_WITH_TIMEOUT(DEText != deText->property("text"), 1000);
0453 
0454         // check SYNC RA/Dec
0455         ekos->mountModule()->sync(raText->property("text").toString(), deText->property("text").toString());
0456         QTRY_VERIFY_WITH_TIMEOUT(fabs(HA.Hours() -  dms::fromString(haValue->property("text").toString(),
0457                                       false).Hours()) < hourPrecision * 2, 30000);
0458         QTRY_VERIFY_WITH_TIMEOUT(fabs(Dec.Degrees() -  dms::fromString(deValue->property("text").toString(),
0459                                       true).Degrees()) < degreePrecision, 30000);
0460     }
0461 
0462     // close Mount Control
0463     KTRY_MOUNT_CLICK(mountToolBoxB);
0464 #endif
0465 }
0466 
0467 QTEST_KSTARS_MAIN(TestEkosMount)
0468 
0469 #endif // HAVE_INDI