summaryrefslogtreecommitdiffstats
path: root/tests/manual/wasm/qtloader_integration
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/wasm/qtloader_integration')
-rw-r--r--tests/manual/wasm/qtloader_integration/CMakeLists.txt6
-rw-r--r--tests/manual/wasm/qtloader_integration/main.cpp34
-rw-r--r--tests/manual/wasm/qtloader_integration/preload.json10
-rw-r--r--tests/manual/wasm/qtloader_integration/test_body.js126
4 files changed, 146 insertions, 30 deletions
diff --git a/tests/manual/wasm/qtloader_integration/CMakeLists.txt b/tests/manual/wasm/qtloader_integration/CMakeLists.txt
index 24c5607cd8..2603a05135 100644
--- a/tests/manual/wasm/qtloader_integration/CMakeLists.txt
+++ b/tests/manual/wasm/qtloader_integration/CMakeLists.txt
@@ -37,3 +37,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/test_body.js
${CMAKE_CURRENT_BINARY_DIR}/test_body.js)
+
+add_custom_command(
+ TARGET tst_qtloader_integration POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/preload.json
+ ${CMAKE_CURRENT_BINARY_DIR}/preload.json)
diff --git a/tests/manual/wasm/qtloader_integration/main.cpp b/tests/manual/wasm/qtloader_integration/main.cpp
index ed8a57bcc6..4bb502b69c 100644
--- a/tests/manual/wasm/qtloader_integration/main.cpp
+++ b/tests/manual/wasm/qtloader_integration/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtWidgets/QtWidgets>
#include <iostream>
@@ -49,14 +49,34 @@ std::string logicalDpi()
return out.str();
}
+std::string preloadedFiles()
+{
+ QStringList files = QDir("/preload").entryList(QDir::Files);
+ std::ostringstream out;
+ out << "[";
+ const char *separator = "";
+ for (const auto &file : files) {
+ out << separator;
+ out << file.toStdString();
+ separator = ",";
+ }
+ out << "]";
+ return out.str();
+}
+
void crash()
{
std::abort();
}
+void stackOverflow()
+{
+ stackOverflow(); // should eventually termniate with exception
+}
+
void exitApp()
{
- exit(ExitValueFromExitApp);
+ emscripten_force_exit(ExitValueFromExitApp);
}
void produceOutput()
@@ -120,7 +140,7 @@ int main(int argc, char **argv)
std::find(arguments.begin(), arguments.end(), QStringLiteral("--exit-immediately"))
!= arguments.end();
if (exitImmediately)
- return ExitValueImmediateReturn;
+ emscripten_force_exit(ExitValueImmediateReturn);
const bool crashImmediately =
std::find(arguments.begin(), arguments.end(), QStringLiteral("--crash-immediately"))
@@ -128,8 +148,15 @@ int main(int argc, char **argv)
if (crashImmediately)
crash();
+ const bool stackOverflowImmediately =
+ std::find(arguments.begin(), arguments.end(), QStringLiteral("--stack-owerflow-immediately"))
+ != arguments.end();
+ if (stackOverflowImmediately)
+ stackOverflow();
+
const bool noGui = std::find(arguments.begin(), arguments.end(), QStringLiteral("--no-gui"))
!= arguments.end();
+
if (!noGui) {
AppWindow window;
window.show();
@@ -145,6 +172,7 @@ EMSCRIPTEN_BINDINGS(qtLoaderIntegrationTest)
emscripten::function("screenInformation", &screenInformation);
emscripten::function("logicalDpi", &logicalDpi);
+ emscripten::function("preloadedFiles", &preloadedFiles);
emscripten::function("crash", &crash);
emscripten::function("exitApp", &exitApp);
emscripten::function("produceOutput", &produceOutput);
diff --git a/tests/manual/wasm/qtloader_integration/preload.json b/tests/manual/wasm/qtloader_integration/preload.json
new file mode 100644
index 0000000000..d7e09911ff
--- /dev/null
+++ b/tests/manual/wasm/qtloader_integration/preload.json
@@ -0,0 +1,10 @@
+[
+ {
+ "source": "qtloader.js",
+ "destination": "/preload/qtloader.js"
+ },
+ {
+ "source": "$QTDIR/qtlogo.svg",
+ "destination": "/preload/qtlogo.svg"
+ }
+]
diff --git a/tests/manual/wasm/qtloader_integration/test_body.js b/tests/manual/wasm/qtloader_integration/test_body.js
index f23db3a978..4fb49c31aa 100644
--- a/tests/manual/wasm/qtloader_integration/test_body.js
+++ b/tests/manual/wasm/qtloader_integration/test_body.js
@@ -1,5 +1,5 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDXLicenseIdentifier: LicenseRefQtCommercial OR GPL3.0only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import { Mock, assert, TestRunner } from './testrunner.js';
@@ -48,10 +48,32 @@ export class QtLoaderIntegrationTests
'config.qt is required, expected an object', caughtException.message);
}
- async useDefaultOnMissingEntryFunction()
+ async missingEntryFunction()
{
- const instance = await qtLoad({ arguments: ['--no-gui'], qt: {}});
- assert.isNotUndefined(instance);
+ let caughtException;
+ try {
+ await qtLoad({ qt: {}});
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal(
+ 'config.qt.entryFunction is required, expected a function', caughtException.message);
+ }
+
+ async badEntryFunction()
+ {
+ let caughtException;
+ try {
+ await qtLoad({ qt: { entryFunction: 'invalid' }});
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal(
+ 'config.qt.entryFunction is required, expected a function', caughtException.message);
}
async environmentVariables()
@@ -62,7 +84,7 @@ export class QtLoaderIntegrationTests
variable1: 'value1',
variable2: 'value2'
},
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#testScreenContainers[0]]
}
});
@@ -79,7 +101,7 @@ export class QtLoaderIntegrationTests
const instance = await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: this.#testScreenContainers
}
});
@@ -125,7 +147,7 @@ export class QtLoaderIntegrationTests
{
const instance = await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: this.#testScreenContainers,
}
});
@@ -177,16 +199,16 @@ export class QtLoaderIntegrationTests
// Fetch/Compile the module once; reuse for each instance. This is also if the page wants to
// initiate the .wasm file download fetch as early as possible, before the browser has
// finished fetching and parsing testapp.js and qtloader.js
- const modulePromise = WebAssembly.compileStreaming(fetch('tst_qtloader_integration.wasm'));
+ const module = WebAssembly.compileStreaming(fetch('tst_qtloader_integration.wasm'));
const instances = await Promise.all([1, 2, 3].map(i => qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#addScreenContainer(`screen-container-${i}`, {
width: `${i * 10}px`,
height: `${i * 10}px`,
})],
- modulePromise,
+ module,
}
})));
// Confirm the identity of instances by querying their screen widths and heights
@@ -222,7 +244,7 @@ export class QtLoaderIntegrationTests
accumulatedStdout += output;
},
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
@@ -230,14 +252,26 @@ export class QtLoaderIntegrationTests
assert.equal('Sample output!', accumulatedStdout);
}
- async moduleProvided()
+ async modulePromiseProvided()
{
await qtLoad({
qt: {
entryFunction: createQtAppInstance,
containerElements: [this.#testScreenContainers[0]],
- modulePromise: WebAssembly.compileStreaming(
- await fetch('tst_qtloader_integration.wasm'))
+ module: WebAssembly.compileStreaming(
+ fetch('tst_qtloader_integration.wasm'))
+ }
+ });
+ }
+
+ async moduleProvided()
+ {
+ await qtLoad({
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: [this.#testScreenContainers[0]],
+ module: await WebAssembly.compileStreaming(
+ fetch('tst_qtloader_integration.wasm'))
}
});
}
@@ -247,7 +281,7 @@ export class QtLoaderIntegrationTests
const instance = await qtLoad({
arguments: ['--no-gui', 'arg1', 'other', 'yetanotherarg'],
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
const args = this.#callTestInstanceApi(instance, 'retrieveArguments');
@@ -263,9 +297,9 @@ export class QtLoaderIntegrationTests
try {
await qtLoad({
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
containerElements: [this.#testScreenContainers[0]],
- modulePromise: Promise.reject(new Error('Failed to load')),
+ module: Promise.reject(new Error('Failed to load')),
}
});
} catch (e) {
@@ -282,7 +316,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
@@ -304,20 +338,44 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui', '--crash-immediately'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
} catch (e) {
caughtException = e;
}
- // An exception should have been thrown from load()
- assert.equal('RuntimeError', caughtException.name);
+ assert.isTrue(caughtException !== undefined);
+ assert.equal(1, onExitMock.calls.length);
+ const exitStatus = onExitMock.calls[0][0];
+ assert.isTrue(exitStatus.crashed);
+ assert.isUndefined(exitStatus.code);
+ assert.isNotUndefined(exitStatus.text);
+ }
+
+ async stackOwerflowImmediately()
+ {
+ const onExitMock = new Mock();
+ let caughtException;
+ try {
+ await qtLoad({
+ arguments: ['--no-gui', '--stack-owerflow-immediately'],
+ qt: {
+ onExit: onExitMock,
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ } catch (e) {
+ caughtException = e;
+ }
+ assert.isTrue(caughtException !== undefined);
assert.equal(1, onExitMock.calls.length);
const exitStatus = onExitMock.calls[0][0];
assert.isTrue(exitStatus.crashed);
assert.isUndefined(exitStatus.code);
+ // text should be "RangeError: Maximum call stack
+ // size exceeded", or similar.
assert.isNotUndefined(exitStatus.text);
}
@@ -328,7 +386,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
onAbort: onAbortMock,
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
@@ -346,7 +404,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
// The module is running. onExit should not have been called.
@@ -361,7 +419,7 @@ export class QtLoaderIntegrationTests
const exitStatus = onExitMock.calls[0][0];
assert.isFalse(exitStatus.crashed);
assert.equal(instance.EXIT_VALUE_FROM_EXIT_APP, exitStatus.code);
- assert.isNotUndefined(exitStatus.text);
+ assert.isUndefined(exitStatus.text);
}
async exitImmediately()
@@ -371,7 +429,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui', '--exit-immediately'],
qt: {
onExit: onExitMock,
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
assert.equal(1, onExitMock.calls.length);
@@ -380,7 +438,7 @@ export class QtLoaderIntegrationTests
assert.isFalse(exitStatusFromOnExit.crashed);
assert.equal(instance.EXIT_VALUE_IMMEDIATE_RETURN, exitStatusFromOnExit.code);
- assert.isNotUndefined(exitStatusFromOnExit.text);
+ assert.isUndefined(exitStatusFromOnExit.text);
}
async userQuitCallbackCalled()
@@ -390,7 +448,7 @@ export class QtLoaderIntegrationTests
arguments: ['--no-gui'],
quit: quitMock,
qt: {
- entryFunction: createQtAppInstance,
+ entryFunction: tst_qtloader_integration_entry,
}
});
try {
@@ -405,6 +463,20 @@ export class QtLoaderIntegrationTests
assert.equal('ExitStatus', exception.name);
}
+ async preloadFiles()
+ {
+ const instance = await qtLoad({
+ arguments: ["--no-gui"],
+ qt: {
+ preload: ['preload.json'],
+ qtdir: '.',
+ }
+ });
+ const preloadedFiles = instance.preloadedFiles();
+ // Verify that preloaded file list matches files specified in preload.json
+ assert.equal("[qtloader.js,qtlogo.svg]", preloadedFiles);
+ }
+
#callTestInstanceApi(instance, apiName)
{
return eval(instance[apiName]());