#include #include #include #include #include #include #include Q_DECLARE_METATYPE(Seconds); Q_DECLARE_METATYPE(DateTimeRangeTransformation); DateTimeRange computeZoom(QDateTime start, QDateTime stop, double zoom) { double start_epoch = start.toMSecsSinceEpoch(); double stop_epoch = stop.toMSecsSinceEpoch(); auto delta = stop_epoch - start_epoch; auto dt_ms = (zoom - 1.) * (double(delta)) / 2.; return DateTimeRange{(start_epoch - dt_ms) / 1000., (stop_epoch + dt_ms) / 1000.}; } class TestDateTimeRange : public QObject { Q_OBJECT private slots: void testRangeDelta_data() { QTest::addColumn("tstart"); QTest::addColumn("tend"); QTest::addColumn("expected"); auto now = QDateTime::currentDateTime(); auto yesterday = QDateTime::currentDateTime().addDays(-1); QTest::newRow("No delta") << now << now << 0.; QTest::newRow("One day delta") << yesterday << now << 60. * 60. * 24.; QTest::newRow("Minus one day delta") << now << yesterday << -60. * 60. * 24.; } void testRangeDelta() { QFETCH(QDateTime, tstart); QFETCH(QDateTime, tend); QFETCH(double, expected); auto range = DateTimeRange::fromDateTime(tstart, tend); double delta = range.delta(); // Since it is built from QDateTime don't expect better resolution QVERIFY((delta - expected) <= 0.002); } void testRangeShift_data() { QTest::addColumn("initial"); QTest::addColumn>("shift"); QTest::addColumn("expected"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto range = DateTimeRange::fromDateTime(yestd, now); QTest::newRow("No shift") << range << Seconds{0.} << range; QTest::newRow("One milisecond left") << range << Seconds{-.001} << DateTimeRange::fromDateTime(yestd.addMSecs(-1.), now.addMSecs(-1.)); QTest::newRow("One milisecond right") << range << Seconds{.001} << DateTimeRange::fromDateTime(yestd.addMSecs(1.), now.addMSecs(1.)); QTest::newRow("One second left") << range << Seconds{-1.} << DateTimeRange::fromDateTime(yestd.addSecs(-1.), now.addSecs(-1.)); QTest::newRow("One second right") << range << Seconds{1.} << DateTimeRange::fromDateTime(yestd.addSecs(1.), now.addSecs(1.)); QTest::newRow("One year left") << range << Seconds{-365. * 24. * 60. * 60.} << DateTimeRange::fromDateTime(yestd.addSecs(-365 * 24 * 60 * 60), now.addSecs(-365 * 24 * 60 * 60)); QTest::newRow("One year right") << range << Seconds{365. * 24. * 60. * 60.} << DateTimeRange::fromDateTime(yestd.addSecs(365 * 24 * 60 * 60), now.addSecs(365 * 24 * 60 * 60)); } void testRangeShift() { QFETCH(DateTimeRange, initial); QFETCH(Seconds, shift); QFETCH(DateTimeRange, expected); QCOMPARE(initial + shift, expected); } void testRangeZoom_data() { QTest::addColumn("initial"); QTest::addColumn("zoom"); QTest::addColumn("expected"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto range = DateTimeRange::fromDateTime(yestd, now); QTest::newRow("No zoom") << range << 1. << range; QTest::newRow("Zoom IN 0.001") << range << 1.001 << computeZoom(yestd, now, 1.001); QTest::newRow("Zoom OUT 0.001") << range << 0.999 << computeZoom(yestd, now, 0.999); } void testRangeZoom() { QFETCH(DateTimeRange, initial); QFETCH(double, zoom); QFETCH(DateTimeRange, expected); QCOMPARE(initial * zoom, expected); } void testRangeContains_data() { QTest::addColumn("range"); QTest::addColumn("range2"); QTest::addColumn("contains"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto range = DateTimeRange::fromDateTime(yestd, now); QTest::newRow("Same range") << range << range << true; QTest::newRow("Smaller range") << range << range * 0.8 << true; QTest::newRow("Bigger range") << range << range * 1.2 << false; QTest::newRow("Shifted range with overlap") << range << range + Seconds{1000.} << false; QTest::newRow("Shifted range without overlap") << range << range + Seconds{24. * 60. * 60. * 10} << false; } void testRangeContains() { QFETCH(DateTimeRange, range); QFETCH(DateTimeRange, range2); QFETCH(bool, contains); QCOMPARE(range.contains(range2), contains); } void testRangeIntersect_data() { QTest::addColumn("range"); QTest::addColumn("range2"); QTest::addColumn("contains"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto tomorrow = QDateTime::currentDateTime().addDays(1); auto range = DateTimeRange::fromDateTime(yestd, now); auto range2 = DateTimeRange::fromDateTime(now, tomorrow); QTest::newRow("Same range") << range << range << true; QTest::newRow("Smaller range") << range << range * 0.8 << true; QTest::newRow("Bigger range") << range << range * 1.2 << true; QTest::newRow("Shifted range with overlap") << range << range + Seconds{1000.} << true; QTest::newRow("Shifted range with overlaping boundary") << range << range2 << true; QTest::newRow("Shifted range .1 seonds outside") << range << range2 + Seconds{.1} << false; QTest::newRow("Shifted range without overlap") << range << range + Seconds{24. * 60. * 60. * 10} << false; } void testRangeIntersect() { QFETCH(DateTimeRange, range); QFETCH(DateTimeRange, range2); QFETCH(bool, contains); QCOMPARE(range.intersect(range2), contains); } void testRangeTransformations_data() { QTest::addColumn("range1"); QTest::addColumn("range2"); QTest::addColumn("transformation"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto range = DateTimeRange::fromDateTime(yestd, now); QTest::newRow("Same range") << range << range << DateTimeRangeTransformation{1., Seconds{0.}}; QTest::newRow("Transformatio 1.1x + 10s") << range << range * 1.1 + Seconds{10.} << DateTimeRangeTransformation{1.1, Seconds{10.}}; QTest::newRow("Transformatio 1.x + 10s") << range << range * 1. + Seconds{10.} << DateTimeRangeTransformation{1., Seconds{10.}}; QTest::newRow("Transformatio 1.1x + 0s") << range << range * 1.1 + Seconds{0.} << DateTimeRangeTransformation{1.1, Seconds{0.}}; QTest::newRow("Transformatio 0.9x - 10s") << range << range * 0.9 + Seconds{-10.} << DateTimeRangeTransformation{0.9, Seconds{-10.}}; } void testRangeTransformations() { QFETCH(DateTimeRange, range1); QFETCH(DateTimeRange, range2); QFETCH(DateTimeRangeTransformation, transformation); auto computed_tr = DateTimeRangeHelper::computeTransformation(range1, range2).value(); QCOMPARE(computed_tr, transformation); QCOMPARE(range1.transform(transformation), range2); QCOMPARE(range1.transform(computed_tr), range2); } void testRangeDiff_data() { QTest::addColumn("source"); QTest::addColumn("destination"); QTest::addColumn("count"); auto now = QDateTime::currentDateTime(); auto yestd = QDateTime::currentDateTime().addDays(-1); auto range = DateTimeRange::fromDateTime(yestd, now); QTest::newRow("Same range") << range << range << 0; QTest::newRow("No missing data (zoom in)") << range << range * 0.9 << 0; QTest::newRow("Missing data on both sides (zoom out)") << range << range * 2. << 2; QTest::newRow("Missing data on left side (pan left)") << range << range - Seconds{1000.} << 1; QTest::newRow("Missing data on right side (pan right)") << range << range + Seconds{1000.} << 1; QTest::newRow("Missing data on right side no intersect (big pan right)") << range << range + Seconds{24. * 60. * 60. * 2} << 1; QTest::newRow("Missing data on left side no intersect (big pan left)") << range << range - Seconds{24. * 60. * 60. * 2} << 1; } void testRangeDiff() { QFETCH(DateTimeRange, source); QFETCH(DateTimeRange, destination); QFETCH(int, count); auto diff = destination - source; QCOMPARE(diff.size(), count); for(const auto& range : diff) { QVERIFY(range.delta().value > 0.); } } }; QTEST_MAIN(TestDateTimeRange) #include "TestDateTimeRange.moc"