1 parent
ebf8ff7869
commit
41599fa82f
67 files changed
+8775
-4
No files matched your search
@@ -0,0 +1,450 @@
|
||||
#include "testenv.h"
|
||||
#include "fixtures.h"
|
||||
|
||||
#include "gamelauncher.h"
|
||||
#include "javalocator.h"
|
||||
#include "localization.h"
|
||||
#include "minecraftversion.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSignalSpy>
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
const QChar kSep = u';';
|
||||
const char *kNativeName = "lwjgl.dll";
|
||||
#elif defined(Q_OS_MACOS)
|
||||
const QChar kSep = u':';
|
||||
const char *kNativeName = "liblwjgl.dylib";
|
||||
#else
|
||||
const QChar kSep = u':';
|
||||
const char *kNativeName = "liblwjgl.so";
|
||||
#endif
|
||||
|
||||
QString nat(const QString &path)
|
||||
{
|
||||
return QDir::toNativeSeparators(path);
|
||||
}
|
||||
|
||||
MinecraftLibrary lib(const QString &name, const QString &path, bool native = false)
|
||||
{
|
||||
MinecraftLibrary library;
|
||||
library.name = name;
|
||||
library.path = path;
|
||||
library.native = native;
|
||||
return library;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class TestGameLauncher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QString m_game;
|
||||
|
||||
MinecraftVersion modernVersion() const
|
||||
{
|
||||
MinecraftVersion v;
|
||||
v.id = QStringLiteral("1.20.1");
|
||||
v.mainClass = QStringLiteral("net.minecraft.client.main.Main");
|
||||
v.type = QStringLiteral("release");
|
||||
v.assetIndexId = QStringLiteral("5");
|
||||
v.assetsKind = QStringLiteral("5");
|
||||
v.clientJarPath = m_game + QStringLiteral("/versions/1.20.1/1.20.1.jar");
|
||||
v.javaMajor = 17;
|
||||
v.jvmArgs = QStringList{"-Djava.library.path=${natives_directory}",
|
||||
"-Dminecraft.launcher.brand=${launcher_name}",
|
||||
"-Dminecraft.launcher.version=${launcher_version}",
|
||||
"-Dunknown=${not_a_variable}",
|
||||
"-cp", "${classpath}"};
|
||||
v.gameArgs = QStringList{"--username", "${auth_player_name}", "--version", "${version_name}",
|
||||
"--gameDir", "${game_directory}", "--assetsDir", "${assets_root}",
|
||||
"--assetIndex", "${assets_index_name}", "--uuid", "${auth_uuid}",
|
||||
"--accessToken", "${auth_access_token}", "--clientId", "${clientid}",
|
||||
"--xuid", "${auth_xuid}", "--userType", "${user_type}",
|
||||
"--versionType", "${version_type}", "--mystery", "${unknown_thing}"};
|
||||
v.libraries << lib("com.mojang:brigadier:1.1.8", "com/mojang/brigadier-1.1.8.jar")
|
||||
<< lib("org.lwjgl:lwjgl:3.3.1", "org/lwjgl/lwjgl-3.3.1.jar")
|
||||
<< lib("org.lwjgl:lwjgl:3.3.1:natives", "org/lwjgl/lwjgl-3.3.1-natives.jar", true);
|
||||
return v;
|
||||
}
|
||||
|
||||
LaunchOptions options() const
|
||||
{
|
||||
LaunchOptions o;
|
||||
o.gameDir = m_game;
|
||||
o.versionId = QStringLiteral("1.20.1");
|
||||
o.playerName = QStringLiteral("Steve");
|
||||
o.uuid = QStringLiteral("0123456789abcdef0123456789abcdef");
|
||||
o.accessToken = QStringLiteral("secret-token");
|
||||
o.userType = QStringLiteral("msa");
|
||||
o.minMemoryMb = 1024;
|
||||
o.maxMemoryMb = 6144;
|
||||
return o;
|
||||
}
|
||||
|
||||
static QString valueAfter(const QStringList &args, const QString &flag)
|
||||
{
|
||||
const qsizetype i = args.indexOf(flag);
|
||||
return (i >= 0 && i + 1 < args.size()) ? args.at(i + 1) : QString();
|
||||
}
|
||||
|
||||
void createGameFiles(const MinecraftVersion &v)
|
||||
{
|
||||
Fixtures::write(v.clientJarPath, "client");
|
||||
Fixtures::write(m_game + "/libraries/com/mojang/brigadier-1.1.8.jar", "lib");
|
||||
Fixtures::write(m_game + "/libraries/org/lwjgl/lwjgl-3.3.1.jar", "lib");
|
||||
Fixtures::makeZip(m_game + "/libraries/org/lwjgl/lwjgl-3.3.1-natives.jar",
|
||||
{{QStringLiteral("META-INF/MANIFEST.MF"), "x"},
|
||||
{QStringLiteral("linux/x64/org/lwjgl/") + kNativeName, "native-bytes"},
|
||||
{QStringLiteral("skip/") + kNativeName + ".sha1", "hash"}});
|
||||
Fixtures::write(m_game + "/assets/indexes/5.json", "{}");
|
||||
QDir().mkpath(m_game + "/assets/objects");
|
||||
}
|
||||
|
||||
private slots:
|
||||
void init()
|
||||
{
|
||||
TestEnv::resetLauncherRoot();
|
||||
m_game = TestEnv::freshDir(QStringLiteral("game"));
|
||||
}
|
||||
|
||||
// --- buildArguments ---------------------------------------------------------
|
||||
|
||||
void substitutesVariables()
|
||||
{
|
||||
const MinecraftVersion v = modernVersion();
|
||||
const QString natives = m_game + "/versions/1.20.1/natives";
|
||||
const QStringList args = GameLauncher::buildArguments(options(), v, natives);
|
||||
|
||||
QCOMPARE(args.at(0), QStringLiteral("-Xms1024M"));
|
||||
QCOMPARE(args.at(1), QStringLiteral("-Xmx6144M"));
|
||||
QVERIFY(args.contains("-Djava.library.path=" + nat(natives)));
|
||||
QVERIFY(args.contains("-Dminecraft.launcher.brand=BiLauncher"));
|
||||
QVERIFY(args.contains(QStringLiteral("-Dminecraft.launcher.version=") + QStringLiteral(LAUNCHER_VERSION)));
|
||||
// Неизвестный плейсхолдер — аргумент выбрасывается целиком.
|
||||
QVERIFY(!args.join(' ').contains("not_a_variable"));
|
||||
QVERIFY(!args.contains("${unknown_thing}"));
|
||||
QVERIFY(args.contains("--mystery")); // сам флаг остаётся, как у официального лаунчера
|
||||
|
||||
// classpath: обычные библиотеки, без нативов, клиентский jar последним.
|
||||
const QStringList cp = valueAfter(args, "-cp").split(kSep);
|
||||
QCOMPARE(cp, QStringList({nat(m_game + "/libraries/com/mojang/brigadier-1.1.8.jar"),
|
||||
nat(m_game + "/libraries/org/lwjgl/lwjgl-3.3.1.jar"),
|
||||
nat(v.clientJarPath)}));
|
||||
|
||||
// mainClass — после jvm-аргументов, перед игровыми.
|
||||
const qsizetype main = args.indexOf(v.mainClass);
|
||||
QVERIFY(main > args.indexOf("-cp"));
|
||||
QVERIFY(main < args.indexOf("--username"));
|
||||
|
||||
QCOMPARE(valueAfter(args, "--username"), QStringLiteral("Steve"));
|
||||
QCOMPARE(valueAfter(args, "--version"), QStringLiteral("1.20.1"));
|
||||
QCOMPARE(valueAfter(args, "--gameDir"), nat(m_game));
|
||||
QCOMPARE(valueAfter(args, "--assetsDir"), nat(m_game + "/assets"));
|
||||
QCOMPARE(valueAfter(args, "--assetIndex"), QStringLiteral("5"));
|
||||
QCOMPARE(valueAfter(args, "--uuid"), QStringLiteral("0123456789abcdef0123456789abcdef"));
|
||||
QCOMPARE(valueAfter(args, "--accessToken"), QStringLiteral("secret-token"));
|
||||
QCOMPARE(valueAfter(args, "--clientId"), QStringLiteral("0")); // пустой → «0»
|
||||
QCOMPARE(valueAfter(args, "--xuid"), QStringLiteral("0"));
|
||||
QCOMPARE(valueAfter(args, "--userType"), QStringLiteral("msa"));
|
||||
QCOMPARE(valueAfter(args, "--versionType"), QStringLiteral("release"));
|
||||
QVERIFY(!args.contains("--width"));
|
||||
QVERIFY(!args.contains("--fullscreen"));
|
||||
QVERIFY(!args.contains("--server"));
|
||||
}
|
||||
|
||||
void legacyAssetsAndSession()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
v.assetsKind = QStringLiteral("legacy");
|
||||
v.gameArgs = QStringList{"--session", "${auth_session}", "--assetsDir", "${game_assets}"};
|
||||
const QStringList args = GameLauncher::buildArguments(options(), v, m_game + "/n");
|
||||
QCOMPARE(valueAfter(args, "--session"),
|
||||
QStringLiteral("token:secret-token:0123456789abcdef0123456789abcdef"));
|
||||
QCOMPARE(valueAfter(args, "--assetsDir"), nat(m_game + "/assets/virtual/legacy"));
|
||||
|
||||
v.assetsKind = QStringLiteral("pre-1.6");
|
||||
QCOMPARE(valueAfter(GameLauncher::buildArguments(options(), v, m_game + "/n"), "--assetsDir"),
|
||||
nat(m_game + "/assets/virtual/legacy"));
|
||||
v.assetsKind = QStringLiteral("5");
|
||||
QCOMPARE(valueAfter(GameLauncher::buildArguments(options(), v, m_game + "/n"), "--assetsDir"),
|
||||
nat(m_game + "/assets"));
|
||||
}
|
||||
|
||||
void memoryAndExtraJvmArgs()
|
||||
{
|
||||
LaunchOptions o = options();
|
||||
o.minMemoryMb = 0;
|
||||
o.maxMemoryMb = 0;
|
||||
o.extraJvmArgs = QStringList{"-XX:+UseG1GC", "-Dfoo=bar"};
|
||||
const QStringList args = GameLauncher::buildArguments(o, modernVersion(), m_game + "/n");
|
||||
QVERIFY(!args.join(' ').contains("-Xms"));
|
||||
QVERIFY(!args.join(' ').contains("-Xmx"));
|
||||
QCOMPARE(args.at(0), QStringLiteral("-XX:+UseG1GC"));
|
||||
QCOMPARE(args.at(1), QStringLiteral("-Dfoo=bar"));
|
||||
}
|
||||
|
||||
void authlibInjectorGoesFirst()
|
||||
{
|
||||
LaunchOptions o = options();
|
||||
o.authlibInjectorPath = m_game + "/authlib-injector.jar";
|
||||
const QStringList args = GameLauncher::buildArguments(o, modernVersion(), m_game + "/n");
|
||||
QCOMPARE(args.at(0), "-javaagent:" + nat(o.authlibInjectorPath) + "=ely.by");
|
||||
QCOMPARE(args.at(1), QStringLiteral("-Dauthlibinjector.side=client"));
|
||||
QCOMPARE(args.at(2), QStringLiteral("-Xms1024M"));
|
||||
}
|
||||
|
||||
void windowSizeAndFullscreen()
|
||||
{
|
||||
LaunchOptions o = options();
|
||||
o.windowWidth = 1280;
|
||||
o.windowHeight = 720;
|
||||
o.fullscreen = true;
|
||||
MinecraftVersion v = modernVersion();
|
||||
QStringList args = GameLauncher::buildArguments(o, v, m_game + "/n");
|
||||
QCOMPARE(valueAfter(args, "--width"), QStringLiteral("1280"));
|
||||
QCOMPARE(valueAfter(args, "--height"), QStringLiteral("720"));
|
||||
QCOMPARE(args.count("--fullscreen"), 1);
|
||||
|
||||
// У версии свои аргументы разрешения — лаунчер свои не дублирует.
|
||||
v.hasCustomResolutionArgs = true;
|
||||
v.gameArgs << "--width" << "${resolution_width}" << "--height" << "${resolution_height}";
|
||||
args = GameLauncher::buildArguments(o, v, m_game + "/n");
|
||||
QCOMPARE(args.count("--width"), 1);
|
||||
QCOMPARE(valueAfter(args, "--width"), QStringLiteral("1280"));
|
||||
|
||||
// Только ширина — не передаём ничего.
|
||||
o.windowHeight = 0;
|
||||
o.fullscreen = false;
|
||||
args = GameLauncher::buildArguments(o, modernVersion(), m_game + "/n");
|
||||
QVERIFY(!args.contains("--width"));
|
||||
QVERIFY(!args.contains("--fullscreen"));
|
||||
}
|
||||
|
||||
void serverAutoJoin_data()
|
||||
{
|
||||
QTest::addColumn<bool>("quickPlay");
|
||||
QTest::addColumn<QString>("address");
|
||||
QTest::addColumn<QStringList>("expectedTail");
|
||||
|
||||
QTest::newRow("quickplay") << true << "play.example.com:25570"
|
||||
<< QStringList{"--quickPlayMultiplayer", "play.example.com:25570"};
|
||||
QTest::newRow("legacy with port") << false << "play.example.com:25570"
|
||||
<< QStringList{"--server", "play.example.com", "--port", "25570"};
|
||||
QTest::newRow("legacy default port") << false << "play.example.com"
|
||||
<< QStringList{"--server", "play.example.com", "--port", "25565"};
|
||||
}
|
||||
|
||||
void serverAutoJoin()
|
||||
{
|
||||
QFETCH(bool, quickPlay);
|
||||
QFETCH(QString, address);
|
||||
QFETCH(QStringList, expectedTail);
|
||||
LaunchOptions o = options();
|
||||
o.serverAddress = address;
|
||||
MinecraftVersion v = modernVersion();
|
||||
v.supportsQuickPlay = quickPlay;
|
||||
const QStringList args = GameLauncher::buildArguments(o, v, m_game + "/n");
|
||||
QCOMPARE(args.mid(args.size() - expectedTail.size()), expectedTail);
|
||||
}
|
||||
|
||||
void forgeIgnoreListGetsClientJar()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
v.jvmArgs.prepend("-DignoreList=bootstraplauncher,securejarhandler,${version_name}.jar");
|
||||
QStringList args = GameLauncher::buildArguments(options(), v, m_game + "/n");
|
||||
// ${version_name} = 1.20.1 совпадает с именем jar — дописывать нечего.
|
||||
QCOMPARE(args.filter("-DignoreList=").constFirst(),
|
||||
QStringLiteral("-DignoreList=bootstraplauncher,securejarhandler,1.20.1.jar"));
|
||||
|
||||
// Профиль Forge со своим id, а jar родительский — имя jar дописывается.
|
||||
v.id = QStringLiteral("1.20.1-forge-47.4.0");
|
||||
args = GameLauncher::buildArguments(options(), v, m_game + "/n");
|
||||
QCOMPARE(args.filter("-DignoreList=").constFirst(),
|
||||
QStringLiteral("-DignoreList=bootstraplauncher,securejarhandler,1.20.1-forge-47.4.0.jar,1.20.1.jar"));
|
||||
}
|
||||
|
||||
void loggingArgumentOnlyWhenConfigExists()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
v.loggingArgument = QStringLiteral("-Dlog4j.configurationFile=${path}");
|
||||
v.loggingConfigPath = m_game + "/assets/log_configs/client-1.12.xml";
|
||||
QVERIFY(GameLauncher::buildArguments(options(), v, m_game + "/n").filter("log4j").isEmpty());
|
||||
|
||||
Fixtures::write(v.loggingConfigPath, "<xml/>");
|
||||
const QStringList args = GameLauncher::buildArguments(options(), v, m_game + "/n");
|
||||
QCOMPARE(args.filter("log4j"), QStringList{"-Dlog4j.configurationFile=" + nat(v.loggingConfigPath)});
|
||||
QVERIFY(args.indexOf(args.filter("log4j").constFirst()) < args.indexOf(v.mainClass));
|
||||
}
|
||||
|
||||
// --- missingFiles / extractNatives -------------------------------------------
|
||||
|
||||
void missingFiles()
|
||||
{
|
||||
const MinecraftVersion v = modernVersion();
|
||||
LaunchOptions o = options();
|
||||
|
||||
o.gameDir = m_game + "/does-not-exist";
|
||||
QCOMPARE(GameLauncher::missingFiles(o, v), QStringList{nat(o.gameDir)});
|
||||
|
||||
o = options();
|
||||
QStringList missing = GameLauncher::missingFiles(o, v);
|
||||
QVERIFY(missing.contains(nat(v.clientJarPath)));
|
||||
QVERIFY(missing.contains(nat(m_game + "/libraries/com/mojang/brigadier-1.1.8.jar")));
|
||||
QVERIFY(missing.contains(nat(m_game + "/assets/indexes/5.json")));
|
||||
QCOMPARE(GameLauncher::missingFiles(o, v, 2).size(), 2);
|
||||
|
||||
createGameFiles(v);
|
||||
QVERIFY(GameLauncher::missingFiles(o, v).isEmpty());
|
||||
|
||||
QDir(m_game + "/assets/objects").removeRecursively();
|
||||
QCOMPARE(GameLauncher::missingFiles(o, v), QStringList{nat(m_game + "/assets/objects")});
|
||||
}
|
||||
|
||||
void extractNatives()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
createGameFiles(v);
|
||||
const QString natives = m_game + "/versions/1.20.1/natives";
|
||||
|
||||
QString error;
|
||||
QVERIFY2(GameLauncher::extractNatives(options(), v, natives, &error), qPrintable(error));
|
||||
// Только сама библиотека: без META-INF и без .sha1, в плоскую папку.
|
||||
QCOMPARE(Fixtures::listTree(natives), QStringList{QString::fromLatin1(kNativeName)});
|
||||
QCOMPARE(Fixtures::readFile(natives + u'/' + kNativeName), QByteArray("native-bytes"));
|
||||
|
||||
// Повторный запуск поверх готовой папки — успех.
|
||||
QVERIFY(GameLauncher::extractNatives(options(), v, natives, &error));
|
||||
|
||||
// extractExclude по префиксу пути внутри архива.
|
||||
QDir(natives).removeRecursively();
|
||||
v.libraries[2].extractExclude = QStringList{"linux/"};
|
||||
QVERIFY(GameLauncher::extractNatives(options(), v, natives, &error));
|
||||
QVERIFY(Fixtures::listTree(natives).isEmpty());
|
||||
|
||||
// Архива нет вовсе.
|
||||
const QString jar = m_game + "/libraries/org/lwjgl/lwjgl-3.3.1-natives.jar";
|
||||
QFile::remove(jar);
|
||||
error.clear();
|
||||
QVERIFY(!GameLauncher::extractNatives(options(), v, natives, &error));
|
||||
QCOMPARE(error, Loc::text("launch.error.nativeReadFailed").arg(nat(jar)));
|
||||
|
||||
// Битый архив: QZipReader::isReadable() проверяет только, что файл открылся,
|
||||
// поэтому испорченный jar «распаковывается» в ничто без ошибки, и игра
|
||||
// падает уже на загрузке LWJGL. Фиксируем текущее поведение.
|
||||
Fixtures::write(jar, "not a zip");
|
||||
error.clear();
|
||||
QEXPECT_FAIL("", "битый jar с нативами не распознаётся как ошибка (QZipReader::isReadable)", Continue);
|
||||
QVERIFY(!GameLauncher::extractNatives(options(), v, natives, &error));
|
||||
}
|
||||
|
||||
// --- launch (с подставной java) ----------------------------------------------
|
||||
|
||||
void launchRunsJavaAndReportsExit()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
createGameFiles(v);
|
||||
const QString argsFile = m_game + "/java-args.txt";
|
||||
const QString java = Fixtures::installFakeJava(m_game + "/jdk", "17.0.8",
|
||||
{"args_file=" + argsFile, "stdout=[main] Setting user: Steve",
|
||||
"stdout=Game crashed? no", "exit=0"});
|
||||
LaunchOptions o = options();
|
||||
o.javaPath = java;
|
||||
|
||||
GameLauncher launcher;
|
||||
QSignalSpy started(&launcher, &GameLauncher::gameStarted);
|
||||
QSignalSpy finished(&launcher, &GameLauncher::gameFinished);
|
||||
QSignalSpy output(&launcher, &GameLauncher::output);
|
||||
QSignalSpy progress(&launcher, &GameLauncher::progress);
|
||||
|
||||
QString error;
|
||||
QVERIFY2(launcher.launch(o, v, &error), qPrintable(error));
|
||||
QCOMPARE(started.count(), 1);
|
||||
// Токен скрыт в показанной строке запуска.
|
||||
const QString shown = started.constFirst().constFirst().toString();
|
||||
QVERIFY(!shown.contains("secret-token"));
|
||||
QVERIFY(shown.contains("--accessToken"));
|
||||
|
||||
QTRY_COMPARE_WITH_TIMEOUT(finished.count(), 1, 15000);
|
||||
QCOMPARE(finished.constFirst().at(0).toInt(), 0);
|
||||
QCOMPARE(finished.constFirst().at(1).toBool(), false);
|
||||
QVERIFY(!launcher.isRunning());
|
||||
QVERIFY(progress.count() >= 3);
|
||||
|
||||
QStringList lines;
|
||||
for (const QList<QVariant> &call : output)
|
||||
lines << call.constFirst().toString();
|
||||
QVERIFY(lines.contains("[main] Setting user: Steve"));
|
||||
|
||||
// Java получила те же аргументы, что строит buildArguments, и в рабочей папке игры.
|
||||
const QStringList received = QString::fromLocal8Bit(Fixtures::readFile(argsFile)).split(u'\n', Qt::SkipEmptyParts);
|
||||
QCOMPARE(received, GameLauncher::buildArguments(o, v, m_game + "/versions/1.20.1/natives"));
|
||||
QVERIFY(QFile::exists(m_game + "/versions/1.20.1/natives/" + kNativeName));
|
||||
}
|
||||
|
||||
void launchReportsCrash()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
createGameFiles(v);
|
||||
LaunchOptions o = options();
|
||||
o.javaPath = Fixtures::installFakeJava(m_game + "/jdk-crash", "17.0.8", {"crash=1"});
|
||||
|
||||
GameLauncher launcher;
|
||||
QSignalSpy finished(&launcher, &GameLauncher::gameFinished);
|
||||
QString error;
|
||||
QVERIFY2(launcher.launch(o, v, &error), qPrintable(error));
|
||||
QTRY_COMPARE_WITH_TIMEOUT(finished.count(), 1, 15000);
|
||||
QCOMPARE(finished.constFirst().at(1).toBool(), true);
|
||||
}
|
||||
|
||||
void launchRefusesWhileRunningAndTerminate()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
createGameFiles(v);
|
||||
LaunchOptions o = options();
|
||||
o.javaPath = Fixtures::installFakeJava(m_game + "/jdk-slow", "17.0.8", {"sleep_ms=30000"});
|
||||
|
||||
GameLauncher launcher;
|
||||
QSignalSpy finished(&launcher, &GameLauncher::gameFinished);
|
||||
QString error;
|
||||
QVERIFY(launcher.launch(o, v, &error));
|
||||
QVERIFY(launcher.isRunning());
|
||||
|
||||
QVERIFY(!launcher.launch(o, v, &error));
|
||||
QCOMPARE(error, Loc::text("common.error.gameRunning"));
|
||||
|
||||
launcher.terminate();
|
||||
QTRY_COMPARE_WITH_TIMEOUT(finished.count(), 1, 15000);
|
||||
QVERIFY(!launcher.isRunning());
|
||||
}
|
||||
|
||||
void launchFailsOnMissingFilesAndOldJava()
|
||||
{
|
||||
MinecraftVersion v = modernVersion();
|
||||
LaunchOptions o = options();
|
||||
GameLauncher launcher;
|
||||
QSignalSpy started(&launcher, &GameLauncher::gameStarted);
|
||||
|
||||
QString error;
|
||||
QVERIFY(!launcher.launch(o, v, &error));
|
||||
QVERIFY(error.startsWith(Loc::text("launch.error.filesMissing").section(u'%', 0, 0)));
|
||||
|
||||
createGameFiles(v);
|
||||
// На машине может стоять своя Java 17+: тогда лаунчер законно выберет её.
|
||||
for (const QString &candidate : JavaLocator::findAll(m_game)) {
|
||||
if (JavaLocator::majorVersion(candidate) >= 17)
|
||||
QSKIP("в системе есть Java 17+, проверка «слишком старой Java» невозможна");
|
||||
}
|
||||
o.javaPath = Fixtures::installFakeJava(m_game + "/jdk8", "1.8.0_392");
|
||||
error.clear();
|
||||
QVERIFY(!launcher.launch(o, v, &error));
|
||||
QCOMPARE(error, Loc::text("java.error.tooOld").arg(17).arg(8).arg(nat(o.javaPath)));
|
||||
QCOMPARE(started.count(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
BILAUNCHER_TEST_MAIN(TestGameLauncher)
|
||||
#include "tst_gamelauncher.moc"
|
||||
Reference in new issue
Block a user