// Самопроверка FakeInternet: если она красная, остальные сетевые тесты // бессмысленны — значит, перехват трафика на этой платформе не работает. #include "testenv.h" #include "fakeinternet.h" #include "nettest.h" #include #include #include class TestFakeInternet : public QObject { Q_OBJECT FakeInternet m_net; QNetworkReply *get(QNetworkAccessManager &manager, const QString &url) { return manager.get(QNetworkRequest(QUrl(url))); } static bool waitFinished(QNetworkReply *reply) { if (reply->isFinished()) return true; QSignalSpy spy(reply, &QNetworkReply::finished); return spy.wait(15000); } private slots: void initTestCase() { BILAUNCHER_START_FAKE_INTERNET(m_net); } void init() { m_net.reset(); } void httpsGetIsIntercepted() { m_net.route(QStringLiteral("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json"), FakeResponse::json(QByteArrayLiteral("{\"ok\":true}"))); QNetworkAccessManager manager; QScopedPointer reply( get(manager, QStringLiteral("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json?x=1"))); QVERIFY(waitFinished(reply.data())); QCOMPARE(reply->error(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->readAll(), QByteArrayLiteral("{\"ok\":true}")); QCOMPARE(m_net.hits(QStringLiteral("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json")), 1); QCOMPARE(m_net.requests().constFirst().query, QStringLiteral("x=1")); } void postBodyAndHeaders() { m_net.route(QStringLiteral("https://authserver.ely.by/auth/authenticate"), [](const FakeRequest &request) { return FakeResponse::json(request.body, request.method == "POST" ? 200 : 405); }); QNetworkAccessManager manager; QNetworkRequest request(QUrl(QStringLiteral("https://authserver.ely.by/auth/authenticate"))); request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json")); QScopedPointer reply(manager.post(request, QByteArrayLiteral("{\"a\":1}"))); QVERIFY(waitFinished(reply.data())); QCOMPARE(reply->readAll(), QByteArrayLiteral("{\"a\":1}")); QCOMPARE(m_net.requests().constFirst().header("content-type"), QByteArrayLiteral("application/json")); } void prefixRoutesAndKeepAlive() { m_net.route(QStringLiteral("https://resources.download.minecraft.net/*"), [](const FakeRequest &request) { return FakeResponse::text(request.path.toUtf8()); }); QNetworkAccessManager manager; for (int i = 0; i < 5; ++i) { const QString path = QStringLiteral("/ab/ab%1").arg(i); QScopedPointer reply( get(manager, QStringLiteral("https://resources.download.minecraft.net") + path)); QVERIFY(waitFinished(reply.data())); QCOMPARE(reply->readAll(), path.toUtf8()); } QCOMPARE(m_net.requests().size(), 5); } void unknownRouteIs404AndRecorded() { QNetworkAccessManager manager; QTest::ignoreMessage(QtWarningMsg, QRegularExpression(QStringLiteral("FakeInternet: нет маршрута"))); QScopedPointer reply(get(manager, QStringLiteral("https://example.invalid/x"))); QVERIFY(waitFinished(reply.data())); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 404); QCOMPARE(m_net.unmatched(), QStringList{QStringLiteral("https://example.invalid/x")}); } void errorStatusesAndDrop() { m_net.route(QStringLiteral("https://a.test/500"), FakeResponse::error(500)); m_net.route(QStringLiteral("https://a.test/drop"), [] { FakeResponse response; response.drop = true; return response; }()); QNetworkAccessManager manager; QScopedPointer r500(get(manager, QStringLiteral("https://a.test/500"))); QVERIFY(waitFinished(r500.data())); QCOMPARE(r500->error(), QNetworkReply::InternalServerError); QScopedPointer drop(get(manager, QStringLiteral("https://a.test/drop"))); QVERIFY(waitFinished(drop.data())); QVERIFY(drop->error() != QNetworkReply::NoError); } void truncatedResponse_data() { QTest::addColumn("bytes"); QTest::newRow("empty") << 0; QTest::newRow("short") << 10; QTest::newRow("multiple-tls-records") << 65536; QTest::newRow("last-byte-missing") << 256 * 1024 - 1; } void truncatedResponse() { QFETCH(int, bytes); const QByteArray body(256 * 1024, 'x'); FakeResponse cut = FakeResponse::bytes(body); cut.truncateTo = bytes; m_net.route(QStringLiteral("https://a.test/short"), cut); QNetworkAccessManager manager; QScopedPointer shortReply(get(manager, QStringLiteral("https://a.test/short"))); QVERIFY2(waitFinished(shortReply.data()), qPrintable(m_net.diagnostics() + "\nClient: " + shortReply->errorString())); QVERIFY(shortReply->error() != QNetworkReply::NoError); QCOMPARE(shortReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(shortReply->readAll(), body.left(bytes)); } void plainHttpThroughProxy() { m_net.route(QStringLiteral("http://plain.test/hello"), FakeResponse::text("hi")); QNetworkAccessManager manager; QScopedPointer reply(get(manager, QStringLiteral("http://plain.test/hello"))); QVERIFY(waitFinished(reply.data())); QCOMPARE(reply->readAll(), QByteArrayLiteral("hi")); QCOMPARE(m_net.requests().constFirst().scheme, QStringLiteral("http")); } }; BILAUNCHER_TEST_MAIN(TestFakeInternet) #include "tst_fakeinternet.moc"