File indexing completed on 2024-05-05 12:01:55
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