From 7bc517e20bfc5d131a16b92262048e647cce618b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 27 Nov 2024 17:01:57 +0100 Subject: [PATCH] Make autotests even more robust against timeouts These now use the information about job back-off strategies to calculate precisely how long they should wait for a job to complete. --- autotests/testolmaccount.cpp | 46 +++++++++++++++++++----------------- autotests/testutils.h | 13 +++++++--- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/autotests/testolmaccount.cpp b/autotests/testolmaccount.cpp index eb0214c26..ef6296f39 100644 --- a/autotests/testolmaccount.cpp +++ b/autotests/testolmaccount.cpp @@ -214,7 +214,7 @@ void TestOlmAccount::uploadOneTimeKeys() QCOMPARE(oneTimeKeyCounts.value(Curve25519Key), 5); }, [] { QFAIL("upload failed"); }); - QVERIFY(waitForFuture(uploadFuture)); + QVERIFY(waitForJob(uploadFuture)); } void TestOlmAccount::uploadSignedOneTimeKeys() @@ -233,7 +233,7 @@ void TestOlmAccount::uploadSignedOneTimeKeys() QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), nKeys); }, [] { QFAIL("upload failed"); }); - QVERIFY(waitForFuture(uploadFuture)); + QVERIFY(waitForJob(uploadFuture)); } void TestOlmAccount::uploadKeys() @@ -249,7 +249,7 @@ void TestOlmAccount::uploadKeys() QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), 1); }, [] { QFAIL("upload failed"); }); - QVERIFY(waitForFuture(request)); + QVERIFY(waitForJob(request)); } void TestOlmAccount::queryTest() @@ -265,7 +265,7 @@ void TestOlmAccount::queryTest() .then([](const QHash& aliceOneTimeKeyCounts) { QCOMPARE(aliceOneTimeKeyCounts.value(SignedCurve25519Key), 1); }); - QVERIFY(waitForFuture(aliceUploadKeysRequest)); + QVERIFY(waitForJob(aliceUploadKeysRequest)); auto bobOlm = bob->olmAccount(); bobOlm->generateOneTimeKeys(1); @@ -274,7 +274,7 @@ void TestOlmAccount::queryTest() .then([](const QHash& bobOneTimeKeyCounts) { QCOMPARE(bobOneTimeKeyCounts.value(SignedCurve25519Key), 1); }); - QVERIFY(waitForFuture(bobUploadKeysRequest)); + QVERIFY(waitForJob(bobUploadKeysRequest)); // Each user is requests each other's keys. const QHash deviceKeysForBob{ { bob->userId(), {} } }; @@ -292,7 +292,7 @@ void TestOlmAccount::queryTest() QCOMPARE(aliceDevKeys.keys, bobOlm->deviceKeys().keys); QCOMPARE(aliceDevKeys.signatures, bobOlm->deviceKeys().signatures); }); - QVERIFY(waitForFuture(queryBobKeysResult)); + QVERIFY(waitForJob(queryBobKeysResult)); const QHash deviceKeysForAlice{ { alice->userId(), {} } }; const auto queryAliceKeysResult = @@ -309,7 +309,7 @@ void TestOlmAccount::queryTest() QCOMPARE(devKeys.keys, aliceOlm->deviceKeys().keys); QCOMPARE(devKeys.signatures, aliceOlm->deviceKeys().signatures); }); - QVERIFY(waitForFuture(queryAliceKeysResult)); + QVERIFY(waitForJob(queryAliceKeysResult)); } void TestOlmAccount::claimKeys() @@ -324,7 +324,7 @@ void TestOlmAccount::claimKeys() .then([bob](const QHash& oneTimeKeyCounts) { QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), 1); }); - QVERIFY(waitForFuture(request)); + QVERIFY(waitForJob(request)); // Alice retrieves bob's keys & claims one signed one-time key. const QHash deviceKeysToQuery{ { bob->userId(), {} } }; @@ -336,7 +336,7 @@ void TestOlmAccount::claimKeys() QVERIFY(verifyIdentitySignature(bobDevices.value(bob->deviceId()), bob->deviceId(), bob->userId())); }); - QVERIFY(waitForFuture(queryKeysJob)); + QVERIFY(waitForJob(queryKeysJob)); // Retrieve the identity key for the current device to check after claiming // const auto& bobEd25519 = @@ -363,7 +363,7 @@ void TestOlmAccount::claimKeys() } }, [] { QFAIL("Claim job failed"); }); - QVERIFY(waitForFuture(claimKeysJob)); + QVERIFY(waitForJob(claimKeysJob)); } void TestOlmAccount::claimMultipleKeys() @@ -380,7 +380,7 @@ void TestOlmAccount::claimMultipleKeys() .then([](const QHash& oneTimeKeyCounts) { QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), 10); }); - QVERIFY(waitForFuture(aliceUploadKeyRequest)); + QVERIFY(waitForJob(aliceUploadKeyRequest)); auto olm1 = alice1->olmAccount(); olm1->generateOneTimeKeys(10); @@ -389,7 +389,7 @@ void TestOlmAccount::claimMultipleKeys() .then([](const QHash& oneTimeKeyCounts) { QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), 10); }); - QVERIFY(waitForFuture(alice1UploadKeyRequest)); + QVERIFY(waitForJob(alice1UploadKeyRequest)); auto olm2 = alice2->olmAccount(); olm2->generateOneTimeKeys(10); @@ -398,7 +398,7 @@ void TestOlmAccount::claimMultipleKeys() .then([](const QHash& oneTimeKeyCounts) { QCOMPARE(oneTimeKeyCounts.value(SignedCurve25519Key), 10); }); - QVERIFY(waitForFuture(alice2UploadKeyRequest)); + QVERIFY(waitForJob(alice2UploadKeyRequest)); // Bob will claim keys from all Alice's devices CREATE_CONNECTION(bob, "bob3"_L1, "secret"_L1, "BobPhone"_L1) @@ -412,22 +412,24 @@ void TestOlmAccount::claimMultipleKeys() bob->callApi(oneTimeKeys).then([alice](const ClaimKeysJob::Response& r) { QCOMPARE(r.oneTimeKeys.value(alice->userId()).size(), 3); }); - QVERIFY(waitForFuture(claimResult)); + QVERIFY(waitForJob(claimResult)); } void TestOlmAccount::enableEncryption() { CREATE_CONNECTION(alice, "alice9"_L1, "secret"_L1, "AlicePhone"_L1) - const auto futureRoom = alice->createRoom(Connection::PublishRoom, {}, {}, {}, {}) - .then([alice](const QString& roomId) { - auto room = alice->room(roomId); - room->activateEncryption(); - return room; - }); - QVERIFY(waitForFuture(futureRoom)); + auto createRoomJob = alice->createRoom(Connection::PublishRoom, {}, {}, {}, {}); + auto futureEncryptedRoom = createRoomJob.then([alice](const QString& roomId) { + auto room = alice->room(roomId); + room->activateEncryption(); + return room; + }); + QVERIFY(waitForJob(createRoomJob)); alice->syncLoop(); - QVERIFY(QTest::qWaitFor([room = futureRoom.result()] { return room->usesEncryption(); }, 40000)); + // Give extra 5 seconds for the network roundtrip + QVERIFY(QTest::qWaitFor(std::bind_front(&Room::usesEncryption, futureEncryptedRoom.result()), + SyncJob::defaultTimeoutMillis * 2 + 5000)); } QTEST_GUILESS_MAIN(TestOlmAccount) diff --git a/autotests/testutils.h b/autotests/testutils.h index 77291c1b7..bd4d78a0e 100644 --- a/autotests/testutils.h +++ b/autotests/testutils.h @@ -11,6 +11,8 @@ namespace Quotient { class Connection; +template +class JobHandle; std::shared_ptr createTestConnection(QLatin1StringView localUserName, QLatin1StringView secret, @@ -22,8 +24,13 @@ std::shared_ptr createTestConnection(QLatin1StringView localUserName if (!VAR) \ QFAIL("Could not set up test connection"); -inline bool waitForFuture(const auto& ft) - requires requires { ft.isFinished(); } +template +inline bool waitForJob(const Quotient::JobHandle& job) { - return QTest::qWaitFor([ft] { return ft.isFinished(); }, 40000); + const auto& [timeouts, retryIntervals, _] = job->currentBackoffStrategy(); + return QTest::qWaitFor([job] { return job.isFinished(); }, + std::chrono::milliseconds( + std::reduce(timeouts.cbegin(), timeouts.cend()) + + std::reduce(retryIntervals.cbegin(), retryIntervals.cend())) + .count()); }