summaryrefslogtreecommitdiffstats
path: root/tests/manual/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/wasm')
-rw-r--r--tests/manual/wasm/CMakeLists.txt1
-rw-r--r--tests/manual/wasm/a11y/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basic_widgets.html2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/main.cpp2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp2
-rw-r--r--tests/manual/wasm/a11y/basic_widgets/tabswidget.h2
-rw-r--r--tests/manual/wasm/clipboard/CMakeLists.txt13
-rw-r--r--tests/manual/wasm/clipboard/main.cpp2
-rw-r--r--tests/manual/wasm/clipboard/mainwindow.cpp37
-rw-r--r--tests/manual/wasm/clipboard/mainwindow.h2
-rw-r--r--tests/manual/wasm/cursors/MainWindow.cpp2
-rw-r--r--tests/manual/wasm/cursors/MainWindow.h2
-rw-r--r--tests/manual/wasm/cursors/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/asyncify_exec/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/dialog_exec/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html2
-rw-r--r--tests/manual/wasm/eventloop/eventloop_auto/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/main_exec/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/main_noexec/main.cpp2
-rw-r--r--tests/manual/wasm/eventloop/thread_exec/main.cpp2
-rw-r--r--tests/manual/wasm/localfiles/main.cpp5
-rw-r--r--tests/manual/wasm/localfonts/CMakeLists.txt4
-rw-r--r--tests/manual/wasm/localfonts/fontloading/CMakeLists.txt20
-rw-r--r--tests/manual/wasm/localfonts/fontloading/fontloading.html167
-rw-r--r--tests/manual/wasm/localfonts/fontloading/main.cpp78
-rw-r--r--tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_client_mainthread/main.cpp2
-rw-r--r--tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_client_secondarythread/main.cpp2
-rw-r--r--tests/manual/wasm/network/echo_server/CMakeLists.txt2
-rw-r--r--tests/manual/wasm/network/echo_server/main.cpp2
-rw-r--r--tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt4
-rw-r--r--tests/manual/wasm/network/sockify_sockets_auto/main.cpp2
-rw-r--r--tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/CMakeLists.txt30
-rw-r--r--tests/manual/wasm/qstdweb/files_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/files_main.cpp20
-rw-r--r--tests/manual/wasm/qstdweb/iodevices_auto.html10
-rw-r--r--tests/manual/wasm/qstdweb/iodevices_main.cpp103
-rw-r--r--tests/manual/wasm/qstdweb/promise_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/promise_main.cpp2
-rw-r--r--tests/manual/wasm/qstdweb/qwasmcompositor_auto.html2
-rw-r--r--tests/manual/wasm/qstdweb/qwasmcompositor_main.cpp16
-rw-r--r--tests/manual/wasm/qtloader_integration/CMakeLists.txt45
-rw-r--r--tests/manual/wasm/qtloader_integration/main.cpp183
-rw-r--r--tests/manual/wasm/qtloader_integration/preload.json10
-rw-r--r--tests/manual/wasm/qtloader_integration/test_body.js517
-rw-r--r--tests/manual/wasm/qtloader_integration/tst_qtloader_integration.html13
-rw-r--r--tests/manual/wasm/qtwasmtestlib/README.md4
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp2
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.h2
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js12
-rw-r--r--tests/manual/wasm/rasterwindow/main.cpp2
-rw-r--r--tests/manual/wasm/rasterwindow/rasterwindow.cpp2
-rw-r--r--tests/manual/wasm/rasterwindow/rasterwindow.h2
-rwxr-xr-xtests/manual/wasm/shared/run.sh4
-rw-r--r--tests/manual/wasm/shared/testrunner.js91
62 files changed, 1369 insertions, 96 deletions
diff --git a/tests/manual/wasm/CMakeLists.txt b/tests/manual/wasm/CMakeLists.txt
index f625defb21..b13f6781b8 100644
--- a/tests/manual/wasm/CMakeLists.txt
+++ b/tests/manual/wasm/CMakeLists.txt
@@ -7,6 +7,7 @@ add_subdirectory(a11y)
if(QT_FEATURE_widgets)
add_subdirectory(cursors)
add_subdirectory(localfiles)
+add_subdirectory(localfonts)
add_subdirectory(qstdweb)
add_subdirectory(clipboard)
endif()
diff --git a/tests/manual/wasm/a11y/CMakeLists.txt b/tests/manual/wasm/a11y/CMakeLists.txt
index 5268d53c8b..dee39e1f5f 100644
--- a/tests/manual/wasm/a11y/CMakeLists.txt
+++ b/tests/manual/wasm/a11y/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
if(QT_FEATURE_widgets)
add_subdirectory(basic_widgets)
endif()
diff --git a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
index 11534bdf68..a028f96e1c 100644
--- a/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
+++ b/tests/manual/wasm/a11y/basic_widgets/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(a11y_basic_widgets
GUI
SOURCES
diff --git a/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html b/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
index 899e72bb00..091809be5c 100644
--- a/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
+++ b/tests/manual/wasm/a11y/basic_widgets/basic_widgets.html
@@ -7,7 +7,7 @@
<script>
window.onload = async () => {
- let qt_instance = await createQtAppInstance({
+ let qt_instance = await a11y_basic_widgets_entry({
qtContainerElements: [document.getElementById("qt_container")],
});
}
diff --git a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp
index eaf736160a..dc1688f5b9 100644
--- a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp
+++ b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 "basica11ywidget.h"
diff --git a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h
index c8d9a4157b..b990d163e5 100644
--- a/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h
+++ b/tests/manual/wasm/a11y/basic_widgets/basica11ywidget.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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>
#include "tabswidget.h"
diff --git a/tests/manual/wasm/a11y/basic_widgets/main.cpp b/tests/manual/wasm/a11y/basic_widgets/main.cpp
index 5417195ecf..52d72428bb 100644
--- a/tests/manual/wasm/a11y/basic_widgets/main.cpp
+++ b/tests/manual/wasm/a11y/basic_widgets/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 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 <QApplication>
#include <QtWidgets>
diff --git a/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp b/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp
index 19bd0cf71b..63428c965a 100644
--- a/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp
+++ b/tests/manual/wasm/a11y/basic_widgets/tabswidget.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 "tabswidget.h"
diff --git a/tests/manual/wasm/a11y/basic_widgets/tabswidget.h b/tests/manual/wasm/a11y/basic_widgets/tabswidget.h
index 0d7983cb42..6405c0dab7 100644
--- a/tests/manual/wasm/a11y/basic_widgets/tabswidget.h
+++ b/tests/manual/wasm/a11y/basic_widgets/tabswidget.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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
#ifndef TABDIALOG_H
#define TABDIALOG_H
diff --git a/tests/manual/wasm/clipboard/CMakeLists.txt b/tests/manual/wasm/clipboard/CMakeLists.txt
index 09f56a5f01..40fb8ca308 100644
--- a/tests/manual/wasm/clipboard/CMakeLists.txt
+++ b/tests/manual/wasm/clipboard/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from clipboard.pro.
-
#####################################################################
## clipboard Binary:
#####################################################################
@@ -12,6 +10,8 @@ qt_internal_add_manual_test(clipboard
SOURCES
main.cpp
mainwindow.cpp mainwindow.h mainwindow.ui
+ NO_PCH_SOURCES
+ main.cpp # undef QT_NO_FOREACH
LIBRARIES
Qt::Core
Qt::Gui
@@ -38,12 +38,3 @@ qt_internal_extend_target(clipboard CONDITION (QT_MAJOR_VERSION GREATER 4)
LIBRARIES
Qt::Widgets
)
-
-#### Keys ignored in scope 3:.:.:clipboard.pro:QNX:
-# target.path = "/tmp/$${TARGET}/bin"
-
-#### Keys ignored in scope 5:.:.:clipboard.pro:UNIX AND NOT ANDROID:
-# target.path = "/opt/$${TARGET}/bin"
-
-#### Keys ignored in scope 6:.:.:clipboard.pro:NOT target.path_ISEMPTY:
-# INSTALLS = "target"
diff --git a/tests/manual/wasm/clipboard/main.cpp b/tests/manual/wasm/clipboard/main.cpp
index 7142125ff7..aa838f6670 100644
--- a/tests/manual/wasm/clipboard/main.cpp
+++ b/tests/manual/wasm/clipboard/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 "mainwindow.h"
diff --git a/tests/manual/wasm/clipboard/mainwindow.cpp b/tests/manual/wasm/clipboard/mainwindow.cpp
index 77d6582775..c67c795b05 100644
--- a/tests/manual/wasm/clipboard/mainwindow.cpp
+++ b/tests/manual/wasm/clipboard/mainwindow.cpp
@@ -1,5 +1,7 @@
// Copyright (C) 2021 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
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
#include "mainwindow.h"
#include "ui_mainwindow.h"
@@ -12,6 +14,7 @@
#include <QKeyEvent>
#include <QMimeDatabase>
#include <QFileInfo>
+#include <QCryptographicHash>
#ifdef Q_OS_WASM
#include <emscripten.h>
@@ -262,20 +265,23 @@ void MainWindow::dropEvent(QDropEvent* e)
QString urlStr = url.toDisplayString();
int size = urlStr.length();
sizeStr.setNum(size);
+
+ QString fileName = url.toLocalFile();
+ QString sha1;
+ QFile file(fileName);
+ if (file.exists()) {
+ file.open(QFile::ReadOnly);
+ sha1 = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Sha1).toHex();
+ }
+
ui->textEdit_2->insertPlainText(" Drop has url data length: " + sizeStr + "\n");
- ui->textEdit_2->insertPlainText(urlStr + "\n");
-
- QString fname = url.toLocalFile();
- QFileInfo info(fname);
- if (info.exists()) { // this is a file
- QMimeDatabase db;
- QMimeType mt = db.mimeTypeForFile(info);
- if (mt.name().contains("image")) {
- QImage image = QImage(fname);
- setImage(image);
- }
+ if (sha1.isEmpty()) {
+ ui->textEdit->insertPlainText(urlStr);
}
+ ui->textEdit_2->insertPlainText(" " + urlStr + (!sha1.isEmpty() ? " sha1 " + sha1.left(8) : "") + "\n");
+
}
+ ui->textEdit_2->insertPlainText("\n");
if (e->mimeData()->hasImage()) {
qsizetype imageSize = qvariant_cast<QImage>(e->mimeData()->imageData()).sizeInBytes();
@@ -292,14 +298,15 @@ void MainWindow::dropEvent(QDropEvent* e)
int size = e->mimeData()->html().length();
sizeStr.setNum(size);
ui->textEdit_2->insertPlainText(" Drop has html data length: " + sizeStr + "\n");
- ui->textEdit_2->insertPlainText(e->mimeData()->html()+"\n");
- ui->textEdit->insertHtml(e->mimeData()->html()+"<br>");
+ for (const auto &line : e->mimeData()->html().split('\n', Qt::SkipEmptyParts))
+ ui->textEdit_2->insertPlainText(" " + line + "\n");
}
if (e->mimeData()->hasText()) {
int size = e->mimeData()->text().length();
sizeStr.setNum(size);
ui->textEdit_2->insertPlainText(" Drop has text data length: " + sizeStr + "\n");
- ui->textEdit_2->insertPlainText(e->mimeData()->text());
+ for (const auto &line : e->mimeData()->text().split('\n', Qt::SkipEmptyParts))
+ ui->textEdit_2->insertPlainText(" " + line + "\n");
}
const QString message = tr(" Drop accepted, %1 ")
diff --git a/tests/manual/wasm/clipboard/mainwindow.h b/tests/manual/wasm/clipboard/mainwindow.h
index d06b213971..fe101ad494 100644
--- a/tests/manual/wasm/clipboard/mainwindow.h
+++ b/tests/manual/wasm/clipboard/mainwindow.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
diff --git a/tests/manual/wasm/cursors/MainWindow.cpp b/tests/manual/wasm/cursors/MainWindow.cpp
index b62c6752aa..c6e4fbcca1 100644
--- a/tests/manual/wasm/cursors/MainWindow.cpp
+++ b/tests/manual/wasm/cursors/MainWindow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 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 "MainWindow.h"
#include "ui_MainWindow.h"
diff --git a/tests/manual/wasm/cursors/MainWindow.h b/tests/manual/wasm/cursors/MainWindow.h
index ed570a72c4..ebaeed9e5c 100644
--- a/tests/manual/wasm/cursors/MainWindow.h
+++ b/tests/manual/wasm/cursors/MainWindow.h
@@ -1,5 +1,5 @@
// Copyright (C) 2019 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
#pragma once
#include <QMainWindow>
diff --git a/tests/manual/wasm/cursors/main.cpp b/tests/manual/wasm/cursors/main.cpp
index 99a1d41524..9a59cdd994 100644
--- a/tests/manual/wasm/cursors/main.cpp
+++ b/tests/manual/wasm/cursors/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 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 "MainWindow.h"
#include <QApplication>
diff --git a/tests/manual/wasm/eventloop/asyncify_exec/main.cpp b/tests/manual/wasm/eventloop/asyncify_exec/main.cpp
index ab3018c12e..f09163184d 100644
--- a/tests/manual/wasm/eventloop/asyncify_exec/main.cpp
+++ b/tests/manual/wasm/eventloop/asyncify_exec/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtCore>
// This test shows how to use asyncify to enable blocking the main
diff --git a/tests/manual/wasm/eventloop/dialog_exec/main.cpp b/tests/manual/wasm/eventloop/dialog_exec/main.cpp
index adf8a02c37..f5b072fc0b 100644
--- a/tests/manual/wasm/eventloop/dialog_exec/main.cpp
+++ b/tests/manual/wasm/eventloop/dialog_exec/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtGui>
#include <QtWidgets>
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt b/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
index 9bfa875be7..88ddfac4c8 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
+++ b/tests/manual/wasm/eventloop/eventloop_auto/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
include_directories(../../qtwasmtestlib/)
# default buid
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
index 7ff9d8e7f2..e8e35abcbb 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
+++ b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="eventloop_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(eventloop_auto_entry, document.getElementById("log"));
};
</script>
<p>Running event dispatcher auto test.</p>
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
index a277c9b9e0..f09b29d85b 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
+++ b/tests/manual/wasm/eventloop/eventloop_auto/eventloop_auto_asyncify.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="eventloop_auto_asyncify.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(eventloop_auto_asyncify_entry, document.getElementById("log"));
};
</script>
<p>Running event dispatcher auto test.</p>
diff --git a/tests/manual/wasm/eventloop/eventloop_auto/main.cpp b/tests/manual/wasm/eventloop/eventloop_auto/main.cpp
index b2ff6779fd..32af372b62 100644
--- a/tests/manual/wasm/eventloop/eventloop_auto/main.cpp
+++ b/tests/manual/wasm/eventloop/eventloop_auto/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QCoreApplication>
#include <QtCore/QEvent>
diff --git a/tests/manual/wasm/eventloop/main_exec/main.cpp b/tests/manual/wasm/eventloop/main_exec/main.cpp
index c981fd4c2c..17eccafe18 100644
--- a/tests/manual/wasm/eventloop/main_exec/main.cpp
+++ b/tests/manual/wasm/eventloop/main_exec/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtGui>
// This example demonstrates how the standard Qt main()
diff --git a/tests/manual/wasm/eventloop/main_noexec/main.cpp b/tests/manual/wasm/eventloop/main_noexec/main.cpp
index 18d0542137..6ddd88bd14 100644
--- a/tests/manual/wasm/eventloop/main_noexec/main.cpp
+++ b/tests/manual/wasm/eventloop/main_noexec/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtGui>
// This example demonstrates how to create QGuiApplication
diff --git a/tests/manual/wasm/eventloop/thread_exec/main.cpp b/tests/manual/wasm/eventloop/thread_exec/main.cpp
index b24be17e5b..589066b34d 100644
--- a/tests/manual/wasm/eventloop/thread_exec/main.cpp
+++ b/tests/manual/wasm/eventloop/thread_exec/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtGui>
class EventTarget : public QObject
diff --git a/tests/manual/wasm/localfiles/main.cpp b/tests/manual/wasm/localfiles/main.cpp
index 39d9f21901..862bff50a4 100644
--- a/tests/manual/wasm/localfiles/main.cpp
+++ b/tests/manual/wasm/localfiles/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 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 <emscripten/val.h>
@@ -91,7 +91,8 @@ private Q_SLOTS:
{
QFileDialog::getOpenFileContent(
m_filterEdit->text(),
- std::bind(&AppWindow::onFileContentReady, this, std::placeholders::_1, std::placeholders::_2));
+ std::bind(&AppWindow::onFileContentReady, this, std::placeholders::_1, std::placeholders::_2),
+ &m_loadFileUi);
}
void onSaveClicked()
diff --git a/tests/manual/wasm/localfonts/CMakeLists.txt b/tests/manual/wasm/localfonts/CMakeLists.txt
new file mode 100644
index 0000000000..b5df4ad9fa
--- /dev/null
+++ b/tests/manual/wasm/localfonts/CMakeLists.txt
@@ -0,0 +1,4 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+add_subdirectory(fontloading)
diff --git a/tests/manual/wasm/localfonts/fontloading/CMakeLists.txt b/tests/manual/wasm/localfonts/fontloading/CMakeLists.txt
new file mode 100644
index 0000000000..c3dc37d27d
--- /dev/null
+++ b/tests/manual/wasm/localfonts/fontloading/CMakeLists.txt
@@ -0,0 +1,20 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_manual_test(fontloading
+ GUI
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Widgets
+)
+
+add_custom_command(
+ TARGET fontloading POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/fontloading.html
+ ${CMAKE_CURRENT_BINARY_DIR}/fontloading.html)
+#add_custom_target(html DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fontloading.html)
+#add_dependencies(fontloading html)
diff --git a/tests/manual/wasm/localfonts/fontloading/fontloading.html b/tests/manual/wasm/localfonts/fontloading/fontloading.html
new file mode 100644
index 0000000000..619217205b
--- /dev/null
+++ b/tests/manual/wasm/localfonts/fontloading/fontloading.html
@@ -0,0 +1,167 @@
+<!doctype html>
+
+<script src="qtloader.js"></script>
+<script src="fontloading.js"></script>
+
+<style>
+ body {
+ padding: 5px;
+ }
+
+ .container {
+ display: flex;
+ }
+
+ .column {
+ flex: 1;
+ }
+</style>
+
+
+<script>
+
+ // UI
+ let familyCount;
+ let families;
+
+ // Data
+ let fontFamilies = new Set();
+ let loadStartTime;
+
+ // App
+ let instance;
+
+ async function updatePermissionStatus() {
+ let permissonStatusElement = document.getElementById("permissonStatus");
+ let permissionStatus = await navigator.permissions.query({ name: "local-fonts" })
+ permissonStatusElement.innerHTML = permissionStatus.state;
+ }
+
+ window.onload = async () => {
+ let supported = document.getElementById("supported");
+ let permissonStatus = document.getElementById("permissonStatus");
+ let permission = document.getElementById("permission");
+ let defaultfonts = document.getElementById("defaultfonts");
+ let allfonts = document.getElementById("allfonts");
+ let start = document.getElementById("start");
+ let loadFonts = document.getElementById("loadFonts");
+ startupTime = document.getElementById("startupTime");
+ familyCount = document.getElementById("familyCount");
+ families = document.getElementById("families");
+
+ fontFamilies.clear();
+
+ let localFontsAccessSupported = window.queryLocalFonts ? true : false
+ if (localFontsAccessSupported) {
+ supported.innerHTML = "True"
+ } else {
+ supported.innerHTML = "False"
+ return;
+ }
+
+ updatePermissionStatus();
+
+ const module = WebAssembly.compileStreaming(fetch('fontloading.wasm'));
+
+ start.onclick = async () => {
+
+ // Delete any previous instance.
+ if (instance) {
+ instance.deleteapp(); // see main.cpp
+ instance = null;
+ }
+
+ loadStartTime = performance.now();
+ startupTime.innerHTML = 0;
+ familyCount.innerHTML = 0;
+ let localFontFamilyLoadCollection = "NoFontFamilies"
+ if (defaultfonts.checked)
+ localFontFamilyLoadCollection = "DefaultFontFamilies"
+ else if (allfonts.checked)
+ localFontFamilyLoadCollection = "AllFontFamilies"
+
+ let qtcontainer = document.getElementById("qtcontainer");
+ qtcontainer.innerHTML = ""; // clear children
+ qtcontainer.style.visibility = "hidden";
+
+ let extraFonts = document.getElementById("extrafonts").value.split(",");
+
+ let config = {
+ qt: {
+ module: module,
+ containerElements: [qtcontainer],
+ onLoaded: () => {
+ console.log("JS: onLoaded")
+ qtcontainer.style.visibility = "visible";
+ },
+ entryFunction: window.fontloading_entry,
+ localFonts: {
+ requestPermission: permission.checked,
+ familiesCollection: localFontFamilyLoadCollection,
+ extraFamilies: extraFonts,
+ }
+ }
+ }
+ instance = await qtLoad(config);
+
+ updatePermissionStatus();
+ }
+
+ loadFonts.onclick = async () => {
+ loadStartTime = null; // disable timer
+ let fontsFamilies = document.getElementById("extraRuntimeFontFamilies").value.split(",");
+ console.log("extraRuntimeFontFamilies: " + fontsFamilies);
+ instance.qtLoadLocalFontFamilies(fontsFamilies);
+ }
+ };
+
+ function fontFamiliesLoaded(count) {
+ familyCount.innerHTML = count;
+ if (loadStartTime) {
+ elapsed = performance.now() - loadStartTime;
+ startupTime.innerHTML = Math.round(elapsed + 1);
+ }
+ }
+
+ function fontFamilyLoaded(family) {
+ fontFamilies.add(family);
+ }
+
+</script>
+
+<h2>Local Font Loading Test</h2>
+<p>Click "Load" button below to load the Qt test app with the specified settings. This test provides additional logs on the JavaScript console.</p>
+
+<div class="container">
+ <div class="column">
+ <span>Browser supports the Local Font Access API: </span><span id="supported" style="font-weight: bold;"></span><br>
+ <span>Local Font Access permission status: </span><span id="permissonStatus" style="font-weight: bold;"></span><br>
+ <br>
+ <input type="checkbox" id="permission"><label for="permission">Ask for Local Font access permission on startup</label><br>
+ <input type="radio" id="nofonts" name="fontset"></input><label for="nofonts">No local fonts</label><br>
+ <input type="radio" id="defaultfonts" name="fontset" checked></input><label for="defaultfonts">Default local fonts (web-safe fonts)</label><br>
+ <input type="radio" id="allfonts" name="fontset"></input><label for="allfonts">All local fonts (warning: extremely slow)</label><br>
+ <br>
+ <label for="extrafonts">Extra Font Families (comma separated) </label><input type="text" id="extrafonts" value=""></input><br>
+ <br>
+ <input type="checkbox" id="permission"><label for="permission">Enable 'Fonts' Logging Category</label><br>
+ <input type="checkbox" id="permission"><label for="permission">Enable Font Streaming</label><br>
+ <br>
+ <button type="button" id="start">Start Application</button><br>
+ <br>
+
+ <span>Startup time: </span><span id="startupTime"></span><br>
+ <span>Font family count: </span><span id="familyCount"></span><br>
+ <span>Font families: </span><span id="families"></span><br>
+ <br>
+
+ <button type="button" id="loadFonts">Load Extra Fonts</button>
+ <input type="text" id="extraRuntimeFontFamilies" value=""></input><br>
+ </div>
+
+ <div class="column">
+ <div id="qtcontainer" style="width: 100%; height: 300px; visibility: hidden;"></div>
+ </div>
+</div>
+
+
diff --git a/tests/manual/wasm/localfonts/fontloading/main.cpp b/tests/manual/wasm/localfonts/fontloading/main.cpp
new file mode 100644
index 0000000000..3824c8b871
--- /dev/null
+++ b/tests/manual/wasm/localfonts/fontloading/main.cpp
@@ -0,0 +1,78 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtGui>
+#include <QtWidgets>
+
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
+
+using namespace emscripten;
+
+class FontViewer : public QWidget
+{
+public:
+ FontViewer() {
+ QTextEdit *edit = new QTextEdit;
+ edit->setPlainText("The quick brown fox jumps over the lazy dog\nHow quickly daft jumping zebras vex\nPack my box with five dozen liquor jugs");
+
+ QComboBox *combo = new QComboBox;
+ combo->addItems(QFontDatabase::families());
+
+ connect(combo, &QComboBox::currentTextChanged, [=](const QString &family) {
+ QFont font(family);
+ edit->setFont(font);
+ });
+
+ QObject::connect(qApp, &QGuiApplication::fontDatabaseChanged, [=]() {
+ QStringList families = QFontDatabase::families();
+ combo->clear();
+ combo->addItems(families);
+ });
+
+ QLayout *layout = new QVBoxLayout;
+ layout->addWidget(edit);
+ layout->addWidget(combo);
+ setLayout(layout);
+ }
+};
+
+FontViewer *g_viewer = nullptr;
+QApplication *g_app = nullptr;
+
+void deleteapp() {
+ delete g_viewer;
+ delete g_app;
+};
+
+EMSCRIPTEN_BINDINGS(fonloading) {
+ function("deleteapp", &deleteapp);
+}
+
+int main(int argc, char **argv)
+{
+ qDebug() << "C++ main: Creating application";
+ g_app = new QApplication(argc, argv);
+
+ // Make sure there is one call to fontFamiliesLoaded at startup,
+ // even if no further fonts are loaded.
+ QTimer::singleShot(0, [=]() {
+ emscripten::val window = emscripten::val::global("window");
+ window.call<void>("fontFamiliesLoaded", QFontDatabase::families().count());
+ });
+
+ g_viewer = new FontViewer();
+ g_viewer->show();
+
+ QObject::connect(g_app, &QGuiApplication::fontDatabaseChanged, [=]() {
+ QStringList families = QFontDatabase::families();
+
+ emscripten::val window = emscripten::val::global("window");
+
+ window.call<void>("fontFamiliesLoaded", families.count());
+ for (int i = 0; i < families.count(); ++i) {
+ window.call<void>("fontFamilyLoaded", families[i].toStdString());
+ }
+ });
+}
+
diff --git a/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt b/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
index 05416c0b66..4b81661c79 100644
--- a/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_client_mainthread/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(echo_client_mainthread
GUI
SOURCES
diff --git a/tests/manual/wasm/network/echo_client_mainthread/main.cpp b/tests/manual/wasm/network/echo_client_mainthread/main.cpp
index 9a0ac1a60a..ef696e5978 100644
--- a/tests/manual/wasm/network/echo_client_mainthread/main.cpp
+++ b/tests/manual/wasm/network/echo_client_mainthread/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtCore>
#include <QtNetwork>
diff --git a/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt b/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
index a1f2bef254..d240e9e70b 100644
--- a/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_client_secondarythread/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(echo_client_secondarythread
GUI
SOURCES
diff --git a/tests/manual/wasm/network/echo_client_secondarythread/main.cpp b/tests/manual/wasm/network/echo_client_secondarythread/main.cpp
index 615706727f..52cea93495 100644
--- a/tests/manual/wasm/network/echo_client_secondarythread/main.cpp
+++ b/tests/manual/wasm/network/echo_client_secondarythread/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 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 <QtCore>
#include <QtNetwork>
diff --git a/tests/manual/wasm/network/echo_server/CMakeLists.txt b/tests/manual/wasm/network/echo_server/CMakeLists.txt
index cf98163fb8..72ec413a0e 100644
--- a/tests/manual/wasm/network/echo_server/CMakeLists.txt
+++ b/tests/manual/wasm/network/echo_server/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
project(echo_server)
cmake_minimum_required(VERSION 3.19)
diff --git a/tests/manual/wasm/network/echo_server/main.cpp b/tests/manual/wasm/network/echo_server/main.cpp
index 9ea15b7caa..3a67cabc79 100644
--- a/tests/manual/wasm/network/echo_server/main.cpp
+++ b/tests/manual/wasm/network/echo_server/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtCore>
#include <QtNetwork>
diff --git a/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt b/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
index f69bd80259..68a3993778 100644
--- a/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
+++ b/tests/manual/wasm/network/sockify_sockets_auto/CMakeLists.txt
@@ -1,8 +1,10 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(sockify_sockets_auto
SOURCES
main.cpp
../../qtwasmtestlib/qtwasmtestlib.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Core
Qt::Network
)
diff --git a/tests/manual/wasm/network/sockify_sockets_auto/main.cpp b/tests/manual/wasm/network/sockify_sockets_auto/main.cpp
index 313ac716b6..b6aa232b4a 100644
--- a/tests/manual/wasm/network/sockify_sockets_auto/main.cpp
+++ b/tests/manual/wasm/network/sockify_sockets_auto/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 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 <qtwasmtestlib.h>
#include <QtCore>
diff --git a/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html b/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
index 5376249a71..080ada94e7 100644
--- a/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
+++ b/tests/manual/wasm/network/sockify_sockets_auto/sockify_sockets_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="sockify_sockets_auto.js"></script>
<script>
window.onload = async () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(sockify_sockets_auto_entry, document.getElementById("log"));
};
</script>
<p> Sockify tunneled sockets auto test.
diff --git a/tests/manual/wasm/qstdweb/CMakeLists.txt b/tests/manual/wasm/qstdweb/CMakeLists.txt
index 234b12bab9..39039c3910 100644
--- a/tests/manual/wasm/qstdweb/CMakeLists.txt
+++ b/tests/manual/wasm/qstdweb/CMakeLists.txt
@@ -1,3 +1,5 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(promise_auto
SOURCES
promise_main.cpp
@@ -25,7 +27,7 @@ qt_internal_add_manual_test(files_auto
SOURCES
files_main.cpp
../qtwasmtestlib/qtwasmtestlib.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Core
Qt::CorePrivate
Qt::GuiPrivate
@@ -49,7 +51,7 @@ qt_internal_add_manual_test(qwasmcompositor_auto
SOURCES
qwasmcompositor_main.cpp
../qtwasmtestlib/qtwasmtestlib.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Core
Qt::CorePrivate
Qt::GuiPrivate
@@ -70,3 +72,27 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/qtwasmtestlib.js)
target_link_options(qwasmcompositor_auto PRIVATE -sASYNCIFY -Os)
+
+qt_internal_add_manual_test(iodevices_auto
+ SOURCES
+ iodevices_main.cpp
+ ../qtwasmtestlib/qtwasmtestlib.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::CorePrivate
+ Qt::GuiPrivate
+)
+
+add_custom_command(
+ TARGET iodevices_auto POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/iodevices_auto.html
+ ${CMAKE_CURRENT_BINARY_DIR}/iodevices_auto.html)
+
+add_custom_command(
+ TARGET iodevices_auto POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/../qtwasmtestlib/qtwasmtestlib.js
+ ${CMAKE_CURRENT_BINARY_DIR}/qtwasmtestlib.js)
+
+target_link_options(iodevices_auto PRIVATE -sASYNCIFY -Os)
diff --git a/tests/manual/wasm/qstdweb/files_auto.html b/tests/manual/wasm/qstdweb/files_auto.html
index 71e8088dfb..9027fdc660 100644
--- a/tests/manual/wasm/qstdweb/files_auto.html
+++ b/tests/manual/wasm/qstdweb/files_auto.html
@@ -6,7 +6,7 @@
<script type="text/javascript" src="files_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(files_auto_entry, document.getElementById("log"));
};
</script>
<p>Running files auto test.</p>
diff --git a/tests/manual/wasm/qstdweb/files_main.cpp b/tests/manual/wasm/qstdweb/files_main.cpp
index 4dfae7e13b..45939feb10 100644
--- a/tests/manual/wasm/qstdweb/files_main.cpp
+++ b/tests/manual/wasm/qstdweb/files_main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QCoreApplication>
#include <QtCore/QEvent>
@@ -320,8 +320,8 @@ void FilesTest::selectOneFileWithFileDialog()
QWASMSUCCESS();
});
- QWasmLocalFileAccess::openFile(
- {QStringLiteral("*")}, fileSelectedCallback->get(), acceptFileCallback->get(), fileDataReadyCallback->get());
+ QWasmLocalFileAccess::openFile("*", fileSelectedCallback->get(), acceptFileCallback->get(),
+ fileDataReadyCallback->get());
}
void FilesTest::selectMultipleFilesWithFileDialog()
@@ -377,9 +377,9 @@ void FilesTest::selectMultipleFilesWithFileDialog()
}
});
- QWasmLocalFileAccess::openFiles(
- {QStringLiteral("*")}, QWasmLocalFileAccess::FileSelectMode::MultipleFiles,
- fileSelectedCallback->get(), acceptFileCallback->get(), fileDataReadyCallback->get());
+ QWasmLocalFileAccess::openFiles("*", QWasmLocalFileAccess::FileSelectMode::MultipleFiles,
+ fileSelectedCallback->get(), acceptFileCallback->get(),
+ fileDataReadyCallback->get());
}
void FilesTest::cancelFileDialog()
@@ -398,8 +398,8 @@ void FilesTest::cancelFileDialog()
auto* acceptFileCallback = Own(new MockCallback<char*, uint64_t, const std::string&>());
auto* fileDataReadyCallback = Own(new MockCallback<void>());
- QWasmLocalFileAccess::openFile(
- {QStringLiteral("*")}, fileSelectedCallback->get(), acceptFileCallback->get(), fileDataReadyCallback->get());
+ QWasmLocalFileAccess::openFile("*", fileSelectedCallback->get(), acceptFileCallback->get(),
+ fileDataReadyCallback->get());
}
void FilesTest::rejectFile()
@@ -430,8 +430,8 @@ void FilesTest::rejectFile()
return nullptr;
});
- QWasmLocalFileAccess::openFile(
- {QStringLiteral("*")}, fileSelectedCallback->get(), acceptFileCallback->get(), fileDataReadyCallback->get());
+ QWasmLocalFileAccess::openFile("*", fileSelectedCallback->get(), acceptFileCallback->get(),
+ fileDataReadyCallback->get());
}
void FilesTest::saveFileWithFileDialog()
diff --git a/tests/manual/wasm/qstdweb/iodevices_auto.html b/tests/manual/wasm/qstdweb/iodevices_auto.html
new file mode 100644
index 0000000000..7937b8a483
--- /dev/null
+++ b/tests/manual/wasm/qstdweb/iodevices_auto.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<script type="text/javascript" src="qtwasmtestlib.js"></script>
+<script type="text/javascript" src="iodevices_auto.js"></script>
+<script>
+ window.onload = () => {
+ runTestCase(iodevices_auto_entry, document.getElementById("log"));
+ };
+</script>
+<p>Running qstdweb iodevices auto test.</p>
+<div id="log"></div>
diff --git a/tests/manual/wasm/qstdweb/iodevices_main.cpp b/tests/manual/wasm/qstdweb/iodevices_main.cpp
new file mode 100644
index 0000000000..0dbdd0084e
--- /dev/null
+++ b/tests/manual/wasm/qstdweb/iodevices_main.cpp
@@ -0,0 +1,103 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/QtCore>
+#include <QtCore/private/qstdweb_p.h>
+
+#include <qtwasmtestlib.h>
+
+#include "emscripten.h"
+
+using qstdweb::ArrayBuffer;
+using qstdweb::Uint8Array;
+using qstdweb::Blob;
+using qstdweb::BlobIODevice;
+using qstdweb::Uint8ArrayIODevice;
+
+class WasmIoDevicesTest: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void blobIODevice();
+ void uint8ArrayIODevice();
+};
+
+// Creates a test arraybuffer with byte values [0..size] % 256 * 2
+char testByteValue(int i) { return (i % 256) * 2; }
+ArrayBuffer createTestArrayBuffer(int size)
+{
+ ArrayBuffer buffer(size);
+ Uint8Array array(buffer);
+ for (int i = 0; i < size; ++i)
+ array.val().set(i, testByteValue(i));
+ return buffer;
+}
+
+void WasmIoDevicesTest::blobIODevice()
+{
+ if (!qstdweb::canBlockCallingThread()) {
+ QtWasmTest::completeTestFunction(QtWasmTest::TestResult::Skip, "requires asyncify");
+ return;
+ }
+
+ // Create test buffer and BlobIODevice
+ const int bufferSize = 16;
+ BlobIODevice blobDevice(Blob::fromArrayBuffer(createTestArrayBuffer(bufferSize)));
+
+ // Read back byte for byte from the device
+ QWASMVERIFY(blobDevice.open(QIODevice::ReadOnly));
+ for (int i = 0; i < bufferSize; ++i) {
+ char byte;
+ blobDevice.seek(i);
+ blobDevice.read(&byte, 1);
+ QWASMCOMPARE(byte, testByteValue(i));
+ }
+
+ blobDevice.close();
+ QWASMVERIFY(!blobDevice.open(QIODevice::WriteOnly));
+ QWASMSUCCESS();
+}
+
+void WasmIoDevicesTest::uint8ArrayIODevice()
+{
+ // Create test buffer and Uint8ArrayIODevice
+ const int bufferSize = 1024;
+ Uint8Array array(createTestArrayBuffer(bufferSize));
+ Uint8ArrayIODevice arrayDevice(array);
+
+ // Read back byte for byte from the device
+ QWASMVERIFY(arrayDevice.open(QIODevice::ReadWrite));
+ for (int i = 0; i < bufferSize; ++i) {
+ char byte;
+ arrayDevice.seek(i);
+ arrayDevice.read(&byte, 1);
+ QWASMCOMPARE(byte, testByteValue(i));
+ }
+
+ // Write a different set of bytes
+ QWASMCOMPARE(arrayDevice.seek(0), true);
+ for (int i = 0; i < bufferSize; ++i) {
+ char byte = testByteValue(i + 1);
+ arrayDevice.seek(i);
+ QWASMCOMPARE(arrayDevice.write(&byte, 1), 1);
+ }
+
+ // Verify that the original array was updated
+ QByteArray copy = QByteArray::fromEcmaUint8Array(array.val());
+ for (int i = 0; i < bufferSize; ++i)
+ QWASMCOMPARE(copy.at(i), testByteValue(i + 1));
+
+ arrayDevice.close();
+ QWASMSUCCESS();
+}
+
+int main(int argc, char **argv)
+{
+ auto testObject = std::make_shared<WasmIoDevicesTest>();
+ QtWasmTest::initTestCase<QCoreApplication>(argc, argv, testObject);
+ return 0;
+}
+
+#include "iodevices_main.moc"
+
diff --git a/tests/manual/wasm/qstdweb/promise_auto.html b/tests/manual/wasm/qstdweb/promise_auto.html
index 786145419f..94a8dbb88a 100644
--- a/tests/manual/wasm/qstdweb/promise_auto.html
+++ b/tests/manual/wasm/qstdweb/promise_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="promise_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(promise_auto_entry, document.getElementById("log"));
};
</script>
<p>Running promise auto test.</p>
diff --git a/tests/manual/wasm/qstdweb/promise_main.cpp b/tests/manual/wasm/qstdweb/promise_main.cpp
index 351f06c91d..c5f6f7f412 100644
--- a/tests/manual/wasm/qstdweb/promise_main.cpp
+++ b/tests/manual/wasm/qstdweb/promise_main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QCoreApplication>
#include <QtCore/QEvent>
diff --git a/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html b/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
index 26daecdf41..f33aab0b9c 100644
--- a/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
+++ b/tests/manual/wasm/qstdweb/qwasmcompositor_auto.html
@@ -3,7 +3,7 @@
<script type="text/javascript" src="qwasmcompositor_auto.js"></script>
<script>
window.onload = () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(qwasmcompositor_auto_entry, document.getElementById("log"));
};
</script>
<p>Running files auto test.</p>
diff --git a/tests/manual/wasm/qstdweb/qwasmcompositor_main.cpp b/tests/manual/wasm/qstdweb/qwasmcompositor_main.cpp
index 8b5807a8dd..e1a9cf604d 100644
--- a/tests/manual/wasm/qstdweb/qwasmcompositor_main.cpp
+++ b/tests/manual/wasm/qstdweb/qwasmcompositor_main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QEvent>
#include <QtCore/QObject>
@@ -7,7 +7,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qoffscreensurface.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
-#include <QtGui/private/qrhigles2_p.h>
+#include <QtGui/rhi/qrhi.h>
#include <qtwasmtestlib.h>
@@ -66,7 +66,7 @@ void Window::keyPressEvent(QKeyEvent *)
void Window::init()
{
- QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers | QRhi::EnableProfiling;
+ QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
m_fallbackSurface.reset(QRhiGles2InitParams::newFallbackSurface());
QRhiGles2InitParams params;
@@ -94,10 +94,8 @@ public:
QWasmCompositorTest() : m_window(val::global("window")), m_testSupport(val::object())
{
m_window.set("testSupport", m_testSupport);
- m_testSupport.set("qtAddContainerElement",
- emscripten::val::module_property("qtAddContainerElement"));
- m_testSupport.set("qtRemoveContainerElement",
- emscripten::val::module_property("qtRemoveContainerElement"));
+ m_testSupport.set("qtSetContainerElements",
+ emscripten::val::module_property("qtSetContainerElements"));
}
~QWasmCompositorTest() noexcept
@@ -118,12 +116,12 @@ private:
});
m_cleanup.emplace_back([]() mutable {
EM_ASM({
- testSupport.qtRemoveContainerElement(testSupport.screenElement);
+ testSupport.qtSetContainerElements([]);
testSupport.screenElement.parentElement.removeChild(testSupport.screenElement);
});
});
- EM_ASM({ testSupport.qtAddContainerElement(testSupport.screenElement); });
+ EM_ASM({ testSupport.qtSetContainerElements([testSupport.screenElement]); });
}
template<class T>
diff --git a/tests/manual/wasm/qtloader_integration/CMakeLists.txt b/tests/manual/wasm/qtloader_integration/CMakeLists.txt
new file mode 100644
index 0000000000..2603a05135
--- /dev/null
+++ b/tests/manual/wasm/qtloader_integration/CMakeLists.txt
@@ -0,0 +1,45 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_manual_test(tst_qtloader_integration
+ GUI
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::Widgets
+)
+
+set_target_properties(tst_qtloader_integration PROPERTIES QT_WASM_EXTRA_EXPORTED_METHODS "ENV")
+
+add_custom_command(
+ TARGET tst_qtloader_integration POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/tst_qtloader_integration.html
+ ${CMAKE_CURRENT_BINARY_DIR}/tst_qtloader_integration.html)
+
+add_custom_command(
+ TARGET tst_qtloader_integration POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/plugins/platforms/wasm/qtloader.js
+ ${CMAKE_CURRENT_BINARY_DIR}/qtloader.js)
+
+add_custom_command(
+ TARGET tst_qtloader_integration POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/../shared/testrunner.js
+ ${CMAKE_CURRENT_BINARY_DIR}/testrunner.js)
+
+add_custom_command(
+ TARGET tst_qtloader_integration POST_BUILD
+ 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
new file mode 100644
index 0000000000..4bb502b69c
--- /dev/null
+++ b/tests/manual/wasm/qtloader_integration/main.cpp
@@ -0,0 +1,183 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#include <QtWidgets/QtWidgets>
+
+#include <iostream>
+#include <sstream>
+
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
+#include <emscripten.h>
+
+#include <QtGui/qpa/qplatformscreen.h>
+
+namespace {
+constexpr int ExitValueImmediateReturn = 42;
+constexpr int ExitValueFromExitApp = 22;
+
+std::string screenInformation()
+{
+ auto screens = qGuiApp->screens();
+ std::ostringstream out;
+ out << "[";
+ const char *separator = "";
+ for (const auto &screen : screens) {
+ out << separator;
+ out << "[" << std::to_string(screen->geometry().x()) << ","
+ << std::to_string(screen->geometry().y()) << ","
+ << std::to_string(screen->geometry().width()) << ","
+ << std::to_string(screen->geometry().height()) << "]";
+ separator = ",";
+ }
+ out << "]";
+ return out.str();
+}
+
+std::string logicalDpi()
+{
+ auto screens = qGuiApp->screens();
+ std::ostringstream out;
+ out << "[";
+ const char *separator = "";
+ for (const auto &screen : screens) {
+ out << separator;
+ out << "[" << std::to_string(screen->handle()->logicalDpi().first) << ", "
+ << std::to_string(screen->handle()->logicalDpi().second) << "]";
+ separator = ",";
+ }
+ out << "]";
+ 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()
+{
+ emscripten_force_exit(ExitValueFromExitApp);
+}
+
+void produceOutput()
+{
+ fprintf(stdout, "Sample output!\n");
+}
+
+std::string retrieveArguments()
+{
+ auto arguments = QApplication::arguments();
+ std::ostringstream out;
+ out << "[";
+ const char *separator = "";
+ for (const auto &argument : arguments) {
+ out << separator;
+ out << "'" << argument.toStdString() << "'";
+ separator = ",";
+ }
+ out << "]";
+ return out.str();
+}
+
+std::string getEnvironmentVariable(std::string name) {
+ return QString::fromLatin1(qgetenv(name.c_str())).toStdString();
+}
+} // namespace
+
+class AppWindow : public QObject
+{
+ Q_OBJECT
+public:
+ AppWindow() : m_layout(new QVBoxLayout(&m_ui))
+ {
+ addWidget<QLabel>("Qt Loader integration tests");
+
+ m_ui.setLayout(m_layout);
+ }
+
+ void show() { m_ui.show(); }
+
+ ~AppWindow() = default;
+
+private:
+ template<class T, class... Args>
+ T *addWidget(Args... args)
+ {
+ T *widget = new T(std::forward<Args>(args)..., &m_ui);
+ m_layout->addWidget(widget);
+ return widget;
+ }
+
+ QWidget m_ui;
+ QVBoxLayout *m_layout;
+};
+
+int main(int argc, char **argv)
+{
+ QApplication application(argc, argv);
+ const auto arguments = application.arguments();
+ const bool exitImmediately =
+ std::find(arguments.begin(), arguments.end(), QStringLiteral("--exit-immediately"))
+ != arguments.end();
+ if (exitImmediately)
+ emscripten_force_exit(ExitValueImmediateReturn);
+
+ const bool crashImmediately =
+ std::find(arguments.begin(), arguments.end(), QStringLiteral("--crash-immediately"))
+ != arguments.end();
+ 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();
+ return application.exec();
+ }
+ return application.exec();
+}
+
+EMSCRIPTEN_BINDINGS(qtLoaderIntegrationTest)
+{
+ emscripten::constant("EXIT_VALUE_IMMEDIATE_RETURN", ExitValueImmediateReturn);
+ emscripten::constant("EXIT_VALUE_FROM_EXIT_APP", ExitValueFromExitApp);
+
+ emscripten::function("screenInformation", &screenInformation);
+ emscripten::function("logicalDpi", &logicalDpi);
+ emscripten::function("preloadedFiles", &preloadedFiles);
+ emscripten::function("crash", &crash);
+ emscripten::function("exitApp", &exitApp);
+ emscripten::function("produceOutput", &produceOutput);
+ emscripten::function("retrieveArguments", &retrieveArguments);
+ emscripten::function("getEnvironmentVariable", &getEnvironmentVariable);
+}
+
+#include "main.moc"
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
new file mode 100644
index 0000000000..4fb49c31aa
--- /dev/null
+++ b/tests/manual/wasm/qtloader_integration/test_body.js
@@ -0,0 +1,517 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import { Mock, assert, TestRunner } from './testrunner.js';
+
+export class QtLoaderIntegrationTests
+{
+ #testScreenContainers = []
+
+ async beforeEach()
+ {
+ this.#addScreenContainer('screen-container-0', { width: '200px', height: '300px' });
+ }
+
+ async afterEach()
+ {
+ this.#testScreenContainers.forEach(screenContainer =>
+ {
+ document.body.removeChild(screenContainer);
+ });
+ this.#testScreenContainers = [];
+ }
+
+ async missingConfig()
+ {
+ let caughtException;
+ try {
+ await qtLoad();
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal('config is required, expected an object', caughtException.message);
+ }
+
+ async missingQtSection()
+ {
+ let caughtException;
+ try {
+ await qtLoad({});
+ } catch (e) {
+ caughtException = e;
+ }
+
+ assert.isNotUndefined(caughtException);
+ assert.equal(
+ 'config.qt is required, expected an object', caughtException.message);
+ }
+
+ async missingEntryFunction()
+ {
+ 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()
+ {
+ const instance = await qtLoad({
+ qt: {
+ environment: {
+ variable1: 'value1',
+ variable2: 'value2'
+ },
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: [this.#testScreenContainers[0]]
+ }
+ });
+ assert.isTrue(instance.getEnvironmentVariable('variable1') === 'value1');
+ assert.isTrue(instance.getEnvironmentVariable('variable2') === 'value2');
+ }
+
+ async screenContainerManipulations()
+ {
+ // ... (do other things), then call addContainerElement() to add a new container/screen.
+ // This can happen either before or after load() is called - loader will route the
+ // call to instance when it's ready.
+ this.#addScreenContainer('appcontainer1', { width: '100px', height: '100px' })
+
+ const instance = await qtLoad({
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: this.#testScreenContainers
+ }
+ });
+ {
+ const screenInformation = this.#getScreenInformation(instance);
+
+ assert.equal(2, screenInformation.length);
+ assert.equal(200, screenInformation[0].width);
+ assert.equal(300, screenInformation[0].height);
+ assert.equal(100, screenInformation[1].width);
+ assert.equal(100, screenInformation[1].height);
+ }
+
+ this.#addScreenContainer('appcontainer2', { width: '234px', height: '99px' })
+ instance.qtSetContainerElements(this.#testScreenContainers);
+
+ {
+ const screenInformation = this.#getScreenInformation(instance);
+
+ assert.equal(3, screenInformation.length);
+ assert.equal(200, screenInformation[0].width);
+ assert.equal(300, screenInformation[0].height);
+ assert.equal(100, screenInformation[1].width);
+ assert.equal(100, screenInformation[1].height);
+ assert.equal(234, screenInformation[2].width);
+ assert.equal(99, screenInformation[2].height);
+ }
+
+ document.body.removeChild(this.#testScreenContainers.splice(2, 1)[0]);
+ instance.qtSetContainerElements(this.#testScreenContainers);
+ {
+ const screenInformation = this.#getScreenInformation(instance);
+
+ assert.equal(2, screenInformation.length);
+ assert.equal(200, screenInformation[0].width);
+ assert.equal(300, screenInformation[0].height);
+ assert.equal(100, screenInformation[1].width);
+ assert.equal(100, screenInformation[1].height);
+ }
+ }
+
+ async primaryScreenIsAlwaysFirst()
+ {
+ const instance = await qtLoad({
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: this.#testScreenContainers,
+ }
+ });
+ this.#addScreenContainer(
+ 'appcontainer3', { width: '12px', height: '24px' },
+ container => this.#testScreenContainers.splice(0, 0, container));
+ this.#addScreenContainer(
+ 'appcontainer4', { width: '34px', height: '68px' },
+ container => this.#testScreenContainers.splice(1, 0, container));
+
+ instance.qtSetContainerElements(this.#testScreenContainers);
+ {
+ const screenInformation = this.#getScreenInformation(instance);
+
+ assert.equal(3, screenInformation.length);
+ // The primary screen (at position 0) is always at 0
+ assert.equal(12, screenInformation[0].width);
+ assert.equal(24, screenInformation[0].height);
+ // Other screens are pushed at the back
+ assert.equal(200, screenInformation[1].width);
+ assert.equal(300, screenInformation[1].height);
+ assert.equal(34, screenInformation[2].width);
+ assert.equal(68, screenInformation[2].height);
+ }
+
+ this.#testScreenContainers.forEach(screenContainer =>
+ {
+ document.body.removeChild(screenContainer);
+ });
+ this.#testScreenContainers = [
+ this.#addScreenContainer('appcontainer5', { width: '11px', height: '12px' }),
+ this.#addScreenContainer('appcontainer6', { width: '13px', height: '14px' }),
+ ];
+
+ instance.qtSetContainerElements(this.#testScreenContainers);
+ {
+ const screenInformation = this.#getScreenInformation(instance);
+
+ assert.equal(2, screenInformation.length);
+ assert.equal(11, screenInformation[0].width);
+ assert.equal(12, screenInformation[0].height);
+ assert.equal(13, screenInformation[1].width);
+ assert.equal(14, screenInformation[1].height);
+ }
+ }
+
+ async multipleInstances()
+ {
+ // 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 module = WebAssembly.compileStreaming(fetch('tst_qtloader_integration.wasm'));
+
+ const instances = await Promise.all([1, 2, 3].map(i => qtLoad({
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: [this.#addScreenContainer(`screen-container-${i}`, {
+ width: `${i * 10}px`,
+ height: `${i * 10}px`,
+ })],
+ module,
+ }
+ })));
+ // Confirm the identity of instances by querying their screen widths and heights
+ {
+ const screenInformation = this.#getScreenInformation(instances[0]);
+ console.log();
+ assert.equal(1, screenInformation.length);
+ assert.equal(10, screenInformation[0].width);
+ assert.equal(10, screenInformation[0].height);
+ }
+ {
+ const screenInformation = this.#getScreenInformation(instances[1]);
+ assert.equal(1, screenInformation.length);
+ assert.equal(20, screenInformation[0].width);
+ assert.equal(20, screenInformation[0].height);
+ }
+ {
+ const screenInformation = this.#getScreenInformation(instances[2]);
+ assert.equal(1, screenInformation.length);
+ assert.equal(30, screenInformation[0].width);
+ assert.equal(30, screenInformation[0].height);
+ }
+ }
+
+ async consoleMode()
+ {
+ // 'Console mode' for autotesting type scenarios
+ let accumulatedStdout = '';
+ const instance = await qtLoad({
+ arguments: ['--no-gui'],
+ print: output =>
+ {
+ accumulatedStdout += output;
+ },
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+
+ this.#callTestInstanceApi(instance, 'produceOutput');
+ assert.equal('Sample output!', accumulatedStdout);
+ }
+
+ async modulePromiseProvided()
+ {
+ await qtLoad({
+ qt: {
+ entryFunction: createQtAppInstance,
+ containerElements: [this.#testScreenContainers[0]],
+ 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'))
+ }
+ });
+ }
+
+ async arguments()
+ {
+ const instance = await qtLoad({
+ arguments: ['--no-gui', 'arg1', 'other', 'yetanotherarg'],
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ const args = this.#callTestInstanceApi(instance, 'retrieveArguments');
+ assert.equal(5, args.length);
+ assert.isTrue('arg1' === args[2]);
+ assert.equal('other', args[3]);
+ assert.equal('yetanotherarg', args[4]);
+ }
+
+ async moduleProvided_exceptionThrownInFactory()
+ {
+ let caughtException;
+ try {
+ await qtLoad({
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ containerElements: [this.#testScreenContainers[0]],
+ module: Promise.reject(new Error('Failed to load')),
+ }
+ });
+ } catch (e) {
+ caughtException = e;
+ }
+ assert.isTrue(caughtException !== undefined);
+ assert.equal('Failed to load', caughtException.message);
+ }
+
+ async abort()
+ {
+ const onExitMock = new Mock();
+ const instance = await qtLoad({
+ arguments: ['--no-gui'],
+ qt: {
+ onExit: onExitMock,
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ try {
+ instance.crash();
+ } catch { }
+ 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 abortImmediately()
+ {
+ const onExitMock = new Mock();
+ let caughtException;
+ try {
+ await qtLoad({
+ arguments: ['--no-gui', '--crash-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);
+ 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);
+ }
+
+ async userAbortCallbackCalled()
+ {
+ const onAbortMock = new Mock();
+ let instance = await qtLoad({
+ arguments: ['--no-gui'],
+ onAbort: onAbortMock,
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ try {
+ instance.crash();
+ } catch (e) {
+ // emscripten throws an 'Aborted' error here, which we ignore for the sake of the test
+ }
+ assert.equal(1, onAbortMock.calls.length);
+ }
+
+ async exit()
+ {
+ const onExitMock = new Mock();
+ let instance = await qtLoad({
+ arguments: ['--no-gui'],
+ qt: {
+ onExit: onExitMock,
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ // The module is running. onExit should not have been called.
+ assert.equal(0, onExitMock.calls.length);
+ try {
+ instance.exitApp();
+ } catch (e) {
+ // emscripten throws a 'Runtime error: unreachable' error here. We ignore it for the
+ // sake of the test.
+ }
+ assert.equal(1, onExitMock.calls.length);
+ const exitStatus = onExitMock.calls[0][0];
+ assert.isFalse(exitStatus.crashed);
+ assert.equal(instance.EXIT_VALUE_FROM_EXIT_APP, exitStatus.code);
+ assert.isUndefined(exitStatus.text);
+ }
+
+ async exitImmediately()
+ {
+ const onExitMock = new Mock();
+ const instance = await qtLoad({
+ arguments: ['--no-gui', '--exit-immediately'],
+ qt: {
+ onExit: onExitMock,
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ assert.equal(1, onExitMock.calls.length);
+
+ const exitStatusFromOnExit = onExitMock.calls[0][0];
+
+ assert.isFalse(exitStatusFromOnExit.crashed);
+ assert.equal(instance.EXIT_VALUE_IMMEDIATE_RETURN, exitStatusFromOnExit.code);
+ assert.isUndefined(exitStatusFromOnExit.text);
+ }
+
+ async userQuitCallbackCalled()
+ {
+ const quitMock = new Mock();
+ let instance = await qtLoad({
+ arguments: ['--no-gui'],
+ quit: quitMock,
+ qt: {
+ entryFunction: tst_qtloader_integration_entry,
+ }
+ });
+ try {
+ instance.exitApp();
+ } catch (e) {
+ // emscripten throws a 'Runtime error: unreachable' error here. We ignore it for the
+ // sake of the test.
+ }
+ assert.equal(1, quitMock.calls.length);
+ const [exitCode, exception] = quitMock.calls[0];
+ assert.equal(instance.EXIT_VALUE_FROM_EXIT_APP, exitCode);
+ 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]());
+ }
+
+ #getScreenInformation(instance)
+ {
+ return this.#callTestInstanceApi(instance, 'screenInformation').map(elem => ({
+ x: elem[0],
+ y: elem[1],
+ width: elem[2],
+ height: elem[3],
+ }));
+ }
+
+ #addScreenContainer(id, style, inserter)
+ {
+ const container = (() =>
+ {
+ const container = document.createElement('div');
+ container.id = id;
+ container.style.width = style.width;
+ container.style.height = style.height;
+ document.body.appendChild(container);
+ return container;
+ })();
+ inserter ? inserter(container) : this.#testScreenContainers.push(container);
+ return container;
+ }
+}
+
+(async () =>
+{
+ const runner = new TestRunner(new QtLoaderIntegrationTests(), {
+ timeoutSeconds: 10
+ });
+ await runner.runAll();
+})();
diff --git a/tests/manual/wasm/qtloader_integration/tst_qtloader_integration.html b/tests/manual/wasm/qtloader_integration/tst_qtloader_integration.html
new file mode 100644
index 0000000000..7aa7528a1d
--- /dev/null
+++ b/tests/manual/wasm/qtloader_integration/tst_qtloader_integration.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en-us">
+
+<head>
+ <title>tst_qtloader_integration</title>
+ <script src='tst_qtloader_integration.js'></script>
+ <script src="qtloader.js" defer></script>
+ <script type="module" src="test_body.js" defer></script>
+</head>
+
+<body></body>
+
+</html>
diff --git a/tests/manual/wasm/qtwasmtestlib/README.md b/tests/manual/wasm/qtwasmtestlib/README.md
index 515c33ae6a..6de81fe8b4 100644
--- a/tests/manual/wasm/qtwasmtestlib/README.md
+++ b/tests/manual/wasm/qtwasmtestlib/README.md
@@ -48,7 +48,7 @@ Finally provide an html file which hosts the test runner and calls runTestCase()
<script type="text/javascript" src="test_case.js"></script>
<script>
window.onload = async () => {
- runTestCase(document.getElementById("log"));
+ runTestCase(entryFunction, document.getElementById("log"));
};
</script>
<p>Running Foo auto test.</p>
@@ -67,7 +67,7 @@ html file provides container elements which becomes QScreens for the test code.
window.onload = async () => {
let log = document.getElementById("log")
let containers = [document.getElementById("container")];
- runTestCase(log, containers);
+ runTestCase(entryFunction, log, containers);
};
</script>
<p>Running Foo auto test.</p>
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
index d86b8ee2c0..ec03c7209a 100644
--- a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qtwasmtestlib.h"
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.h b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.h
index 5dcc41419e..2307ed1ccd 100644
--- a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.h
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QT_WASM_TESTRUNNER_H
#define QT_WASM_TESTRUNNER_H
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
index eaf518d1ef..d4f815b887 100644
--- a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
@@ -1,5 +1,5 @@
// Copyright (C) 2022 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
// A minimal async test runner for Qt async auto tests.
//
@@ -77,12 +77,13 @@ async function runTestFunction(instance, name) {
}
}
-async function runTestCaseImpl(testFunctionStarted, testFunctionCompleted, qtContainers) {
+async function runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers)
+{
// Create test case instance
const config = {
qtContainerElements: qtContainers || []
}
- const instance = await createQtAppInstance(config);
+ const instance = await entryFunction(config);
// Run all test functions
const functionsString = instance.getTestFunctions();
@@ -124,10 +125,11 @@ function testFunctionCompleted(status) {
g_htmlLogElement.innerHTML += line;
}
-async function runTestCase(htmlLogElement, qtContainers) {
+async function runTestCase(entryFunction, htmlLogElement, qtContainers)
+{
g_htmlLogElement = htmlLogElement;
try {
- await runTestCaseImpl(testFunctionStarted, testFunctionCompleted, qtContainers);
+ await runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers);
g_htmlLogElement.innerHTML += "<br> DONE"
} catch (err) {
g_htmlLogElement.innerHTML += err
diff --git a/tests/manual/wasm/rasterwindow/main.cpp b/tests/manual/wasm/rasterwindow/main.cpp
index 38921c8c30..576b73112b 100644
--- a/tests/manual/wasm/rasterwindow/main.cpp
+++ b/tests/manual/wasm/rasterwindow/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 <QtGui>
#include "rasterwindow.h"
diff --git a/tests/manual/wasm/rasterwindow/rasterwindow.cpp b/tests/manual/wasm/rasterwindow/rasterwindow.cpp
index b8da476d46..8fd036c274 100644
--- a/tests/manual/wasm/rasterwindow/rasterwindow.cpp
+++ b/tests/manual/wasm/rasterwindow/rasterwindow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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 "rasterwindow.h"
RasterWindow::RasterWindow()
diff --git a/tests/manual/wasm/rasterwindow/rasterwindow.h b/tests/manual/wasm/rasterwindow/rasterwindow.h
index b01efb9ddb..e488420440 100644
--- a/tests/manual/wasm/rasterwindow/rasterwindow.h
+++ b/tests/manual/wasm/rasterwindow/rasterwindow.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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
#ifndef RASTERWINDOW_H
#define RASTERWINDOW_H
diff --git a/tests/manual/wasm/shared/run.sh b/tests/manual/wasm/shared/run.sh
index d8ae18919c..f04e45278c 100755
--- a/tests/manual/wasm/shared/run.sh
+++ b/tests/manual/wasm/shared/run.sh
@@ -1,7 +1,7 @@
#! /bin/bash
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
set -m
@@ -20,7 +20,7 @@ trap removeServer EXIT
script_dir=`dirname ${BASH_SOURCE[0]}`
cd "$script_dir/../../../../"
-python3 -m http.server 8001 &
+python3 util/wasm/qtwasmserver/qtwasmserver.py -p 8001 &
cleanupPid=$!
cd -
diff --git a/tests/manual/wasm/shared/testrunner.js b/tests/manual/wasm/shared/testrunner.js
index da87026b03..197e3bfa6d 100644
--- a/tests/manual/wasm/shared/testrunner.js
+++ b/tests/manual/wasm/shared/testrunner.js
@@ -1,6 +1,84 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+function parseQuery()
+{
+ const trimmed = window.location.search.substring(1);
+ return new Map(
+ trimmed.length === 0 ?
+ [] :
+ trimmed.split('&').map(paramNameAndValue =>
+ {
+ const [name, value] = paramNameAndValue.split('=');
+ return [decodeURIComponent(name), value ? decodeURIComponent(value) : ''];
+ }));
+}
+
+export class assert
+{
+ static isFalse(value)
+ {
+ if (value !== false)
+ throw new Error(`Assertion failed, expected to be false, was ${value}`);
+ }
+
+ static isTrue(value)
+ {
+ if (value !== true)
+ throw new Error(`Assertion failed, expected to be true, was ${value}`);
+ }
+
+ static isUndefined(value)
+ {
+ if (typeof value !== 'undefined')
+ throw new Error(`Assertion failed, expected to be undefined, was ${value}`);
+ }
+
+ static isNotUndefined(value)
+ {
+ if (typeof value === 'undefined')
+ throw new Error(`Assertion failed, expected not to be undefined, was ${value}`);
+ }
+
+ static equal(expected, actual)
+ {
+ if (expected !== actual)
+ throw new Error(`Assertion failed, expected to be ${expected}, was ${actual}`);
+ }
+
+ static notEqual(expected, actual)
+ {
+ if (expected === actual)
+ throw new Error(`Assertion failed, expected not to be ${expected}`);
+ }
+}
+
+export class Mock extends Function
+{
+ #calls = [];
+
+ constructor()
+ {
+ super()
+ const proxy = new Proxy(this, {
+ apply: (target, _, args) => target.onCall(...args)
+ });
+ proxy.thisMock = this;
+
+ return proxy;
+ }
+
+ get calls()
+ {
+ return this.thisMock.#calls;
+ }
+
+ onCall(...args)
+ {
+ this.#calls.push(args);
+ }
+}
+
function output(message)
{
const outputLine = document.createElement('div');
@@ -15,10 +93,12 @@ function output(message)
export class TestRunner
{
#testClassInstance
+ #timeoutSeconds
- constructor(testClassInstance)
+ constructor(testClassInstance, config)
{
this.#testClassInstance = testClassInstance;
+ this.#timeoutSeconds = config?.timeoutSeconds ?? 2;
}
async run(testCase)
@@ -39,8 +119,8 @@ export class TestRunner
const timeout = window.setTimeout(() =>
{
rejected = true;
- reject(new Error('Timeout after 2 seconds'));
- }, 2000);
+ reject(new Error(`Timeout after ${this.#timeoutSeconds} seconds`));
+ }, this.#timeoutSeconds * 1000);
prototype[testCase].apply(this.#testClassInstance).then(() =>
{
if (!rejected) {
@@ -61,12 +141,15 @@ export class TestRunner
async runAll()
{
+ const query = parseQuery();
+ const testFilter = query.has('testfilter') ? new RegExp(query.get('testfilter')) : undefined;
+
const SPECIAL_FUNCTIONS =
['beforeEach', 'afterEach', 'beforeAll', 'afterAll', 'constructor'];
const prototype = Object.getPrototypeOf(this.#testClassInstance);
const testFunctions =
Object.getOwnPropertyNames(prototype).filter(
- entry => SPECIAL_FUNCTIONS.indexOf(entry) === -1);
+ entry => SPECIAL_FUNCTIONS.indexOf(entry) === -1 && (!testFilter || entry.match(testFilter)));
if (prototype.beforeAll)
await prototype.beforeAll.apply(this.#testClassInstance);