File indexing completed on 2025-01-05 04:37:21
0001 /* 0002 SPDX-FileCopyrightText: 2010 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include <QObject> 0008 #include <QtTest> 0009 #include <ctime> 0010 #include <interfaces/peerinterface.h> 0011 #include <peer/chunkcounter.h> 0012 #include <peer/superseeder.h> 0013 #include <util/log.h> 0014 0015 using namespace bt; 0016 0017 #define NUM_CHUNKS 10 0018 #define INVALID_CHUNK 0xFFFFFFFF 0019 0020 static int peer_cnt = 0; 0021 0022 class DummyPeer : public PeerInterface 0023 { 0024 public: 0025 DummyPeer() 0026 : PeerInterface(PeerID(), NUM_CHUNKS) 0027 { 0028 QString name = QStringLiteral("%1").arg(peer_cnt++); 0029 if (name.size() < 20) 0030 name = name.leftJustified(20, QLatin1Char(' ')); 0031 peer_id = PeerID(name.toLatin1().constData()); 0032 allowed_chunk = INVALID_CHUNK; 0033 allow_called = false; 0034 } 0035 0036 ~DummyPeer() override 0037 { 0038 } 0039 0040 void reset() 0041 { 0042 pieces.setAll(false); 0043 allowed_chunk = INVALID_CHUNK; 0044 } 0045 0046 void have(Uint32 chunk) 0047 { 0048 pieces.set(chunk, true); 0049 } 0050 0051 void haveAll() 0052 { 0053 pieces.setAll(true); 0054 } 0055 0056 void kill() override 0057 { 0058 killed = true; 0059 } 0060 0061 Uint32 averageDownloadSpeed() const override 0062 { 0063 return 0; 0064 } 0065 0066 void chunkAllowed(Uint32 chunk) override 0067 { 0068 allowed_chunk = chunk; 0069 allow_called = true; 0070 } 0071 0072 void handlePacket(const bt::Uint8 *packet, Uint32 size) override 0073 { 0074 Q_UNUSED(packet); 0075 Q_UNUSED(size); 0076 } 0077 0078 Uint32 allowed_chunk; 0079 bool allow_called; 0080 }; 0081 0082 class SuperSeedTest : public QObject 0083 { 0084 Q_OBJECT 0085 public: 0086 SuperSeedTest(QObject *parent = nullptr) 0087 : QObject(parent) 0088 { 0089 } 0090 0091 bool allowCalled(PeerInterface *peer) 0092 { 0093 return ((DummyPeer *)peer)->allow_called && ((DummyPeer *)peer)->allowed_chunk != INVALID_CHUNK; 0094 } 0095 0096 private Q_SLOTS: 0097 void initTestCase() 0098 { 0099 bt::InitLog("superseedtest.log"); 0100 allow_called = false; 0101 } 0102 0103 void cleanupTestCase() 0104 { 0105 } 0106 0107 void testSuperSeeding() 0108 { 0109 Out(SYS_GEN | LOG_DEBUG) << "testSuperSeeding" << endl; 0110 SuperSeeder ss(NUM_CHUNKS); 0111 // First test, all tree should get a chunk 0112 for (int i = 0; i < 3; i++) { 0113 DummyPeer *p = &peer[i]; 0114 ss.peerAdded(p); 0115 QVERIFY(allowCalled(p)); 0116 p->allow_called = false; 0117 } 0118 0119 ss.dump(); 0120 0121 DummyPeer *uploader = &peer[0]; 0122 DummyPeer *downloader = &peer[1]; 0123 DummyPeer *next = &peer[2]; 0124 // Simulate normal superseeding operation 0125 for (int i = 0; i < 4; i++) { 0126 Out(SYS_GEN | LOG_DEBUG) << "======================================" << endl; 0127 Uint32 prev_chunk = uploader->allowed_chunk; 0128 // Now simulate b downloaded the first chunk from a 0129 Uint32 chunk = prev_chunk; 0130 0131 Out(SYS_GEN | LOG_DEBUG) << "uploader = " << uploader->getPeerID().toString() << endl; 0132 Out(SYS_GEN | LOG_DEBUG) << "downloader = " << downloader->getPeerID().toString() << endl; 0133 Out(SYS_GEN | LOG_DEBUG) << "chunk = " << chunk << endl; 0134 0135 if (uploader->allowed_chunk == downloader->allowed_chunk) { 0136 uploader->have(chunk); 0137 downloader->have(chunk); 0138 ss.have(downloader, chunk); 0139 Out(SYS_GEN | LOG_DEBUG) << "prev_chunk = " << chunk << ", uploader->allowed_chunk = " << uploader->allowed_chunk << endl; 0140 QVERIFY(uploader->allowed_chunk != prev_chunk && uploader->allowed_chunk != INVALID_CHUNK); 0141 QVERIFY(allowCalled(uploader)); 0142 uploader->allow_called = false; 0143 QVERIFY(!allowCalled(downloader)); 0144 } else { 0145 uploader->have(chunk); 0146 downloader->have(chunk); 0147 ss.have(downloader, chunk); 0148 Out(SYS_GEN | LOG_DEBUG) << "prev_chunk = " << chunk << ", uploader->allowed_chunk = " << uploader->allowed_chunk << endl; 0149 QVERIFY(uploader->allowed_chunk != prev_chunk && uploader->allowed_chunk != INVALID_CHUNK); 0150 QVERIFY(allowCalled(uploader)); // allow should be called again on the uploader 0151 uploader->allow_called = false; 0152 } 0153 0154 // Cycle through peers 0155 DummyPeer *n = uploader; 0156 uploader = downloader; 0157 downloader = next; 0158 next = n; 0159 0160 ss.dump(); 0161 } 0162 } 0163 #if 0 0164 void testSeed() 0165 { 0166 Out(SYS_GEN | LOG_DEBUG) << "testSeed" << endl; 0167 SuperSeeder ss(NUM_CHUNKS, this); 0168 0169 for (int i = 0; i < 4; i++) 0170 peer[i].reset(); 0171 0172 // First test, all tree should get a chunk 0173 for (int i = 0; i < 3; i++) { 0174 DummyPeer* p = &peer[i]; 0175 ss.peerAdded(p); 0176 QVERIFY(allowCalled(p)); 0177 QVERIFY(p->allowed_chunk != INVALID_CHUNK); 0178 target.clear(); 0179 } 0180 0181 ss.dump(); 0182 0183 // Now simulate a seed sending a have all message 0184 peer[3].haveAll(); 0185 ss.haveAll(&peer[3]); 0186 QVERIFY(allow_called == false); 0187 target.clear(); 0188 0189 // Continue superseeding 0190 DummyPeer* uploader = &peer[0]; 0191 DummyPeer* downloader = &peer[1]; 0192 DummyPeer* next = &peer[2]; 0193 for (int i = 0; i < 4; i++) { 0194 Out(SYS_GEN | LOG_DEBUG) << "======================================" << endl; 0195 Uint32 prev_chunk = uploader->allowed_chunk; 0196 // Now simulate b downloaded the first chunk from a 0197 Uint32 chunk = prev_chunk; 0198 0199 Out(SYS_GEN | LOG_DEBUG) << "uploader = " << uploader->getPeerID().toString() << endl; 0200 Out(SYS_GEN | LOG_DEBUG) << "downloader = " << downloader->getPeerID().toString() << endl; 0201 Out(SYS_GEN | LOG_DEBUG) << "chunk = " << chunk << endl; 0202 0203 uploader->have(chunk); 0204 downloader->have(chunk); 0205 ss.have(downloader, chunk); 0206 QVERIFY(allowCalled(uploader)); // allow should be called again on the uploader 0207 0208 Out(SYS_GEN | LOG_DEBUG) << "prev_chunk = " << chunk << ", uploader->allowed_chunk = " << uploader->allowed_chunk << endl; 0209 QVERIFY(uploader->allowed_chunk != prev_chunk && uploader->allowed_chunk != INVALID_CHUNK); 0210 target.clear(); 0211 0212 // Cycle through peers 0213 DummyPeer* n = uploader; 0214 uploader = downloader; 0215 downloader = next; 0216 next = n; 0217 0218 ss.dump(); 0219 } 0220 0221 } 0222 #endif 0223 private: 0224 DummyPeer peer[4]; 0225 bool allow_called; 0226 }; 0227 0228 QTEST_MAIN(SuperSeedTest) 0229 0230 #include "superseedtest.moc"