Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qcoro for openSUSE:Factory checked 
in at 2023-05-10 16:16:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qcoro (Old)
 and      /work/SRC/openSUSE:Factory/.qcoro.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qcoro"

Wed May 10 16:16:20 2023 rev:8 rq:1085641 version:0.9.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/qcoro/qcoro.changes      2023-02-09 
16:23:25.174778676 +0100
+++ /work/SRC/openSUSE:Factory/.qcoro.new.1533/qcoro.changes    2023-05-10 
16:16:22.422211339 +0200
@@ -1,0 +2,17 @@
+Thu Apr 27 08:23:17 UTC 2023 - Christophe Marin <[email protected]>
+
+- Update to 0.9.0
+  * Make QCoro::Generator properly move-constructible
+  * iOS support: handle QProcess being not available
+  * Fix QCoro::connect with QFutures
+  * Fix debug build against MSVC2022
+  * Fix CheckAtomic failing on Windows with Clang
+  * Make how Qt packages are found more convenient
+  * Fix clang 16 builds
+  * Fix crash in QCoroSignal when signal is received after
+  * destruction
+  * Fix connecting to member function pointers
+  * QML: Add declarative API for awaiting a task
+  * Implement QCoroTest
+
+-------------------------------------------------------------------

Old:
----
  qcoro-0.8.0.tar.gz

New:
----
  qcoro-0.9.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qcoro.spec ++++++
--- /var/tmp/diff_new_pack.BaOK8f/_old  2023-05-10 16:16:22.862213942 +0200
+++ /var/tmp/diff_new_pack.BaOK8f/_new  2023-05-10 16:16:22.866213965 +0200
@@ -36,7 +36,7 @@
 %endif
 #
 Name:           qcoro%{?_pkg_name_suffix}
-Version:        0.8.0
+Version:        0.9.0
 Release:        0
 Summary:        Coroutines for Qt
 License:        MIT
@@ -63,6 +63,7 @@
 # C++-20 support is needed. Qt6 already requires gcc10
 %if 0%{?qt5} && 0%{?suse_version} == 1500
 BuildRequires:  gcc10-c++
+BuildRequires:  gcc10-PIE
 %endif
 
 %description
@@ -166,18 +167,12 @@
 # 20220713: tests still randomly fail, mostly on arm
 #%%ctest
 
