diff options
Diffstat (limited to 'tests/manual/wasm/qtloader_integration')
-rw-r--r-- | tests/manual/wasm/qtloader_integration/CMakeLists.txt | 6 | ||||
-rw-r--r-- | tests/manual/wasm/qtloader_integration/main.cpp | 34 | ||||
-rw-r--r-- | tests/manual/wasm/qtloader_integration/preload.json | 10 | ||||
-rw-r--r-- | tests/manual/wasm/qtloader_integration/test_body.js | 126 |
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]()); |