File indexing completed on 2024-05-12 04:59:53
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 #include <QTest> 0007 0008 #include <future> 0009 #include <thread> 0010 0011 #include "transfer.h" 0012 0013 class TransferTest : public QObject 0014 { 0015 Q_OBJECT 0016 private Q_SLOTS: 0017 void testSegmentOnSmallFile() 0018 { 0019 // Files smaller than our minimal segment size ought to be transferred in one go 0020 // otherwise we have a chance of degrading performance. 0021 QCOMPARE(TransferSegment(1).buf.size(), 1); 0022 } 0023 0024 void testMaxSegment() 0025 { 0026 // Large files may only use up to a given maximum. 0027 QCOMPARE(TransferSegment(512 * 1024 * 1024).buf.size(), c_maxSegmentSize); 0028 } 0029 0030 void testIdealSegmentSize() 0031 { 0032 QCOMPARE(TransferSegment(64 * 1024 * 1024).buf.size(), 1342177); 0033 } 0034 0035 void testSegment() 0036 { 0037 TransferSegment s(8); 0038 QCOMPARE(s.buf.size(), 8); 0039 memset(s.buf.data(), 1, 8); 0040 QCOMPARE(s.buf.data()[0], 1); 0041 } 0042 0043 void testRing() 0044 { 0045 TransferRingBuffer ring(8); 0046 for (auto i = 0; i <= 32; ++i) { 0047 { 0048 auto s = ring.nextFree(); 0049 memset(s->buf.data(), i, 8); 0050 ring.push(); 0051 } 0052 { 0053 auto s = ring.pop(); 0054 QCOMPARE(s->buf.data()[0], static_cast<char>(i)); 0055 ring.unpop(); 0056 } 0057 } 0058 } 0059 0060 void testRingThreadedSlowPush() 0061 { 0062 const auto runs = 127; 0063 const auto fileSize = 8; 0064 TransferRingBuffer ring(fileSize); 0065 0066 std::atomic<bool> abort(false); 0067 0068 auto pullFuture = std::async(std::launch::async, [&ring, &abort]() -> bool { 0069 for (auto i = 0; i <= runs && !abort; ++i) { 0070 auto s = ring.pop(); 0071 if (!QTest::qCompare(s->buf.data()[0], 0072 static_cast<char>(i), 0073 qPrintable(QStringLiteral("On pull iteration %1").arg(i)), 0074 "", 0075 __FILE__, 0076 __LINE__)) { 0077 abort = true; 0078 return false; 0079 } 0080 ring.unpop(); 0081 } 0082 return true; 0083 }); 0084 0085 auto pushFuture = std::async(std::launch::async, [&ring, &abort]() -> bool { 0086 for (auto i = 0; i <= runs && !abort; ++i) { 0087 auto s = ring.nextFree(); 0088 memset(s->buf.data(), i, fileSize); 0089 ring.push(); 0090 if (abort) { 0091 ring.done(); 0092 return false; 0093 } 0094 // Slow down this thread to simulate slow network reads. 0095 std::this_thread::sleep_for(std::chrono::milliseconds(5)); 0096 } 0097 ring.done(); 0098 return true; 0099 }); 0100 0101 pushFuture.wait(); 0102 pullFuture.wait(); 0103 0104 QVERIFY(pushFuture.get()); 0105 QVERIFY(pullFuture.get()); 0106 } 0107 0108 void testRingThreadedSlowPull() 0109 { 0110 const auto runs = 127; 0111 const auto fileSize = 8; 0112 TransferRingBuffer ring(fileSize); 0113 0114 std::atomic<bool> abort(false); 0115 0116 auto pullFuture = std::async(std::launch::async, [&ring, &abort]() -> bool { 0117 for (auto i = 0; i <= runs && !abort; ++i) { 0118 auto s = ring.pop(); 0119 if (!QTest::qCompare(s->buf.data()[0], 0120 static_cast<char>(i), 0121 qPrintable(QStringLiteral("On pull iteration %1").arg(i)), 0122 "", 0123 __FILE__, 0124 __LINE__)) { 0125 abort = true; 0126 } 0127 // Slow down this thread to simulate slow local writes. 0128 std::this_thread::sleep_for(std::chrono::milliseconds(5)); 0129 ring.unpop(); 0130 } 0131 return true; 0132 }); 0133 0134 auto pushFuture = std::async(std::launch::async, [&ring, &abort]() -> bool { 0135 for (auto i = 0; i <= runs && !abort; ++i) { 0136 auto s = ring.nextFree(); 0137 memset(s->buf.data(), i, fileSize); 0138 if (abort) { 0139 ring.done(); 0140 return false; 0141 } 0142 ring.push(); 0143 } 0144 ring.done(); 0145 return true; 0146 }); 0147 0148 pushFuture.wait(); 0149 pullFuture.wait(); 0150 0151 QVERIFY(pushFuture.get()); 0152 QVERIFY(pullFuture.get()); 0153 } 0154 }; 0155 0156 QTEST_GUILESS_MAIN(TransferTest) 0157 0158 #include "transfertest.moc"