diff mbox series

[RFC,1/1] support/testing: add python-pyqt5 test

Message ID 20240110202319.139004-1-ju.o@free.fr
State Superseded
Headers show
Series [RFC,1/1] support/testing: add python-pyqt5 test | expand

Commit Message

Julien Olivain Jan. 10, 2024, 8:23 p.m. UTC
Signed-off-by: Julien Olivain <ju.o@free.fr>
---
Few notes:

This runtime test was suggested by Thomas in:
https://lists.buildroot.org/pipermail/buildroot/2023-December/681113.html

In order to work, the patch
https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/
needs to be also applied.

I tested this patch on branch master at commit 22393c9 with commands:

    make check-package
    ...
    0 warnings generated

    support/testing/run-tests \
        -d dl -o output_folder \
        tests.package.test_python_pyqt5
    ...
    OK

Doing this test, I've spotted few issues:

The test needs to select BR2_PACKAGE_QT5BASE_WIDGETS=y
otherwise, the build fails. I believe this is a missing build
dependency in python-pyqt5 (to be confirmed).

Also, Qt5 no longer ships fonts. So the test application runs
without any text. It shows a warning on the console:

    QFontDatabase: Cannot find font directory /usr/lib/fonts.
    Note that Qt no longer ships fonts. Deploy some (from https://dejavu-fonts.github.io/ for example) or switch to fontconfig.

It's not a real problem for the test. But using
(Py)Qt5 with EGLFS directly on KMS/DRM (i.e. without X11 nor Weston)
seems a valid use-case. I was not able to install fonts without X11.
---
 DEVELOPERS                                    |  2 +
 .../tests/package/test_python_pyqt5.py        | 61 +++++++++++++++++++
 .../test_python_pyqt5/linux-vkms.fragment     |  1 +
 .../rootfs-overlay/root/pyqt5test.py          | 60 ++++++++++++++++++
 4 files changed, 124 insertions(+)
 create mode 100644 support/testing/tests/package/test_python_pyqt5.py
 create mode 100644 support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
 create mode 100755 support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py

Comments

Ralf Dragon Jan. 10, 2024, 9:06 p.m. UTC | #1
Hi Julien,

that looks really nice!

Out of curiosity, I am continuing to try to build PyQt5 with 
PyQt-builder which could also be used to eventually build PyQt6. I don't 
have too much time, so it likely will take some time but the test will 
be quite handy to complete the project.

Best,

Ralf



Am 10.01.24 um 21:23 schrieb Julien Olivain:
> Signed-off-by: Julien Olivain <ju.o@free.fr>
> ---
> Few notes:
>
> This runtime test was suggested by Thomas in:
> https://lists.buildroot.org/pipermail/buildroot/2023-December/681113.html
>
> In order to work, the patch
> https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/
> needs to be also applied.
>
> I tested this patch on branch master at commit 22393c9 with commands:
>
>      make check-package
>      ...
>      0 warnings generated
>
>      support/testing/run-tests \
>          -d dl -o output_folder \
>          tests.package.test_python_pyqt5
>      ...
>      OK
>
> Doing this test, I've spotted few issues:
>
> The test needs to select BR2_PACKAGE_QT5BASE_WIDGETS=y
> otherwise, the build fails. I believe this is a missing build
> dependency in python-pyqt5 (to be confirmed).
>
> Also, Qt5 no longer ships fonts. So the test application runs
> without any text. It shows a warning on the console:
>
>      QFontDatabase: Cannot find font directory /usr/lib/fonts.
>      Note that Qt no longer ships fonts. Deploy some (from https://dejavu-fonts.github.io/ for example) or switch to fontconfig.
>
> It's not a real problem for the test. But using
> (Py)Qt5 with EGLFS directly on KMS/DRM (i.e. without X11 nor Weston)
> seems a valid use-case. I was not able to install fonts without X11.
> ---
>   DEVELOPERS                                    |  2 +
>   .../tests/package/test_python_pyqt5.py        | 61 +++++++++++++++++++
>   .../test_python_pyqt5/linux-vkms.fragment     |  1 +
>   .../rootfs-overlay/root/pyqt5test.py          | 60 ++++++++++++++++++
>   4 files changed, 124 insertions(+)
>   create mode 100644 support/testing/tests/package/test_python_pyqt5.py
>   create mode 100644 support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>   create mode 100755 support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>
> diff --git a/DEVELOPERS b/DEVELOPERS
> index d7543247f2..7aecb828e4 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -1806,6 +1806,8 @@ F:	support/testing/tests/package/test_python_magic_wormhole.py
>   F:	support/testing/tests/package/test_python_midiutil.py
>   F:	support/testing/tests/package/test_python_ml_dtypes.py
>   F:	support/testing/tests/package/test_python_pyalsa.py
> +F:	support/testing/tests/package/test_python_pyqt5.py
> +F:	support/testing/tests/package/test_python_pyqt5/
>   F:	support/testing/tests/package/test_python_spake2.py
>   F:	support/testing/tests/package/test_rdma_core.py
>   F:	support/testing/tests/package/test_rdma_core/
> diff --git a/support/testing/tests/package/test_python_pyqt5.py b/support/testing/tests/package/test_python_pyqt5.py
> new file mode 100644
> index 0000000000..6ef0577878
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5.py
> @@ -0,0 +1,61 @@
> +import os
> +
> +import infra.basetest
> +
> +
> +class TestPythonPyQt5(infra.basetest.BRTest):
> +    # We use a specific configuration for:
> +    # - using Aarch64, to have more than 256MB memory,
> +    # - using a kernel config fragment, to enable VKMS,
> +    # - to have an ext4 rootfs image exposed as a virtio storage
> +    #   (rather than cpio initrd). This will save some memory, as the
> +    #   rootfs image is big.
> +    config = \
> +        f"""
> +        BR2_aarch64=y
> +        BR2_TOOLCHAIN_EXTERNAL=y
> +        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
> +        BR2_LINUX_KERNEL=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
> +        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
> +        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
> +        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{infra.filepath("tests/package/test_python_pyqt5/linux-vkms.fragment")}"
> +        BR2_PACKAGE_LIBDRM=y
> +        BR2_PACKAGE_MESA3D=y
> +        BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST=y
> +        BR2_PACKAGE_MESA3D_LLVM=y
> +        BR2_PACKAGE_MESA3D_OPENGL_EGL=y
> +        BR2_PACKAGE_MESA3D_OPENGL_ES=y
> +        BR2_PACKAGE_PYTHON3=y
> +        BR2_PACKAGE_PYTHON_PYQT5=y
> +        BR2_PACKAGE_QT5=y
> +        BR2_PACKAGE_QT5BASE_EGLFS=y
> +        BR2_PACKAGE_QT5BASE_WIDGETS=y
> +        BR2_ROOTFS_OVERLAY="{infra.filepath("tests/package/test_python_pyqt5/rootfs-overlay")}"
> +        BR2_TARGET_ROOTFS_EXT2=y
> +        BR2_TARGET_ROOTFS_EXT2_4=y
> +        BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
> +        # BR2_TARGET_ROOTFS_TAR is not set
> +        """.format(
> +            )
> +
> +    def test_run(self):
> +        drive = os.path.join(self.builddir, "images", "rootfs.ext4")
> +        kern = os.path.join(self.builddir, "images", "Image")
> +        self.emulator.boot(arch="aarch64",
> +                           kernel=kern,
> +                           kernel_cmdline=["root=/dev/vda console=ttyAMA0"],
> +                           options=["-M", "virt", "-cpu", "cortex-a57", "-m", "512M",
> +                                    "-drive", f"file={drive},if=virtio,format=raw"])
> +        self.emulator.login()
> +
> +        # We run the test application with a customized message.
> +        msg = "Hello Buildroot."
> +        cmd = f'/root/pyqt5test.py "{msg}"'
> +        self.assertRunOk(cmd, timeout=30)
> +
> +        # We check the test message is present in the file created by
> +        # the previous application execution.
> +        cmd = f'grep -F "{msg}" /root/message.txt'
> +        self.assertRunOk(cmd)
> diff --git a/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
> new file mode 100644
> index 0000000000..ec2ed4460c
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
> @@ -0,0 +1 @@
> +CONFIG_DRM_VKMS=y
> diff --git a/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
> new file mode 100755
> index 0000000000..3efeed7687
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
> @@ -0,0 +1,60 @@
> +#! /usr/bin/env python3
> +#
> +# This is a test application for PyQt5. It is showing a text label and
> +# a "quit" button. The text of the label can be set with the first
> +# (non-Qt) command line argument. A timer will send a click signal to
> +# the quit button after 3 seconds. When quitting, the text of the
> +# label is saved in a "message.txt" file in the current working
> +# directory.
> +
> +import sys
> +
> +from PyQt5.QtCore import PYQT_VERSION_STR, QFile, QIODevice, QT_VERSION_STR, QTextStream, QTimer, Qt
> +from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
> +
> +
> +class TestApp(QWidget):
> +
> +    def __init__(self, message, parent=None):
> +        super(TestApp, self).__init__(parent)
> +
> +        self.label = QLabel(message)
> +        self.label.setAlignment(Qt.AlignCenter)
> +
> +        self.button = QPushButton("Quit")
> +        self.button.clicked.connect(self.on_button_clicked)
> +
> +        self.layout = QVBoxLayout()
> +        self.layout.addWidget(self.label)
> +        self.layout.addWidget(self.button)
> +
> +        self.setLayout(self.layout)
> +
> +        self.timer = QTimer()
> +        self.timer.timeout.connect(self.button.click)
> +
> +    def on_button_clicked(self):
> +        self.save_message()
> +        app.quit()
> +
> +    def save_message(self):
> +        f = QFile("message.txt")
> +        if f.open(QIODevice.WriteOnly):
> +            QTextStream(f) << (self.label.text() + '\n')
> +        f.close()
> +
> +
> +if __name__ == "__main__":
> +    print("PyQt5 test for Buildroot")
> +    print(f"Qt version {QT_VERSION_STR}")
> +    print(f"PyQt version {PYQT_VERSION_STR}")
> +
> +    msg = "Hello World"
> +    app = QApplication(sys.argv)
> +    args = app.arguments()
> +    if len(args) > 1:
> +        msg = args[1]
> +    testApp = TestApp(message=msg)
> +    testApp.show()
> +    testApp.timer.start(3000)
> +    sys.exit(app.exec())
Ralf Dragon March 6, 2024, 6:24 p.m. UTC | #2
Hi all,

I think this thread got forgotten and nothing has been merged yet.

To summarize

- there is a nice test now which confirms that my patch 
https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/ 
seems to be needed for the runtime

- the test uncovered 2 problems, one direct dependency and another 
runtime dependency (fonts)

What would be the next step to get this integrated?

Best,

Ralf



Am 10.01.24 um 21:23 schrieb Julien Olivain:
> Signed-off-by: Julien Olivain<ju.o@free.fr>
> ---
> Few notes:
>
> This runtime test was suggested by Thomas in:
> https://lists.buildroot.org/pipermail/buildroot/2023-December/681113.html
>
> In order to work, the patch
> https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/
> needs to be also applied.
>
> I tested this patch on branch master at commit 22393c9 with commands:
>
>      make check-package
>      ...
>      0 warnings generated
>
>      support/testing/run-tests \
>          -d dl -o output_folder \
>          tests.package.test_python_pyqt5
>      ...
>      OK
>
> Doing this test, I've spotted few issues:
>
> The test needs to select BR2_PACKAGE_QT5BASE_WIDGETS=y
> otherwise, the build fails. I believe this is a missing build
> dependency in python-pyqt5 (to be confirmed).
>
> Also, Qt5 no longer ships fonts. So the test application runs
> without any text. It shows a warning on the console:
>
>      QFontDatabase: Cannot find font directory /usr/lib/fonts.
>      Note that Qt no longer ships fonts. Deploy some (fromhttps://dejavu-fonts.github.io/  for example) or switch to fontconfig.
>
> It's not a real problem for the test. But using
> (Py)Qt5 with EGLFS directly on KMS/DRM (i.e. without X11 nor Weston)
> seems a valid use-case. I was not able to install fonts without X11.
> ---
>   DEVELOPERS                                    |  2 +
>   .../tests/package/test_python_pyqt5.py        | 61 +++++++++++++++++++
>   .../test_python_pyqt5/linux-vkms.fragment     |  1 +
>   .../rootfs-overlay/root/pyqt5test.py          | 60 ++++++++++++++++++
>   4 files changed, 124 insertions(+)
>   create mode 100644 support/testing/tests/package/test_python_pyqt5.py
>   create mode 100644 support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>   create mode 100755 support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>
> diff --git a/DEVELOPERS b/DEVELOPERS
> index d7543247f2..7aecb828e4 100644
> --- a/DEVELOPERS
> +++ b/DEVELOPERS
> @@ -1806,6 +1806,8 @@ F:	support/testing/tests/package/test_python_magic_wormhole.py
>   F:	support/testing/tests/package/test_python_midiutil.py
>   F:	support/testing/tests/package/test_python_ml_dtypes.py
>   F:	support/testing/tests/package/test_python_pyalsa.py
> +F:	support/testing/tests/package/test_python_pyqt5.py
> +F:	support/testing/tests/package/test_python_pyqt5/
>   F:	support/testing/tests/package/test_python_spake2.py
>   F:	support/testing/tests/package/test_rdma_core.py
>   F:	support/testing/tests/package/test_rdma_core/
> diff --git a/support/testing/tests/package/test_python_pyqt5.py b/support/testing/tests/package/test_python_pyqt5.py
> new file mode 100644
> index 0000000000..6ef0577878
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5.py
> @@ -0,0 +1,61 @@
> +import os
> +
> +import infra.basetest
> +
> +
> +class TestPythonPyQt5(infra.basetest.BRTest):
> +    # We use a specific configuration for:
> +    # - using Aarch64, to have more than 256MB memory,
> +    # - using a kernel config fragment, to enable VKMS,
> +    # - to have an ext4 rootfs image exposed as a virtio storage
> +    #   (rather than cpio initrd). This will save some memory, as the
> +    #   rootfs image is big.
> +    config = \
> +        f"""
> +        BR2_aarch64=y
> +        BR2_TOOLCHAIN_EXTERNAL=y
> +        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
> +        BR2_LINUX_KERNEL=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
> +        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
> +        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
> +        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
> +        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{infra.filepath("tests/package/test_python_pyqt5/linux-vkms.fragment")}"
> +        BR2_PACKAGE_LIBDRM=y
> +        BR2_PACKAGE_MESA3D=y
> +        BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST=y
> +        BR2_PACKAGE_MESA3D_LLVM=y
> +        BR2_PACKAGE_MESA3D_OPENGL_EGL=y
> +        BR2_PACKAGE_MESA3D_OPENGL_ES=y
> +        BR2_PACKAGE_PYTHON3=y
> +        BR2_PACKAGE_PYTHON_PYQT5=y
> +        BR2_PACKAGE_QT5=y
> +        BR2_PACKAGE_QT5BASE_EGLFS=y
> +        BR2_PACKAGE_QT5BASE_WIDGETS=y
> +        BR2_ROOTFS_OVERLAY="{infra.filepath("tests/package/test_python_pyqt5/rootfs-overlay")}"
> +        BR2_TARGET_ROOTFS_EXT2=y
> +        BR2_TARGET_ROOTFS_EXT2_4=y
> +        BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
> +        # BR2_TARGET_ROOTFS_TAR is not set
> +        """.format(
> +            )
> +
> +    def test_run(self):
> +        drive = os.path.join(self.builddir, "images", "rootfs.ext4")
> +        kern = os.path.join(self.builddir, "images", "Image")
> +        self.emulator.boot(arch="aarch64",
> +                           kernel=kern,
> +                           kernel_cmdline=["root=/dev/vda console=ttyAMA0"],
> +                           options=["-M", "virt", "-cpu", "cortex-a57", "-m", "512M",
> +                                    "-drive", f"file={drive},if=virtio,format=raw"])
> +        self.emulator.login()
> +
> +        # We run the test application with a customized message.
> +        msg = "Hello Buildroot."
> +        cmd = f'/root/pyqt5test.py "{msg}"'
> +        self.assertRunOk(cmd, timeout=30)
> +
> +        # We check the test message is present in the file created by
> +        # the previous application execution.
> +        cmd = f'grep -F "{msg}" /root/message.txt'
> +        self.assertRunOk(cmd)
> diff --git a/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
> new file mode 100644
> index 0000000000..ec2ed4460c
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
> @@ -0,0 +1 @@
> +CONFIG_DRM_VKMS=y
> diff --git a/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
> new file mode 100755
> index 0000000000..3efeed7687
> --- /dev/null
> +++ b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
> @@ -0,0 +1,60 @@
> +#! /usr/bin/env python3
> +#
> +# This is a test application for PyQt5. It is showing a text label and
> +# a "quit" button. The text of the label can be set with the first
> +# (non-Qt) command line argument. A timer will send a click signal to
> +# the quit button after 3 seconds. When quitting, the text of the
> +# label is saved in a "message.txt" file in the current working
> +# directory.
> +
> +import sys
> +
> +from PyQt5.QtCore import PYQT_VERSION_STR, QFile, QIODevice, QT_VERSION_STR, QTextStream, QTimer, Qt
> +from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
> +
> +
> +class TestApp(QWidget):
> +
> +    def __init__(self, message, parent=None):
> +        super(TestApp, self).__init__(parent)
> +
> +        self.label = QLabel(message)
> +        self.label.setAlignment(Qt.AlignCenter)
> +
> +        self.button = QPushButton("Quit")
> +        self.button.clicked.connect(self.on_button_clicked)
> +
> +        self.layout = QVBoxLayout()
> +        self.layout.addWidget(self.label)
> +        self.layout.addWidget(self.button)
> +
> +        self.setLayout(self.layout)
> +
> +        self.timer = QTimer()
> +        self.timer.timeout.connect(self.button.click)
> +
> +    def on_button_clicked(self):
> +        self.save_message()
> +        app.quit()
> +
> +    def save_message(self):
> +        f = QFile("message.txt")
> +        if f.open(QIODevice.WriteOnly):
> +            QTextStream(f) << (self.label.text() + '\n')
> +        f.close()
> +
> +
> +if __name__ == "__main__":
> +    print("PyQt5 test for Buildroot")
> +    print(f"Qt version {QT_VERSION_STR}")
> +    print(f"PyQt version {PYQT_VERSION_STR}")
> +
> +    msg = "Hello World"
> +    app = QApplication(sys.argv)
> +    args = app.arguments()
> +    if len(args) > 1:
> +        msg = args[1]
> +    testApp = TestApp(message=msg)
> +    testApp.show()
> +    testApp.timer.start(3000)
> +    sys.exit(app.exec())
Julien Olivain March 9, 2024, 5:36 p.m. UTC | #3
Hi Ralf, All,

On 06/03/2024 19:24, Ralf Dragon wrote:
> Hi all,
> 
> I think this thread got forgotten and nothing has been merged yet.
> 
> To summarize
> 
> - there is a nice test now which confirms that my patch
> https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/
> seems to be needed for the runtime
> 
> - the test uncovered 2 problems, one direct dependency and another
> runtime dependency (fonts)
> 
> What would be the next step to get this integrated?

On my side, I recently updated this runtime test:

1. I am no longer able to reproduce the build issue when
BR2_PACKAGE_QT5BASE_WIDGETS is unset (as of master branch at commit 
31abe2f).
My runtime test does require QWidgets, so I simply kept it in my test 
config.
We'll see if autobuilders catch something...

2. I was also able to fix the font issue: Buildroot actually includes
a standalone font package in "package/dejavu" (I initially though, as 
its
name suggests, that it was the dejavu programs, rather than the fonts). 
Adding
it and fontconfig also makes Qt5 able to load those fonts (in a KMS/DRM
configuration).

I'll send a v2 of this runtime test.

Also, I think your initial python-pyqt5-sip proposal will also need a 
v2. I'll
reply to your initial submission by adding my review comments.

With those two v2, I hope we could get this merged.

> Best,
> 
> Ralf
> 
> Am 10.01.24 um 21:23 schrieb Julien Olivain:
> 
>> Signed-off-by: Julien Olivain <ju.o@free.fr>
>> ---
>> Few notes:
>> 
>> This runtime test was suggested by Thomas in:
>> 
> https://lists.buildroot.org/pipermail/buildroot/2023-December/681113.html
>> 
>> In order to work, the patch
>> 
> https://patchwork.ozlabs.org/project/buildroot/patch/20231212160112.94272-2-hypnotoad@lindra.de/
>> needs to be also applied.
>> 
>> I tested this patch on branch master at commit 22393c9 with
>> commands:
>> 
>> make check-package
>> ...
>> 0 warnings generated
>> 
>> support/testing/run-tests \
>> -d dl -o output_folder \
>> tests.package.test_python_pyqt5
>> ...
>> OK
>> 
>> Doing this test, I've spotted few issues:
>> 
>> The test needs to select BR2_PACKAGE_QT5BASE_WIDGETS=y
>> otherwise, the build fails. I believe this is a missing build
>> dependency in python-pyqt5 (to be confirmed).
>> 
>> Also, Qt5 no longer ships fonts. So the test application runs
>> without any text. It shows a warning on the console:
>> 
>> QFontDatabase: Cannot find font directory /usr/lib/fonts.
>> Note that Qt no longer ships fonts. Deploy some (from
>> https://dejavu-fonts.github.io/ for example) or switch to
>> fontconfig.
>> 
>> It's not a real problem for the test. But using
>> (Py)Qt5 with EGLFS directly on KMS/DRM (i.e. without X11 nor Weston)
>> seems a valid use-case. I was not able to install fonts without X11.
>> ---
>> DEVELOPERS                                    |  2 +
>> .../tests/package/test_python_pyqt5.py        | 61
>> +++++++++++++++++++
>> .../test_python_pyqt5/linux-vkms.fragment     |  1 +
>> .../rootfs-overlay/root/pyqt5test.py          | 60
>> ++++++++++++++++++
>> 4 files changed, 124 insertions(+)
>> create mode 100644
>> support/testing/tests/package/test_python_pyqt5.py
>> create mode 100644
>> support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>> create mode 100755
>> 
> support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>> 
>> diff --git a/DEVELOPERS b/DEVELOPERS
>> index d7543247f2..7aecb828e4 100644
>> --- a/DEVELOPERS
>> +++ b/DEVELOPERS
>> @@ -1806,6 +1806,8 @@ F:
>> support/testing/tests/package/test_python_magic_wormhole.py
>> F:    support/testing/tests/package/test_python_midiutil.py
>> F:    support/testing/tests/package/test_python_ml_dtypes.py
>> F:    support/testing/tests/package/test_python_pyalsa.py
>> +F:    support/testing/tests/package/test_python_pyqt5.py
>> +F:    support/testing/tests/package/test_python_pyqt5/
>> F:    support/testing/tests/package/test_python_spake2.py
>> F:    support/testing/tests/package/test_rdma_core.py
>> F:    support/testing/tests/package/test_rdma_core/
>> diff --git a/support/testing/tests/package/test_python_pyqt5.py
>> b/support/testing/tests/package/test_python_pyqt5.py
>> new file mode 100644
>> index 0000000000..6ef0577878
>> --- /dev/null
>> +++ b/support/testing/tests/package/test_python_pyqt5.py
>> @@ -0,0 +1,61 @@
>> +import os
>> +
>> +import infra.basetest
>> +
>> +
>> +class TestPythonPyQt5(infra.basetest.BRTest):
>> +    # We use a specific configuration for:
>> +    # - using Aarch64, to have more than 256MB memory,
>> +    # - using a kernel config fragment, to enable VKMS,
>> +    # - to have an ext4 rootfs image exposed as a virtio storage
>> +    #   (rather than cpio initrd). This will save some memory, as
>> the
>> +    #   rootfs image is big.
>> +    config = \
>> +        f"""
>> +        BR2_aarch64=y
>> +        BR2_TOOLCHAIN_EXTERNAL=y
>> +        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
>> +        BR2_LINUX_KERNEL=y
>> +        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
>> +        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
>> +        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
>> +
>> 
> BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
>> +
>> 
> BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{infra.filepath("tests/package/test_python_pyqt5/linux-vkms.fragment")}"
>> +        BR2_PACKAGE_LIBDRM=y
>> +        BR2_PACKAGE_MESA3D=y
>> +        BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST=y
>> +        BR2_PACKAGE_MESA3D_LLVM=y
>> +        BR2_PACKAGE_MESA3D_OPENGL_EGL=y
>> +        BR2_PACKAGE_MESA3D_OPENGL_ES=y
>> +        BR2_PACKAGE_PYTHON3=y
>> +        BR2_PACKAGE_PYTHON_PYQT5=y
>> +        BR2_PACKAGE_QT5=y
>> +        BR2_PACKAGE_QT5BASE_EGLFS=y
>> +        BR2_PACKAGE_QT5BASE_WIDGETS=y
>> +
>> 
> BR2_ROOTFS_OVERLAY="{infra.filepath("tests/package/test_python_pyqt5/rootfs-overlay")}"
>> +        BR2_TARGET_ROOTFS_EXT2=y
>> +        BR2_TARGET_ROOTFS_EXT2_4=y
>> +        BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
>> +        # BR2_TARGET_ROOTFS_TAR is not set
>> +        """.format(
>> +            )
>> +
>> +    def test_run(self):
>> +        drive = os.path.join(self.builddir, "images",
>> "rootfs.ext4")
>> +        kern = os.path.join(self.builddir, "images", "Image")
>> +        self.emulator.boot(arch="aarch64",
>> +                           kernel=kern,
>> +                           kernel_cmdline=["root=/dev/vda
>> console=ttyAMA0"],
>> +                           options=["-M", "virt", "-cpu",
>> "cortex-a57", "-m", "512M",
>> +                                    "-drive",
>> f"file={drive},if=virtio,format=raw"])
>> +        self.emulator.login()
>> +
>> +        # We run the test application with a customized message.
>> +        msg = "Hello Buildroot."
>> +        cmd = f'/root/pyqt5test.py "{msg}"'
>> +        self.assertRunOk(cmd, timeout=30)
>> +
>> +        # We check the test message is present in the file created
>> by
>> +        # the previous application execution.
>> +        cmd = f'grep -F "{msg}" /root/message.txt'
>> +        self.assertRunOk(cmd)
>> diff --git
>> 
> a/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>> 
> b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>> new file mode 100644
>> index 0000000000..ec2ed4460c
>> --- /dev/null
>> +++
>> 
> b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
>> @@ -0,0 +1 @@
>> +CONFIG_DRM_VKMS=y
>> diff --git
>> 
> a/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>> 
> b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>> new file mode 100755
>> index 0000000000..3efeed7687
>> --- /dev/null
>> +++
>> 
> b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
>> @@ -0,0 +1,60 @@
>> +#! /usr/bin/env python3
>> +#
>> +# This is a test application for PyQt5. It is showing a text label
>> and
>> +# a "quit" button. The text of the label can be set with the first
>> +# (non-Qt) command line argument. A timer will send a click signal
>> to
>> +# the quit button after 3 seconds. When quitting, the text of the
>> +# label is saved in a "message.txt" file in the current working
>> +# directory.
>> +
>> +import sys
>> +
>> +from PyQt5.QtCore import PYQT_VERSION_STR, QFile, QIODevice,
>> QT_VERSION_STR, QTextStream, QTimer, Qt
>> +from PyQt5.QtWidgets import QApplication, QLabel, QPushButton,
>> QVBoxLayout, QWidget
>> +
>> +
>> +class TestApp(QWidget):
>> +
>> +    def __init__(self, message, parent=None):
>> +        super(TestApp, self).__init__(parent)
>> +
>> +        self.label = QLabel(message)
>> +        self.label.setAlignment(Qt.AlignCenter)
>> +
>> +        self.button = QPushButton("Quit")
>> +        self.button.clicked.connect(self.on_button_clicked)
>> +
>> +        self.layout = QVBoxLayout()
>> +        self.layout.addWidget(self.label)
>> +        self.layout.addWidget(self.button)
>> +
>> +        self.setLayout(self.layout)
>> +
>> +        self.timer = QTimer()
>> +        self.timer.timeout.connect(self.button.click)
>> +
>> +    def on_button_clicked(self):
>> +        self.save_message()
>> +        app.quit()
>> +
>> +    def save_message(self):
>> +        f = QFile("message.txt")
>> +        if f.open(QIODevice.WriteOnly):
>> +            QTextStream(f) << (self.label.text() + '\n')
>> +        f.close()
>> +
>> +
>> +if __name__ == "__main__":
>> +    print("PyQt5 test for Buildroot")
>> +    print(f"Qt version {QT_VERSION_STR}")
>> +    print(f"PyQt version {PYQT_VERSION_STR}")
>> +
>> +    msg = "Hello World"
>> +    app = QApplication(sys.argv)
>> +    args = app.arguments()
>> +    if len(args) > 1:
>> +        msg = args[1]
>> +    testApp = TestApp(message=msg)
>> +    testApp.show()
>> +    testApp.timer.start(3000)
>> +    sys.exit(app.exec())

Best regards,

Julien.
diff mbox series

Patch

diff --git a/DEVELOPERS b/DEVELOPERS
index d7543247f2..7aecb828e4 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -1806,6 +1806,8 @@  F:	support/testing/tests/package/test_python_magic_wormhole.py
 F:	support/testing/tests/package/test_python_midiutil.py
 F:	support/testing/tests/package/test_python_ml_dtypes.py
 F:	support/testing/tests/package/test_python_pyalsa.py
+F:	support/testing/tests/package/test_python_pyqt5.py
+F:	support/testing/tests/package/test_python_pyqt5/
 F:	support/testing/tests/package/test_python_spake2.py
 F:	support/testing/tests/package/test_rdma_core.py
 F:	support/testing/tests/package/test_rdma_core/
diff --git a/support/testing/tests/package/test_python_pyqt5.py b/support/testing/tests/package/test_python_pyqt5.py
new file mode 100644
index 0000000000..6ef0577878
--- /dev/null
+++ b/support/testing/tests/package/test_python_pyqt5.py
@@ -0,0 +1,61 @@ 
+import os
+
+import infra.basetest
+
+
+class TestPythonPyQt5(infra.basetest.BRTest):
+    # We use a specific configuration for:
+    # - using Aarch64, to have more than 256MB memory,
+    # - using a kernel config fragment, to enable VKMS,
+    # - to have an ext4 rootfs image exposed as a virtio storage
+    #   (rather than cpio initrd). This will save some memory, as the
+    #   rootfs image is big.
+    config = \
+        f"""
+        BR2_aarch64=y
+        BR2_TOOLCHAIN_EXTERNAL=y
+        BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
+        BR2_LINUX_KERNEL=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+        BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.72"
+        BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+        BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
+        BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{infra.filepath("tests/package/test_python_pyqt5/linux-vkms.fragment")}"
+        BR2_PACKAGE_LIBDRM=y
+        BR2_PACKAGE_MESA3D=y
+        BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SWRAST=y
+        BR2_PACKAGE_MESA3D_LLVM=y
+        BR2_PACKAGE_MESA3D_OPENGL_EGL=y
+        BR2_PACKAGE_MESA3D_OPENGL_ES=y
+        BR2_PACKAGE_PYTHON3=y
+        BR2_PACKAGE_PYTHON_PYQT5=y
+        BR2_PACKAGE_QT5=y
+        BR2_PACKAGE_QT5BASE_EGLFS=y
+        BR2_PACKAGE_QT5BASE_WIDGETS=y
+        BR2_ROOTFS_OVERLAY="{infra.filepath("tests/package/test_python_pyqt5/rootfs-overlay")}"
+        BR2_TARGET_ROOTFS_EXT2=y
+        BR2_TARGET_ROOTFS_EXT2_4=y
+        BR2_TARGET_ROOTFS_EXT2_SIZE="256M"
+        # BR2_TARGET_ROOTFS_TAR is not set
+        """.format(
+            )
+
+    def test_run(self):
+        drive = os.path.join(self.builddir, "images", "rootfs.ext4")
+        kern = os.path.join(self.builddir, "images", "Image")
+        self.emulator.boot(arch="aarch64",
+                           kernel=kern,
+                           kernel_cmdline=["root=/dev/vda console=ttyAMA0"],
+                           options=["-M", "virt", "-cpu", "cortex-a57", "-m", "512M",
+                                    "-drive", f"file={drive},if=virtio,format=raw"])
+        self.emulator.login()
+
+        # We run the test application with a customized message.
+        msg = "Hello Buildroot."
+        cmd = f'/root/pyqt5test.py "{msg}"'
+        self.assertRunOk(cmd, timeout=30)
+
+        # We check the test message is present in the file created by
+        # the previous application execution.
+        cmd = f'grep -F "{msg}" /root/message.txt'
+        self.assertRunOk(cmd)
diff --git a/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
new file mode 100644
index 0000000000..ec2ed4460c
--- /dev/null
+++ b/support/testing/tests/package/test_python_pyqt5/linux-vkms.fragment
@@ -0,0 +1 @@ 
+CONFIG_DRM_VKMS=y
diff --git a/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
new file mode 100755
index 0000000000..3efeed7687
--- /dev/null
+++ b/support/testing/tests/package/test_python_pyqt5/rootfs-overlay/root/pyqt5test.py
@@ -0,0 +1,60 @@ 
+#! /usr/bin/env python3
+#
+# This is a test application for PyQt5. It is showing a text label and
+# a "quit" button. The text of the label can be set with the first
+# (non-Qt) command line argument. A timer will send a click signal to
+# the quit button after 3 seconds. When quitting, the text of the
+# label is saved in a "message.txt" file in the current working
+# directory.
+
+import sys
+
+from PyQt5.QtCore import PYQT_VERSION_STR, QFile, QIODevice, QT_VERSION_STR, QTextStream, QTimer, Qt
+from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
+
+
+class TestApp(QWidget):
+
+    def __init__(self, message, parent=None):
+        super(TestApp, self).__init__(parent)
+
+        self.label = QLabel(message)
+        self.label.setAlignment(Qt.AlignCenter)
+
+        self.button = QPushButton("Quit")
+        self.button.clicked.connect(self.on_button_clicked)
+
+        self.layout = QVBoxLayout()
+        self.layout.addWidget(self.label)
+        self.layout.addWidget(self.button)
+
+        self.setLayout(self.layout)
+
+        self.timer = QTimer()
+        self.timer.timeout.connect(self.button.click)
+
+    def on_button_clicked(self):
+        self.save_message()
+        app.quit()
+
+    def save_message(self):
+        f = QFile("message.txt")
+        if f.open(QIODevice.WriteOnly):
+            QTextStream(f) << (self.label.text() + '\n')
+        f.close()
+
+
+if __name__ == "__main__":
+    print("PyQt5 test for Buildroot")
+    print(f"Qt version {QT_VERSION_STR}")
+    print(f"PyQt version {PYQT_VERSION_STR}")
+
+    msg = "Hello World"
+    app = QApplication(sys.argv)
+    args = app.arguments()
+    if len(args) > 1:
+        msg = args[1]
+    testApp = TestApp(message=msg)
+    testApp.show()
+    testApp.timer.start(3000)
+    sys.exit(app.exec())