-%post -n libQCoro%{_qt_suffix}Core%{sonum}  -p /sbin/ldconfig
-%post -n libQCoro%{_qt_suffix}DBus%{sonum}  -p /sbin/ldconfig
-%post -n libQCoro%{_qt_suffix}Network%{sonum}  -p /sbin/ldconfig
-%post -n libQCoro%{_qt_suffix}Qml%{sonum}  -p /sbin/ldconfig
-%post -n libQCoro%{_qt_suffix}Quick%{sonum}  -p /sbin/ldconfig
-%post -n libQCoro%{_qt_suffix}WebSockets%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}Core%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}DBus%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}Network%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}Qml%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}Quick%{sonum}  -p /sbin/ldconfig
-%postun -n libQCoro%{_qt_suffix}WebSockets%{sonum}  -p /sbin/ldconfig
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}Core%{sonum}
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}DBus%{sonum}
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}Network%{sonum}
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}Qml%{sonum}
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}Quick%{sonum}
+%ldconfig_scriptlets -n libQCoro%{_qt_suffix}WebSockets%{sonum}
 
 %files -n libQCoro%{_qt_suffix}Core%{sonum}
 %license LICENSES/*
@@ -214,6 +209,7 @@
 %{_libdir}/cmake/QCoro%{_qt_suffix}Network/
 %{_libdir}/cmake/QCoro%{_qt_suffix}Qml/
 %{_libdir}/cmake/QCoro%{_qt_suffix}Quick/
+%{_libdir}/cmake/QCoro%{_qt_suffix}Test/
 %{_libdir}/cmake/QCoro%{_qt_suffix}WebSockets/
 %{_libdir}/libQCoro%{_qt_suffix}Core.so
 %{_libdir}/libQCoro%{_qt_suffix}DBus.so

++++++ qcoro-0.8.0.tar.gz -> qcoro-0.9.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qcoro-0.8.0/.github/workflows/build-docker-images.yml 
new/qcoro-0.9.0/.github/workflows/build-docker-images.yml
--- old/qcoro-0.8.0/.github/workflows/build-docker-images.yml   2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/.github/workflows/build-docker-images.yml   2023-04-27 
10:09:19.000000000 +0200
@@ -72,5 +72,5 @@
         push: true
         tags: ${{ steps.meta.outputs.tags }}
         labels: ${{ steps.meta.outputs.labels }}
-        file: docker/Dockerfile
+        file: docker/Dockerfile.${{ matrix.compiler }}
         context: docker
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/.github/workflows/build-linux.yml 
new/qcoro-0.9.0/.github/workflows/build-linux.yml
--- old/qcoro-0.8.0/.github/workflows/build-linux.yml   2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/.github/workflows/build-linux.yml   2023-04-27 
10:09:19.000000000 +0200
@@ -9,13 +9,13 @@
   pull_request:
     types: [opened, synchronize, reopened, edited]
 
-
 env:
   BUILD_TYPE: Debug
   QTEST_FUNCTION_TIMEOUT: 60000
 
 
 jobs:
+
   generate-matrix:
     name: Generate build matrix
     runs-on: ubuntu-latest
@@ -35,6 +35,10 @@
     strategy:
       matrix: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
+    defaults:
+      run:
+        shell: bash -l {0}
+
 
     runs-on: ${{ matrix.runs_on }}
     name: ${{ matrix.platform }}-${{ matrix.compiler_full }}-qt-${{ 
matrix.qt_version }}
@@ -51,7 +55,6 @@
         cmake -E make_directory build
 
     - name: Configure CMake
-      shell: bash
       run: |
         QT_VERSION_MAJOR=$(echo ${{ matrix.qt_version }} | cut -d'.' -f1)
 
@@ -69,12 +72,10 @@
           ${EXTRA_CMAKE_FLAGS}
 
     - name: Build
-      shell: bash
       run: |
         cmake --build build --config $BUILD_TYPE --parallel $(nproc) --verbose
 
     - name: Test
-      shell: bash
       run: |
         cd build
         QT_LOGGING_TO_CONSOLE=1 ctest -C $BUILD_TYPE \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/.github/workflows/generate-matrix.py 
new/qcoro-0.9.0/.github/workflows/generate-matrix.py
--- old/qcoro-0.8.0/.github/workflows/generate-matrix.py        2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/.github/workflows/generate-matrix.py        2023-04-27 
10:09:19.000000000 +0200
@@ -36,7 +36,7 @@
             },
             {
                 "name": "clang",
-                "versions": [ "11", "14", "dev" ]
+                "versions": [ "11", "14", "16", "dev" ]
             }
         ]
     }
@@ -61,7 +61,7 @@
     if compiler == "gcc":
         return "gcc"
     elif compiler == "clang":
-        return "silkeh/clang"
+        return "debian"
     else:
         return None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/CMakeLists.txt 
new/qcoro-0.9.0/CMakeLists.txt
--- old/qcoro-0.8.0/CMakeLists.txt      2023-01-31 20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/CMakeLists.txt      2023-04-27 10:09:19.000000000 +0200
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.18.4)
-set(qcoro_VERSION 0.8.0)
+set(qcoro_VERSION 0.9.0)
 set(qcoro_SOVERSION 0)
 project(qcoro LANGUAGES CXX VERSION ${qcoro_VERSION})
 
@@ -33,6 +33,8 @@
 add_feature_info(QtQuick QCORO_WITH_QTQUICK "Build QtQuick support")
 option(QCORO_WITH_QML "Build QML integration features" ON)
 add_feature_info(QtQml QCORO_WITH_QML "Build QML integration features")
+option(QCORO_WITH_QTTEST "Build QtTest support" ON)
+add_feature_info(QtTest QCORO_WITH_QTTEST "Build QtTest support")
 
 #-----------------------------------------------------------#
 # Dependencies
@@ -63,6 +65,9 @@
     # Qt6 needs access to private API
     list(APPEND REQUIRED_QT6_COMPONENTS QmlPrivate)
 endif()
+if (QCORO_WITH_QTTEST)
+    list(APPEND REQUIRED_QT_COMPONENTS Test)
+endif()
 if (QCORO_BUILD_EXAMPLES)
     list(APPEND REQUIRED_QT_COMPONENTS Widgets Concurrent)
 endif()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/cmake/CheckAtomic.cmake 
new/qcoro-0.9.0/cmake/CheckAtomic.cmake
--- old/qcoro-0.8.0/cmake/CheckAtomic.cmake     2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/cmake/CheckAtomic.cmake     2023-04-27 10:09:19.000000000 
+0200
@@ -8,7 +8,7 @@
 
 function(check_working_cxx_atomics varname)
   set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
-  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
+  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++20")
   CHECK_CXX_SOURCE_COMPILES("
 #include <atomic>
 std::atomic<int> x;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/cmake/QCoroFindQt.cmake 
new/qcoro-0.9.0/cmake/QCoroFindQt.cmake
--- old/qcoro-0.8.0/cmake/QCoroFindQt.cmake     2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/cmake/QCoroFindQt.cmake     2023-04-27 10:09:19.000000000 
+0200
@@ -12,17 +12,11 @@
             set(ARGS_QT_VERSION 5)
         endif()
     endif()
+    
+    list(APPEND REQUIRED_QT_COMPONENTS 
"${ARGS_QT${ARGS_QT_VERSION}_COMPONENTS}")
+    list(FILTER REQUIRED_QT_COMPONENTS EXCLUDE REGEX "Private$$")
 
-    foreach (component IN LISTS ARGS_COMPONENTS 
ARGS_QT${ARGS_QT_VERSION}_COMPONENTS)
-        message(STATUS "Qt component: ${component}")
-        if ("${component}" MATCHES "Private$$")
-            string(REPLACE "Private" "" base_component "${component}")
-            find_package(Qt${ARGS_QT_VERSION}${base_component} REQUIRED 
COMPONENTS Private)
-        else()
-            find_package(Qt${ARGS_QT_VERSION}${component} REQUIRED)
-        endif()
-    endforeach()
+    find_package(Qt${ARGS_QT_VERSION} REQUIRED COMPONENTS 
${REQUIRED_QT_COMPONENTS})
 
     set(${ARGS_FOUND_VER_VAR} ${ARGS_QT_VERSION})
 endmacro()
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/docker/Dockerfile 
new/qcoro-0.9.0/docker/Dockerfile
--- old/qcoro-0.8.0/docker/Dockerfile   2023-01-31 20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/docker/Dockerfile   1970-01-01 01:00:00.000000000 +0100
@@ -1,48 +0,0 @@
-# SPDX-FileCopyrightText: 2022 Daniel Vrátil <[email protected]>
-# SPDX-License-Identifier: MIT
-#
-# Docker image for specific versions of clang or gcc and specific version of 
Qt.
-
-ARG compiler_version
-ARG compiler_image
-FROM ${compiler_image}:${compiler_version}
-ARG qt_version
-ARG qt_modules
-ARG qt_archives
-
-SHELL ["/bin/bash", "-c"]
-
-RUN source /etc/os-release && \
-    if [[ "${VERSION_ID}" == "10" ]]; then \
-        echo "deb http://deb.debian.org/debian buster-backports main" > 
/etc/apt/sources.list.d/backports.list; \
-    fi
-
-RUN apt-get update \
-    && apt-get upgrade --yes \
-    && apt-get install --yes --no-install-recommends \
-        cmake=3.18.4\* cmake-data=3.18.4\* \
-        python3-pip python3-setuptools python3-wheel python3-dev \
-        dbus dbus-x11 \
-        libglib2.0-dev libxkbcommon-dev libfreetype6-dev libfontconfig1-dev \
-        libssl-dev \
-        libegl-dev libgl-dev libegl1=1.3.2\* libgl1=1.3.2\* libglx0=1.3.2\* 
libglvnd0=1.3.2\* \
-        libvulkan-dev \
-    && apt-get clean
-
-# Workaround a bug in CMake (?) which tries to look for OpenGL-related 
libraries
-# in /usr/lib/x86_64-unknown-linux-gnu instead of /usr/lib/x86_64-linux-gnu
-RUN ln -s x86_64-linux-gnu /usr/lib/x86_64-unknown-linux-gnu
-
-RUN pip3 install aqtinstall
-
-WORKDIR /root
-
-COPY install-qt.sh ./install-qt.sh
-
-RUN ./install-qt.sh "${qt_version}" "${qt_modules}" "${qt_archives}"
-
-ENV QT_BASE_DIR "/opt/qt/${qt_version}/gcc_64"
-ENV PATH "${QT_BASE_DIR}/bin:${PATH}"
-ENV CMAKE_PREFIX_PATH="${QT_BASE_DIR}/lib/cmake"
-ENV LD_LIBRARY_PATH "${QT_BASE_DIR}/lib:${LD_LIBRARY_PATH}"
-ENV XDG_DATA_DIRS "${QT_BASE_DIR}/share:${XDG_DATA_DIRS}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/docker/Dockerfile.clang 
new/qcoro-0.9.0/docker/Dockerfile.clang
--- old/qcoro-0.8.0/docker/Dockerfile.clang     1970-01-01 01:00:00.000000000 
+0100
+++ new/qcoro-0.9.0/docker/Dockerfile.clang     2023-04-27 10:09:19.000000000 
+0200
@@ -0,0 +1,68 @@
+# SPDX-FileCopyrightText: 2022 Daniel Vrátil <[email protected]>
+# SPDX-License-Identifier: MIT
+#
+# Docker image for specific versions of clang and specific version of Qt.
+
+FROM debian:bullseye
+ARG compiler_version
+ARG qt_version
+ARG qt_modules
+ARG qt_archives
+
+SHELL ["/bin/bash", "-c"]
+
+# Install build & runtime dependencies
+RUN apt-get update \
+    && apt-get upgrade --yes \
+    && apt-get install --yes --no-install-recommends \
+        cmake=3.18.4\* cmake-data=3.18.4\* \
+        make \
+        python3-pip python3-setuptools python3-wheel python3-dev \
+        dbus dbus-x11 \
+        libglib2.0-dev libxkbcommon-dev libfreetype6-dev libfontconfig1-dev \
+        libssl-dev \
+        libegl-dev libgl-dev libegl1=1.3.2\* libgl1=1.3.2\* libglx0=1.3.2\* 
libglvnd0=1.3.2\* \
+        libvulkan-dev
+
+# Install and set up clang
+RUN \
+    # Set up env \
+    if [ "${compiler_version}" == "dev" ]; then \
+        export CLANG_VERSION_SUFFIX=""; \
+    else \
+        export CLANG_VERSION_SUFFIX="-${compiler_version}"; \
+    fi && \
+    echo "export CC=\"/usr/bin/clang${CLANG_VERSION_SUFFIX}\"" >> 
/etc/profile.d/clang.sh && \
+    echo "export CXX=\"/usr/bin/clang++${CLANG_VERSION_SUFFIX}\"" >> 
/etc/profile.d/clang.sh && \
+    # Install tools needed to add the clang repository \
+    apt-get install --yes --no-install-recommends ca-certificates wget gnupg 
&& \
+    # Add clang repository \
+    echo "deb http://apt.llvm.org/bullseye/ 
llvm-toolchain-bullseye${CLANG_VERSION_SUFFIX} main" > 
/etc/apt/sources.list.d/llvm.list && \
+    echo "deb-src http://apt.llvm.org/bullseye/ 
llvm-toolchain-bullseye${CLANG_VERSION_SUFFIX} main" >> 
/etc/apt/sources.list.d/llvm.list && \
+    wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
+    # Install clang \
+    apt-get update && \
+    apt-get install --yes --install-recommends clang${CLANG_VERSION_SUFFIX} && 
\
+    clang_major_version=$(clang${CLANG_VERSION_SUFFIX} --version | grep -Eo 
"[0-9]+.[0-9]+.[0-9]+" | cut -d'.' -f1) && \
+    if [ ${clang_major_version} -gt 11 ]; then \
+        apt-get install --yes --no-install-recommends 
libclang-rt-${clang_major_version}-dev; \
+    fi
+
+# Workaround a bug in CMake (?) which tries to look for OpenGL-related 
libraries
+# in /usr/lib/x86_64-unknown-linux-gnu instead of /usr/lib/x86_64-linux-gnu
+RUN ln -s x86_64-linux-gnu /usr/lib/x86_64-unknown-linux-gnu
+
+# Install Qt
+WORKDIR /root
+RUN pip3 install aqtinstall
+COPY install-qt.sh ./install-qt.sh
+RUN ./install-qt.sh "${qt_version}" "${qt_modules}" "${qt_archives}"
+
+# Set Qt up environment
+ENV QT_BASE_DIR "/opt/qt/${qt_version}/gcc_64"
+ENV PATH "${QT_BASE_DIR}/bin:${PATH}"
+ENV CMAKE_PREFIX_PATH "${QT_BASE_DIR}/lib/cmake"
+ENV LD_LIBRARY_PATH "${QT_BASE_DIR}/lib:${LD_LIBRARY_PATH}"
+ENV XDG_DATA_DIRS "${QT_BASE_DIR}/share:${XDG_DATA_DIRS}"
+
+ENTRYPOINT [ "/bin/bash", "-l" ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/docker/Dockerfile.gcc 
new/qcoro-0.9.0/docker/Dockerfile.gcc
--- old/qcoro-0.8.0/docker/Dockerfile.gcc       1970-01-01 01:00:00.000000000 
+0100
+++ new/qcoro-0.9.0/docker/Dockerfile.gcc       2023-04-27 10:09:19.000000000 
+0200
@@ -0,0 +1,48 @@
+# SPDX-FileCopyrightText: 2022 Daniel Vrátil <[email protected]>
+# SPDX-License-Identifier: MIT
+#
+# Docker image for specific versions of gcc and specific version of Qt.
+
+ARG compiler_version
+FROM gcc:${compiler_version}
+ARG qt_version
+ARG qt_modules
+ARG qt_archives
+
+SHELL ["/bin/bash", "-c"]
+
+# Enable backports in older GCC images to get access to newer cmake
+RUN source /etc/os-release && \
+    if [[ "${VERSION_ID}" == "10" ]]; then \
+        echo "deb http://deb.debian.org/debian buster-backports main" > 
/etc/apt/sources.list.d/backports.list; \
+    fi
+
+# Install build-time and runtime dependencies
+RUN apt-get update \
+    && apt-get upgrade --yes \
+    && apt-get install --yes --no-install-recommends \
+        cmake=3.18.4\* cmake-data=3.18.4\* \
+        python3-pip python3-setuptools python3-wheel python3-dev \
+        dbus dbus-x11 \
+        libglib2.0-dev libxkbcommon-dev libfreetype6-dev libfontconfig1-dev \
+        libssl-dev \
+        libegl-dev libgl-dev libegl1=1.3.2\* libgl1=1.3.2\* libglx0=1.3.2\* 
libglvnd0=1.3.2\* \
+        libvulkan-dev \
+    && apt-get clean
+
+# Workaround a bug in CMake (?) which tries to look for OpenGL-related 
libraries
+# in /usr/lib/x86_64-unknown-linux-gnu instead of /usr/lib/x86_64-linux-gnu
+RUN ln -s x86_64-linux-gnu /usr/lib/x86_64-unknown-linux-gnu
+
+# Install Qt
+WORKDIR /root
+RUN pip3 install aqtinstall
+COPY install-qt.sh ./install-qt.sh
+RUN ./install-qt.sh "${qt_version}" "${qt_modules}" "${qt_archives}"
+
+# Set up environment
+ENV QT_BASE_DIR "/opt/qt/${qt_version}/gcc_64"
+ENV PATH "${QT_BASE_DIR}/bin:${PATH}"
+ENV CMAKE_PREFIX_PATH="${QT_BASE_DIR}/lib/cmake"
+ENV LD_LIBRARY_PATH "${QT_BASE_DIR}/lib:${LD_LIBRARY_PATH}"
+ENV XDG_DATA_DIRS "${QT_BASE_DIR}/share:${XDG_DATA_DIRS}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qcoro-0.8.0/docs/news/2023/2023-04-27-qcoro-0.9.0-announcement.md 
new/qcoro-0.9.0/docs/news/2023/2023-04-27-qcoro-0.9.0-announcement.md
--- old/qcoro-0.8.0/docs/news/2023/2023-04-27-qcoro-0.9.0-announcement.md       
1970-01-01 01:00:00.000000000 +0100
+++ new/qcoro-0.9.0/docs/news/2023/2023-04-27-qcoro-0.9.0-announcement.md       
2023-04-27 10:09:19.000000000 +0200
@@ -0,0 +1,77 @@
+---
+title: QCoro 0.9.0 Release Announcement
+date: "2023-04-27"
+description: >
+  Important bugfixes, huge improvement to QML support and a brand new Test 
module.
+---
+
+<!--
+SPDX-FileCopyrightText: 2023 Daniel Vrátil <[email protected]>
+
+SPDX-License-Identifier: GFDL-1.3-or-later
+-->
+
+# QCoro 0.9.0 Release Announcement
+
+Another smallish release with just a few new features, but quite important 
bugfixes.
+
+As always, thank you to everyone who reported issues and contributed to QCoro.
+Your help is much appreciated!
+
+## Enhanced QML Support
+
+Jonah Brüchert has improved the QML support by introducing a declarative API 
to await
+a task result.
+
+Previously a task result could have only been obtained inside a JavaScript 
function:
+
+```qml
+Label {
+    id: usernameLabel
+    Component.onCompleted: {
+        api.getUserName().then(function(result) {
+            usernameLabel.text = result
+        })
+    }
+}
+```
+
+With QCoro 0.9.0 you can use the new declarative API to use the result of an 
asynchronous
+task in a property binding:
+
+```qml
+Label {
+    id: usernameLabel
+    text: api.getUserName().await("Loading...").value
+}
+```
+
+The `Label` will now show the string "Loading..." while the asynchronous task 
is running
+and will automatically change to the result of the task once if finishes.
+
+You can check the [`QCoro::QmlTask` documentation][qcoro-qmltask-docs] for 
more details.
+
+## QCoroTest Module
+
+Yet another release with a new QCoro module! This time it's for tests! The 
QCoroTest
+module contains macros (e.g., `QCORO_VERIFY`, `QCORO_COMPARE`, ...) that are 
basically
+identical to their QtTest counteparts with the only difference being that they 
can be 
+used inside a coroutine.
+
+We already had this macros inside QCoro test suite almost since the very 
beginning
+and realized they can be useful to our users as well, since they will likely 
want
+to have unittests for their coroutine code.
+
+In some of the next releases we would like to add a little bit more 
infrastructure
+to make writing unittests for coroutines with QtTest even easier.
+
+Check the [`QCoroTest` module documentation][qcoro-test-docs] with a full list 
of
+the test macros.
+
+## Full changelog
+
+[See changelog on 
Github](https://github.com/danvratil/qcoro/releases/tag/v0.9.0)
+
+[qcoro-qmltask-docs]: https://qcoro.dvratil.cz/reference/qml/qmltask/
+[qcoro-test-docs]: https://qcoro.dvratil.cz/reference/test/
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/docs/reference/qml/qmltask.md 
new/qcoro-0.9.0/docs/reference/qml/qmltask.md
--- old/qcoro-0.8.0/docs/reference/qml/qmltask.md       2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/docs/reference/qml/qmltask.md       2023-04-27 
10:09:19.000000000 +0200
@@ -37,6 +37,7 @@
 }
 ```
 
+QmlTasks can call a JavaScript function when they complete:
 ```QML
 Example {
     Component.onCompleted: {
@@ -44,6 +45,20 @@
     }
 }
 ```
+
+They can also set properties when the value is available:
+```QML
+import QCoro 0
+import io.me.qmlmodule 1.0
+
+Item {
+    Example { id: store }
+
+    Label {
+        text: store.fetchValue("key").await().value
+    }
+}
+```
 
 
 [qdoc-qml]: https://doc.qt.io/qt-5/qvariant.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/docs/reference/test/index.md 
new/qcoro-0.9.0/docs/reference/test/index.md
--- old/qcoro-0.8.0/docs/reference/test/index.md        1970-01-01 
01:00:00.000000000 +0100
+++ new/qcoro-0.9.0/docs/reference/test/index.md        2023-04-27 
10:09:19.000000000 +0200
@@ -0,0 +1,66 @@
+<!--
+SPDX-FileCopyrightText: 2023 Daniel Vrátil <[email protected]>
+SPDX-License-Identifier: GFDL-1.3-or-later
+-->
+
+# Test Module
+
+The `Test` module contains coroutine-friendly versions of tests macros
+from the [QtTest][qdoc-qtest] module.
+
+## CMake Usage
+
+```cmake
+find_package(QCoro6 COMPONENTS Test)
+...
+target_link_libraries(my-target QCoro::Test)
+```
+
+## QMake Usage
+
+```
+QT += QCoroTest
+```
+
+## Test Macros
+
+The module contains a bunch of test macros that behave identically to their 
QtTest
+counterparts, the only difference being that they can be used inside a 
coroutine.
+
+```cpp
+#include <QCoroTest>
+```
+
+* [`QCORO_COMPARE(actual, expected)`][qdoc-qcompare]
+* [`QCORO_EXPECT_FAIL(dataIndex, comment, mode)`][qdoc-qexpect-fail]
+* [`QCORO_FAIL(message)`][qdoc-qfail]
+* [`QCORO_SKIP(description)`][qdoc-qskip]
+* [`QCORO_TEST(data, testElement)`][qdoc-qtest]
+* [`QCORO_TRY_COMPARE(actual, expected)`][qdoc-qtry-compare]
+* [`QCORO_TRY_COMPARE_WITH_TIMEOUT(actual, expected, 
timeout)`][qdoc-qtry-compare-with-timeout]
+* [`QCORO_TRY_VERIFY2(condition, message)`][qdoc-qtry-verify2]
+* [`QCORO_TRY_VERIFY(condition)`][qdoc-qtry-verify]
+* [`QCORO_TRY_VERIFY2_WITH_TIMEOUT(condition, message, 
timeout)`][qdoc-qtry-verify2-with-timeout]
+* [`QCORO_TRY_VERIFY_WITH_TIMEOUT(condition, 
timeout)`][qdoc-qtry-verify-with-timeout]
+* [`QCORO_VERIFY2(condition, message)`][qdoc-qverify2]
+* [`QCORO_VERIFY(condition)`][qdoc-qverify]
+* [`QCORO_VERIFY_EXCEPTION_THROWN(expression, 
exceptionType)`][qdoc-qverify-exception-thrown]
+
+
+[qdoc-qtest]: https://doc.qt.io/qt-5/qttest-index.html
+[qdoc-qcompare]: https://doc.qt.io/qt-5/qtest.html#QCOMPARE
+[qdoc-qexpect-fail]: https://doc.qt.io/qt-5/qtest.html#QEXPECT_FAIL
+[qdoc-qfail]: https://doc.qt.io/qt-5/qtest.html#QFAIL
+[qdoc-qskip]: https://doc.qt.io/qt-5/qtest.html#QSKIP
+[qdoc-qtest]: https://doc.qt.io/qt-5/qtest.html#QTEST
+[qdoc-qtry-compare]: https://doc.qt.io/qt-5/qtest.html#QTRY_COMPARE
+[qdoc-qtry-compare-with-timeout]: 
https://doc.qt.io/qt-5/qtest.html#QTRY_COMPARE_WITH_TIMEOUT
+[qdoc-qtry-verify2]: https://doc.qt.io/qt-5/qtest.html#QTRY_VERIFY2
+[qdoc-qtry-verify]: https://doc.qt.io/qt-5/qtest.html#QTRY_VERIFY
+[qdoc-qtry-verify2-with-timeout]: 
https://doc.qt.io/qt-5/qtest.html#QTRY_VERIFY2_WITH_TIMEOUT
+[qdoc-qtry-verify-with-timeout]: 
https://doc.qt.io/qt-5/qtest.html#QTRY_VERIFY_WITH_TIMEOUT
+[qdoc-qverify2]: https://doc.qt.io/qt-5/qtest.html#QVERIFY2
+[qdoc-qverify]: https://doc.qt.io/qt-5/qtest.html#QVERIFY
+[qdoc-qverify-exception-thrown]: 
https://doc.qt.io/qt-5/qtest.html#QVERIFY_EXCEPTION_THROWN
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/mkdocs.yml new/qcoro-0.9.0/mkdocs.yml
--- old/qcoro-0.8.0/mkdocs.yml  2023-01-31 20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/mkdocs.yml  2023-04-27 10:09:19.000000000 +0200
@@ -101,6 +101,8 @@
       - Qml:
         - reference/qml/index.md
         - QCoro::QmlTask: reference/qml/qmltask.md
+      - Test:
+        - reference/test/index.md
     - Changelog: changelog.md
     - About:
         - License: about/license.md
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/CMakeLists.txt 
new/qcoro-0.9.0/qcoro/CMakeLists.txt
--- old/qcoro-0.8.0/qcoro/CMakeLists.txt        2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/CMakeLists.txt        2023-04-27 10:09:19.000000000 
+0200
@@ -94,3 +94,7 @@
 if (QCORO_WITH_QML)
     add_subdirectory(qml)
 endif()
+
+if (QCORO_WITH_QTTEST)
+    add_subdirectory(test)
+endif()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/QCoroMacros.cmake 
new/qcoro-0.9.0/qcoro/QCoroMacros.cmake
--- old/qcoro-0.8.0/qcoro/QCoroMacros.cmake     2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/QCoroMacros.cmake     2023-04-27 10:09:19.000000000 
+0200
@@ -5,7 +5,9 @@
         if (MSVC)
             # clang-cl behaves like MSVC and enables coroutines automatically 
when C++20 is enabled
         else()
-            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts")
+            if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16")
+                set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts")
+            endif()
         endif()
     elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
         # MSVC auto-enables coroutine support when C++20 is enabled
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/core/qcoroprocess.cpp 
new/qcoro-0.9.0/qcoro/core/qcoroprocess.cpp
--- old/qcoro-0.8.0/qcoro/core/qcoroprocess.cpp 2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/core/qcoroprocess.cpp 2023-04-27 10:09:19.000000000 
+0200
@@ -2,6 +2,10 @@
 //
 // SPDX-License-Identifier: MIT
 
+#include <QtGlobal>
+
+#if QT_CONFIG(process)
+
 #include "qcoroprocess.h"
 #include "qcorosignal.h"
 
@@ -51,3 +55,5 @@
     static_cast<QProcess *>(mDevice.data())->start(program, arguments, mode);
     return waitForStarted(timeout);
 }
+
+#endif // QT_CONFIG(process)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/core/qcoroprocess.h 
new/qcoro-0.9.0/qcoro/core/qcoroprocess.h
--- old/qcoro-0.8.0/qcoro/core/qcoroprocess.h   2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/core/qcoroprocess.h   2023-04-27 10:09:19.000000000 
+0200
@@ -12,6 +12,8 @@
 
 #include <QIODevice>
 
+#if QT_CONFIG(process)
+
 class QProcess;
 
 namespace QCoro::detail {
@@ -126,3 +128,4 @@
     return QCoro::detail::QCoroProcess{p};
 }
 
+#endif // QT_CONFIG(process)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/core/qcorosignal.h 
new/qcoro-0.9.0/qcoro/core/qcorosignal.h
--- old/qcoro-0.8.0/qcoro/core/qcorosignal.h    2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/core/qcorosignal.h    2023-04-27 10:09:19.000000000 
+0200
@@ -105,11 +105,13 @@
     using typename QCoroSignalBase<T, FuncPtr>::result_type;
 
     QCoroSignal(T *obj, FuncPtr &&ptr, std::chrono::milliseconds timeout)
-        : QCoroSignalBase<T, FuncPtr>(obj, std::forward<FuncPtr>(ptr), 
timeout) {}
+        : QCoroSignalBase<T, FuncPtr>(obj, std::forward<FuncPtr>(ptr), timeout)
+        , mDummyReceiver(std::make_unique<QObject>()) {}
     QCoroSignal(const QCoroSignal &) = delete;
     QCoroSignal(QCoroSignal &&other) noexcept
         : QCoroSignalBase<T, FuncPtr>(std::move(other))
-        , mResult(std::move(other.mResult)) {
+        , mResult(std::move(other.mResult))
+        , mDummyReceiver(std::move(other.mDummyReceiver)) {
         if (this->mConn) {
             QObject::disconnect(this->mConn);
             setupConnection();
@@ -119,6 +121,7 @@
     QCoroSignal &operator=(QCoroSignal &&other) noexcept {
         QCoroSignalBase<T, FuncPtr>::operator=(std::move(other));
         std::swap(mResult, other.mResult);
+        std::swap(mDummyReceiver, other.mDummyReceiver);
         if (this->mConn) {
             QObject::disconnect(this->mConn);
             setupConnection();
@@ -148,7 +151,7 @@
     void setupConnection() {
         Q_ASSERT(!this->mConn);
         this->mConn = QObject::connect(
-            this->mObj, this->mFuncPtr, this->mObj,
+            this->mObj, this->mFuncPtr, this->mDummyReceiver.get(),
             [this](auto &&...args) mutable {
                 if (this->mTimeoutTimer) {
                     this->mTimeoutTimer->stop();
@@ -165,6 +168,7 @@
 
     result_type mResult;
     std::coroutine_handle<> mAwaitingCoroutine;
+    std::unique_ptr<QObject> mDummyReceiver;
 };
 
 template<concepts::QObject T, typename FuncPtr>
@@ -237,7 +241,7 @@
             return;
         }
         this->mConn = QObject::connect(
-            this->mObj, this->mFuncPtr, this->mObj,
+            this->mObj, this->mFuncPtr, &this->mDummyReceiver,
             [this](auto && ...args) mutable {
                 if (this->mTimeoutTimer) {
                     this->mTimeoutTimer->stop();
@@ -253,6 +257,7 @@
 
     std::coroutine_handle<> mAwaitingCoroutine;
     std::deque<typename result_type::value_type> mQueue;
+    QObject mDummyReceiver;
 };
 
 template<concepts::QObject T, typename FuncPtr>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/qcorogenerator.h 
new/qcoro-0.9.0/qcoro/qcorogenerator.h
--- old/qcoro-0.8.0/qcoro/qcorogenerator.h      2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/qcorogenerator.h      2023-04-27 10:09:19.000000000 
+0200
@@ -236,9 +236,16 @@
     using iterator = GeneratorIterator<T>;
 
     explicit Generator() = default;
-    Generator(Generator &&) noexcept = default;
+    Generator(Generator &&other) noexcept {
+        mGeneratorCoroutine = other.mGeneratorCoroutine;
+        other.mGeneratorCoroutine = 
std::coroutine_handle<promise_type>::from_address(nullptr);
+    }
     Generator(const Generator &) = delete;
-    Generator &operator=(Generator &&) noexcept = default;
+    Generator &operator=(Generator &&other) noexcept {
+            mGeneratorCoroutine = other.mGeneratorCoroutine;
+            other.mGeneratorCoroutine = 
std::coroutine_handle<promise_type>::from_address(nullptr);
+            return *this;
+    };
     Generator &operator=(const Generator &) = delete;
     /**
      * @brief Destroys this Generator object and the associated generator 
coroutine.
@@ -246,7 +253,9 @@
      * All values allocated on the generator stack are destroyed automatically.
      */
     ~Generator() {
-        mGeneratorCoroutine.destroy();
+        if (mGeneratorCoroutine.address() != nullptr) {
+            mGeneratorCoroutine.destroy();
+        }
     }
 
     /**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/qcorotask.h 
new/qcoro-0.9.0/qcoro/qcorotask.h
--- old/qcoro-0.8.0/qcoro/qcorotask.h   2023-01-31 20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/qcoro/qcorotask.h   2023-04-27 10:09:19.000000000 +0200
@@ -581,7 +581,7 @@
 
 private:
     template<typename ThenCallback, typename ... Args>
-    auto invokeCb(ThenCallback &&callback, Args && ... args) {
+    auto invokeCb(ThenCallback &&callback, [[maybe_unused]] Args && ... args) {
         if constexpr (std::is_invocable_v<ThenCallback, Args ...>) {
             return callback(std::forward<Args>(args) ...);
         } else {
@@ -780,7 +780,7 @@
  *        For all other types, it takes a value of the type as single argument.
  */
 template <typename T, typename QObjectSubclass, typename Callback>
