File indexing completed on 2024-04-14 14:12:09

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 
0008 #include "test_ekos_scheduler.h"
0009 
0010 #if defined(HAVE_INDI)
0011 
0012 #include "kstars_ui_tests.h"
0013 #include "test_ekos.h"
0014 #include "test_ekos_simulator.h"
0015 #include "ekos/scheduler/scheduler.h"
0016 
0017 TestEkosScheduler::TestEkosScheduler(QObject *parent) : QObject(parent)
0018 {
0019 }
0020 
0021 void TestEkosScheduler::init()
0022 {
0023 }
0024 
0025 void TestEkosScheduler::cleanup()
0026 {
0027 }
0028 
0029 void TestEkosScheduler::initTestCase()
0030 {
0031     KVERIFY_EKOS_IS_HIDDEN();
0032     KTRY_OPEN_EKOS();
0033     KVERIFY_EKOS_IS_OPENED();
0034     KTRY_EKOS_START_SIMULATORS();
0035 
0036     // HACK: Reset clock to initial conditions
0037     KHACK_RESET_EKOS_TIME();
0038 }
0039 
0040 void TestEkosScheduler::cleanupTestCase()
0041 {
0042     KTRY_EKOS_STOP_SIMULATORS();
0043     KTRY_CLOSE_EKOS();
0044     KVERIFY_EKOS_IS_HIDDEN();
0045 }
0046 
0047 void TestEkosScheduler::testScheduleManipulation_data()
0048 {
0049 #if 0
0050 #if QT_VERSION < 0x050900
0051     QSKIP("Skipping fixture-based test on old QT version.");
0052 #else
0053     QTest::addColumn<QString>("NAME");
0054     QTest::addColumn<QString>("RA");
0055     QTest::addColumn<QString>("DEC");
0056 
0057     // Altitude computation taken from SchedulerJob::findAltitude
0058     GeoLocation * const geo = KStarsData::Instance()->geo();
0059     KStarsDateTime const now(KStarsData::Instance()->lt());
0060     KSNumbers const numbers(now.djd());
0061     CachingDms const LST = geo->GSTtoLST(geo->LTtoUT(now).gst());
0062 
0063     std::list<char const *> Objects = { "Polaris", "Mizar", "M 51", "M 13", "M 47", "Vega", "NGC 2238", "M 81" };
0064     size_t count = 0;
0065 
0066     foreach (char const *name, Objects)
0067     {
0068         SkyObject const * const so = KStars::Instance()->data()->objectNamed(name);
0069         if (so != nullptr)
0070         {
0071             SkyObject o(*so);
0072             o.updateCoordsNow(&numbers);
0073             o.EquatorialToHorizontal(&LST, geo->lat());
0074             if (10.0 < o.alt().Degrees())
0075             {
0076                 QTest::addRow("%s", name)
0077                         << name
0078                         << o.ra().toHMSString()
0079                         << o.dec().toDMSString();
0080                 count++;
0081             }
0082             else QWARN(QString("Fixture '%1' altitude is '%2' degrees, discarding.").arg(name).arg(
0083                                so->alt().Degrees()).toStdString().c_str());
0084         }
0085     }
0086 
0087     if (!count)
0088         QSKIP("No usable fixture objects, bypassing test.");
0089 #endif
0090 #endif
0091 }
0092 
0093 void TestEkosScheduler::testScheduleManipulation()
0094 {
0095     Ekos::Manager * const ekos = Ekos::Manager::Instance();
0096 
0097     // Wait for Scheduler to come up, switch to Scheduler tab
0098     QTRY_VERIFY_WITH_TIMEOUT(ekos->schedulerModule() != nullptr, 5000);
0099     KTRY_EKOS_GADGET(QTabWidget, toolsWidget);
0100     toolsWidget->setCurrentWidget(ekos->schedulerModule());
0101     QTRY_COMPARE_WITH_TIMEOUT(toolsWidget->currentWidget(), ekos->schedulerModule(), 1000);
0102 
0103     KTRY_SCHEDULER_GADGET(QLineEdit, nameEdit);
0104     KTRY_SCHEDULER_GADGET(dmsBox, raBox);
0105     KTRY_SCHEDULER_GADGET(dmsBox, decBox);
0106     KTRY_SCHEDULER_GADGET(QLineEdit, sequenceEdit);
0107     KTRY_SCHEDULER_GADGET(QPushButton, addToQueueB);
0108     KTRY_SCHEDULER_GADGET(QPushButton, removeFromQueueB);
0109 
0110     // Computation taken from SchedulerJob::findAltitude
0111     GeoLocation * const geo = KStarsData::Instance()->geo();
0112     KStarsDateTime const now(KStarsData::Instance()->lt());
0113     KSNumbers const numbers(now.djd());
0114     CachingDms const LST = geo->GSTtoLST(geo->LTtoUT(now).gst());
0115 
0116     raBox->setText("1h 2' 3\"");
0117     decBox->setText("1° 2' 3\"");
0118     sequenceEdit->setText(QString("%1%201x1s_Lum.esq").arg(QDir::current().currentPath()).arg(
0119                               QDir::separator())); // %20 to retain the next '1'
0120 
0121     QEXPECT_FAIL("", "The sequence file editbox cannot be edited directly, and changing its text does not allow to add a job",
0122                  Continue);
0123     QTRY_VERIFY_WITH_TIMEOUT(addToQueueB->isEnabled(), 200);
0124 
0125     const int count = 20;
0126     QStringList seqs;
0127     seqs << QString("%1%201x1s_Lum.esq").arg(QDir::current().currentPath()).arg(
0128              QDir::separator()); // %20 to retain the next '1'
0129     seqs << QString("%1%201x1s_RGBLumRGB.esq").arg(QDir::current().currentPath()).arg(
0130              QDir::separator()); // %20 to retain the next '1'
0131 
0132     KTRY_SCHEDULER_GADGET(QTableWidget, queueTable);
0133 
0134     // Add objects to the schedule
0135     for (int i = 0; i < count; i++)
0136     {
0137         QCOMPARE(queueTable->rowCount(), i);
0138 
0139         nameEdit->setText(QString("Object-%1").arg(i));
0140 
0141         SkyObject o(SkyObject::TYPE_UNKNOWN, LST.radians() - (double)i / 10 + (double)count / 2, 45.0);
0142         raBox->setText(o.ra().toHMSString());
0143         QVERIFY(abs(raBox->createDms().Hours() - o.ra().Hours()) <= 15.0 / 3600.0);
0144         decBox->setText(o.dec().toDMSString());
0145         QVERIFY(abs(decBox->createDms().Degrees() - o.dec().Degrees()) <= 1.0 / 3600.0);
0146         sequenceEdit->setText(seqs[i % seqs.count()]);
0147 
0148         Ekos::Manager::Instance()->schedulerModule()->addObject(&o);
0149         Ekos::Manager::Instance()->schedulerModule()->setSequence(sequenceEdit->text());
0150         nameEdit->setText(QString("Object-%1").arg(i));
0151 
0152         // Add object -- note adding can be quite slow
0153         KTRY_SCHEDULER_CLICK(addToQueueB);
0154         QTRY_COMPARE_WITH_TIMEOUT(queueTable->rowCount(), i + 1, 5000);
0155     }
0156 
0157     // Verify each row
0158     for (int i = 0; i < count; i++)
0159     {
0160         queueTable->selectRow(i % queueTable->rowCount());
0161         QCOMPARE(qPrintable(nameEdit->text()), qPrintable(QString("Object-%1").arg(i)));
0162         QCOMPARE(qPrintable(sequenceEdit->text()), qPrintable(seqs[i % seqs.count()]));
0163         SkyObject o(SkyObject::TYPE_UNKNOWN, LST.radians() - (double)i / 10 + (double)count / 2, 45.0);
0164         QCOMPARE(qPrintable(dms::fromString(raBox->text(), false).toHMSString()), qPrintable(o.ra().toHMSString()));
0165         QCOMPARE(qPrintable(dms::fromString(decBox->text(), true).toDMSString()), qPrintable(o.dec().toDMSString()));
0166     }
0167 
0168     // Select a job, remove it and press the add button. the old one should be added below
0169     // This verifies the fix to the issue causing sequence files to be messed up when pasting jobs
0170     for (int i = count - 2; i > 0; i--)
0171     {
0172         queueTable->selectRow(std::min(i, queueTable->rowCount() - 1));
0173 
0174         KTRY_SCHEDULER_CLICK(removeFromQueueB);
0175         KTRY_SCHEDULER_CLICK(addToQueueB);
0176         queueTable->selectRow(std::min(i + 1, queueTable->rowCount() - 1));
0177 
0178         QCOMPARE(qPrintable(nameEdit->text()), qPrintable(QString("Object-%1").arg(i)));
0179         QCOMPARE(qPrintable(sequenceEdit->text()), qPrintable(seqs[i % seqs.count()]));
0180         SkyObject o(SkyObject::TYPE_UNKNOWN, LST.radians() - (double)i / 10 + (double)count / 2, 45.0);
0181         QCOMPARE(qPrintable(dms::fromString(raBox->text(), false).toHMSString()), qPrintable(o.ra().toHMSString()));
0182         QCOMPARE(qPrintable(dms::fromString(decBox->text(), true).toDMSString()), qPrintable(o.dec().toDMSString()));
0183     }
0184 
0185     // Remove objects from the schedule
0186     for (int i = 0; i < count; i++)
0187     {
0188         QCOMPARE(queueTable->rowCount(), count - i);
0189 
0190         //QEXPECT_FAIL("", "Removal button is ineffective when there is no line selection.", Continue);
0191         //QTRY_COMPARE_WITH_TIMEOUT(queueTable->rowCount(), count - i, 5000);
0192 
0193         // Select a line, remove job - note removal can be quite slow
0194         const int pos = i % queueTable->rowCount();
0195         queueTable->selectRow(pos);
0196         //queueTable->selectionModel()->select(queueTable->model()->index(i % queueTable->model()->rowCount(), 0), QItemSelectionModel::SelectCurrent);
0197         KTRY_SCHEDULER_CLICK(removeFromQueueB);
0198         QTRY_COMPARE_WITH_TIMEOUT(queueTable->rowCount(), count - i - 1, 5000);
0199 
0200         // After a removal, no row is selected, no further removal possible
0201         QVERIFY(!removeFromQueueB->isEnabled());
0202     }
0203 
0204     QCOMPARE(queueTable->rowCount(), 0);
0205 }
0206 
0207 QTEST_KSTARS_MAIN(TestEkosScheduler)
0208 
0209 #endif // HAVE_INDI