1 /*
2     SPDX-FileCopyrightText: 2021 Kwon-Young Choi <kwon-young.choi@hotmail.fr>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 /* Project Includes */
8 #include "test_placeholderpath.h"
9 #include "ekos/capture/sequencejob.h"
10 #include "ekos/scheduler/schedulerjob.h"
11 #include "ekos/capture/placeholderpath.h"
12 
13 #include <QFile>
14 #include <QRegularExpression>
15 #include <QRegularExpressionMatch>
16 
TestPlaceholderPath()17 TestPlaceholderPath::TestPlaceholderPath() : QObject()
18 {
19 }
20 
~TestPlaceholderPath()21 TestPlaceholderPath::~TestPlaceholderPath()
22 {
23 }
24 
25 // helper functions
parseCSV(const QString filename,const QList<const char * > columns)26 void parseCSV(const QString filename, const QList<const char*> columns)
27 {
28     QFile testDataFile(filename);
29 
30     if (!testDataFile.open(QIODevice::ReadOnly))
31     {
32         qDebug() << testDataFile.errorString();
33         QFAIL("error");
34     }
35 
36     // checking csv header
37     int columnCpt = 0;
38     QByteArray line = testDataFile.readLine().replace("\n", "");
39 
40     for (auto el : line.split(','))
41     {
42         if (columns.size() <= columnCpt)
43             QFAIL("too many csv columns");
44         else if (el != columns[columnCpt])
45         {
46             QFAIL(QString("csv columns incorrect %1 %2").arg(el, columns[columnCpt]).toStdString().c_str());
47         }
48         columnCpt++;
49     }
50 
51     if (columns.size() != columnCpt)
52         QFAIL("not enough csv columns");
53 
54     int cpt = 0;
55 
56     while (!testDataFile.atEnd())
57     {
58         QByteArray line = testDataFile.readLine().replace("\n", "");
59         QTestData &row = QTest::addRow("%d", cpt);
60         for (auto el : line.split(','))
61         {
62             row << QString::fromStdString(el.toStdString());
63         }
64         cpt++;
65     }
66 }
67 
buildXML(QString Exposure,QString Filter,QString Type,QString Prefix,QString RawPrefix,QString FilterEnabled,QString ExpEnabled,QString TimeStampEnabled,QString FITSDirectory)68 XMLEle* buildXML(
69     QString Exposure,
70     QString Filter,
71     QString Type,
72     QString Prefix,
73     QString RawPrefix,
74     QString FilterEnabled,
75     QString ExpEnabled,
76     QString TimeStampEnabled,
77     QString FITSDirectory
78 )
79 {
80     XMLEle *root = NULL;
81     XMLEle *ep, *subEP;
82     root = addXMLEle(root, "root");
83 
84     if (!Exposure.isEmpty())
85     {
86         ep = addXMLEle(root, "Exposure");
87         editXMLEle(ep, Exposure.toStdString().c_str());
88     }
89 
90     if (!Filter.isEmpty())
91     {
92         ep = addXMLEle(root, "Filter");
93         editXMLEle(ep, Filter.toStdString().c_str());
94     }
95 
96     if (!Type.isEmpty())
97     {
98         ep = addXMLEle(root, "Type");
99         editXMLEle(ep, Type.toStdString().c_str());
100     }
101 
102     if (!Prefix.isEmpty())
103     {
104         ep = addXMLEle(root, "Prefix");
105         if (!RawPrefix.isEmpty())
106         {
107             subEP = addXMLEle(ep, "RawPrefix");
108             editXMLEle(subEP, RawPrefix.toStdString().c_str());
109         }
110         if (!FilterEnabled.isEmpty())
111         {
112             subEP = addXMLEle(ep, "FilterEnabled");
113             editXMLEle(subEP, FilterEnabled.toStdString().c_str());
114         }
115         if (!ExpEnabled.isEmpty())
116         {
117             subEP = addXMLEle(ep, "ExpEnabled");
118             editXMLEle(subEP, ExpEnabled.toStdString().c_str());
119         }
120         if (!TimeStampEnabled.isEmpty())
121         {
122             subEP = addXMLEle(ep, "TimeStampEnabled");
123             editXMLEle(subEP, TimeStampEnabled.toStdString().c_str());
124         }
125     }
126 
127     if (!FITSDirectory.isEmpty())
128     {
129         ep = addXMLEle(root, "FITSDirectory");
130         editXMLEle(ep, FITSDirectory.toStdString().c_str());
131     }
132 
133     //prXMLEle(stdout, root, 0);
134 
135     return root;
136 }
137 
testSchedulerProcessJobInfo_data()138 void TestPlaceholderPath::testSchedulerProcessJobInfo_data()
139 {
140 #if QT_VERSION < 0x050900
141     QSKIP("Skipping fixture-based test on old QT version.");
142 #else
143     const QList<const char*> columns =
144     {
145         "Exposure",
146         "Filter",
147         "Type",
148         "Prefix",
149         "RawPrefix",
150         "FilterEnabled",
151         "ExpEnabled",
152         "FITSDirectory",
153         "targetName",
154         "signature",
155     };
156     for (const auto &column : columns)
157     {
158         QTest::addColumn<QString>(column);
159     }
160     parseCSV(":/testSchedulerProcessJobInfo_data.csv", columns);
161 
162 #endif
163 }
164 
testSchedulerProcessJobInfo()165 void TestPlaceholderPath::testSchedulerProcessJobInfo()
166 {
167 #if QT_VERSION < 0x050900
168     QSKIP("Skipping fixture-based test on old QT version.");
169 #else
170     QFETCH(QString, Exposure);
171     QFETCH(QString, Filter);
172     QFETCH(QString, Type);
173     QFETCH(QString, Prefix);
174     QFETCH(QString, RawPrefix);
175     QFETCH(QString, FilterEnabled);
176     QFETCH(QString, ExpEnabled);
177     QFETCH(QString, FITSDirectory);
178     /*
179      * replace \s / ( ) : * ~ " characters by _
180      * Remove any two or more __ by _
181      * Remove any _ at the end
182      */
183     QFETCH(QString, targetName);
184     QFETCH(QString, signature);
185 
186     XMLEle *root = buildXML(
187                        Exposure,
188                        Filter,
189                        Type,
190                        Prefix,
191                        RawPrefix,
192                        FilterEnabled,
193                        ExpEnabled,
194                        "",
195                        FITSDirectory);
196 
197     Ekos::SequenceJob job(root);
198     QCOMPARE(job.getFilterName(), Filter);
199     auto placeholderPath = Ekos::PlaceholderPath();
200     placeholderPath.processJobInfo(&job, targetName);
201 
202     QCOMPARE(job.getSignature(), signature);
203 
204     delXMLEle(root);
205 #endif
206 }
207 
testCaptureAddJob_data()208 void TestPlaceholderPath::testCaptureAddJob_data()
209 {
210 #if QT_VERSION < 0x050900
211     QSKIP("Skipping fixture-based test on old QT version.");
212 #else
213     const QList<const char*> columns =
214     {
215         "Exposure",
216         "Filter",
217         "Type",
218         "Prefix",
219         "RawPrefix",
220         "FilterEnabled",
221         "ExpEnabled",
222         "FITSDirectory",
223         "targetName",
224         "signature",
225     };
226     for (const auto &column : columns)
227     {
228         QTest::addColumn<QString>(column);
229     }
230     parseCSV(":/testSchedulerProcessJobInfo_data.csv", columns);
231 #endif
232 }
233 
testCaptureAddJob()234 void TestPlaceholderPath::testCaptureAddJob()
235 {
236 #if QT_VERSION < 0x050900
237     QSKIP("Skipping fixture-based test on old QT version.");
238 #else
239     QFETCH(QString, Exposure);
240     QFETCH(QString, Filter);
241     QFETCH(QString, Type);
242     QFETCH(QString, Prefix);
243     QFETCH(QString, RawPrefix);
244     QFETCH(QString, FilterEnabled);
245     QFETCH(QString, ExpEnabled);
246     QFETCH(QString, FITSDirectory);
247     /*
248      * replace \s / ( ) : * ~ " characters by _
249      * Remove any two or more __ by _
250      * Remove any _ at the end
251      */
252     QFETCH(QString, targetName);
253     QFETCH(QString, signature);
254 
255     XMLEle *root = buildXML(
256                        Exposure,
257                        Filter,
258                        Type,
259                        Prefix,
260                        RawPrefix,
261                        FilterEnabled,
262                        ExpEnabled,
263                        "",
264                        FITSDirectory);
265 
266     // for addJob, targetName should already be sanitized
267     // taken from scheduler.cpp:2491-2495
268     targetName = targetName.replace( QRegularExpression("\\s|/|\\(|\\)|:|\\*|~|\"" ), "_" )
269                  // Remove any two or more __
270                  .replace( QRegularExpression("_{2,}"), "_")
271                  // Remove any _ at the end
272                  .replace( QRegularExpression("_$"), "");
273     Ekos::SequenceJob job(root);
274     QCOMPARE(job.getFilterName(), Filter);
275     auto placeholderPath = Ekos::PlaceholderPath();
276     placeholderPath.addJob(&job, targetName);
277 
278     QCOMPARE(job.getSignature(), signature);
279 
280     delXMLEle(root);
281 #endif
282 }
283 
testCCDGenerateFilename_data()284 void TestPlaceholderPath::testCCDGenerateFilename_data()
285 {
286 #if QT_VERSION < 0x050900
287     QSKIP("Skipping fixture-based test on old QT version.");
288 #else
289     QTest::addColumn<QString>("format");
290     QTest::addColumn<bool>("batch_mode");
291     QTest::addColumn<QString>("fitsDir");
292     QTest::addColumn<QString>("seqPrefix");
293     QTest::addColumn<int>("nextSequenceID");
294     QTest::addColumn<QString>("desiredFilename");
295 
296     // format
297     QTest::addRow("0")  << ""      << false << ""    << ""            << 0 << "/.+/kstars/000";
298     QTest::addRow("1")  << ""      << false << ""    << ""            << 1 << "/.+/kstars/001";
299     QTest::addRow("2")  << ""      << false << ""    << "_ISO8601"    << 0 <<
300                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000";
301     QTest::addRow("3")  << ""      << false << ""    << "_ISO8601"    << 1 <<
302                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001";
303     QTest::addRow("4")  << ""      << false << ""    << "_ISO8601bar" << 0 <<
304                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000";
305     QTest::addRow("5")  << ""      << false << ""    << "_ISO8601bar" << 1 <<
306                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001";
307     QTest::addRow("6")  << ""      << false << ""    << "bar"         << 0 << "/.+/kstars/bar_000";
308     QTest::addRow("7")  << ""      << false << ""    << "bar"         << 1 << "/.+/kstars/bar_001";
309     QTest::addRow("8")  << ""      << false << "foo" << ""            << 0 << "/.+/kstars/000";
310     QTest::addRow("9")  << ""      << false << "foo" << ""            << 1 << "/.+/kstars/001";
311     QTest::addRow("10") << ""      << false << "foo" << "_ISO8601"    << 0 <<
312                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000";
313     QTest::addRow("11") << ""      << false << "foo" << "_ISO8601"    << 1 <<
314                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001";
315     QTest::addRow("12") << ""      << false << "foo" << "_ISO8601bar" << 0 <<
316                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000";
317     QTest::addRow("13") << ""      << false << "foo" << "_ISO8601bar" << 1 <<
318                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001";
319     QTest::addRow("14") << ""      << false << "foo" << "bar"         << 0 << "/.+/kstars/bar_000";
320     QTest::addRow("15") << ""      << false << "foo" << "bar"         << 1 << "/.+/kstars/bar_001";
321     QTest::addRow("16") << ""      << true  << ""    << ""            << 0 << "/.+/000";
322     QTest::addRow("17") << ""      << true  << ""    << ""            << 1 << "/.+/001";
323     QTest::addRow("18") << ""      << true  << ""    << "_ISO8601"    << 0 <<
324                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000";
325     QTest::addRow("19") << ""      << true  << ""    << "_ISO8601"    << 1 <<
326                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001";
327     QTest::addRow("20") << ""      << true  << ""    << "_ISO8601bar" << 0 <<
328                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000";
329     QTest::addRow("21") << ""      << true  << ""    << "_ISO8601bar" << 1 <<
330                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001";
331     QTest::addRow("22") << ""      << true  << ""    << "bar"         << 0 << "/.+/bar_000";
332     QTest::addRow("23") << ""      << true  << ""    << "bar"         << 1 << "/.+/bar_001";
333     QTest::addRow("24") << ""      << true  << "foo" << ""            << 0 << "foo/000";
334     QTest::addRow("25") << ""      << true  << "foo" << ""            << 1 << "foo/001";
335     QTest::addRow("26") << ""      << true  << "foo" << "_ISO8601"    << 0 <<
336                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000";
337     QTest::addRow("27") << ""      << true  << "foo" << "_ISO8601"    << 1 <<
338                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001";
339     QTest::addRow("28") << ""      << true  << "foo" << "_ISO8601bar" << 0 <<
340                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000";
341     QTest::addRow("29") << ""      << true  << "foo" << "_ISO8601bar" << 1 <<
342                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001";
343     QTest::addRow("30") << ""      << true  << "foo" << "bar"         << 0 << "foo/bar_000";
344     QTest::addRow("31") << ""      << true  << "foo" << "bar"         << 1 << "foo/bar_001";
345     QTest::addRow("32") << ".fits" << false << ""    << ""            << 0 << "/.+/kstars/000.fits";
346     QTest::addRow("33") << ".fits" << false << ""    << ""            << 1 << "/.+/kstars/001.fits";
347     QTest::addRow("34") << ".fits" << false << ""    << "_ISO8601"    << 0 <<
348                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000.fits";
349     QTest::addRow("35") << ".fits" << false << ""    << "_ISO8601"    << 1 <<
350                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001.fits";
351     QTest::addRow("36") << ".fits" << false << ""    << "_ISO8601bar" << 0 <<
352                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000.fits";
353     QTest::addRow("37") << ".fits" << false << ""    << "_ISO8601bar" << 1 <<
354                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001.fits";
355     QTest::addRow("38") << ".fits" << false << ""    << "bar"         << 0 << "/.+/kstars/bar_000.fits";
356     QTest::addRow("39") << ".fits" << false << ""    << "bar"         << 1 << "/.+/kstars/bar_001.fits";
357     QTest::addRow("40") << ".fits" << false << "foo" << ""            << 0 << "/.+/kstars/000.fits";
358     QTest::addRow("41") << ".fits" << false << "foo" << ""            << 1 << "/.+/kstars/001.fits";
359     QTest::addRow("42") << ".fits" << false << "foo" << "_ISO8601"    << 0 <<
360                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000.fits";
361     QTest::addRow("43") << ".fits" << false << "foo" << "_ISO8601"    << 1 <<
362                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001.fits";
363     QTest::addRow("44") << ".fits" << false << "foo" << "_ISO8601bar" << 0 <<
364                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000.fits";
365     QTest::addRow("45") << ".fits" << false << "foo" << "_ISO8601bar" << 1 <<
366                         "/.+/kstars/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001.fits";
367     QTest::addRow("46") << ".fits" << false << "foo" << "bar"         << 0 << "/.+/kstars/bar_000.fits";
368     QTest::addRow("47") << ".fits" << false << "foo" << "bar"         << 1 << "/.+/kstars/bar_001.fits";
369     QTest::addRow("48") << ".fits" << true  << ""    << ""            << 0 << "/.+/000.fits";
370     QTest::addRow("49") << ".fits" << true  << ""    << ""            << 1 << "/.+/001.fits";
371     QTest::addRow("50") << ".fits" << true  << ""    << "_ISO8601"    << 0 <<
372                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000.fits";
373     QTest::addRow("51") << ".fits" << true  << ""    << "_ISO8601"    << 1 <<
374                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001.fits";
375     QTest::addRow("52") << ".fits" << true  << ""    << "_ISO8601bar" << 0 <<
376                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000.fits";
377     QTest::addRow("53") << ".fits" << true  << ""    << "_ISO8601bar" << 1 <<
378                         "/.+/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001.fits";
379     QTest::addRow("54") << ".fits" << true  << ""    << "bar"         << 0 << "/.+/bar_000.fits";
380     QTest::addRow("55") << ".fits" << true  << ""    << "bar"         << 1 << "/.+/bar_001.fits";
381     QTest::addRow("56") << ".fits" << true  << "foo" << ""            << 0 << "foo/000.fits";
382     QTest::addRow("57") << ".fits" << true  << "foo" << ""            << 1 << "foo/001.fits";
383     QTest::addRow("58") << ".fits" << true  << "foo" << "_ISO8601"    << 0 <<
384                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_000.fits";
385     QTest::addRow("59") << ".fits" << true  << "foo" << "_ISO8601"    << 1 <<
386                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}_001.fits";
387     QTest::addRow("60") << ".fits" << true  << "foo" << "_ISO8601bar" << 0 <<
388                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_000.fits";
389     QTest::addRow("61") << ".fits" << true  << "foo" << "_ISO8601bar" << 1 <<
390                         "foo/_\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}bar_001.fits";
391     QTest::addRow("62") << ".fits" << true  << "foo" << "bar"         << 0 << "foo/bar_000.fits";
392     QTest::addRow("63") << ".fits" << true  << "foo" << "bar"         << 1 << "foo/bar_001.fits";
393 #endif
394 }
395 
testCCDGenerateFilename()396 void TestPlaceholderPath::testCCDGenerateFilename()
397 {
398 #if QT_VERSION < 0x050900
399     QSKIP("Skipping fixture-based test on old QT version.");
400 #else
401     QFETCH(QString, format);
402     QFETCH(bool, batch_mode);
403     QFETCH(QString, fitsDir);
404     QFETCH(QString, seqPrefix);
405     QFETCH(int, nextSequenceID);
406     QFETCH(QString, desiredFilename);
407 
408     QString filename;
409     auto placeholderPath = Ekos::PlaceholderPath();
410     placeholderPath.generateFilenameOld(format, batch_mode, &filename, fitsDir, seqPrefix, nextSequenceID);
411 
412     QVERIFY(QRegularExpression(desiredFilename).match(filename).hasMatch());
413 #endif
414 }
415 
testSequenceJobSignature_data()416 void TestPlaceholderPath::testSequenceJobSignature_data()
417 {
418 #if QT_VERSION < 0x050900
419     QSKIP("Skipping fixture-based test on old QT version.");
420 #else
421     QTest::addColumn<QString>("localDir");
422     QTest::addColumn<QString>("directoryPostfix");
423     QTest::addColumn<QString>("fullPrefix");
424     QTest::addColumn<QString>("signature");
425 
426     QTest::addRow("empty")                                << ""     << ""    << ""     << "/";
427     QTest::addRow("localDir")                             << "/foo" << ""    << ""     << "/foo/";
428     QTest::addRow("directoryPostfix")                     << ""     << "bar" << ""     << "bar/";
429     QTest::addRow("fullPrefix")                           << ""     << ""    << "toto" << "/toto";
430     QTest::addRow("localDir+directoryPostfix")            << "/foo" << "bar" << ""     << "/foobar/";
431     QTest::addRow("directoryPostfix+fullPrefix")          << ""     << "bar" << "toto" << "bar/toto";
432     QTest::addRow("localDir+fullPrefix")                  << "/foo" << ""    << "toto" << "/foo/toto";
433     QTest::addRow("localDir+directoryPostfix+fullPrefix") << "/foo" << "bar" << "toto" << "/foobar/toto";
434 #endif
435 }
436 
Q_DECLARE_METATYPE(CCDFrameType)437 Q_DECLARE_METATYPE(CCDFrameType)
438 
439 void TestPlaceholderPath::testSequenceJobSignature()
440 {
441 #if QT_VERSION < 0x050900
442     QSKIP("Skipping fixture-based test on old QT version.");
443 #else
444     QFETCH(QString, localDir);
445     QFETCH(QString, directoryPostfix);
446     QFETCH(QString, fullPrefix);
447     QFETCH(QString, signature);
448 
449     auto job = new Ekos::SequenceJob();
450     job->setLocalDir(localDir);
451     job->setDirectoryPostfix(directoryPostfix);
452     job->setFullPrefix(fullPrefix);
453 
454     QCOMPARE(job->getSignature(), signature);
455 
456     delete job;
457 #endif
458 }
459 
testFullNamingSequence_data()460 void TestPlaceholderPath::testFullNamingSequence_data()
461 {
462 #if QT_VERSION < 0x050900
463     QSKIP("Skipping fixture-based test on old QT version.");
464 #else
465     const QList<const char*> columns =
466     {
467         "Exposure",
468         "Filter",
469         "Type",
470         "Prefix",
471         "RawPrefix",
472         "FilterEnabled",
473         "ExpEnabled",
474         "TimeStampEnabled",
475         "FITSDirectory",
476         "targetName",
477         "batch_mode",
478         "nextSequenceID",
479         "result",
480     };
481     for (const auto &column : columns)
482     {
483         QTest::addColumn<QString>(column);
484     }
485     parseCSV(":/testFullNamingSequence_data.csv", columns);
486 #endif
487 }
488 
testFullNamingSequence()489 void TestPlaceholderPath::testFullNamingSequence()
490 {
491 #if QT_VERSION < 0x050900
492     QSKIP("Skipping fixture-based test on old QT version.");
493 #else
494 
495     QFETCH(QString, Exposure);
496     QFETCH(QString, Filter);
497     QFETCH(QString, Type);
498     QFETCH(QString, Prefix);
499     QFETCH(QString, RawPrefix);
500     QFETCH(QString, FilterEnabled);
501     QFETCH(QString, ExpEnabled);
502     QFETCH(QString, TimeStampEnabled);
503     QFETCH(QString, FITSDirectory);
504     QFETCH(QString, targetName);
505     QFETCH(QString, batch_mode);
506     QFETCH(QString, nextSequenceID);
507     QFETCH(QString, result);
508 
509     XMLEle *root = buildXML(
510                        Exposure,
511                        Filter,
512                        Type,
513                        Prefix,
514                        RawPrefix,
515                        FilterEnabled,
516                        ExpEnabled,
517                        TimeStampEnabled,
518                        FITSDirectory);
519 
520     Ekos::SequenceJob job(root);
521     auto placeholderPath = Ekos::PlaceholderPath();
522     // for addJob, targetName should already be sanitized
523     // taken from scheduler.cpp:2491-2495
524     targetName = targetName.replace( QRegularExpression("\\s|/|\\(|\\)|:|\\*|~|\"" ), "_" )
525                  // Remove any two or more __
526                  .replace( QRegularExpression("_{2,}"), "_")
527                  // Remove any _ at the end
528                  .replace( QRegularExpression("_$"), "");
529     placeholderPath.addJob(&job, targetName);
530     QString fitsDir, filename;
531     // from sequencejob.cpp:302-303
532     if (job.getLocalDir().isEmpty() == false)
533         fitsDir = job.getLocalDir() + job.getDirectoryPostfix();
534     placeholderPath.generateFilenameOld(".fits", bool(batch_mode.toInt()), &filename, fitsDir, job.getFullPrefix(),
535                                         nextSequenceID.toInt());
536     //QCOMPARE(filename, result);
537     QVERIFY2(QRegularExpression(result).match(filename).hasMatch(),
538              QString("\nExpected: %1\nObtained: %2\n").arg(result, filename).toStdString().c_str());
539 
540 #endif
541 }
542 
testFlexibleNaming_data()543 void TestPlaceholderPath::testFlexibleNaming_data()
544 {
545 #if QT_VERSION < 0x050900
546     QSKIP("Skipping fixture-based test on old QT version.");
547 #else
548     const QList<const char*> columns =
549     {
550         "Exposure",
551         "Filter",
552         "Type",
553         "Prefix",
554         "RawPrefix",
555         "FilterEnabled",
556         "ExpEnabled",
557         "TimeStampEnabled",
558         "seqFilename",
559         "targetName",
560         "batch_mode",
561         "nextSequenceID",
562         "format",
563         "result",
564     };
565     for (const auto &column : columns)
566     {
567         QTest::addColumn<QString>(column);
568     }
569     QTest::addRow("infinite")  << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/%f_100x30s_RGB.esq"
570                                << "" << "1" << "" << "%f"  << "^%f_100x30s_RGB\\.fits$";
571     QTest::addRow("f")  << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
572                         "1" << "" << "%f"  << "^100x30s_RGB\\.fits$";
573     QTest::addRow("p")  << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
574                         "1" << "" << "%p"  << "^/home/user/Images/NGC7635\\.fits$";
575     QTest::addRow("p1") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
576                         "1" << "" << "%p1" << "^/home/user/Images/NGC7635\\.fits$";
577     QTest::addRow("p2") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
578                         "1" << "" << "%p2" << "^/home/user/Images\\.fits$";
579     QTest::addRow("p3") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
580                         "1" << "" << "%p3" << "^/home/user\\.fits$";
581     QTest::addRow("p4") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
582                         "1" << "" << "%p4" << "^/home\\.fits$";
583     QTest::addRow("d")  << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
584                         "1" << "" << "%d"  << "^NGC7635\\.fits$";
585     QTest::addRow("d1") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
586                         "1" << "" << "%d1" << "^NGC7635\\.fits$";
587     QTest::addRow("d2") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
588                         "1" << "" << "%d2" << "^Images\\.fits$";
589     QTest::addRow("d3") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
590                         "1" << "" << "%d3" << "^user\\.fits$";
591     QTest::addRow("d4") << "" << "" << "" << "" << "" << "" << "" << "" << "/home/user/Images/NGC7635/100x30s_RGB.esq" << "" <<
592                         "1" << "" << "%d4" << "^home\\.fits$";
593 
594     QTest::addRow("t")  << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << "target" << "" << ""
595                         << "%t"  << "^/tmp/kstars/target\\.fits$";
596     QTest::addRow("T")  << ""      << ""      << "Light" << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << ""
597                         << "%T"  << "^/tmp/kstars/Light\\.fits$";
598     QTest::addRow("F")  << ""      << "sobel" << ""      << "prefix" << "" << "1" << ""  << ""  << "" << ""       << "" << ""
599                         << "%F"  << "^/tmp/kstars/sobel\\.fits$";
600     QTest::addRow("e")  << "0.001" << ""      << ""      << "prefix" << "" << ""  << "1" << ""  << "" << ""       << "" << ""
601                         << "%e"  << "^/tmp/kstars/0.001_secs\\.fits$";
602     QTest::addRow("D")  << ""      << ""      << ""      << "prefix" << "" << ""  << ""  << "1" << "" << ""       << "" << ""
603                         << "%D"  << "^/tmp/kstars/\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}\\.fits$";
604     QTest::addRow("s")  << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << "1"
605                         << "%s"  << "^/tmp/kstars/1\\.fits$";
606     QTest::addRow("s1") << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << "1"
607                         << "%s1" << "^/tmp/kstars/1\\.fits$";
608     QTest::addRow("s2") << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << "1"
609                         << "%s2" << "^/tmp/kstars/01\\.fits$";
610     QTest::addRow("s3") << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << "1"
611                         << "%s3" << "^/tmp/kstars/001\\.fits$";
612     QTest::addRow("s4") << ""      << ""      << ""      << ""       << "" << ""  << ""  << ""  << "" << ""       << "" << "1"
613                         << "%s4" << "^/tmp/kstars/0001\\.fits$";
614 
615     QTest::addRow("_s") << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "1" << "_%s" <<
616                         "^/tmp/kstars/_1\\.fits$";
617     QTest::addRow("unknown1") << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "%b" <<
618                               "^/tmp/kstars/%b\\.fits$";
619     QTest::addRow("unknown2") << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "" << "%f_%a_%t" <<
620                               "^/tmp/kstars/%a_\\.fits$";
621 
622     parseCSV(":/testFlexibleNaming_data.csv", columns);
623 #endif
624 }
625 
testFlexibleNaming()626 void TestPlaceholderPath::testFlexibleNaming()
627 {
628 #if QT_VERSION < 0x050900
629     QSKIP("Skipping fixture-based test on old QT version.");
630 #else
631     QFETCH(QString, Exposure);
632     QFETCH(QString, Filter);
633     QFETCH(QString, Type);
634     QFETCH(QString, Prefix);
635     QFETCH(QString, RawPrefix);
636     QFETCH(QString, FilterEnabled);
637     QFETCH(QString, ExpEnabled);
638     QFETCH(QString, TimeStampEnabled);
639     QFETCH(QString, seqFilename);
640     QFETCH(QString, targetName);
641     QFETCH(QString, batch_mode);
642     QFETCH(QString, nextSequenceID);
643     QFETCH(QString, format);
644     QFETCH(QString, result);
645 
646     XMLEle *root = buildXML(
647                        Exposure,
648                        Filter,
649                        Type,
650                        Prefix,
651                        RawPrefix,
652                        FilterEnabled,
653                        ExpEnabled,
654                        TimeStampEnabled,
655                        "");
656 
657     Ekos::SequenceJob job(root);
658     auto placeholderPath = Ekos::PlaceholderPath(seqFilename);
659     QString filename;
660     bool bm = bool(batch_mode.toInt());
661     int i = nextSequenceID.toInt();
662     placeholderPath.generateFilename(format, job, targetName, bm, i, ".fits", &filename);
663     QVERIFY2(QRegularExpression(result).match(filename).hasMatch(),
664              QString("\nExpected: %1\nObtained: %2\n").arg(result, filename).toStdString().c_str());
665 
666     job.setTargetName(targetName);
667     placeholderPath.setGenerateFilenameSettings(job);
668     placeholderPath.generateFilename(format, job.isTimestampPrefixEnabled(), bm, i, ".fits", &filename);
669     QVERIFY2(QRegularExpression(result).match(filename).hasMatch(),
670              QString("\nExpected: %1\nObtained: %2\n").arg(result, filename).toStdString().c_str());
671 #endif
672 }
673 
testFlexibleNamingChangeBehavior_data()674 void TestPlaceholderPath::testFlexibleNamingChangeBehavior_data()
675 {
676 #if QT_VERSION < 0x050900
677     QSKIP("Skipping fixture-based test on old QT version.");
678 #else
679     const QList<const char*> columns =
680     {
681         "Exposure",
682         "Filter",
683         "Type",
684         "Prefix",
685         "RawPrefix",
686         "FilterEnabled",
687         "ExpEnabled",
688         "TimeStampEnabled",
689         "seqFilename",
690         "targetName",
691         "batch_mode",
692         "nextSequenceID",
693         "format",
694         "old_result",
695         "new_result",
696     };
697     for (const auto &column : columns)
698     {
699         QTest::addColumn<QString>(column);
700     }
701     parseCSV(":/testFlexibleNamingChangeBehavior_data.csv", columns);
702 #endif
703 }
704 
testFlexibleNamingChangeBehavior()705 void TestPlaceholderPath::testFlexibleNamingChangeBehavior()
706 {
707 #if QT_VERSION < 0x050900
708     QSKIP("Skipping fixture-based test on old QT version.");
709 #else
710     QFETCH(QString, Exposure);
711     QFETCH(QString, Filter);
712     QFETCH(QString, Type);
713     QFETCH(QString, Prefix);
714     QFETCH(QString, RawPrefix);
715     QFETCH(QString, FilterEnabled);
716     QFETCH(QString, ExpEnabled);
717     QFETCH(QString, TimeStampEnabled);
718     QFETCH(QString, seqFilename);
719     QFETCH(QString, targetName);
720     QFETCH(QString, batch_mode);
721     QFETCH(QString, nextSequenceID);
722     QFETCH(QString, format);
723     QFETCH(QString, old_result);
724     QFETCH(QString, new_result);
725 
726     XMLEle *root = buildXML(
727                        Exposure,
728                        Filter,
729                        Type,
730                        Prefix,
731                        RawPrefix,
732                        FilterEnabled,
733                        ExpEnabled,
734                        TimeStampEnabled,
735                        "");
736 
737     Ekos::SequenceJob job(root);
738     auto placeholderPath = Ekos::PlaceholderPath(seqFilename);
739     QString filename;
740     bool bm = bool(batch_mode.toInt());
741     int i = nextSequenceID.toInt();
742     placeholderPath.generateFilename(format, job, targetName, bm, i, ".fits", &filename);
743     QEXPECT_FAIL("", "original filename had __ or // or /_ that are now removed", Continue);
744     QVERIFY2(QRegularExpression(old_result).match(filename).hasMatch(),
745              QString("\nNot Expected: %1\nObtained: %2\n").arg(old_result, filename).toStdString().c_str());
746     QVERIFY2(QRegularExpression(new_result).match(filename).hasMatch(),
747              QString("\nExpected: %1\nObtained: %2\n").arg(new_result, filename).toStdString().c_str());
748 
749     job.setTargetName(targetName);
750     placeholderPath.setGenerateFilenameSettings(job);
751     placeholderPath.generateFilename(format, job.isTimestampPrefixEnabled(), bm, i, ".fits", &filename);
752     QEXPECT_FAIL("", "original filename had __ or // or /_ that are now removed", Continue);
753     QVERIFY2(QRegularExpression(old_result).match(filename).hasMatch(),
754              QString("\nNot Expected: %1\nObtained: %2\n").arg(old_result, filename).toStdString().c_str());
755     QVERIFY2(QRegularExpression(new_result).match(filename).hasMatch(),
756              QString("\nExpected: %1\nObtained: %2\n").arg(new_result, filename).toStdString().c_str());
757 #endif
758 }
759 
testRemainingPlaceholders_data()760 void TestPlaceholderPath::testRemainingPlaceholders_data()
761 {
762 #if QT_VERSION < 0x050900
763     QSKIP("Skipping fixture-based test on old QT version.");
764 #else
765     QTest::addColumn<QString>("Filename");
766     QTest::addColumn<QStringList>("Result");
767     QTest::addRow("0")  << "test.fits" << QStringList();
768     QTest::addRow("1")  << "%f_test.fits" << QStringList({"%f"});
769     QTest::addRow("2")  << "%p/%f_test.fits" << QStringList({"%p", "%f"});
770 #endif
771 }
772 
testRemainingPlaceholders()773 void TestPlaceholderPath::testRemainingPlaceholders()
774 {
775 #if QT_VERSION < 0x050900
776     QSKIP("Skipping fixture-based test on old QT version.");
777 #else
778     QFETCH(QString, Filename);
779     QFETCH(QStringList, Result);
780 
781     auto remainingPlaceholders = Ekos::PlaceholderPath::remainingPlaceholders(Filename);
782     QCOMPARE(remainingPlaceholders, Result);
783 #endif
784 }
785 QTEST_GUILESS_MAIN(TestPlaceholderPath)
786