-requires std::is_invocable_v<Callback> || std::is_invocable_v<Callback, T> || 
std::is_invocable_v<Callback, QObjectSubclass *>
+requires std::is_invocable_v<Callback> || std::is_invocable_v<Callback, T> || 
std::is_invocable_v<Callback, QObjectSubclass *> || 
std::is_invocable_v<Callback, QObjectSubclass *, T>
 void connect(QCoro::Task<T> &&task, QObjectSubclass *context, Callback func) {
     QPointer ctxWatcher = context;
     if constexpr (std::is_same_v<T, void>) {
@@ -796,12 +796,10 @@
     } else {
         task.then([ctxWatcher, func = std::move(func)](auto &&value) {
             if (ctxWatcher) {
-                if constexpr (std::is_invocable_v<Callback, T>) {
-                    if constexpr (std::is_member_function_pointer_v<Callback>) 
{
-                        
(ctxWatcher->*func)(std::forward<decltype(value)>(value));
-                    } else {
-                        func(std::forward<decltype(value)>(value));
-                    }
+                if constexpr (std::is_invocable_v<Callback, QObjectSubclass, 
T>) {
+                    (ctxWatcher->*func)(std::forward<decltype(value)>(value));
+                } else if constexpr (std::is_invocable_v<Callback, T>) {
+                    func(std::forward<decltype(value)>(value));
                 } else {
                     Q_UNUSED(value);
                     if constexpr (std::is_member_function_pointer_v<Callback>) 
{
@@ -817,7 +815,7 @@
 
 template <typename T, typename QObjectSubclass, typename Callback>
 requires detail::TaskConvertible<T>
-        && (std::is_invocable_v<Callback> || std::is_invocable_v<Callback, 
detail::awaitable_return_type_t<T>> || std::is_invocable_v<Callback, 
QObjectSubclass *>)
+        && (std::is_invocable_v<Callback> || std::is_invocable_v<Callback, 
detail::convertible_awaitable_return_type_t<T>> || 
std::is_invocable_v<Callback, QObjectSubclass *> || 
std::is_invocable_v<Callback, QObjectSubclass *, T>)
         && (!detail::isTask_v<T>)
 void connect(T &&future, QObjectSubclass *context, Callback func) {
     auto task = detail::toTask(std::move(future));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/qml/qcoroqml.cpp 
new/qcoro-0.9.0/qcoro/qml/qcoroqml.cpp
--- old/qcoro-0.8.0/qcoro/qml/qcoroqml.cpp      2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/qml/qcoroqml.cpp      2023-04-27 10:09:19.000000000 
+0200
@@ -10,4 +10,5 @@
 
 void QCoro::Qml::registerTypes() {
     qRegisterMetaType<QCoro::QmlTask>();
+    qmlRegisterAnonymousType<QCoro::QmlTaskListener>("QCoro", 0);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/qml/qcoroqmltask.cpp 
new/qcoro-0.9.0/qcoro/qml/qcoroqmltask.cpp
--- old/qcoro-0.8.0/qcoro/qml/qcoroqmltask.cpp  2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/qml/qcoroqmltask.cpp  2023-04-27 10:09:19.000000000 
+0200
@@ -9,7 +9,10 @@
 #include <optional>
 
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4458 4201)
 #include <private/qjsvalue_p.h>
+QT_WARNING_POP
 #endif
 
 Q_DECLARE_LOGGING_CATEGORY(qcoroqml)
@@ -70,4 +73,29 @@
     });
 }
 
+QmlTaskListener *QmlTask::await(const QVariant &intermediateValue)
+{
+    QPointer listener = new QmlTaskListener();
+    if (!intermediateValue.isNull()) {
+        listener->setValue(QVariant(intermediateValue));
+    }
+    d->task->then([listener](auto &&value) {
+        if (listener) {
+            listener->setValue(std::move(value));
+        }
+    });
+    return listener;
+}
+
+QVariant QmlTaskListener::value() const
+{
+    return m_value;
+}
+
+void QmlTaskListener::setValue(QVariant &&value)
+{
+    m_value = std::move(value);
+    Q_EMIT valueChanged();
+}
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/qml/qcoroqmltask.h 
new/qcoro-0.9.0/qcoro/qml/qcoroqmltask.h
--- old/qcoro-0.8.0/qcoro/qml/qcoroqmltask.h    2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/qml/qcoroqmltask.h    2023-04-27 10:09:19.000000000 
+0200
@@ -17,6 +17,8 @@
 
 struct QmlTaskPrivate;
 
+class QmlTaskListener;
+
 //! QML type that allows to react to asynchronous computations from QML
 struct QCOROQML_EXPORT QmlTask {
     Q_GADGET
@@ -77,10 +79,36 @@
      */
     Q_INVOKABLE void then(QJSValue func);
 
+    //! Allows to use tasks in property bindings
+    /*!
+     * The value property is initially null, and will be updated to the actual 
value once it is available.
+     * Example usage:
+     * ```
+     * text: asyncLoadText().await().value
+     * ```
+     *
+     * Optionally, an intermediate value can be passed to await,
+     * which will be returned by value while calculating the asynchronous 
result.
+     */
+    Q_INVOKABLE QCoro::QmlTaskListener *await(const QVariant 
&intermediateValue = {});
+
 private:
     QSharedDataPointer<QmlTaskPrivate> d;
 };
 
+class QmlTaskListener : public QObject {
+    Q_OBJECT
+    Q_PROPERTY(QVariant value READ value NOTIFY valueChanged)
+
+public:
+    QVariant value() const;
+    void setValue(QVariant &&value);
+    Q_SIGNAL void valueChanged();
+
+private:
+    QVariant m_value;
+};
+
 }
 
 Q_DECLARE_METATYPE(QCoro::QmlTask)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/test/CMakeLists.txt 
new/qcoro-0.9.0/qcoro/test/CMakeLists.txt
--- old/qcoro-0.8.0/qcoro/test/CMakeLists.txt   1970-01-01 01:00:00.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/test/CMakeLists.txt   2023-04-27 10:09:19.000000000 
+0200
@@ -0,0 +1,13 @@
+# SPDX-FileCopyrightText: 2023 Daniel Vrátil <[email protected]>
+#
+# SPDX-License-Identifier: MIT
+
+add_qcoro_library(
+    NAME Test
+    INTERFACE
+    CAMELCASE_HEADERS
+        QCoroTest
+    QT_LINK_LIBRARIES
+        INTERFACE Test
+)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/qcoro/test/qcorotest.h 
new/qcoro-0.9.0/qcoro/test/qcorotest.h
--- old/qcoro-0.8.0/qcoro/test/qcorotest.h      1970-01-01 01:00:00.000000000 
+0100
+++ new/qcoro-0.9.0/qcoro/test/qcorotest.h      2023-04-27 10:09:19.000000000 
+0200
@@ -0,0 +1,190 @@
+// SPDX-FileCopyrightText: 2022 Daniel Vrátil <[email protected]>
+//
+// SPDX-License-Identifier: MIT
+
+/*
+ * This code is very closely based on qtestcase.h header file from Qt
+ * Copyright (c) 2016 The Qt Company Ltd., LGPLv3/GPLv2 or GPLv3 or any
+ * later version approved by the KDE Free Qt Foundation.
+ */
+
+#pragma once
+
+#include <qtestcase.h>
+#include <QString>
+
+/**
+ * @brief Coroutine-friendly version of QVERIFY test macro.
+ **/
+#define QCORO_VERIFY(statement)                                                
                    \
+    do {                                                                       
                    \
+        if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", 
__FILE__, __LINE__))     \
+            co_return;                                                         
                    \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QFAIL test macro.
+ **/
+#define QCORO_FAIL(message)                                                    
                    \
+    do {                                                                       
                    \
+        QTest::qFail(static_cast<const char *>(message), __FILE__, __LINE__);  
                    \
+        co_return;                                                             
                    \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QVERIFY2 test macro.
+ **/
+#define QCORO_VERIFY2(statement, description) \
+    do { \
+        if (statement) { \
+            if (!QTest::qVerify(true, #statement, static_cast<const char 
*>(description), __FILE__, __LINE__)) \
+                co_return; \
+        } else { \
+            if (!QTest::qVerify(false, #statement, static_cast<const char 
*>(description), __FILE__, __LINE__)) \
+                co_return; \
+        } \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QCOMPARE test macro.
+ **/
+#define QCORO_COMPARE(actual, expected)                                        
                    \
+    do {                                                                       
                    \
+        if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, 
__LINE__))            \
+            co_return;                                                         
                    \
+    } while (false)
+
+
+#if !defined(QT_NO_EXCEPTIONS)
+
+/**
+ * @brief Coroutine-friendly version of QVERIFY_EXCEPTION_THROWN macro.
+ **/
+#define QCORO_VERIFY_EXCEPTION_THROWN(expression, exceptionType)               
                    \
+    do {                                                                       
                    \
+        try {                                                                  
                    \
+            try {                                                              
                    \
+                expression;                                                    
                    \
+                QTest::qFail("Expected exception of type " #exceptionType " to 
be thrown"          \
+                             " but no exception caught",                       
                    \
+                             __FILE__, __LINE__);                              
                    \
+                co_return;                                                     
                    \
+            } catch (const exceptionType &) {}                                 
                    \
+        } catch (const std::exception &e) {                                    
                    \
+            const QByteArray msg = QByteArray() +                              
                    \
+                                   "Expected exception of type " 
#exceptionType                    \
+                                   " to be thrown, but std::exception caught 
with message " +      \
+                                   e.what();                                   
                    \
+            QTest::qFail(msg.constData(), __FILE__, __LINE__);                 
                    \
+            co_return;                                                         
                    \
+        } catch (...) {                                                        
                    \
+            QTest::qFail("Expected exception of type " #exceptionType " to be 
thrown"              \
+                         " but unknown exception caught",                      
                    \
+                         __FILE__, __LINE__);                                  
                    \
+            co_return;                                                         
                    \
+        }                                                                      
                    \
+    } while (false)
+
+#else // QT_NO_EXCEPTIONS
+
+#define QCORO_VERIFY_EXCEPTION_THROWN(expression, exceptionType) \
+    static_assert(false, "Support of exceptions is disabled")
+
+#endif // QT_NO_EXCEPTIONS
+
+/* @cond INTERNAL */
+
+#define QCORO_TRY_TIMEOUT_DEBUG_IMPL(expr, timeoutValue, step) \
+        if (!(expr)) { \
+            QTRY_LOOP_IMPL((expr), (2 * timeoutValue), step); \
+            if (expr) { \
+                QString msg = QString::fromUtf8("QTestLib: This test case 
check (\"%1\") failed because the requested timeout (%2 ms) was too short, %3 
ms would have been sufficient this time."); \
+                msg = 
msg.arg(QString::fromUtf8(#expr)).arg(timeoutValue).arg(timeoutValue + 
qt_test_i); \
+                QCORO_FAIL(qPrintable(msg)); \
+            } \
+        }
+
+#define QCORO_TRY_IMPL(expr, timeout) \
+    const int qcoro_test_step = timeout < 350 ? timeout / 7 + 1 : 50; \
+    const int qcoro_test_timeoutValue = timeout; \
+    { QCORO_TRY_LOOP_IMPL((expr), qcoro_test_timeoutValue, qcoro_test_step); } 
\
+    QCORO_TRY_TIMEOUT_DEBUG_IMPL((expr), qcoro_test_timeoutValue, 
qcoro_test_step) \
+
+/* @endcond */
+
+/**
+ * @brief Coroutine-friendly version of QVERIFY_WITH_TIMEOUT test macro.
+ **/
+#define QCORO_TRY_VERIFY_WITH_TIMEOUT(expr, timeout) \
+    do { \
+        QCORO_TRY_IMPL((expr), timeout); \
+        QCORO_VERIFY(expr); \
+    } while (false);
+
+/**
+ * @brief Coroutine-friendly version of QTRY_VERIFY test macro.
+ **/
+#define QCORO_TRY_VERIFY(expr) QCORO_TRY_VERIFY_WITH_TIMEOUT((expr), 5000)
+
+/**
+ * @brief Coroutine-friendly version of QTRY_VERIFY2_WITH_TIMEOUT test macro.
+ **/
+#define QCORO_TRY_VERIFY2_WITH_TIMEOUT(expr, messageExpression, timeout) \
+    do { \
+        QCORO_TRY_IMPL((expr), timeout); \
+        QCORO_VERIFY2((expr), messageExpression); \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QTRY_VERIFY2 test macro.
+ **/
+#define QCORO_TRY_VERIFY2(expr, messageExpression) \
+    QCORO_TRY_VERIFY2_WITH_TIMEOUT((expr), (messageExpression), 5000)
+
+/**
+ * @brief Coroutine-friendly version of QTRY_COMPARE_WITH_TIMEOUT test macro.
+ **/
+#define QCORO_TRY_COMPARE_WITH_TIMEOUT(expr, expected, timeout) \
+    do { \
+        QCORO_TRY_IMPL(((expr) == (expected)), timeout); \
+        QCORO_COMPARE((expr), expected); \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QTRY_COMPARE test macro.
+ **/
+#define QCORO_TRY_COMPARE(expr, expected) \
+    QCORO_TRY_COMPARE_WITH_TIMEOUT((expr), (expected), 5000)
+
+/**
+ * @internal
+ **/
+#define QCORO_SKIP_INTERNAL(statement) \
+    do { \
+        QTest::qSkip(static_cast<const char *>(statement), __FILE__, 
__LINE__); \
+        co_return; \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QSKIP test macro.
+ **/
+#define QCORO_SKIP(statement, ...) QCORO_SKIP_INTERNAL(statement)
+
+/**
+ * @brief Coroutine-friendly version of QEXPECT_FAIL test macro.
+ **/
+#define QCORO_EXPECT_FAIL(dataIndex, comment, mode) \
+    do { \
+        if (!QTest::qExpectFail(dataIndex, static_cast<const char *>(comment), 
QTest::mode, __FILE__, __LINE__)) \
+        co_return; \
+    } while (false)
+
+/**
+ * @brief Coroutine-friendly version of QTEST test macro.
+ **/
+#define QCORO_TEST(actual, testElement) \
+    do { \
+        if (!QTest::qTest(actual, testElement, #actual, #testElement, 
__FILE__, __LINE__)) \
+            co_return; \
+    } while (false)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/requirements.txt 
new/qcoro-0.9.0/requirements.txt
--- old/qcoro-0.8.0/requirements.txt    2023-01-31 20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/requirements.txt    2023-04-27 10:09:19.000000000 +0200
@@ -1,7 +1,7 @@
 setuptools
 wheel
-pymdown-extensions~=9.9
-pygments~=2.14
+pymdown-extensions~=9.11
+pygments~=2.15
 mkdocs
 mkdocs-material
 mkdocs-section-index
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/CMakeLists.txt 
new/qcoro-0.9.0/tests/CMakeLists.txt
--- old/qcoro-0.8.0/tests/CMakeLists.txt        2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/CMakeLists.txt        2023-04-27 10:09:19.000000000 
+0200
@@ -23,7 +23,7 @@
     target_link_libraries(
         test-${_name}
         PRIVATE
-        qcoro_test
+        qcoro_testlib
         QCoro${QT_VERSION_MAJOR}Core
         Qt${QT_VERSION_MAJOR}::Core
         Qt${QT_VERSION_MAJOR}::Test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/qcoroasyncgenerator.cpp 
new/qcoro-0.9.0/tests/qcoroasyncgenerator.cpp
--- old/qcoro-0.8.0/tests/qcoroasyncgenerator.cpp       2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/tests/qcoroasyncgenerator.cpp       2023-04-27 
10:09:19.000000000 +0200
@@ -168,6 +168,25 @@
         QCORO_COMPARE(testvalue, 4);
     }
 
+    QCoro::Task<> testMovedGenerator_coro(QCoro::TestContext) {
+        const auto createGenerator = []() -> QCoro::AsyncGenerator<int> {
+            for (int i = 0; i < 4; ++i) {
+                co_await sleep(10ms);
+                co_yield i;
+            }
+        };
+
+        auto originalGenerator = createGenerator();
+        auto generator = std::move(originalGenerator);
+        int testvalue = 0;
+        for (auto it = co_await generator.begin(), end = generator.end(); it 
!= end; co_await ++it) {
+            int value = *it;
+            QCORO_COMPARE(value, testvalue++);
+        }
+        QCORO_COMPARE(testvalue, 4);
+
+    }
+
     QCoro::Task<> testException_coro(QCoro::TestContext) {
         const auto createGenerator = []() -> QCoro::AsyncGenerator<int> {
             for (int i = 0; i < 4; ++i) {
@@ -243,6 +262,7 @@
     addTest(ReferenceGenerator)
     addTest(ConstReferenceGenerator)
     addTest(MoveonlyGenerator)
+    addTest(MovedGenerator)
     addTest(Exception)
     addTest(ExceptionInDereference)
     addTest(ExceptionInBegin)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/qcorogenerator.cpp 
new/qcoro-0.9.0/tests/qcorogenerator.cpp
--- old/qcoro-0.8.0/tests/qcorogenerator.cpp    2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/qcorogenerator.cpp    2023-04-27 10:09:19.000000000 
+0200
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MIT
 
 #include "qcorogenerator.h"
-#include "testmacros.h"
+#include "qcorotest.h"
 
 #include <QObject>
 #include <QTest>
@@ -145,6 +145,25 @@
             ++it;
         }
         QCOMPARE(testval, 4);
+    }
+
+    void testMovedGenerator() {
+        const auto createGenerator = []() -> QCoro::Generator<int> {
+            for (int i = 0; i < 4; ++i) {
+                co_yield i;
+            }
+        };
+
+        auto originalGenerator = createGenerator();
+        auto generator = std::move(originalGenerator);
+        auto it = generator.begin();
+        int testval = 0;
+        while (it != generator.end()) {
+            int value = *it;
+            QCOMPARE(value, testval++);
+            ++it;
+        }
+        QCOMPARE(testval, 4);
     }
 
     void testException() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/qcoroqmltask.cpp 
new/qcoro-0.9.0/tests/qcoroqmltask.cpp
--- old/qcoro-0.8.0/tests/qcoroqmltask.cpp      2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/qcoroqmltask.cpp      2023-04-27 10:09:19.000000000 
+0200
@@ -47,7 +47,7 @@
     Q_INVOKABLE void reportTestSuccess() {
         numTestsPassed++;
 
-        if (numTestsPassed == 3) { // Number of java script functions that 
call reportTestSuccess
+        if (numTestsPassed == 4) { // Number of java script functions that 
call reportTestSuccess
             Q_EMIT success();
         }
     }
@@ -72,9 +72,21 @@
 
         engine.loadData(R"(
 import qcoro.test 0.1
+import QCoro 0
 import QtQuick 2.7
 
 QtObject {
+    property string value: 
QmlObject.qmlTaskFromFuture().await("Loading...").value
+
+    property string valueWithoutIntermediate: 
QmlObject.qmlTaskFromFuture().await().value
+
+    onValueChanged: {
+        if (value == "Success") {
+            console.log("awaiting finished")
+            QmlObject.reportTestSuccess()
+        }
+    }
+
     Component.onCompleted: {
         QmlObject.startTimer().then(() => {
             console.log("QCoro::Task JavaScript callback called")
@@ -106,6 +118,7 @@
             timeout->stop();
             running = false;
         });
+
         // Crash the test in case the timeout was reachaed without the 
callback being called
         connect(timeout, &QTimer::timeout, this, [&]() {
 #if defined(Q_CC_CLANG) && defined(Q_OS_WINDOWS)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/qcorosignal.cpp 
new/qcoro-0.9.0/tests/qcorosignal.cpp
--- old/qcoro-0.8.0/tests/qcorosignal.cpp       2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/qcorosignal.cpp       2023-04-27 10:09:19.000000000 
+0200
@@ -48,6 +48,27 @@
     QTimer mTimer;
 };
 
+
+class SimpleSignal: public QObject {
+    Q_OBJECT
+public:
+    void send(int id) {
+        Q_EMIT messageReceived(id);
+    }
+
+    Q_SIGNAL void messageReceived(int id);
+
+    QCoro::Task<int> waitForMessage(int id) {
+        QCORO_FOREACH(int msgId, qCoroSignalListener(this, 
&SimpleSignal::messageReceived)) {
+            if (msgId == id) {
+                co_return id;
+            }
+        }
+
+        co_return -1;
+    }
+};
+
 class QCoroSignalTest : public QCoro::TestObject<QCoroSignalTest> {
     Q_OBJECT
 
@@ -279,6 +300,16 @@
         QCORO_COMPARE(count, 10);
     }
 
+    QCoro::Task<> testSignalAfterListenerQuits_coro(QCoro::TestContext) {
+        SimpleSignal simple;
+        auto msg1 = simple.waitForMessage(1);
+        auto msg2 = simple.waitForMessage(2);
+        simple.send(1);
+        simple.send(2);
+        QCORO_COMPARE(co_await msg1, 1);
+        QCORO_COMPARE(co_await msg2, 2);
+    }
+
 private Q_SLOTS:
     addTest(Triggers)
     addTest(ReturnsValue)
@@ -298,6 +329,7 @@
     addTest(SignalListenerTuple)
     addTest(SignalListenerTimeout)
     addTest(SignalListenerQueue)
+    addTest(SignalAfterListenerQuits)
 };
 
 QTEST_GUILESS_MAIN(QCoroSignalTest)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/testlibs/CMakeLists.txt 
new/qcoro-0.9.0/tests/testlibs/CMakeLists.txt
--- old/qcoro-0.8.0/tests/testlibs/CMakeLists.txt       2023-01-31 
20:50:01.000000000 +0100
+++ new/qcoro-0.9.0/tests/testlibs/CMakeLists.txt       2023-04-27 
10:09:19.000000000 +0200
@@ -1,11 +1,12 @@
-add_library(qcoro_test
+add_library(qcoro_testlib
     STATIC
     testobject.cpp
     testloop.cpp
 )
-target_include_directories(qcoro_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-target_link_libraries(qcoro_test PUBLIC
+target_include_directories(qcoro_testlib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(qcoro_testlib PUBLIC
     QCoro${QT_VERSION_MAJOR}Core
+    QCoro${QT_VERSION_MAJOR}Test
     Qt${QT_VERSION_MAJOR}::Core
     Qt${QT_VERSION_MAJOR}::Test
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/testlibs/testmacros.h 
new/qcoro-0.9.0/tests/testlibs/testmacros.h
--- old/qcoro-0.8.0/tests/testlibs/testmacros.h 2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/testlibs/testmacros.h 2023-04-27 10:09:19.000000000 
+0200
@@ -4,12 +4,10 @@
 
 #pragma once
 
-
 //! Executes given \c expr with 10ms delay.
 #define QCORO_DELAY(expr)                                                      
                    \
     QTimer::singleShot(10ms, [&]() { expr; })
 
-
 #define QCORO_TEST_TIMEOUT(expr) { \
     const auto start = std::chrono::steady_clock::now(); \
     const bool ok = expr; \
@@ -18,46 +16,4 @@
     QCORO_VERIFY((end - start) < 500ms); \
 }
 
-#define QCORO_VERIFY(statement)                                                
                    \
-    do {                                                                       
                    \
-        if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", 
__FILE__, __LINE__))     \
-            co_return;                                                         
                    \
-    } while (false)
-
-#define QCORO_COMPARE(actual, expected)                                        
                    \
-    do {                                                                       
                    \
-        if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, 
__LINE__))            \
-            co_return;                                                         
                    \
-    } while (false)
-
-#define QCORO_FAIL(message)                                                    
                    \
-    do {                                                                       
                    \
-        QTest::qFail(static_cast<const char *>(message), __FILE__, __LINE__);  
                    \
-        co_return;                                                             
                    \
-    } while (false)
-
-#define QCORO_VERIFY_EXCEPTION_THROWN(expression, exceptionType)               
                    \
-    do {                                                                       
                    \
-        try {                                                                  
                    \
-            try {                                                              
                    \
-                expression;                                                    
                    \
-                QTest::qFail("Expected exception of type " #exceptionType " to 
be thrown"          \
-                             " but no exception caught",                       
                    \
-                             __FILE__, __LINE__);                              
                    \
-                co_return;                                                     
                    \
-            } catch (const exceptionType &) {}                                 
                    \
-        } catch (const std::exception &e) {                                    
                    \
-            const QByteArray msg = QByteArray() +                              
                    \
-                                   "Expected exception of type " 
#exceptionType                    \
-                                   " to be thrown, but std::exception caught 
with message " +      \
-                                   e.what();                                   
                    \
-            QTest::qFail(msg.constData(), __FILE__, __LINE__);                 
                    \
-            co_return;                                                         
                    \
-        } catch (...) {                                                        
                    \
-            QTest::qFail("Expected exception of type " #exceptionType " to be 
thrown"              \
-                         " but unknown exception caught",                      
                    \
-                         __FILE__, __LINE__);                                  
                    \
-            co_return;                                                         
                    \
-        }                                                                      
                    \
-    } while (false)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qcoro-0.8.0/tests/testlibs/testobject.h 
new/qcoro-0.9.0/tests/testlibs/testobject.h
--- old/qcoro-0.8.0/tests/testlibs/testobject.h 2023-01-31 20:50:01.000000000 
+0100
+++ new/qcoro-0.9.0/tests/testlibs/testobject.h 2023-04-27 10:09:19.000000000 
+0200
@@ -4,15 +4,15 @@
 
 #pragma once
 
-#include "testmacros.h"
-
 #include <QEventLoop>
 #include <QObject>
 #include <QTest>
 #include <QTimer>
 #include <QVariant>
 
-#include "qcoro/qcorotask.h"
+#include "qcorotask.h"
+#include "qcorotest.h"
+#include "testmacros.h"
 #include "testloop.h"
 
 #include <chrono>

Reply via email to