1 parent
ebf8ff7869
commit
41599fa82f
67 files changed
+8775
-4
No files matched your search
@@ -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"
|
||||
Reference in new issue
Block a user