1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/test/core/fileprogress_test.cpp
Mick Sayson c7efe320d2 refactor(filetransfer): Move file transfer progress into ToxFile
* Refactor/test ToxFileProgress to ensure that when it's moved it
  behaves well
* Notice problems with speed averaging. We were average speeds without
  keeping track of the times they were over. Adding samples of different
  lengths would result in incorrect speeds. Refactor whole class to correct
* Move ToxFileProgress to be a member of ToxFile
* Remove duplicated members between ToxFile and ToxFileProgress
* Move sample addition into CoreFile
2021-12-11 15:38:35 -08:00

342 lines
10 KiB
C++

/*
Copyright © 2021 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#include "src/core/toxfileprogress.h"
#include <QTest>
#include <limits>
class TestFileProgress : public QObject
{
Q_OBJECT
private slots:
void testSpeed();
void testSpeedReset();
void testDiscardedSample();
void testProgress();
void testRemainingTime();
void testBytesSentPersistence();
void testFileSizePersistence();
void testNoSamples();
void testSpeedUnevenIntervals();
void testDefaultTimeLessThanNow();
void testTimeChange();
void testFinishedSpeed();
void testSamplePeriod();
void testInvalidSamplePeriod();
};
/**
* @brief Test that our speeds are sane while we're on our first few samples
*/
void TestFileProgress::testSpeed()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
// 1 sample has no speed
QCOMPARE(progress.getSpeed(), 0.0);
// Swap buffers. Time should be valid
nextSampleTime = nextSampleTime.addMSecs(500);
// 10 bytes over 0.5s
QVERIFY(progress.addSample(10, nextSampleTime));
QCOMPARE(progress.getSpeed(), 20.0);
// This should evict the first sample, so our time should be relative to the
// first 10 bytes
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(20, nextSampleTime));
// 10 bytes over 1s
QCOMPARE(progress.getSpeed(), 10.0);
}
/**
* @brief Test that resetting our speed puts us back into a sane default state
*/
void TestFileProgress::testSpeedReset()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
// Push enough samples that all samples are initialized
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(10, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(20, nextSampleTime));
QCOMPARE(progress.getSpeed(), 10.0);
progress.resetSpeed();
QCOMPARE(progress.getSpeed(), 0.0);
QCOMPARE(progress.lastSampleTime(), QTime());
QCOMPARE(progress.getBytesSent(), uint64_t(20));
QCOMPARE(progress.getProgress(), 0.2);
// Ensure that pushing new samples after reset works correectly
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(30, nextSampleTime));
// 1 sample has no speed
QCOMPARE(progress.getSpeed(), 0.0);
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(40, nextSampleTime));
QCOMPARE(progress.getSpeed(), 10.0);
}
/**
* @brief Test that invalid samples are discarded
*/
void TestFileProgress::testDiscardedSample()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(20, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
// Sample should be discarded because it's too large
QVERIFY(!progress.addSample(300, nextSampleTime));
QCOMPARE(progress.lastSampleTime(), QTime(1, 0, 1));
// Sample should be discarded because we're going backwards
QVERIFY(!progress.addSample(10, nextSampleTime));
QCOMPARE(progress.lastSampleTime(), QTime(1, 0, 1));
}
/**
* @brief Test that progress is reported correctly
*/
void TestFileProgress::testProgress()
{
auto progress = ToxFileProgress(100, 4000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
QCOMPARE(progress.getProgress(), 0.0);
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(10, nextSampleTime));
QCOMPARE(progress.getProgress(), 0.1);
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(100, nextSampleTime));
QCOMPARE(progress.getProgress(), 1.0);
}
/**
* @brief Test that remaining time is predicted reasonably
*/
void TestFileProgress::testRemainingTime()
{
auto progress = ToxFileProgress(100, 2000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(10, nextSampleTime));
// 10% over 1s, 90% should take 9 more seconds
QCOMPARE(progress.getTimeLeftSeconds(), 9.0);
nextSampleTime = nextSampleTime.addMSecs(10000);
QVERIFY(progress.addSample(100, nextSampleTime));
// Even with a slow final sample, we should have 0 seconds remaining when we
// are complete
QCOMPARE(progress.getTimeLeftSeconds(), 0.0);
}
/**
* @brief Test that the sent bytes keeps the last sample
*/
void TestFileProgress::testBytesSentPersistence()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(10, nextSampleTime));
// First sample
QCOMPARE(progress.getBytesSent(), uint64_t(10));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(20, nextSampleTime));
// Second sample
QCOMPARE(progress.getBytesSent(), uint64_t(20));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(30, nextSampleTime));
// After rollover
QCOMPARE(progress.getBytesSent(), uint64_t(30));
}
/**
* @brief Check that the reported file size matches what was given
*/
void TestFileProgress::testFileSizePersistence()
{
auto progress = ToxFileProgress(33, 1000);
QCOMPARE(progress.getFileSize(), uint64_t(33));
}
/**
* @brief Test that we have sane stats when no samples have been added
*/
void TestFileProgress::testNoSamples()
{
auto progress = ToxFileProgress(100, 1000);
QCOMPARE(progress.getSpeed(), 0.0);
QVERIFY(progress.getTimeLeftSeconds() == std::numeric_limits<double>::infinity());
QCOMPARE(progress.getProgress(), 0.0);
}
/**
* @brief Test that statistics are being average over the entire range of time
* no matter the sample frequency
*/
void TestFileProgress::testSpeedUnevenIntervals()
{
auto progress = ToxFileProgress(100, 4000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(10, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(20, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(3000);
QVERIFY(progress.addSample(50, nextSampleTime));
// 10->50 over 4 seconds
QCOMPARE(progress.getSpeed(), 10.0);
}
void TestFileProgress::testDefaultTimeLessThanNow()
{
auto progress = ToxFileProgress(100, 1000);
QVERIFY(progress.lastSampleTime() < QTime::currentTime());
}
/**
* @brief Test that changing the time resets the speed count. Note that it would
* be better to use the monotonic clock, but it's not trivial to get the
* monotonic clock from Qt's time API
*/
void TestFileProgress::testTimeChange()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(10, nextSampleTime));
nextSampleTime = QTime(0, 0, 0);
QVERIFY(progress.addSample(20, nextSampleTime));
QCOMPARE(progress.getSpeed(), 0.0);
QCOMPARE(progress.getProgress(), 0.2);
nextSampleTime = QTime(0, 0, 1);
QVERIFY(progress.addSample(30, nextSampleTime));
QCOMPARE(progress.getSpeed(), 10.0);
}
/**
* @brief Test that when a file is complete it's speed is set to 0
*/
void TestFileProgress::testFinishedSpeed()
{
auto progress = ToxFileProgress(100, 1000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(10, nextSampleTime));
nextSampleTime = nextSampleTime.addMSecs(1000);
QVERIFY(progress.addSample(100, nextSampleTime));
QCOMPARE(progress.getSpeed(), 0.0);
}
/**
* @brief Test that we are averaged over the past period * samples time, and
* when we roll we lose one sample period of data
*/
void TestFileProgress::testSamplePeriod()
{
// No matter the number of samples, we should always be averaging over 2s
auto progress = ToxFileProgress(100, 2000);
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
nextSampleTime = QTime(1, 0, 0, 500);
QVERIFY(progress.addSample(10, nextSampleTime));
// Even with less than a sample period our speed and size should be updated
QCOMPARE(progress.getSpeed(), 20.0);
QCOMPARE(progress.getBytesSent(), uint64_t(10));
// Add a new sample at 1s, this should replace the previous sample
nextSampleTime = QTime(1, 0, 1);
QVERIFY(progress.addSample(30, nextSampleTime));
QCOMPARE(progress.getSpeed(), 30.0);
QCOMPARE(progress.getBytesSent(), uint64_t(30));
// Add a new sample at 2s, our time should still be relative to 0
nextSampleTime = QTime(1, 0, 2);
QVERIFY(progress.addSample(50, nextSampleTime));
// 50 - 0 over 2s
QCOMPARE(progress.getSpeed(), 25.0);
QCOMPARE(progress.getBytesSent(), uint64_t(50));
}
void TestFileProgress::testInvalidSamplePeriod()
{
auto progress = ToxFileProgress(100, -1);
// Sample period should be healed to 1000
auto nextSampleTime = QTime(1, 0, 0);
QVERIFY(progress.addSample(0, nextSampleTime));
nextSampleTime = QTime(1, 0, 0, 500);
QVERIFY(progress.addSample(10, nextSampleTime));
QCOMPARE(progress.getSpeed(), 20.0);
// Second sample should be removed and we should average over the full
// second
nextSampleTime = QTime(1, 0, 1);
QVERIFY(progress.addSample(30, nextSampleTime));
QCOMPARE(progress.getSpeed(), 30.0);
// First sample should be evicted and we should have an updated speed
nextSampleTime = QTime(1, 0, 2);
QVERIFY(progress.addSample(90, nextSampleTime));
QCOMPARE(progress.getSpeed(), 60.0);
}
QTEST_GUILESS_MAIN(TestFileProgress)
#include "fileprogress_test.moc"