new unit tests, hehe 67
tests / linux (push) Failing after 2m18s
tests / windows (push) Skipped
tests / macos (push) Skipped
tests / package-smoke-linux (push) Skipped
tests / package-smoke-windows (push) Skipped
tests / package-smoke-macos (push) Skipped

Signed-off-by: galeon <dertiellis@gmail.com>
This commit is contained in:
galeon committed 2026-10-12 13:14:08 +03:00
1 parent ebf8ff7869
commit 41599fa82f
67 files changed
+8775 -4

No files matched your search

+181
View File
@@ -0,0 +1,181 @@
#include "testenv.h"
#include "fixtures.h"
#include "nettest.h"
#include "launcherpaths.h"
#include "localization.h"
#include "versionmanifestservice.h"
#include <QJsonArray>
#include <QSignalSpy>
namespace {
const QString kManifest = QStringLiteral("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json");
}
class TestVersionManifestService : public QObject
{
Q_OBJECT
FakeInternet m_net;
private slots:
void initTestCase() { BILAUNCHER_START_FAKE_INTERNET(m_net); }
void init()
{
TestEnv::resetLauncherRoot();
m_net.reset();
}
void loadsSortsAndFilters()
{
m_net.route(kManifest, FakeResponse::json(Fixtures::read("mojang/version_manifest_v2.json")));
VersionManifestService service;
QSignalSpy changed(&service, &VersionManifestService::versionsChanged);
QSignalSpy refreshing(&service, &VersionManifestService::refreshingChanged);
CallResult result;
service.ensureLoaded(result.callback());
QVERIFY(service.isRefreshing());
QTRY_COMPARE_WITH_TIMEOUT(result.calls, 1, 15000);
QVERIFY(result.ok);
QVERIFY(result.warning.isEmpty());
QVERIFY(!service.isRefreshing());
QCOMPARE(changed.count(), 1);
QCOMPARE(refreshing.count(), 2);
// Новые первыми; без id и с http-ссылкой — выброшены.
QStringList ids;
for (const RemoteVersionEntry &entry : service.versions())
ids << entry.id;
QCOMPARE(ids, QStringList({"25w33a", "1.21.8", "1.20.1", "b1.7.3"}));
const auto entry = service.find("1.20.1");
QVERIFY(entry.has_value());
QCOMPARE(entry->type, QStringLiteral("release"));
QCOMPARE(entry->sha1, QStringLiteral("aaaa"));
QCOMPARE(entry->url, QUrl("https://piston-meta.mojang.com/v1/packages/aaaa/1.20.1.json"));
QCOMPARE(entry->releaseTime, QDateTime(QDate(2023, 6, 12), QTime(13, 25, 51), QTimeZone::UTC));
QVERIFY(!service.find("insecure").has_value());
QVERIFY(service.fetchedAt().isValid());
// Кеш на диске записан.
const QJsonObject cache = Fixtures::readJsonFile(LauncherPaths::versionManifestFile());
QCOMPARE(cache.value("versions").toArray().size(), 4);
QVERIFY(!cache.value("fetchedAt").toString().isEmpty());
}
void freshCacheAvoidsNetwork()
{
m_net.route(kManifest, FakeResponse::json(Fixtures::read("mojang/version_manifest_v2.json")));
{
VersionManifestService first;
CallResult r;
first.ensureLoaded(r.callback());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
}
QCOMPARE(m_net.hits(kManifest), 1);
// Новый экземпляр (как после перезапуска лаунчера) берёт свежий кеш.
VersionManifestService second;
CallResult r;
second.ensureLoaded(r.callback());
QVERIFY(second.hasData()); // данные из кеша уже доступны синхронно
QCOMPARE(r.calls, 0); // колбэк — только через цикл событий
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 5000);
QVERIFY(r.ok);
QCOMPARE(m_net.hits(kManifest), 1);
// forceRefresh идёт в сеть даже при свежем кеше.
CallResult forced;
second.ensureLoaded(forced.callback(), true);
QTRY_COMPARE_WITH_TIMEOUT(forced.calls, 1, 15000);
QCOMPARE(m_net.hits(kManifest), 2);
}
void staleCacheIsRefreshed()
{
QJsonObject cache = Fixtures::readJson("mojang/version_manifest_v2.json");
cache["fetchedAt"] = QDateTime::currentDateTimeUtc().addDays(-2).toString(Qt::ISODate);
Fixtures::writeJson(LauncherPaths::versionManifestFile(), cache);
m_net.route(kManifest, FakeResponse::json(Fixtures::read("mojang/version_manifest_v2.json")));
VersionManifestService service;
CallResult r;
service.ensureLoaded(r.callback());
QVERIFY(service.hasData());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
QCOMPARE(m_net.hits(kManifest), 1);
}
void networkErrorWithoutCacheFails()
{
m_net.route(kManifest, FakeResponse::error(503));
VersionManifestService service;
CallResult r;
service.ensureLoaded(r.callback());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
QVERIFY(!r.ok);
QVERIFY(r.warning.startsWith(Loc::text("version.error.manifestFetchFailed").section(u'%', 0, 0)));
QVERIFY(!service.hasData());
}
void networkErrorWithCacheSucceedsWithWarning()
{
QJsonObject cache = Fixtures::readJson("mojang/version_manifest_v2.json");
cache["fetchedAt"] = QDateTime::currentDateTimeUtc().addDays(-2).toString(Qt::ISODate);
Fixtures::writeJson(LauncherPaths::versionManifestFile(), cache);
m_net.route(kManifest, FakeResponse::error(500));
VersionManifestService service;
CallResult r;
service.ensureLoaded(r.callback());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
QVERIFY(r.ok); // офлайн, но список есть
QVERIFY(!r.warning.isEmpty());
QCOMPARE(service.versions().size(), 4);
}
void garbageResponseIsRejected()
{
m_net.route(kManifest, FakeResponse::json("{\"versions\": []}"));
VersionManifestService service;
CallResult r;
service.ensureLoaded(r.callback());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
QVERIFY(!r.ok);
QCOMPARE(r.warning, Loc::text("version.error.manifestUnparsable"));
QVERIFY(!QFile::exists(LauncherPaths::versionManifestFile()));
}
void concurrentCallersShareOneRequest()
{
FakeResponse slow = FakeResponse::json(Fixtures::read("mojang/version_manifest_v2.json"));
slow.delayMs = 300;
m_net.route(kManifest, slow);
VersionManifestService service;
CallResult a, b, c;
service.ensureLoaded(a.callback());
service.ensureLoaded(b.callback());
service.ensureLoaded(c.callback());
QTRY_VERIFY_WITH_TIMEOUT(a.calls == 1 && b.calls == 1 && c.calls == 1, 15000);
QVERIFY(a.ok && b.ok && c.ok);
QCOMPARE(m_net.hits(kManifest), 1);
}
void corruptCacheIsIgnored()
{
Fixtures::write(LauncherPaths::versionManifestFile(), "\x00\x01garbage");
m_net.route(kManifest, FakeResponse::json(Fixtures::read("mojang/version_manifest_v2.json")));
VersionManifestService service;
CallResult r;
service.ensureLoaded(r.callback());
QVERIFY(!service.hasData());
QTRY_COMPARE_WITH_TIMEOUT(r.calls, 1, 15000);
QVERIFY(r.ok);
QVERIFY(service.hasData());
}
};
BILAUNCHER_TEST_MAIN(TestVersionManifestService)
#include "tst_versionmanifestservice.moc"