Platform: prepare() hook and app-specific command-line options
prepare() runs once mode and app key are known, before engine, surfaces and SteamVR; returning false ends exec() with exit code 1 (D21). The base constructor takes the app's own QCommandLineOptions, parses them with its own and exposes them via isOptionSet()/optionValue() (D38). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,5 +31,7 @@ add_test(NAME surfaces_opengl COMMAND tst_surfaces --graphics-api opengl)
|
||||
add_test(NAME surfaces_vulkan COMMAND tst_surfaces --graphics-api vulkan)
|
||||
add_test(NAME surfaces_cli_key COMMAND tst_surfaces --graphics-api opengl)
|
||||
set_tests_properties(surfaces_cli_key PROPERTIES ENVIRONMENT "VRDASH_TEST_CLI_KEY=1")
|
||||
add_test(NAME surfaces_prepare_fail COMMAND tst_surfaces --graphics-api opengl)
|
||||
set_tests_properties(surfaces_prepare_fail PROPERTIES ENVIRONMENT "VRDASH_TEST_PREPARE_FAIL=1")
|
||||
set_tests_properties(surfaces_opengl surfaces_vulkan surfaces_cli_key
|
||||
PROPERTIES SKIP_RETURN_CODE 77)
|
||||
|
||||
+48
-6
@@ -1,8 +1,12 @@
|
||||
// An app with two surfaces, run in snapshot mode: checks surface set-up
|
||||
// (overlay keys, names, sizes, shared engine, backends), the lifecycle hooks
|
||||
// and that every surface renders its own scene. No SteamVR involved.
|
||||
// (overlay keys, names, sizes, shared engine, backends), the lifecycle hooks,
|
||||
// the app's own command-line options and that every surface renders its own
|
||||
// scene. No SteamVR involved.
|
||||
// VRDASH_TEST_PREPARE_FAIL=1: prepare() fails, so exec() must return 1
|
||||
// without calling the other hooks.
|
||||
// Exit codes: 0 pass, 1 fail, 77 skipped (no GPU context).
|
||||
|
||||
#include <QCommandLineOption>
|
||||
#include <QDir>
|
||||
#include <QImage>
|
||||
#include <QTemporaryDir>
|
||||
@@ -21,7 +25,14 @@ bool check(bool condition, const char* what) {
|
||||
|
||||
class TwoSurfaceApp : public DashboardApplication {
|
||||
public:
|
||||
TwoSurfaceApp(int& argc, char** argv) : DashboardApplication(argc, argv) {
|
||||
TwoSurfaceApp(int& argc, char** argv)
|
||||
: DashboardApplication(
|
||||
argc, argv,
|
||||
{QCommandLineOption(QStringLiteral("test-value"),
|
||||
QStringLiteral("An app option."),
|
||||
QStringLiteral("value")),
|
||||
QCommandLineOption(QStringLiteral("test-flag"),
|
||||
QStringLiteral("An app flag, never set."))}) {
|
||||
setQmlModule(QStringLiteral("SurfacesTest"));
|
||||
setDisplayName(QStringLiteral("Test App"));
|
||||
setAppKey(QStringLiteral("config.key"));
|
||||
@@ -35,11 +46,28 @@ class TwoSurfaceApp : public DashboardApplication {
|
||||
}
|
||||
|
||||
QString expectedKey; // --app-key overrides setAppKey()
|
||||
bool failPrepare = false;
|
||||
int prepareCalls = 0;
|
||||
int loadingCalls = 0;
|
||||
int startedCalls = 0;
|
||||
bool ok = true;
|
||||
|
||||
protected:
|
||||
bool prepare(QString* error) override {
|
||||
++prepareCalls;
|
||||
ok &= check(loadingCalls == 0 && startedCalls == 0, "prepare() first");
|
||||
ok &= check(engine() == nullptr && surfaces().isEmpty(),
|
||||
"prepare() before engine and surfaces");
|
||||
ok &= check(mode() == DashboardMode::Snapshot, "mode in prepare()");
|
||||
ok &= check(appKey() == expectedKey, "app key in prepare()");
|
||||
ok &= check(
|
||||
isOptionSet(QStringLiteral("test-value")) &&
|
||||
optionValue(QStringLiteral("test-value")) == QLatin1String("42"),
|
||||
"app option value");
|
||||
ok &= check(!isOptionSet(QStringLiteral("test-flag")), "app option unset");
|
||||
if (failPrepare) *error = QStringLiteral("prepare() failed on purpose");
|
||||
return !failPrepare;
|
||||
}
|
||||
void loading() override {
|
||||
++loadingCalls;
|
||||
Surface* red = surface(QStringLiteral("red"));
|
||||
@@ -80,7 +108,10 @@ int main(int argc, char* argv[]) {
|
||||
QDir(dir.path()).filePath(QStringLiteral("shot.png")).toStdString();
|
||||
// VRDASH_TEST_CLI_KEY=1: also pass --app-key (must win over setAppKey()).
|
||||
const bool cliKey = qEnvironmentVariableIntValue("VRDASH_TEST_CLI_KEY");
|
||||
std::vector<std::string> args = {argv[0], "--snapshot", snapshot};
|
||||
const bool failPrepare =
|
||||
qEnvironmentVariableIntValue("VRDASH_TEST_PREPARE_FAIL");
|
||||
std::vector<std::string> args = {argv[0], "--snapshot", snapshot,
|
||||
"--test-value", "42"};
|
||||
if (cliKey) {
|
||||
args.emplace_back("--app-key");
|
||||
args.emplace_back("cli.key");
|
||||
@@ -93,15 +124,26 @@ int main(int argc, char* argv[]) {
|
||||
TwoSurfaceApp app(cargc, cargs.data());
|
||||
app.expectedKey =
|
||||
cliKey ? QStringLiteral("cli.key") : QStringLiteral("config.key");
|
||||
app.failPrepare = failPrepare;
|
||||
const int result = app.exec();
|
||||
if (failPrepare) {
|
||||
bool ok = app.ok;
|
||||
ok &= check(result == 1, "exec() returns 1 when prepare() fails");
|
||||
ok &= check(
|
||||
app.prepareCalls == 1 && app.loadingCalls == 0 && app.startedCalls == 0,
|
||||
"no hooks after a failed prepare()");
|
||||
fprintf(stderr, ok ? "PASS\n" : "FAILED\n");
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
if (app.loadingCalls == 0) {
|
||||
fprintf(stderr, "SKIP: no render backend (no GPU context?)\n");
|
||||
return 77;
|
||||
}
|
||||
bool ok = app.ok;
|
||||
ok &= check(result == 0, "exec() succeeded");
|
||||
ok &= check(app.loadingCalls == 1 && app.startedCalls == 1,
|
||||
"each hook called once");
|
||||
ok &= check(
|
||||
app.prepareCalls == 1 && app.loadingCalls == 1 && app.startedCalls == 1,
|
||||
"each hook called once");
|
||||
|
||||
const QImage red(QDir(dir.path()).filePath(QStringLiteral("shot-red.png")));
|
||||
const QImage blue(QDir(dir.path()).filePath(QStringLiteral("shot-blue.png")));
|
||||
|
||||
Reference in New Issue
Block a user