File indexing completed on 2025-01-05 04:37:15

0001 #ifndef QT_GUI_LIB
0002 #define QT_GUI_LIB
0003 #endif
0004 
0005 #include <ctime>
0006 
0007 #include <QEventLoop>
0008 #include <QLocale>
0009 #include <QtTest>
0010 
0011 #include "testlib/dummytorrentcreator.h"
0012 #include <diskio/chunkmanager.h>
0013 #include <download/downloader.h>
0014 #include <download/streamingchunkselector.h>
0015 #include <interfaces/piecedownloader.h>
0016 #include <torrent/torrentcontrol.h>
0017 #include <util/bitset.h>
0018 #include <util/error.h>
0019 #include <util/fileops.h>
0020 #include <util/functions.h>
0021 #include <util/log.h>
0022 
0023 using namespace bt;
0024 
0025 const bt::Uint64 TEST_FILE_SIZE = 15 * 1024 * 1024;
0026 
0027 class DummyDownloader : public PieceDownloader
0028 {
0029 public:
0030     ~DummyDownloader() override
0031     {
0032     }
0033 
0034     bool canAddRequest() const override
0035     {
0036         return true;
0037     }
0038     void cancel(const bt::Request &) override
0039     {
0040     }
0041     void cancelAll() override
0042     {
0043     }
0044     bool canDownloadChunk() const override
0045     {
0046         return getNumGrabbed() == 0;
0047     }
0048     void download(const bt::Request &) override
0049     {
0050     }
0051     void checkTimeouts() override
0052     {
0053     }
0054     Uint32 getDownloadRate() const override
0055     {
0056         return 0;
0057     }
0058     QString getName() const override
0059     {
0060         return "foobar";
0061     }
0062     bool isChoked() const override
0063     {
0064         return false;
0065     }
0066 };
0067 
0068 class ExtendedStreamingChunkSelector : public bt::StreamingChunkSelector
0069 {
0070 public:
0071     ExtendedStreamingChunkSelector()
0072     {
0073     }
0074     ~ExtendedStreamingChunkSelector() override
0075     {
0076     }
0077 
0078     void markDownloaded(Uint32 i)
0079     {
0080         cman->chunkDownloaded(i);
0081     }
0082 
0083     Downloader *downloader()
0084     {
0085         return downer;
0086     }
0087 };
0088 
0089 class StreamingChunkSelectorTest : public QEventLoop
0090 {
0091     Q_OBJECT
0092 
0093 public:
0094     StreamingChunkSelectorTest()
0095     {
0096     }
0097 
0098     StreamingChunkSelectorTest(QObject *parent)
0099         : QEventLoop(parent)
0100     {
0101     }
0102 
0103 private Q_SLOTS:
0104     void initTestCase()
0105     {
0106         QLocale::setDefault(QLocale("main"));
0107         bt::InitLibKTorrent();
0108         bt::InitLog("streamingchunkselectortest.log", false, true);
0109     }
0110 
0111     void testSimple()
0112     {
0113         DummyTorrentCreator creator;
0114         bt::TorrentControl tc;
0115         QVERIFY(creator.createSingleFileTorrent(TEST_FILE_SIZE, "test.avi"));
0116 
0117         Out(SYS_GEN | LOG_DEBUG) << "Created " << creator.torrentPath() << endl;
0118         try {
0119             tc.init(nullptr, bt::LoadFile(creator.torrentPath()), creator.tempPath() + "tor0", creator.tempPath() + "data/");
0120             tc.createFiles();
0121         } catch (bt::Error &err) {
0122             Out(SYS_GEN | LOG_DEBUG) << "Failed to load torrent: " << creator.torrentPath() << endl;
0123             QFAIL("Torrent load failure");
0124         }
0125 
0126         ExtendedStreamingChunkSelector *csel = new ExtendedStreamingChunkSelector();
0127         tc.setChunkSelector(csel);
0128         QVERIFY(csel != nullptr);
0129         csel->setSequentialRange(0, 50);
0130 
0131         for (Uint32 i = 0; i < 50; i++) {
0132             DummyDownloader dd;
0133             Uint32 selected = 0xFFFFFFFF;
0134             QVERIFY(csel->select(&dd, selected));
0135             Out(SYS_GEN) << "i = " << i << ", selected = " << selected << endl;
0136             QVERIFY(selected == i);
0137             csel->markDownloaded(i);
0138         }
0139 
0140         // cleanup
0141         tc.setChunkSelector(nullptr);
0142     }
0143 
0144     void testCriticalChunkSpread()
0145     {
0146         DummyTorrentCreator creator;
0147         bt::TorrentControl tc;
0148         QVERIFY(creator.createSingleFileTorrent(2 * TEST_FILE_SIZE, "test2.avi"));
0149 
0150         Out(SYS_GEN | LOG_DEBUG) << "Created " << creator.torrentPath() << endl;
0151         try {
0152             tc.init(nullptr, bt::LoadFile(creator.torrentPath()), creator.tempPath() + "tor0", creator.tempPath() + "data/");
0153             tc.createFiles();
0154         } catch (bt::Error &err) {
0155             Out(SYS_GEN | LOG_DEBUG) << "Failed to load torrent: " << creator.torrentPath() << endl;
0156             QFAIL("Torrent load failure");
0157         }
0158 
0159         ExtendedStreamingChunkSelector *csel = new ExtendedStreamingChunkSelector();
0160         tc.setChunkSelector(csel);
0161         QVERIFY(csel != nullptr);
0162         Downloader *downer = csel->downloader();
0163         QVERIFY(downer != nullptr);
0164 
0165         // Check that critical chunks are spread over multiple peers
0166         csel->setSequentialRange(20, 60);
0167         DummyDownloader dd[32];
0168         for (Uint32 i = 0; i < 32; i++) {
0169             downer->addPieceDownloader(&dd[i]);
0170         }
0171 
0172         // Check the spread of the downloaders
0173         downer->update();
0174         for (Uint32 i = 20; i < csel->criticialWindowSize(); i++) {
0175             QVERIFY(downer->downloading(i));
0176             QVERIFY(downer->download(i)->getNumDownloaders() == 32 / csel->criticialWindowSize());
0177         }
0178 
0179         for (Uint32 i = 0; i < 32; i++) {
0180             QVERIFY(dd[i].getNumGrabbed() == 1);
0181         }
0182 
0183         for (Uint32 i = 0; i < 32; i++) {
0184             downer->removePieceDownloader(&dd[i]);
0185         }
0186         // cleanup
0187         tc.setChunkSelector(nullptr);
0188     }
0189 };
0190 
0191 QTEST_MAIN(StreamingChunkSelectorTest)
0192 
0193 #include "streamingchunkselectortest.moc"