mirror of
https://github.com/simonbrunel/qtpromise.git
synced 2025-07-06 01:05:22 +08:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
22faef4ac3 | |||
eebcb4f364 | |||
051fed5fbc | |||
f610826ef0 | |||
4fa7a37750 | |||
69c07855f4 | |||
4cfe2e54f4 | |||
54d88f16a3 | |||
bdf3619469 | |||
8da467e9da | |||
efb6001b9d |
22
.appveyor.yml
Normal file
22
.appveyor.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
image: Visual Studio 2015
|
||||||
|
|
||||||
|
init:
|
||||||
|
- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio "%VSVER%".0\VC\vcvarsall.bat" %ARCH%
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: '%PATH%;%QTDIR%\bin'
|
||||||
|
matrix:
|
||||||
|
- QTDIR: C:\Qt\5.6\msvc2013
|
||||||
|
VSVER: 12
|
||||||
|
ARCH: x86
|
||||||
|
- QTDIR: C:\Qt\5.9\msvc2013_64
|
||||||
|
VSVER: 12
|
||||||
|
ARCH: x64
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- cmd: qmake qtpromise.pro
|
||||||
|
- cmd: nmake
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- cmd: nmake check
|
||||||
|
|
11
.travis.yml
11
.travis.yml
@ -4,12 +4,15 @@ language: cpp
|
|||||||
compiler: gcc
|
compiler: gcc
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo add-apt-repository -y ppa:beineri/opt-qt542-trusty
|
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
|
- sudo add-apt-repository -y ppa:beineri/opt-qt563-trusty
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install -qq qt54base
|
- sudo apt-get install -qq gcc-4.9 g++-4.9
|
||||||
- source /opt/qt54/bin/qt54-env.sh
|
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
|
||||||
|
- sudo apt-get install -qq qt56base
|
||||||
|
- source /opt/qt56/bin/qt56-env.sh
|
||||||
- wget http://archive.ubuntu.com/ubuntu/pool/universe/l/lcov/lcov_1.13.orig.tar.gz
|
- wget http://archive.ubuntu.com/ubuntu/pool/universe/l/lcov/lcov_1.13.orig.tar.gz
|
||||||
- tar xf lcov_1.13.orig.tar.gz
|
- tar xf lcov_1.13.orig.tar.gz
|
||||||
- cd lcov-1.13/
|
- cd lcov-1.13/
|
||||||
@ -19,7 +22,7 @@ install:
|
|||||||
before_script:
|
before_script:
|
||||||
- qmake --version
|
- qmake --version
|
||||||
- lcov --version
|
- lcov --version
|
||||||
- gcc --version
|
- gcc --version && g++ --version
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- qmake qtpromise.pro CONFIG+=coverage
|
- qmake qtpromise.pro CONFIG+=coverage
|
||||||
|
12
README.md
12
README.md
@ -1,18 +1,20 @@
|
|||||||
<a href="https://promisesaplus.com/" title="Promises/A+ 1.1"><img src="https://promisesaplus.com/assets/logo-small.png" alt="Promises/A+" align="right"/></a>
|
<a href="https://promisesaplus.com/" title="Promises/A+ 1.1"><img src="https://promisesaplus.com/assets/logo-small.png" alt="Promises/A+" align="right"/></a>
|
||||||
|
|
||||||
# QtPromise
|
# QtPromise
|
||||||
|
|
||||||
[](https://www.qpm.io/packages/com.github.simonbrunel.qtpromise/index.html) [](https://travis-ci.org/simonbrunel/qtpromise) [](https://codecov.io/gh/simonbrunel/qtpromise)
|
[](https://www.qpm.io/packages/com.github.simonbrunel.qtpromise/index.html) [](https://travis-ci.org/simonbrunel/qtpromise) [](https://codecov.io/gh/simonbrunel/qtpromise)
|
||||||
|
|
||||||
[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/).
|
[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/).
|
||||||
|
|
||||||
Requires [Qt 5.4](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects).
|
Requires [Qt 5.6](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
* [Getting Started](https://qtpromise.netlify.com/qtpromise/getting-started)
|
* [Getting Started](https://qtpromise.netlify.com/qtpromise/getting-started.html)
|
||||||
* [Thread-Safety](https://qtpromise.netlify.com/qtpromise/thread-safety)
|
* [QtConcurrent](https://qtpromise.netlify.com/qtpromise/qtconcurrent.html)
|
||||||
* [QtConcurrent](https://qtpromise.netlify.com/qtpromise/qtconcurrent)
|
* [Thread-Safety](https://qtpromise.netlify.com/qtpromise/thread-safety.html)
|
||||||
* [API Reference](https://qtpromise.netlify.com/qtpromise/api-reference)
|
* [API Reference](https://qtpromise.netlify.com/qtpromise/api-reference.html)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
QtPromise is available under the [MIT license](LICENSE).
|
QtPromise is available under the [MIT license](LICENSE).
|
||||||
|
40
book.json
40
book.json
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "QtPromise",
|
|
||||||
"description": "Promises/A+ implementation for Qt/C++",
|
|
||||||
"author": "Simon Brunel",
|
|
||||||
"gitbook": "3.2.3",
|
|
||||||
"root": "docs",
|
|
||||||
"plugins": [
|
|
||||||
"-lunr",
|
|
||||||
"-search",
|
|
||||||
"search-plus",
|
|
||||||
"anchorjs",
|
|
||||||
"edit-link",
|
|
||||||
"expand-active-chapter",
|
|
||||||
"ga",
|
|
||||||
"github"
|
|
||||||
],
|
|
||||||
"pluginsConfig": {
|
|
||||||
"anchorjs": {
|
|
||||||
"icon": "#",
|
|
||||||
"placement": "left",
|
|
||||||
"visible": "always"
|
|
||||||
},
|
|
||||||
"edit-link": {
|
|
||||||
"base": "https://github.com/simonbrunel/qtpromise/edit/master/docs"
|
|
||||||
},
|
|
||||||
"ga": {
|
|
||||||
"token": "UA-113899811-1",
|
|
||||||
"configuration": "auto"
|
|
||||||
},
|
|
||||||
"github": {
|
|
||||||
"url": "https://github.com/simonbrunel/qtpromise"
|
|
||||||
},
|
|
||||||
"theme-default": {
|
|
||||||
"showLevel": false,
|
|
||||||
"styles": {
|
|
||||||
"website": "assets/style.css"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
54
docs/.vuepress/config.js
Normal file
54
docs/.vuepress/config.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
module.exports = {
|
||||||
|
title: 'QtPromise',
|
||||||
|
description: 'Promises/A+ implementation for Qt/C++',
|
||||||
|
ga: 'UA-113899811-1',
|
||||||
|
head: [
|
||||||
|
['link', { rel: 'icon', href: `/favicon.png` }],
|
||||||
|
],
|
||||||
|
themeConfig: {
|
||||||
|
repo: 'simonbrunel/qtpromise',
|
||||||
|
lastUpdated: 'Last Updated',
|
||||||
|
editLinks: true,
|
||||||
|
docsDir: 'docs',
|
||||||
|
sidebar: [
|
||||||
|
'qtpromise/getting-started',
|
||||||
|
'qtpromise/qtconcurrent',
|
||||||
|
'qtpromise/thread-safety',
|
||||||
|
'qtpromise/api-reference',
|
||||||
|
{
|
||||||
|
title: 'QPromise',
|
||||||
|
children: [
|
||||||
|
'qtpromise/qpromise/constructor',
|
||||||
|
'qtpromise/qpromise/delay',
|
||||||
|
'qtpromise/qpromise/each',
|
||||||
|
'qtpromise/qpromise/fail',
|
||||||
|
'qtpromise/qpromise/filter',
|
||||||
|
'qtpromise/qpromise/finally',
|
||||||
|
'qtpromise/qpromise/isfulfilled',
|
||||||
|
'qtpromise/qpromise/ispending',
|
||||||
|
'qtpromise/qpromise/isrejected',
|
||||||
|
'qtpromise/qpromise/map',
|
||||||
|
'qtpromise/qpromise/tap',
|
||||||
|
'qtpromise/qpromise/tapfail',
|
||||||
|
'qtpromise/qpromise/then',
|
||||||
|
'qtpromise/qpromise/timeout',
|
||||||
|
'qtpromise/qpromise/wait',
|
||||||
|
'qtpromise/qpromise/all.md',
|
||||||
|
'qtpromise/qpromise/reject.md',
|
||||||
|
'qtpromise/qpromise/resolve.md'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Helpers',
|
||||||
|
children: [
|
||||||
|
'qtpromise/helpers/attempt',
|
||||||
|
'qtpromise/helpers/each',
|
||||||
|
'qtpromise/helpers/filter',
|
||||||
|
'qtpromise/helpers/map',
|
||||||
|
'qtpromise/helpers/qpromise',
|
||||||
|
'qtpromise/helpers/qpromiseall'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
2
docs/.vuepress/override.styl
Normal file
2
docs/.vuepress/override.styl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$accentColor = #23b223
|
||||||
|
$textColor = #404244
|
BIN
docs/.vuepress/public/favicon.ico
Normal file
BIN
docs/.vuepress/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
BIN
docs/.vuepress/public/favicon.png
Normal file
BIN
docs/.vuepress/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
4
docs/.vuepress/style.styl
Normal file
4
docs/.vuepress/style.styl
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@import 'override.styl'
|
||||||
|
|
||||||
|
.content a code
|
||||||
|
color: $accentColor
|
@ -3,13 +3,7 @@
|
|||||||
# QtPromise
|
# QtPromise
|
||||||
[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/).
|
[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/).
|
||||||
|
|
||||||
Requires [Qt 5.4](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects).
|
Requires [Qt 5.6](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects).
|
||||||
|
|
||||||
## QtPromise for C++
|
|
||||||
* [Getting Started](qtpromise/getting-started.md)
|
|
||||||
* [Thread-Safety](qtpromise/thread-safety.md)
|
|
||||||
* [QtConcurrent](qtpromise/qtconcurrent.md)
|
|
||||||
* [API Reference](qtpromise/api-reference.md)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
QtPromise is available under the [MIT license](https://github.com/simonbrunel/qtpromise/blob/master/LICENSE).
|
QtPromise is available under the [MIT license](https://github.com/simonbrunel/qtpromise/blob/master/LICENSE).
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
### QtPromise for C++
|
|
||||||
* [Getting Started](qtpromise/getting-started.md)
|
|
||||||
* [QtConcurrent](qtpromise/qtconcurrent.md)
|
|
||||||
* [Thread-Safety](qtpromise/thread-safety.md)
|
|
||||||
* [API Reference](qtpromise/api-reference.md)
|
|
||||||
* [QPromise](qtpromise/qpromise/constructor.md)
|
|
||||||
* [.delay](qtpromise/qpromise/delay.md)
|
|
||||||
* [.fail](qtpromise/qpromise/fail.md)
|
|
||||||
* [.finally](qtpromise/qpromise/finally.md)
|
|
||||||
* [.isFulfilled](qtpromise/qpromise/isfulfilled.md)
|
|
||||||
* [.isPending](qtpromise/qpromise/ispending.md)
|
|
||||||
* [.isRejected](qtpromise/qpromise/isrejected.md)
|
|
||||||
* [.tap](qtpromise/qpromise/tap.md)
|
|
||||||
* [.tapFail](qtpromise/qpromise/tapfail.md)
|
|
||||||
* [.then](qtpromise/qpromise/then.md)
|
|
||||||
* [.timeout](qtpromise/qpromise/timeout.md)
|
|
||||||
* [.wait](qtpromise/qpromise/wait.md)
|
|
||||||
* [::all (static)](qtpromise/qpromise/all.md)
|
|
||||||
* [::reject (static)](qtpromise/qpromise/reject.md)
|
|
||||||
* [::resolve (static)](qtpromise/qpromise/resolve.md)
|
|
||||||
* [qPromise](qtpromise/helpers/qpromise.md)
|
|
||||||
* [qPromiseAll](qtpromise/helpers/qpromiseall.md)
|
|
@ -1,15 +0,0 @@
|
|||||||
a.anchorjs-link {
|
|
||||||
color: rgba(65, 131, 196, 0.1);
|
|
||||||
font-weight: 400;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 100ms ease-out;
|
|
||||||
z-index: 999;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.anchorjs-link:hover {
|
|
||||||
color: rgba(65, 131, 196, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
font-size: 0.75em !important;
|
|
||||||
}
|
|
@ -1,21 +1,24 @@
|
|||||||
## QPromise
|
# API Reference
|
||||||
|
|
||||||
### Public Members
|
## Functions
|
||||||
|
|
||||||
* [`QPromise<T>::QPromise`](qpromise/constructor.md)
|
* [`QPromise<T>::QPromise`](qpromise/constructor.md)
|
||||||
* [`QPromise<T>::delay`](qpromise/delay.md)
|
* [`QPromise<T>::delay`](qpromise/delay.md)
|
||||||
|
* [`QPromise<T>::each`](qpromise/each.md)
|
||||||
* [`QPromise<T>::fail`](qpromise/fail.md)
|
* [`QPromise<T>::fail`](qpromise/fail.md)
|
||||||
|
* [`QPromise<T>::filter`](qpromise/filter.md)
|
||||||
* [`QPromise<T>::finally`](qpromise/finally.md)
|
* [`QPromise<T>::finally`](qpromise/finally.md)
|
||||||
* [`QPromise<T>::isFulfilled`](qpromise/isfulfilled.md)
|
* [`QPromise<T>::isFulfilled`](qpromise/isfulfilled.md)
|
||||||
* [`QPromise<T>::isPending`](qpromise/ispending.md)
|
* [`QPromise<T>::isPending`](qpromise/ispending.md)
|
||||||
* [`QPromise<T>::isRejected`](qpromise/isrejected.md)
|
* [`QPromise<T>::isRejected`](qpromise/isrejected.md)
|
||||||
|
* [`QPromise<T>::map`](qpromise/map.md)
|
||||||
* [`QPromise<T>::tap`](qpromise/tap.md)
|
* [`QPromise<T>::tap`](qpromise/tap.md)
|
||||||
* [`QPromise<T>::tapFail`](qpromise/tapfail.md)
|
* [`QPromise<T>::tapFail`](qpromise/tapfail.md)
|
||||||
* [`QPromise<T>::then`](qpromise/then.md)
|
* [`QPromise<T>::then`](qpromise/then.md)
|
||||||
* [`QPromise<T>::timeout`](qpromise/timeout.md)
|
* [`QPromise<T>::timeout`](qpromise/timeout.md)
|
||||||
* [`QPromise<T>::wait`](qpromise/wait.md)
|
* [`QPromise<T>::wait`](qpromise/wait.md)
|
||||||
|
|
||||||
### Public Static Members
|
## Static Functions
|
||||||
|
|
||||||
* [`[static] QPromise<T>::all`](qpromise/all.md)
|
* [`[static] QPromise<T>::all`](qpromise/all.md)
|
||||||
* [`[static] QPromise<T>::reject`](qpromise/reject.md)
|
* [`[static] QPromise<T>::reject`](qpromise/reject.md)
|
||||||
@ -23,5 +26,9 @@
|
|||||||
|
|
||||||
## Helpers
|
## Helpers
|
||||||
|
|
||||||
|
* [`QtPromise::attempt`](helpers/attempt.md)
|
||||||
|
* [`QtPromise::each`](helpers/each.md)
|
||||||
|
* [`QtPromise::filter`](helpers/filter.md)
|
||||||
|
* [`QtPromise::map`](helpers/map.md)
|
||||||
* [`qPromise`](helpers/qpromise.md)
|
* [`qPromise`](helpers/qpromise.md)
|
||||||
* [`qPromiseAll`](helpers/qpromiseall.md)
|
* [`qPromiseAll`](helpers/qpromiseall.md)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
# Getting Started
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
QtPromise is a [header-only](https://en.wikipedia.org/wiki/Header-only) library, simply download the [latest release](https://github.com/simonbrunel/qtpromise/releases/latest) (or [`git submodule`](https://git-scm.com/docs/git-submodule)) and include `qtpromise.pri` from your project `.pro`.
|
QtPromise is a [header-only](https://en.wikipedia.org/wiki/Header-only) library, simply download the [latest release](https://github.com/simonbrunel/qtpromise/releases/latest) (or [`git submodule`](https://git-scm.com/docs/git-submodule)) and include `qtpromise.pri` from your project `.pro`.
|
||||||
|
|
||||||
## qpm
|
### qpm
|
||||||
|
|
||||||
Alternatively and **only** if your project relies on [qpm](https://www.qpm.io/), you can install QtPromise as follow:
|
Alternatively and **only** if your project relies on [qpm](https://www.qpm.io/), you can install QtPromise as follow:
|
||||||
|
|
||||||
|
47
docs/qtpromise/helpers/attempt.md
Normal file
47
docs/qtpromise/helpers/attempt.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
title: attempt
|
||||||
|
---
|
||||||
|
|
||||||
|
# QtPromise::attempt
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QtPromise::attempt(Functor functor, Args...) -> QPromise<R>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Functor: Function(Args...) -> R | QPromise<R>
|
||||||
|
```
|
||||||
|
|
||||||
|
Calls `functor` immediately and returns a promise fulfilled with the value returned by
|
||||||
|
`functor`. Any synchronous exceptions will be turned into rejections on the returned
|
||||||
|
promise. This is a convenient method that can be used instead of handling both synchronous
|
||||||
|
and asynchronous exception flows.
|
||||||
|
|
||||||
|
The type `R` of the `output` promise depends on the type returned by the `functor` function.
|
||||||
|
If `functor` returns a promise (or `QFuture`), the `output` promise is delayed and will be
|
||||||
|
resolved by the returned promise.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QByteArray> download(const QUrl& url);
|
||||||
|
|
||||||
|
QPromise<QByteArray> process(const QUrl& url)
|
||||||
|
{
|
||||||
|
return QtPromise::attempt([&]() {
|
||||||
|
if (!url.isValid()) {
|
||||||
|
throw InvalidUrlException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return download(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto output = process(url);
|
||||||
|
|
||||||
|
// 'output' type: QPromise<QByteArray>
|
||||||
|
output.then([](const QByteArray& res) {
|
||||||
|
// {...}
|
||||||
|
}).fail([](const InvalidUrlException& err) {
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
```
|
45
docs/qtpromise/helpers/each.md
Normal file
45
docs/qtpromise/helpers/each.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: each
|
||||||
|
---
|
||||||
|
|
||||||
|
# QtPromise::each
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QtPromise::each(Sequence<T> values, Functor functor) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Functor: Function(T value, int index) -> void | QPromise<void>
|
||||||
|
```
|
||||||
|
|
||||||
|
Calls the given `functor` on each element in `values` then resolves to the original sequence
|
||||||
|
unmodified. If `functor` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fail, `output` immediately rejects with the error
|
||||||
|
of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto output = QtPromise::each(QVector<QUrl>{
|
||||||
|
QUrl("http://a..."),
|
||||||
|
QUrl("http://b..."),
|
||||||
|
QUrl("http://c...")
|
||||||
|
}, [](const QUrl& url, ...) {
|
||||||
|
return QPromise<void>([&](auto resolve, auto reject) {
|
||||||
|
// process url asynchronously ...
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// `output` resolves as soon as all promises returned by
|
||||||
|
// `functor` are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// output type: QPromise<QVector<QUrl>>
|
||||||
|
output.then([](const QVector<QUrl>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [`QPromise<T>::each`](../qpromise/each.md)
|
52
docs/qtpromise/helpers/filter.md
Normal file
52
docs/qtpromise/helpers/filter.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
title: filter
|
||||||
|
---
|
||||||
|
|
||||||
|
# QtPromise::filter
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QtPromise::filter(Sequence<T> values, Filterer filterer) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Filterer: Function(T value, int index) -> bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Iterates over `values` and [filters the sequence](https://en.wikipedia.org/wiki/Filter_%28higher-order_function%29)
|
||||||
|
to another using the given `filterer` function. If `filterer` returns `true`, a copy of the item
|
||||||
|
is put in the `output` sequence, otherwise, the item will not appear in `output`. If `filterer`
|
||||||
|
throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `filterer` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fail, `output` immediately rejects with the error
|
||||||
|
of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto output = QtPromise::filter(QVector{
|
||||||
|
QUrl("http://a..."),
|
||||||
|
QUrl("http://b..."),
|
||||||
|
QUrl("http://c...")
|
||||||
|
}, [](const QUrl& url, ...) {
|
||||||
|
return QPromise<bool>([&](auto resolve, auto reject) {
|
||||||
|
// resolve(true) if 'url' is reachable, else resolve(false)
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 'output' resolves as soon as all promises returned by
|
||||||
|
// 'filterer' are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// 'output' type: QPromise<QVector<QUrl>>
|
||||||
|
output.then([](const QVector<QUrl>& res) {
|
||||||
|
// 'res' contains only reachable URLs
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip NOTE
|
||||||
|
The order of the output sequence values is guarantee to be the same as the original
|
||||||
|
sequence, regardless of completion order of the promises returned by `filterer`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
See also: [`QPromise<T>::filter`](../qpromise/filter.md)
|
51
docs/qtpromise/helpers/map.md
Normal file
51
docs/qtpromise/helpers/map.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
title: map
|
||||||
|
---
|
||||||
|
|
||||||
|
# QtPromise::map
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QtPromise::map(Sequence<T> values, Mapper mapper) -> QPromise<QVector<R>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Mapper: Function(T value, int index) -> R | QPromise<R>
|
||||||
|
```
|
||||||
|
|
||||||
|
Iterates over `values` and [maps the sequence](https://en.wikipedia.org/wiki/Map_%28higher-order_function%29)
|
||||||
|
to another using the given `mapper` function. The type returned by `mapper` determines the type
|
||||||
|
of the `output` promise. If `mapper` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `mapper` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fails, `output` immediately rejects with the
|
||||||
|
error of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto output = QtPromise::map(QVector{
|
||||||
|
QUrl("http://a..."),
|
||||||
|
QUrl("http://b..."),
|
||||||
|
QUrl("http://c...")
|
||||||
|
}, [](const QUrl& url, ...) {
|
||||||
|
return QPromise<QByteArray>([&](auto resolve, auto reject) {
|
||||||
|
// download content at url and resolve
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 'output' resolves as soon as all promises returned by
|
||||||
|
// 'mapper' are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// 'output' type: QPromise<QVector<QByteArray>>
|
||||||
|
output.then([](const QVector<QByteArray>& res) {
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip NOTE
|
||||||
|
The order of the output sequence values is guarantee to be the same as the original
|
||||||
|
sequence, regardless of completion order of the promises returned by `mapper`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
See also: [`QPromise<T>::map`](../qpromise/map.md)
|
@ -1,4 +1,10 @@
|
|||||||
## `qPromise`
|
---
|
||||||
|
title: qPromise
|
||||||
|
---
|
||||||
|
|
||||||
|
# qPromise
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
```
|
```
|
||||||
qPromise(T value) -> QPromise<R>
|
qPromise(T value) -> QPromise<R>
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
## `qPromiseAll`
|
---
|
||||||
|
title: qPromiseAll
|
||||||
|
---
|
||||||
|
|
||||||
|
# qPromiseAll
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
```
|
```
|
||||||
qPromiseAll(Sequence<QPromise<T>> promises) -> QPromise<QVector<T>>
|
qPromiseAll(Sequence<QPromise<T>> promises) -> QPromise<QVector<T>>
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
## `[static] QPromise<T>::all`
|
---
|
||||||
|
title: ::all [static]
|
||||||
|
---
|
||||||
|
|
||||||
|
# QPromise::all [static]
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
```
|
```
|
||||||
[static] QPromise<T>::all(Sequence<QPromise<T>> promises) -> QPromise<QVector<T>>
|
[static] QPromise<T>::all(Sequence<QPromise<T>> promises) -> QPromise<QVector<T>>
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::QPromise`
|
---
|
||||||
|
title: constructor
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::QPromise
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::QPromise(Function resolver)
|
QPromise<T>::QPromise(Function resolver)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -18,7 +24,9 @@ QPromise<int> promise([](const QPromiseResolve<int>& resolve, const QPromiseReje
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** `QPromise<void>` is specialized to not contain any value, meaning that the `resolve` callback takes no argument.
|
::: tip NOTE
|
||||||
|
`QPromise<void>` is specialized to not contain any value, meaning that the `resolve` callback takes no argument.
|
||||||
|
:::
|
||||||
|
|
||||||
**C++14**
|
**C++14**
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::delay`
|
---
|
||||||
|
title: .delay
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::delay
|
||||||
|
|
||||||
|
*Since: 0.2.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::delay(int msec) -> QPromise<T>
|
QPromise<T>::delay(int msec) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
56
docs/qtpromise/qpromise/each.md
Normal file
56
docs/qtpromise/qpromise/each.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: .each
|
||||||
|
---
|
||||||
|
|
||||||
|
# QPromise::each
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<Sequence<T>>::each(Functor functor) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container
|
||||||
|
// - Functor: Function(T value, int index) -> any
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning IMPORTANT
|
||||||
|
This method only applies to promise with sequence value.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Calls the given `functor` on each element in the promise value (i.e. `Sequence<T>`), then resolves to the original sequence unmodified. If `functor` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QByteArray>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.each([](const QByteArray& value, int index) {
|
||||||
|
// process value ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// output type: QPromise<QList<QByteArray>>
|
||||||
|
output.then([](const QList<QByteArray>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QUrl>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.each([](const QUrl& url, ...) {
|
||||||
|
return QPromise<void>([&](auto resolve, auto reject) {
|
||||||
|
// process url asynchronously ...
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// `output` resolves as soon as all promises returned by
|
||||||
|
// `functor` are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// output type: QPromise<QList<QUrl>>
|
||||||
|
output.then([](const QList<QUrl>& res) {
|
||||||
|
// 'res' contains the original values
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [`QtPromise::each`](../helpers/each.md)
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::fail`
|
---
|
||||||
|
title: .fail
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::fail
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::fail(Function onRejected) -> QPromise<T>
|
QPromise<T>::fail(Function onRejected) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
55
docs/qtpromise/qpromise/filter.md
Normal file
55
docs/qtpromise/qpromise/filter.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
title: .filter
|
||||||
|
---
|
||||||
|
|
||||||
|
# QPromise::filter
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<Sequence<T>>::filter(Filter filterer) -> QPromise<Sequence<T>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Filterer: Function(T value, int index) -> bool
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning IMPORTANT
|
||||||
|
This method only applies to promise with sequence value.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Iterates over all the promise values (i.e. `Sequence<T>`) and [filters the sequence](https://en.wikipedia.org/wiki/Filter_%28higher-order_function%29)
|
||||||
|
to another using the given `filterer` function. If `filterer` returns `true`, a copy of the item
|
||||||
|
is put in the `output` sequence, otherwise, the item will not appear in `output`. If `filterer`
|
||||||
|
throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `filterer` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fail, `output` immediately rejects with the error
|
||||||
|
of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QUrl>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.filter([](const QUrl& url, ...) {
|
||||||
|
return url.isValid(); // Keep only valid URLs
|
||||||
|
}).filter([](const QUrl& url, ...) {
|
||||||
|
return QPromise<bool>([&](auto resolve, auto reject) {
|
||||||
|
// resolve(true) if `url` is reachable, else resolve(false)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 'output' resolves as soon as all promises returned by
|
||||||
|
// 'filterer' are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// 'output' type: QPromise<QList<QUrl>>
|
||||||
|
output.then([](const QList<QUrl>& res) {
|
||||||
|
// 'res' contains only reachable URLs
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip NOTE
|
||||||
|
The order of the output sequence values is guarantee to be the same as the original
|
||||||
|
sequence, regardless of completion order of the promises returned by `filterer`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
See also: [`QtPromise::filter`](../helpers/filter.md)
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::finally`
|
---
|
||||||
|
title: .finally
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::finally
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::finally(Function handler) -> QPromise<T>
|
QPromise<T>::finally(Function handler) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
# `QPromise<T>::isFulfilled`
|
---
|
||||||
|
title: .isFulfilled
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::isFulfilled
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::isFulfilled() -> bool
|
QPromise<T>::isFulfilled() -> bool
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
# `QPromise<T>::isPending`
|
---
|
||||||
|
title: .isPending
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::isPending
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::isPending() -> bool
|
QPromise<T>::isPending() -> bool
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
# `QPromise<T>::isRejected`
|
---
|
||||||
|
title: .isRejected
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::isRejected
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::isRejected() -> bool
|
QPromise<T>::isRejected() -> bool
|
||||||
```
|
```
|
||||||
|
|
||||||
|
67
docs/qtpromise/qpromise/map.md
Normal file
67
docs/qtpromise/qpromise/map.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
title: .map
|
||||||
|
---
|
||||||
|
|
||||||
|
# QPromise::map
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<Sequence<T>>::map(Mapper mapper) -> QPromise<QVector<R>>
|
||||||
|
|
||||||
|
// With:
|
||||||
|
// - Sequence: STL compatible container (e.g. QVector, etc.)
|
||||||
|
// - Mapper: Function(T value, int index) -> R | QPromise<R>
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning IMPORTANT
|
||||||
|
This method only applies to promise with sequence value.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Iterates over all the promise values (i.e. `Sequence<T>`) and [maps the sequence](https://en.wikipedia.org/wiki/Map_%28higher-order_function%29)
|
||||||
|
to another using the given `mapper` function. The type returned by `mapper` determines the type
|
||||||
|
of the `output` promise. If `mapper` throws, `output` is rejected with the new exception.
|
||||||
|
|
||||||
|
If `mapper` returns a promise (or `QFuture`), the `output` promise is delayed until all the
|
||||||
|
promises are resolved. If any of the promises fails, `output` immediately rejects with the
|
||||||
|
error of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QPromise<QList<QUrl>> input = {...}
|
||||||
|
|
||||||
|
auto output = input.map([](const QUrl& url, int index) {
|
||||||
|
return QPromise<QByteArray>([&](auto resolve, auto reject) {
|
||||||
|
// download content at 'url' and resolve
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
}).map([](const QByteArray& value, ...) {
|
||||||
|
// process the downloaded QByteArray
|
||||||
|
// {...}
|
||||||
|
return DownloadResult(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 'output' resolves as soon as all promises returned by
|
||||||
|
// 'mapper' are fulfilled or at least one is rejected.
|
||||||
|
|
||||||
|
// 'output' type: QPromise<QVector<DownloadResult>>
|
||||||
|
output.then([](const QVector<DownloadResult>& res) {
|
||||||
|
// {...}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
::: tip NOTE
|
||||||
|
The order of the output sequence values is guarantee to be the same as the original
|
||||||
|
sequence, regardless of completion order of the promises returned by `mapper`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
This function is provided for convenience and is similar to:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
promise.then([](const Sequence<T>& values) {
|
||||||
|
return QtPromise::map(values, [](const T& value, int index) {
|
||||||
|
return // {...}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [`QtPromise::map`](../helpers/map.md)
|
@ -1,6 +1,12 @@
|
|||||||
## `[static] QPromise<T>::reject`
|
---
|
||||||
|
title: ::reject [static]
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::reject [static]
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
[static] QPromise<T>::reject(any reason) -> QPromise<T>
|
[static] QPromise<T>::reject(any reason) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
## `[static] QPromise<T>::resolve`
|
---
|
||||||
|
title: ::resolve [static]
|
||||||
|
---
|
||||||
|
|
||||||
|
# QPromise::resolve [static]
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
```
|
```
|
||||||
[static] QPromise<T>::resolve(T value) -> QPromise<T>
|
[static] QPromise<T>::resolve(T value) -> QPromise<T>
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::tap`
|
---
|
||||||
|
title: .tap
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::tap
|
||||||
|
|
||||||
|
*Since: 0.2.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::tap(Function handler) -> QPromise<T>
|
QPromise<T>::tap(Function handler) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::tapFail`
|
---
|
||||||
|
title: .tapFail
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::tapFail
|
||||||
|
|
||||||
|
*Since: 0.4.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::tapFail(Function handler) -> QPromise<T>
|
QPromise<T>::tapFail(Function handler) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::then`
|
---
|
||||||
|
title: .then
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::then
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::then(Function onFulfilled, Function onRejected) -> QPromise<R>
|
QPromise<T>::then(Function onFulfilled, Function onRejected) -> QPromise<R>
|
||||||
QPromise<T>::then(Function onFulfilled) -> QPromise<R>
|
QPromise<T>::then(Function onFulfilled) -> QPromise<R>
|
||||||
```
|
```
|
||||||
@ -17,9 +23,11 @@ auto output = input.then([](int res) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**: `onRejected` handler is optional, `output` will be rejected with the same reason as `input`.
|
::: tip NOTE
|
||||||
|
`onRejected` handler is optional, in which case `output` will be rejected with
|
||||||
> **Note**: it's recommended to use the [`fail`](fail.md) shorthand to handle errors.
|
the same reason as `input`. Also note that it's recommended to use the
|
||||||
|
[`fail`](fail.md) shorthand to handle errors.
|
||||||
|
:::
|
||||||
|
|
||||||
The type `<R>` of the `output` promise depends on the return type of the `onFulfilled` handler:
|
The type `<R>` of the `output` promise depends on the return type of the `onFulfilled` handler:
|
||||||
|
|
||||||
@ -35,7 +43,11 @@ output.then([](const QString& res) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note**: only `onFulfilled` can change the promise type, `onRejected` **must** return the same type as `onFulfilled`. That also means if `onFulfilled` is `nullptr`, `onRejected` must return the same type as the `input` promise.
|
::: tip NOTE
|
||||||
|
Only `onFulfilled` can change the promise type, `onRejected` **must** return the
|
||||||
|
same type as `onFulfilled`. That also means if `onFulfilled` is `nullptr`,
|
||||||
|
`onRejected` must return the same type as the `input` promise.
|
||||||
|
:::
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
QPromise<int> input = ...
|
QPromise<int> input = ...
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::timeout`
|
---
|
||||||
|
title: .timeout
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::timeout
|
||||||
|
|
||||||
|
*Since: 0.2.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::timeout(int msec, any error = QPromiseTimeoutException) -> QPromise<T>
|
QPromise<T>::timeout(int msec, any error = QPromiseTimeoutException) -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
## `QPromise<T>::wait`
|
---
|
||||||
|
title: .wait
|
||||||
|
---
|
||||||
|
|
||||||
```
|
# QPromise::wait
|
||||||
|
|
||||||
|
*Since: 0.1.0*
|
||||||
|
|
||||||
|
```cpp
|
||||||
QPromise<T>::wait() -> QPromise<T>
|
QPromise<T>::wait() -> QPromise<T>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
## QtConcurrent
|
# QtConcurrent
|
||||||
|
|
||||||
QtPromise integrates with [QtConcurrent](https://doc.qt.io/qt-5/qtconcurrent-index.html) to make easy chaining QFuture with QPromise.
|
QtPromise integrates with [QtConcurrent](https://doc.qt.io/qt-5/qtconcurrent-index.html) to make easy chaining QFuture with QPromise.
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
## Thread-Safety
|
# Thread-Safety
|
||||||
|
|
||||||
QPromise is thread-safe and can be copied and accessed across different threads. QPromise relies on [explicitly data sharing](https://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html#details) and thus `auto p2 = p1` represents the same promise: when `p1` resolves, handlers registered on `p1` and `p2` are called, the fulfilled value being shared between both instances.
|
QPromise is thread-safe and can be copied and accessed across different threads. QPromise relies on [explicitly data sharing](https://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html#details) and thus `auto p2 = p1` represents the same promise: when `p1` resolves, handlers registered on `p1` and `p2` are called, the fulfilled value being shared between both instances.
|
||||||
|
|
||||||
> **Note:** while it's safe to access the resolved value from different threads using [`then`](qpromise/then.md), QPromise provides no guarantee about the object being pointed to. Thread-safety and reentrancy rules for that object still apply.
|
::: warning IMPORTANT
|
||||||
|
While it's safe to access the resolved value from different threads using [`then`](qpromise/then.md), QPromise provides no guarantee about the object being pointed to. Thread-safety and reentrancy rules for that object still apply.
|
||||||
|
:::
|
||||||
|
4
qpm.json
4
qpm.json
@ -10,9 +10,9 @@
|
|||||||
"url": "https://github.com/simonbrunel/qtpromise.git"
|
"url": "https://github.com/simonbrunel/qtpromise.git"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"label": "0.3.0"
|
"label": "0.4.0"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"pri_filename": "qtpromise.pri",
|
"pri_filename": "qtpromise.pri",
|
||||||
"webpage": "https://github.com/simonbrunel/qtpromise"
|
"webpage": "https://qtpromise.netlify.com"
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "qpromise_p.h"
|
#include "qpromise_p.h"
|
||||||
#include "qpromiseerror.h"
|
#include "qpromiseerror.h"
|
||||||
#include "qpromiseglobal.h"
|
#include "qpromiseglobal.h"
|
||||||
|
#include "qpromiseresolver.h"
|
||||||
|
|
||||||
// Qt
|
// Qt
|
||||||
#include <QExplicitlySharedDataPointer>
|
#include <QExplicitlySharedDataPointer>
|
||||||
@ -87,6 +88,16 @@ public:
|
|||||||
template <typename F>
|
template <typename F>
|
||||||
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
||||||
|
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> each(Functor fn);
|
||||||
|
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> filter(Functor fn);
|
||||||
|
|
||||||
|
template <typename Functor>
|
||||||
|
inline typename QtPromisePrivate::PromiseMapper<T, Functor>::PromiseType
|
||||||
|
map(Functor fn);
|
||||||
|
|
||||||
public: // STATIC
|
public: // STATIC
|
||||||
template <template <typename, typename...> class Sequence = QVector, typename ...Args>
|
template <template <typename, typename...> class Sequence = QVector, typename ...Args>
|
||||||
inline static QPromise<QVector<T>> all(const Sequence<QPromise<T>, Args...>& promises);
|
inline static QPromise<QVector<T>> all(const Sequence<QPromise<T>, Args...>& promises);
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#include "qpromise.h"
|
||||||
|
#include "qpromisehelpers.h"
|
||||||
|
|
||||||
// Qt
|
// Qt
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
@ -5,47 +8,6 @@
|
|||||||
|
|
||||||
namespace QtPromise {
|
namespace QtPromise {
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class QPromiseResolve
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QPromiseResolve(QtPromisePrivate::PromiseResolver<T> resolver)
|
|
||||||
: m_resolver(std::move(resolver))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
void operator()(V&& value) const
|
|
||||||
{
|
|
||||||
m_resolver.resolve(std::forward<V>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()() const
|
|
||||||
{
|
|
||||||
m_resolver.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable QtPromisePrivate::PromiseResolver<T> m_resolver;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class QPromiseReject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QPromiseReject(QtPromisePrivate::PromiseResolver<T> resolver)
|
|
||||||
: m_resolver(std::move(resolver))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
void operator()(E&& error) const
|
|
||||||
{
|
|
||||||
m_resolver.reject(std::forward<E>(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable QtPromisePrivate::PromiseResolver<T> m_resolver;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count == 1, int>::type>
|
template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count == 1, int>::type>
|
||||||
inline QPromiseBase<T>::QPromiseBase(F callback)
|
inline QPromiseBase<T>::QPromiseBase(F callback)
|
||||||
@ -193,6 +155,48 @@ inline QPromise<T> QPromiseBase<T>::reject(E&& error)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> QPromise<T>::each(Functor fn)
|
||||||
|
{
|
||||||
|
return this->tap([=](const T& values) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
std::vector<QPromise<void>> promises;
|
||||||
|
for (const auto& v : values) {
|
||||||
|
promises.push_back(
|
||||||
|
QtPromise::attempt(fn, v, i)
|
||||||
|
.then([]() {
|
||||||
|
// Cast to void in case fn returns a non promise value.
|
||||||
|
// TODO remove when implicit cast is implemented.
|
||||||
|
}));
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPromise<void>::all(promises);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
template <typename Functor>
|
||||||
|
inline QPromise<T> QPromise<T>::filter(Functor fn)
|
||||||
|
{
|
||||||
|
return this->then([=](const T& values) {
|
||||||
|
return QtPromise::filter(values, fn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
template <typename Functor>
|
||||||
|
inline typename QtPromisePrivate::PromiseMapper<T, Functor>::PromiseType
|
||||||
|
QPromise<T>::map(Functor fn)
|
||||||
|
{
|
||||||
|
return this->then([=](const T& values) {
|
||||||
|
return QtPromise::map(values, fn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <template <typename, typename...> class Sequence, typename ...Args>
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
inline QPromise<QVector<T>> QPromise<T>::all(const Sequence<QPromise<T>, Args...>& promises)
|
inline QPromise<QVector<T>> QPromise<T>::all(const Sequence<QPromise<T>, Args...>& promises)
|
||||||
|
@ -119,6 +119,13 @@ struct PromiseDeduce<QtPromise::QPromise<T>>
|
|||||||
: public PromiseDeduce<T>
|
: public PromiseDeduce<T>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
|
template <typename Functor, typename... Args>
|
||||||
|
struct PromiseFunctor
|
||||||
|
{
|
||||||
|
using ResultType = typename std::result_of<Functor(Args...)>::type;
|
||||||
|
using PromiseType = typename PromiseDeduce<ResultType>::Type;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct PromiseFulfill
|
struct PromiseFulfill
|
||||||
{
|
{
|
||||||
@ -176,51 +183,17 @@ struct PromiseFulfill<QtPromise::QPromise<void>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename TRes>
|
template <typename Result>
|
||||||
struct PromiseDispatch
|
struct PromiseDispatch
|
||||||
{
|
{
|
||||||
using Promise = typename PromiseDeduce<TRes>::Type;
|
template <typename Resolve, typename Reject, typename Functor, typename... Args>
|
||||||
using ResType = Unqualified<TRes>;
|
static void call(const Resolve& resolve, const Reject& reject, Functor fn, Args&&... args)
|
||||||
|
|
||||||
template <typename THandler, typename TResolve, typename TReject>
|
|
||||||
static void call(const T& value, THandler handler, const TResolve& resolve, const TReject& reject)
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
PromiseFulfill<ResType>::call(handler(value), resolve, reject);
|
PromiseFulfill<Unqualified<Result>>::call(
|
||||||
} catch (...) {
|
fn(std::forward<Args>(args)...),
|
||||||
reject(std::current_exception());
|
resolve,
|
||||||
}
|
reject);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct PromiseDispatch<T, void>
|
|
||||||
{
|
|
||||||
using Promise = QtPromise::QPromise<void>;
|
|
||||||
|
|
||||||
template <typename THandler, typename TResolve, typename TReject>
|
|
||||||
static void call(const T& value, THandler handler, const TResolve& resolve, const TReject& reject)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
handler(value);
|
|
||||||
resolve();
|
|
||||||
} catch (...) {
|
|
||||||
reject(std::current_exception());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TRes>
|
|
||||||
struct PromiseDispatch<void, TRes>
|
|
||||||
{
|
|
||||||
using Promise = typename PromiseDeduce<TRes>::Type;
|
|
||||||
using ResType = Unqualified<TRes>;
|
|
||||||
|
|
||||||
template <typename THandler, typename TResolve, typename TReject>
|
|
||||||
static void call(THandler handler, const TResolve& resolve, const TReject& reject)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
PromiseFulfill<ResType>::call(handler(), resolve, reject);
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
reject(std::current_exception());
|
reject(std::current_exception());
|
||||||
}
|
}
|
||||||
@ -228,15 +201,13 @@ struct PromiseDispatch<void, TRes>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct PromiseDispatch<void, void>
|
struct PromiseDispatch<void>
|
||||||
{
|
{
|
||||||
using Promise = QtPromise::QPromise<void>;
|
template <typename Resolve, typename Reject, typename Functor, typename... Args>
|
||||||
|
static void call(const Resolve& resolve, const Reject& reject, Functor fn, Args&&... args)
|
||||||
template <typename THandler, typename TResolve, typename TReject>
|
|
||||||
static void call(THandler handler, const TResolve& resolve, const TReject& reject)
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
handler();
|
fn(std::forward<Args>(args)...);
|
||||||
resolve();
|
resolve();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
reject(std::current_exception());
|
reject(std::current_exception());
|
||||||
@ -248,7 +219,7 @@ template <typename T, typename THandler, typename TArg = typename ArgsOf<THandle
|
|||||||
struct PromiseHandler
|
struct PromiseHandler
|
||||||
{
|
{
|
||||||
using ResType = typename std::result_of<THandler(T)>::type;
|
using ResType = typename std::result_of<THandler(T)>::type;
|
||||||
using Promise = typename PromiseDispatch<T, ResType>::Promise;
|
using Promise = typename PromiseDeduce<ResType>::Type;
|
||||||
|
|
||||||
template <typename TResolve, typename TReject>
|
template <typename TResolve, typename TReject>
|
||||||
static std::function<void(const T&)> create(
|
static std::function<void(const T&)> create(
|
||||||
@ -257,7 +228,7 @@ struct PromiseHandler
|
|||||||
const TReject& reject)
|
const TReject& reject)
|
||||||
{
|
{
|
||||||
return [=](const T& value) {
|
return [=](const T& value) {
|
||||||
PromiseDispatch<T, ResType>::call(value, std::move(handler), resolve, reject);
|
PromiseDispatch<ResType>::call(resolve, reject, handler, value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -266,7 +237,7 @@ template <typename T, typename THandler>
|
|||||||
struct PromiseHandler<T, THandler, void>
|
struct PromiseHandler<T, THandler, void>
|
||||||
{
|
{
|
||||||
using ResType = typename std::result_of<THandler()>::type;
|
using ResType = typename std::result_of<THandler()>::type;
|
||||||
using Promise = typename PromiseDispatch<T, ResType>::Promise;
|
using Promise = typename PromiseDeduce<ResType>::Type;
|
||||||
|
|
||||||
template <typename TResolve, typename TReject>
|
template <typename TResolve, typename TReject>
|
||||||
static std::function<void(const T&)> create(
|
static std::function<void(const T&)> create(
|
||||||
@ -275,7 +246,7 @@ struct PromiseHandler<T, THandler, void>
|
|||||||
const TReject& reject)
|
const TReject& reject)
|
||||||
{
|
{
|
||||||
return [=](const T&) {
|
return [=](const T&) {
|
||||||
PromiseDispatch<void, ResType>::call(handler, resolve, reject);
|
PromiseDispatch<ResType>::call(resolve, reject, handler);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -284,7 +255,7 @@ template <typename THandler>
|
|||||||
struct PromiseHandler<void, THandler, void>
|
struct PromiseHandler<void, THandler, void>
|
||||||
{
|
{
|
||||||
using ResType = typename std::result_of<THandler()>::type;
|
using ResType = typename std::result_of<THandler()>::type;
|
||||||
using Promise = typename PromiseDispatch<void, ResType>::Promise;
|
using Promise = typename PromiseDeduce<ResType>::Type;
|
||||||
|
|
||||||
template <typename TResolve, typename TReject>
|
template <typename TResolve, typename TReject>
|
||||||
static std::function<void()> create(
|
static std::function<void()> create(
|
||||||
@ -293,7 +264,7 @@ struct PromiseHandler<void, THandler, void>
|
|||||||
const TReject& reject)
|
const TReject& reject)
|
||||||
{
|
{
|
||||||
return [=]() {
|
return [=]() {
|
||||||
PromiseDispatch<void, ResType>::call(handler, resolve, reject);
|
PromiseDispatch<ResType>::call(resolve, reject, handler);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -351,7 +322,7 @@ struct PromiseCatcher
|
|||||||
try {
|
try {
|
||||||
error.rethrow();
|
error.rethrow();
|
||||||
} catch (const TArg& error) {
|
} catch (const TArg& error) {
|
||||||
PromiseDispatch<TArg, ResType>::call(error, handler, resolve, reject);
|
PromiseDispatch<ResType>::call(resolve, reject, handler, error);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
reject(std::current_exception());
|
reject(std::current_exception());
|
||||||
}
|
}
|
||||||
@ -374,7 +345,7 @@ struct PromiseCatcher<T, THandler, void>
|
|||||||
try {
|
try {
|
||||||
error.rethrow();
|
error.rethrow();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PromiseDispatch<void, ResType>::call(handler, resolve, reject);
|
PromiseDispatch<ResType>::call(resolve, reject, handler);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -397,6 +368,18 @@ struct PromiseCatcher<T, std::nullptr_t, void>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, typename F>
|
||||||
|
struct PromiseMapper
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template <typename T, typename F, template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
struct PromiseMapper<Sequence<T, Args...>, F>
|
||||||
|
{
|
||||||
|
using ReturnType = typename std::result_of<F(T, int)>::type;
|
||||||
|
using ResultType = QVector<typename PromiseDeduce<ReturnType>::Type::Type>;
|
||||||
|
using PromiseType = QtPromise::QPromise<ResultType>;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T> class PromiseData;
|
template <typename T> class PromiseData;
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
@ -562,68 +545,6 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class PromiseResolver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PromiseResolver(QtPromise::QPromise<T> promise)
|
|
||||||
: m_d(new Data())
|
|
||||||
{
|
|
||||||
m_d->promise = new QtPromise::QPromise<T>(std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
void reject(E&& error)
|
|
||||||
{
|
|
||||||
auto promise = m_d->promise;
|
|
||||||
if (promise) {
|
|
||||||
Q_ASSERT(promise->isPending());
|
|
||||||
promise->m_d->reject(std::forward<E>(error));
|
|
||||||
promise->m_d->dispatch();
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
void resolve(V&& value)
|
|
||||||
{
|
|
||||||
auto promise = m_d->promise;
|
|
||||||
if (promise) {
|
|
||||||
Q_ASSERT(promise->isPending());
|
|
||||||
promise->m_d->resolve(std::forward<V>(value));
|
|
||||||
promise->m_d->dispatch();
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resolve()
|
|
||||||
{
|
|
||||||
auto promise = m_d->promise;
|
|
||||||
if (promise) {
|
|
||||||
Q_ASSERT(promise->isPending());
|
|
||||||
promise->m_d->resolve();
|
|
||||||
promise->m_d->dispatch();
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Data : public QSharedData
|
|
||||||
{
|
|
||||||
QtPromise::QPromise<T>* promise = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
QExplicitlySharedDataPointer<Data> m_d;
|
|
||||||
|
|
||||||
void release()
|
|
||||||
{
|
|
||||||
Q_ASSERT(m_d->promise);
|
|
||||||
Q_ASSERT(!m_d->promise->isPending());
|
|
||||||
delete m_d->promise;
|
|
||||||
m_d->promise = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QtPromise
|
} // namespace QtPromise
|
||||||
|
|
||||||
#endif // ifndef QTPROMISE_QPROMISE_H
|
#endif // ifndef QTPROMISE_QPROMISE_H
|
||||||
|
@ -38,6 +38,83 @@ static inline QPromise<void> qPromiseAll(const Sequence<QPromise<void>, Args...>
|
|||||||
return QPromise<void>::all(promises);
|
return QPromise<void>::all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Functor, typename... Args>
|
||||||
|
static inline typename QtPromisePrivate::PromiseFunctor<Functor, Args...>::PromiseType
|
||||||
|
attempt(Functor&& fn, Args&&... args)
|
||||||
|
{
|
||||||
|
using namespace QtPromisePrivate;
|
||||||
|
using FunctorType = PromiseFunctor<Functor, Args...>;
|
||||||
|
using PromiseType = typename FunctorType::PromiseType;
|
||||||
|
using ValueType = typename PromiseType::Type;
|
||||||
|
|
||||||
|
// NOTE: std::forward<T<U>>: MSVC 2013 fails when forwarding
|
||||||
|
// template type (error: "expects 4 arguments - 0 provided").
|
||||||
|
// However it succeeds with type alias.
|
||||||
|
// TODO: should we expose QPromise::ResolveType & RejectType?
|
||||||
|
using ResolveType = QPromiseResolve<ValueType>;
|
||||||
|
using RejectType = QPromiseReject<ValueType>;
|
||||||
|
|
||||||
|
return PromiseType(
|
||||||
|
[&](ResolveType&& resolve, RejectType&& reject) {
|
||||||
|
PromiseDispatch<typename FunctorType::ResultType>::call(
|
||||||
|
std::forward<ResolveType>(resolve),
|
||||||
|
std::forward<RejectType>(reject),
|
||||||
|
std::forward<Functor>(fn),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sequence, typename Functor>
|
||||||
|
static inline QPromise<Sequence> each(const Sequence& values, Functor&& fn)
|
||||||
|
{
|
||||||
|
return QPromise<Sequence>::resolve(values).each(std::forward<Functor>(fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sequence, typename Functor>
|
||||||
|
static inline typename QtPromisePrivate::PromiseMapper<Sequence, Functor>::PromiseType
|
||||||
|
map(const Sequence& values, Functor fn)
|
||||||
|
{
|
||||||
|
using namespace QtPromisePrivate;
|
||||||
|
using MapperType = PromiseMapper<Sequence, Functor>;
|
||||||
|
using ResType = typename MapperType::ResultType::value_type;
|
||||||
|
using RetType = typename MapperType::ReturnType;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
std::vector<QPromise<ResType>> promises;
|
||||||
|
for (const auto& v : values) {
|
||||||
|
promises.push_back(QPromise<ResType>([&](
|
||||||
|
const QPromiseResolve<ResType>& resolve,
|
||||||
|
const QPromiseReject<ResType>& reject) {
|
||||||
|
PromiseFulfill<RetType>::call(fn(v, i), resolve, reject);
|
||||||
|
}));
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPromise<ResType>::all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sequence, typename Functor>
|
||||||
|
static inline QPromise<Sequence> filter(const Sequence& values, Functor fn)
|
||||||
|
{
|
||||||
|
return QtPromise::map(values, fn)
|
||||||
|
.then([=](const QVector<bool>& filters) {
|
||||||
|
Sequence filtered;
|
||||||
|
|
||||||
|
auto filter = filters.begin();
|
||||||
|
for (auto& value : values) {
|
||||||
|
if (*filter) {
|
||||||
|
filtered.push_back(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
filter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QtPromise
|
} // namespace QtPromise
|
||||||
|
|
||||||
#endif // QTPROMISE_QPROMISEHELPERS_H
|
#endif // QTPROMISE_QPROMISEHELPERS_H
|
||||||
|
124
src/qtpromise/qpromiseresolver.h
Normal file
124
src/qtpromise/qpromiseresolver.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#ifndef QTPROMISE_QPROMISERESOLVER_H
|
||||||
|
#define QTPROMISE_QPROMISERESOLVER_H
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QExplicitlySharedDataPointer>
|
||||||
|
|
||||||
|
namespace QtPromise {
|
||||||
|
|
||||||
|
template <typename T> class QPromise;
|
||||||
|
|
||||||
|
} // namespace QtPromise
|
||||||
|
|
||||||
|
namespace QtPromisePrivate {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class PromiseResolver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PromiseResolver(QtPromise::QPromise<T> promise)
|
||||||
|
: m_d(new Data())
|
||||||
|
{
|
||||||
|
m_d->promise = new QtPromise::QPromise<T>(std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
void reject(E&& error)
|
||||||
|
{
|
||||||
|
auto promise = m_d->promise;
|
||||||
|
if (promise) {
|
||||||
|
Q_ASSERT(promise->isPending());
|
||||||
|
promise->m_d->reject(std::forward<E>(error));
|
||||||
|
promise->m_d->dispatch();
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
void resolve(V&& value)
|
||||||
|
{
|
||||||
|
auto promise = m_d->promise;
|
||||||
|
if (promise) {
|
||||||
|
Q_ASSERT(promise->isPending());
|
||||||
|
promise->m_d->resolve(std::forward<V>(value));
|
||||||
|
promise->m_d->dispatch();
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolve()
|
||||||
|
{
|
||||||
|
auto promise = m_d->promise;
|
||||||
|
if (promise) {
|
||||||
|
Q_ASSERT(promise->isPending());
|
||||||
|
promise->m_d->resolve();
|
||||||
|
promise->m_d->dispatch();
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Data : public QSharedData
|
||||||
|
{
|
||||||
|
QtPromise::QPromise<T>* promise = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
QExplicitlySharedDataPointer<Data> m_d;
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_d->promise);
|
||||||
|
Q_ASSERT(!m_d->promise->isPending());
|
||||||
|
delete m_d->promise;
|
||||||
|
m_d->promise = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // QtPromisePrivate
|
||||||
|
|
||||||
|
namespace QtPromise {
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class QPromiseResolve
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QPromiseResolve(QtPromisePrivate::PromiseResolver<T> resolver)
|
||||||
|
: m_resolver(std::move(resolver))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
void operator()(V&& value) const
|
||||||
|
{
|
||||||
|
m_resolver.resolve(std::forward<V>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()() const
|
||||||
|
{
|
||||||
|
m_resolver.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable QtPromisePrivate::PromiseResolver<T> m_resolver;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class QPromiseReject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QPromiseReject(QtPromisePrivate::PromiseResolver<T> resolver)
|
||||||
|
: m_resolver(std::move(resolver))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
void operator()(E&& error) const
|
||||||
|
{
|
||||||
|
m_resolver.reject(std::forward<E>(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable QtPromisePrivate::PromiseResolver<T> m_resolver;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QtPromise
|
||||||
|
|
||||||
|
#endif // QTPROMISE_QPROMISERESOLVER_H
|
@ -5,4 +5,5 @@ HEADERS += \
|
|||||||
$$PWD/qpromiseerror.h \
|
$$PWD/qpromiseerror.h \
|
||||||
$$PWD/qpromisefuture.h \
|
$$PWD/qpromisefuture.h \
|
||||||
$$PWD/qpromiseglobal.h \
|
$$PWD/qpromiseglobal.h \
|
||||||
$$PWD/qpromisehelpers.h
|
$$PWD/qpromisehelpers.h \
|
||||||
|
$$PWD/qpromiseresolver.h
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
TARGET = tst_qpromise_all
|
TARGET = tst_helpers_all
|
||||||
SOURCES += $$PWD/tst_all.cpp
|
SOURCES += $$PWD/tst_all.cpp
|
||||||
|
|
||||||
include(../../qtpromise.pri)
|
include(../../qtpromise.pri)
|
221
tests/auto/qtpromise/helpers/all/tst_all.cpp
Normal file
221
tests/auto/qtpromise/helpers/all/tst_all.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_all : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void emptySequence_void();
|
||||||
|
void allPromisesSucceed();
|
||||||
|
void allPromisesSucceed_void();
|
||||||
|
void atLeastOnePromiseReject();
|
||||||
|
void atLeastOnePromiseReject_void();
|
||||||
|
void preserveOrder();
|
||||||
|
void sequenceTypes();
|
||||||
|
void sequenceTypes_void();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_all)
|
||||||
|
#include "tst_all.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
Q_STATIC_ASSERT((std::is_same<typename Sequence::value_type, QPromise<int>>::value));
|
||||||
|
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
Sequence promises{
|
||||||
|
QtPromise::qPromise(42),
|
||||||
|
QtPromise::qPromise(43),
|
||||||
|
QtPromise::qPromise(44)
|
||||||
|
};
|
||||||
|
|
||||||
|
promises.push_back(QtPromise::qPromise(45));
|
||||||
|
promises.insert(++promises.begin(), QtPromise::qPromise(46));
|
||||||
|
promises.pop_back();
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(promises);
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 46, 43, 44}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
struct SequenceTester<Sequence<QPromise<void>, Args...>>
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
Sequence<QPromise<void>, Args...> promises{
|
||||||
|
QtPromise::qPromise(),
|
||||||
|
QtPromise::qPromise(),
|
||||||
|
QtPromise::qPromise()
|
||||||
|
};
|
||||||
|
|
||||||
|
promises.push_back(QtPromise::qPromise());
|
||||||
|
promises.insert(++promises.begin(), QtPromise::qPromise());
|
||||||
|
promises.pop_back();
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(promises);
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_helpers_all::emptySequence()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>());
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::emptySequence_void()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<void>>());
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::allPromisesSucceed()
|
||||||
|
{
|
||||||
|
auto p0 = QtPromise::qPromise(42);
|
||||||
|
auto p1 = QtPromise::qPromise(44);
|
||||||
|
auto p2 = QPromise<int>([](const QPromiseResolve<int>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
|
resolve(43);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p2, p1});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
|
QCOMPARE(p2.isPending(), true);
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(p2.isFulfilled(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::allPromisesSucceed_void()
|
||||||
|
{
|
||||||
|
auto p0 = QtPromise::qPromise();
|
||||||
|
auto p1 = QtPromise::qPromise();
|
||||||
|
auto p2 = QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<void>>{p0, p2, p1});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
|
QCOMPARE(p2.isPending(), true);
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
QCOMPARE(p2.isFulfilled(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::atLeastOnePromiseReject()
|
||||||
|
{
|
||||||
|
auto p0 = QtPromise::qPromise(42);
|
||||||
|
auto p1 = QtPromise::qPromise(44);
|
||||||
|
auto p2 = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
|
reject(QString("foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p2, p1});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
|
QCOMPARE(p2.isPending(), true);
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
QCOMPARE(p2.isRejected(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::atLeastOnePromiseReject_void()
|
||||||
|
{
|
||||||
|
auto p0 = QtPromise::qPromise();
|
||||||
|
auto p1 = QtPromise::qPromise();
|
||||||
|
auto p2 = QPromise<void>([](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
|
reject(QString("foo"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<void>>{p0, p2, p1});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
|
QCOMPARE(p2.isPending(), true);
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
QCOMPARE(p2.isRejected(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::preserveOrder()
|
||||||
|
{
|
||||||
|
auto p0 = QtPromise::qPromise(42).delay(500);
|
||||||
|
auto p1 = QtPromise::qPromise(43).delay(100);
|
||||||
|
auto p2 = QtPromise::qPromise(44).delay(250);
|
||||||
|
|
||||||
|
auto p = QtPromise::qPromiseAll(QVector<QPromise<int>>{p0, p1, p2});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(p0.isPending(), true);
|
||||||
|
QCOMPARE(p1.isPending(), true);
|
||||||
|
QCOMPARE(p2.isPending(), true);
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
|
QCOMPARE(p2.isFulfilled(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// QVector::push_back/append isn't supported since it requires a default
|
||||||
|
// constructor (see https://github.com/simonbrunel/qtpromise/issues/3)
|
||||||
|
|
||||||
|
void tst_helpers_all::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<QPromise<int>>>::exec();
|
||||||
|
//SequenceTester<QVector<QPromise<int>>>::exec();
|
||||||
|
SequenceTester<std::list<QPromise<int>>>::exec();
|
||||||
|
SequenceTester<std::vector<QPromise<int>>>::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_all::sequenceTypes_void()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<QPromise<void>>>::exec();
|
||||||
|
//SequenceTester<QVector<QPromise<void>>>::exec();
|
||||||
|
SequenceTester<std::list<QPromise<void>>>::exec();
|
||||||
|
SequenceTester<std::vector<QPromise<void>>>::exec();
|
||||||
|
}
|
5
tests/auto/qtpromise/helpers/attempt/attempt.pro
Normal file
5
tests/auto/qtpromise/helpers/attempt/attempt.pro
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
QT += concurrent
|
||||||
|
TARGET = tst_helpers_attempt
|
||||||
|
SOURCES += $$PWD/tst_attempt.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
99
tests/auto/qtpromise/helpers/attempt/tst_attempt.cpp
Normal file
99
tests/auto/qtpromise/helpers/attempt/tst_attempt.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtConcurrent>
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
// STL
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_attempt : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void voidResult();
|
||||||
|
void typedResult();
|
||||||
|
void futureResult();
|
||||||
|
void promiseResult();
|
||||||
|
void functorThrows();
|
||||||
|
void callWithParams();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_attempt)
|
||||||
|
#include "tst_attempt.moc"
|
||||||
|
|
||||||
|
void tst_helpers_attempt::voidResult()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([]() {});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_attempt::typedResult()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([]() {
|
||||||
|
return QString("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
||||||
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_attempt::futureResult()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([]() {
|
||||||
|
return QtConcurrent::run([]() {
|
||||||
|
return QString("foo");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_attempt::promiseResult()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([]() {
|
||||||
|
return QtPromise::qPromise(42).delay(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_attempt::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([]() {
|
||||||
|
if (true) {
|
||||||
|
throw QString("bar");
|
||||||
|
}
|
||||||
|
return 42;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
|
||||||
|
QCOMPARE(p.isRejected(), true);
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_attempt::callWithParams()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::attempt([&](int i, const QString& s) {
|
||||||
|
return QString("%1:%2").arg(i).arg(s);
|
||||||
|
}, 42, "foo");
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
||||||
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QString()), QString("42:foo"));
|
||||||
|
}
|
4
tests/auto/qtpromise/helpers/each/each.pro
Normal file
4
tests/auto/qtpromise/helpers/each/each.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_each
|
||||||
|
SOURCES += $$PWD/tst_each.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
154
tests/auto/qtpromise/helpers/each/tst_each.cpp
Normal file
154
tests/auto/qtpromise/helpers/each/tst_each.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_each : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void preserveValues();
|
||||||
|
void ignoreResult();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_each)
|
||||||
|
#include "tst_each.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(Sequence{42, 43, 44}, [&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_helpers_each::emptySequence()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{}, [&](int v, ...) {
|
||||||
|
values << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>());
|
||||||
|
QCOMPARE(values, QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::preserveValues()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::ignoreResult()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
return "Foo";
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::delayedFulfilled()
|
||||||
|
{
|
||||||
|
QMap<int, int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, int index) {
|
||||||
|
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=, &values]() {
|
||||||
|
values[v] = index;
|
||||||
|
resolve(42);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 43) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
if (v == 44) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::functorArguments()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::each(QVector<int>{42, 43, 44}, [&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_each::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
4
tests/auto/qtpromise/helpers/filter/filter.pro
Normal file
4
tests/auto/qtpromise/helpers/filter/filter.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_helpers_filter
|
||||||
|
SOURCES += $$PWD/tst_filter.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
147
tests/auto/qtpromise/helpers/filter/tst_filter.cpp
Normal file
147
tests/auto/qtpromise/helpers/filter/tst_filter.cpp
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_filter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void filterValues();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void preserveOrder();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_filter)
|
||||||
|
#include "tst_filter.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
auto inputs = Sequence{42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
|
||||||
|
auto p = QtPromise::filter(inputs, [](int v, ...) {
|
||||||
|
return v % 3 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({42, 45, 48, 51}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
|
||||||
|
void tst_helpers_filter::emptySequence()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{}, [](int v, ...) {
|
||||||
|
return v % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::filterValues()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return v % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::delayedFulfilled()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<bool>([&](const QPromiseResolve<bool>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
resolve(v % 2 == 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<bool>([&](
|
||||||
|
const QPromiseResolve<bool>& resolve,
|
||||||
|
const QPromiseReject<bool>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 44) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
if (v == 44) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::functorArguments()
|
||||||
|
{
|
||||||
|
QMap<int, int> args;
|
||||||
|
auto p = QtPromise::filter(QVector<int>{42, 43, 44}, [&](int v, int i) {
|
||||||
|
args[v] = i;
|
||||||
|
return i % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(args, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::preserveOrder()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::filter(QVector<int>{500, 100, 300, 250, 400}, [](int v, ...) {
|
||||||
|
return QPromise<bool>::resolve(v > 200).delay(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({500, 300, 250, 400}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_filter::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
@ -1,4 +1,9 @@
|
|||||||
TARGET = tst_helpers
|
TEMPLATE = subdirs
|
||||||
SOURCES += $$PWD/tst_helpers.cpp
|
SUBDIRS += \
|
||||||
|
all \
|
||||||
include(../qtpromise.pri)
|
attempt \
|
||||||
|
each \
|
||||||
|
filter \
|
||||||
|
map \
|
||||||
|
reject \
|
||||||
|
resolve
|
||||||
|
4
tests/auto/qtpromise/helpers/map/map.pro
Normal file
4
tests/auto/qtpromise/helpers/map/map.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_helpers_map
|
||||||
|
SOURCES += $$PWD/tst_map.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
151
tests/auto/qtpromise/helpers/map/tst_map.cpp
Normal file
151
tests/auto/qtpromise/helpers/map/tst_map.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_helpers_map : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void modifyValues();
|
||||||
|
void convertValues();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void preserveOrder();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_helpers_map)
|
||||||
|
#include "tst_map.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(Sequence{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QString::number(v + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_helpers_map::emptySequence()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{}, [](int v, ...) {
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::modifyValues()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::convertValues()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QString::number(v + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::delayedFulfilled()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
resolve(v + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 43) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 43, 44}, [](int v, ...) {
|
||||||
|
if (v == 43) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::functorArguments()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{42, 42, 42}, [](int v, int i) {
|
||||||
|
return v * i;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({0, 42, 84}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::preserveOrder()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::map(QVector<int>{500, 100, 250}, [](int v, ...) {
|
||||||
|
return QPromise<int>::resolve(v + 1).delay(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({501, 101, 251}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_map::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
TARGET = tst_qpromise_reject
|
TARGET = tst_helpers_reject
|
||||||
SOURCES += $$PWD/tst_reject.cpp
|
SOURCES += $$PWD/tst_reject.cpp
|
||||||
|
|
||||||
include(../../qtpromise.pri)
|
include(../../qtpromise.pri)
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
using namespace QtPromise;
|
using namespace QtPromise;
|
||||||
|
|
||||||
class tst_qpromise_reject : public QObject
|
class tst_helpers_reject : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -22,10 +22,10 @@ private Q_SLOTS:
|
|||||||
void rejectWithStdSharedPtr();
|
void rejectWithStdSharedPtr();
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_MAIN(tst_qpromise_reject)
|
QTEST_MAIN(tst_helpers_reject)
|
||||||
#include "tst_reject.moc"
|
#include "tst_reject.moc"
|
||||||
|
|
||||||
void tst_qpromise_reject::rejectWithValue()
|
void tst_helpers_reject::rejectWithValue()
|
||||||
{
|
{
|
||||||
auto p = QPromise<int>::reject(42);
|
auto p = QPromise<int>::reject(42);
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ void tst_qpromise_reject::rejectWithValue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||||
void tst_qpromise_reject::rejectWithQSharedPtr()
|
void tst_helpers_reject::rejectWithQSharedPtr()
|
||||||
{
|
{
|
||||||
QWeakPointer<int> wptr;
|
QWeakPointer<int> wptr;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ void tst_qpromise_reject::rejectWithQSharedPtr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||||
void tst_qpromise_reject::rejectWithStdSharedPtr()
|
void tst_helpers_reject::rejectWithStdSharedPtr()
|
||||||
{
|
{
|
||||||
std::weak_ptr<int> wptr;
|
std::weak_ptr<int> wptr;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
TARGET = tst_qpromise_resolve
|
TARGET = tst_helpers_resolve
|
||||||
SOURCES += $$PWD/tst_resolve.cpp
|
SOURCES += $$PWD/tst_resolve.cpp
|
||||||
|
|
||||||
include(../../qtpromise.pri)
|
include(../../qtpromise.pri)
|
@ -12,41 +12,80 @@
|
|||||||
|
|
||||||
using namespace QtPromise;
|
using namespace QtPromise;
|
||||||
|
|
||||||
class tst_qpromise_resolve : public QObject
|
class tst_helpers_resolve : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void resolveWithValue();
|
void resolveWithValue();
|
||||||
void resolveWithNoValue();
|
void resolveWithNoValue();
|
||||||
|
void resolveWithTypedPromise();
|
||||||
|
void resolveWithVoidPromise();
|
||||||
void resolveWithQSharedPtr();
|
void resolveWithQSharedPtr();
|
||||||
void resolveWithStdSharedPtr();
|
void resolveWithStdSharedPtr();
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_MAIN(tst_qpromise_resolve)
|
QTEST_MAIN(tst_helpers_resolve)
|
||||||
#include "tst_resolve.moc"
|
#include "tst_resolve.moc"
|
||||||
|
|
||||||
void tst_qpromise_resolve::resolveWithValue()
|
void tst_helpers_resolve::resolveWithValue()
|
||||||
{
|
{
|
||||||
const int value = 42;
|
const int value = 42;
|
||||||
auto p0 = QPromise<int>::resolve(value);
|
auto p0 = QPromise<int>::resolve(value);
|
||||||
auto p1 = QPromise<int>::resolve(43);
|
auto p1 = QPromise<int>::resolve(43);
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p0), QPromise<int>>::value));
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<int>>::value));
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
QCOMPARE(p0.isFulfilled(), true);
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
QCOMPARE(p1.isFulfilled(), true);
|
||||||
QCOMPARE(waitForValue(p0, -1), 42);
|
QCOMPARE(waitForValue(p0, -1), 42);
|
||||||
QCOMPARE(waitForValue(p1, -1), 43);
|
QCOMPARE(waitForValue(p1, -1), 43);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qpromise_resolve::resolveWithNoValue()
|
void tst_helpers_resolve::resolveWithNoValue()
|
||||||
{
|
{
|
||||||
auto p = QPromise<void>::resolve();
|
auto p = QPromise<void>::resolve();
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_resolve::resolveWithTypedPromise()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(
|
||||||
|
QPromise<QString>([](const QPromiseResolve<QString>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=](){
|
||||||
|
resolve("foo");
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
||||||
|
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_helpers_resolve::resolveWithVoidPromise()
|
||||||
|
{
|
||||||
|
int check;
|
||||||
|
auto p = QtPromise::qPromise(
|
||||||
|
QPromise<void>([&](const QPromiseResolve<void>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=, &check](){
|
||||||
|
check = 8;
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
||||||
|
|
||||||
|
QCOMPARE(p.isPending(), true);
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
QCOMPARE(check, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||||
void tst_qpromise_resolve::resolveWithQSharedPtr()
|
void tst_helpers_resolve::resolveWithQSharedPtr()
|
||||||
{
|
{
|
||||||
QWeakPointer<int> wptr;
|
QWeakPointer<int> wptr;
|
||||||
|
|
||||||
@ -66,7 +105,7 @@ void tst_qpromise_resolve::resolveWithQSharedPtr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/simonbrunel/qtpromise/issues/6
|
// https://github.com/simonbrunel/qtpromise/issues/6
|
||||||
void tst_qpromise_resolve::resolveWithStdSharedPtr()
|
void tst_helpers_resolve::resolveWithStdSharedPtr()
|
||||||
{
|
{
|
||||||
std::weak_ptr<int> wptr;
|
std::weak_ptr<int> wptr;
|
||||||
|
|
@ -1,244 +0,0 @@
|
|||||||
// QtPromise
|
|
||||||
#include <QtPromise>
|
|
||||||
|
|
||||||
// Qt
|
|
||||||
#include <QtTest>
|
|
||||||
|
|
||||||
using namespace QtPromise;
|
|
||||||
|
|
||||||
class tst_helpers : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void resolve();
|
|
||||||
void resolve_void();
|
|
||||||
void resolve_promise();
|
|
||||||
void resolve_promise_void();
|
|
||||||
|
|
||||||
void allFulfilled();
|
|
||||||
void allFulfilled_void();
|
|
||||||
void allRejected();
|
|
||||||
void allRejected_void();
|
|
||||||
void allEmpty();
|
|
||||||
void allEmpty_void();
|
|
||||||
|
|
||||||
}; // class tst_helpers
|
|
||||||
|
|
||||||
QTEST_MAIN(tst_helpers)
|
|
||||||
#include "tst_helpers.moc"
|
|
||||||
|
|
||||||
void tst_helpers::resolve()
|
|
||||||
{
|
|
||||||
int value = -1;
|
|
||||||
auto p = QtPromise::qPromise(42);
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<int>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
|
|
||||||
p.then([&](int res) {
|
|
||||||
value = res;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(value, 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::resolve_void()
|
|
||||||
{
|
|
||||||
int value = -1;
|
|
||||||
auto p = QtPromise::qPromise();
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
|
|
||||||
p.then([&]() {
|
|
||||||
value = 42;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(value, 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::resolve_promise()
|
|
||||||
{
|
|
||||||
QString value;
|
|
||||||
auto p = QtPromise::qPromise(
|
|
||||||
QPromise<QString>([](const QPromiseResolve<QString>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
resolve("foo");
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QString>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
|
|
||||||
p.then([&](const QString& res) {
|
|
||||||
value = res;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
QCOMPARE(value, QString("foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::resolve_promise_void()
|
|
||||||
{
|
|
||||||
QList<int> values;
|
|
||||||
auto p = QtPromise::qPromise(
|
|
||||||
QPromise<void>([&](const QPromiseResolve<void>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=, &values](){
|
|
||||||
values << 42;
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
|
|
||||||
p.then([&]() {
|
|
||||||
values << 43;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
QCOMPARE(values, QList<int>({42, 43}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allFulfilled()
|
|
||||||
{
|
|
||||||
auto p0 = QtPromise::qPromise(42);
|
|
||||||
auto p1 = QtPromise::qPromise(44);
|
|
||||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
resolve(43);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<int>>{p0, p2, p1});
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isPending(), true);
|
|
||||||
|
|
||||||
QVector<int> values;
|
|
||||||
p.then([&](const QVector<int>& res) {
|
|
||||||
values = res;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isFulfilled(), true);
|
|
||||||
QCOMPARE(values, QVector<int>({42, 43, 44}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allFulfilled_void()
|
|
||||||
{
|
|
||||||
auto p0 = QtPromise::qPromise();
|
|
||||||
auto p1 = QtPromise::qPromise();
|
|
||||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>& resolve) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<void>>{p0, p2, p1});
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isPending(), true);
|
|
||||||
|
|
||||||
p.wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isFulfilled(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allRejected()
|
|
||||||
{
|
|
||||||
auto p0 = QtPromise::qPromise(42);
|
|
||||||
auto p1 = QtPromise::qPromise(44);
|
|
||||||
auto p2 = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
reject(QString("foo"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<int>>{p0, p2, p1});
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isPending(), true);
|
|
||||||
|
|
||||||
QString error;
|
|
||||||
p.fail([&](const QString& err) {
|
|
||||||
error = err;
|
|
||||||
return QVector<int>();
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isRejected(), true);
|
|
||||||
QCOMPARE(p2.isRejected(), true);
|
|
||||||
QCOMPARE(error, QString("foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allRejected_void()
|
|
||||||
{
|
|
||||||
auto p0 = QtPromise::qPromise();
|
|
||||||
auto p1 = QtPromise::qPromise();
|
|
||||||
auto p2 = QPromise<void>([](const QPromiseResolve<void>&, const QPromiseReject<void>& reject) {
|
|
||||||
QtPromisePrivate::qtpromise_defer([=](){
|
|
||||||
reject(QString("foo"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<void>>{p0, p2, p1});
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isPending(), true);
|
|
||||||
QCOMPARE(p0.isFulfilled(), true);
|
|
||||||
QCOMPARE(p1.isFulfilled(), true);
|
|
||||||
QCOMPARE(p2.isPending(), true);
|
|
||||||
|
|
||||||
QString error;
|
|
||||||
p.fail([&](const QString& err) {
|
|
||||||
error = err;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(p.isRejected(), true);
|
|
||||||
QCOMPARE(p2.isRejected(), true);
|
|
||||||
QCOMPARE(error, QString("foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allEmpty()
|
|
||||||
{
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<int>>());
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
|
|
||||||
QVector<int> values;
|
|
||||||
p.then([&](const QVector<int>& res) {
|
|
||||||
values = res;
|
|
||||||
}).wait();
|
|
||||||
|
|
||||||
QCOMPARE(values, QVector<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_helpers::allEmpty_void()
|
|
||||||
{
|
|
||||||
auto p = qPromiseAll(QVector<QPromise<void>>());
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
|
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
// Tests
|
|
||||||
#include "../../shared/utils.h"
|
|
||||||
|
|
||||||
// QtPromise
|
|
||||||
#include <QtPromise>
|
|
||||||
|
|
||||||
// Qt
|
|
||||||
#include <QtTest>
|
|
||||||
|
|
||||||
using namespace QtPromise;
|
|
||||||
|
|
||||||
class tst_qpromise_all : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void qList();
|
|
||||||
//void qVector();
|
|
||||||
void stdList();
|
|
||||||
void stdVector();
|
|
||||||
};
|
|
||||||
|
|
||||||
QTEST_MAIN(tst_qpromise_all)
|
|
||||||
#include "tst_all.moc"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <class Sequence>
|
|
||||||
struct SequenceTester
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <typename, typename...> class Sequence, typename ...Args>
|
|
||||||
struct SequenceTester<Sequence<QPromise<int>, Args...>>
|
|
||||||
{
|
|
||||||
static void exec()
|
|
||||||
{
|
|
||||||
Sequence<QPromise<int>, Args...> promises{
|
|
||||||
QPromise<int>::resolve(42),
|
|
||||||
QPromise<int>::resolve(43),
|
|
||||||
QPromise<int>::resolve(44)
|
|
||||||
};
|
|
||||||
|
|
||||||
promises.push_back(QPromise<int>::resolve(45));
|
|
||||||
promises.insert(++promises.begin(), QPromise<int>::resolve(46));
|
|
||||||
promises.pop_back();
|
|
||||||
|
|
||||||
auto p = QPromise<int>::all(promises);
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
|
||||||
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 46, 43, 44}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <template <typename, typename...> class Sequence, typename ...Args>
|
|
||||||
struct SequenceTester<Sequence<QPromise<void>, Args...>>
|
|
||||||
{
|
|
||||||
static void exec()
|
|
||||||
{
|
|
||||||
Sequence<QPromise<void>, Args...> promises{
|
|
||||||
QPromise<void>::resolve(),
|
|
||||||
QPromise<void>::resolve(),
|
|
||||||
QPromise<void>::resolve()
|
|
||||||
};
|
|
||||||
|
|
||||||
promises.push_back(QPromise<void>::resolve());
|
|
||||||
promises.insert(++promises.begin(), QPromise<void>::resolve());
|
|
||||||
promises.pop_back();
|
|
||||||
|
|
||||||
auto p = QPromise<void>::all(promises);
|
|
||||||
|
|
||||||
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void>>::value));
|
|
||||||
QCOMPARE(waitForValue(p, -1, 42), 42);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
void tst_qpromise_all::qList()
|
|
||||||
{
|
|
||||||
SequenceTester<QList<QPromise<int>>>::exec();
|
|
||||||
SequenceTester<QList<QPromise<void>>>::exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
// QVector::push_back/append isn't supported since it requires a default
|
|
||||||
// constructor (see https://github.com/simonbrunel/qtpromise/issues/3)
|
|
||||||
//void tst_qpromise_all::qVector()
|
|
||||||
//{
|
|
||||||
// SequenceTester<QVector<QPromise<int>>>::exec();
|
|
||||||
// SequenceTester<QVector<QPromise<void>>>::exec();
|
|
||||||
//}
|
|
||||||
|
|
||||||
void tst_qpromise_all::stdList()
|
|
||||||
{
|
|
||||||
SequenceTester<std::list<QPromise<int>>>::exec();
|
|
||||||
SequenceTester<std::list<QPromise<void>>>::exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_qpromise_all::stdVector()
|
|
||||||
{
|
|
||||||
SequenceTester<std::vector<QPromise<int>>>::exec();
|
|
||||||
SequenceTester<std::vector<QPromise<void>>>::exec();
|
|
||||||
}
|
|
@ -34,8 +34,12 @@ void tst_qpromise_delay::fulfilled()
|
|||||||
|
|
||||||
QCOMPARE(waitForValue(p, -1), 42);
|
QCOMPARE(waitForValue(p, -1), 42);
|
||||||
QCOMPARE(p.isFulfilled(), true);
|
QCOMPARE(p.isFulfilled(), true);
|
||||||
QVERIFY(elapsed >= 1000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to
|
|
||||||
QVERIFY(elapsed <= 1000 * 1.05); // keep accuracy within 5% of the desired interval.
|
// Qt::CoarseTimer (default) Coarse timers try to
|
||||||
|
// keep accuracy within 5% of the desired interval.
|
||||||
|
// Require accuracy within 6% for passing the test.
|
||||||
|
QVERIFY(elapsed >= 1000 * 0.94);
|
||||||
|
QVERIFY(elapsed <= 1000 * 1.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_qpromise_delay::rejected()
|
void tst_qpromise_delay::rejected()
|
||||||
@ -51,5 +55,5 @@ void tst_qpromise_delay::rejected()
|
|||||||
|
|
||||||
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
QCOMPARE(p.isRejected(), true);
|
QCOMPARE(p.isRejected(), true);
|
||||||
QVERIFY(elapsed < 5);
|
QVERIFY(elapsed <= 10);
|
||||||
}
|
}
|
||||||
|
4
tests/auto/qtpromise/qpromise/each/each.pro
Normal file
4
tests/auto/qtpromise/qpromise/each/each.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_each
|
||||||
|
SOURCES += $$PWD/tst_each.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
170
tests/auto/qtpromise/qpromise/each/tst_each.cpp
Normal file
170
tests/auto/qtpromise/qpromise/each/tst_each.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_qpromise_each : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void preserveValues();
|
||||||
|
void ignoreResult();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qpromise_each)
|
||||||
|
#include "tst_each.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QtPromise::qPromise(Sequence{42, 43, 44}).each([&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
}).each([&](int v, ...) {
|
||||||
|
values << v;
|
||||||
|
return QString("foo");
|
||||||
|
}).each([&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
return QPromise<QString>::resolve(QString("foo")).then([&](){
|
||||||
|
values << -1;
|
||||||
|
});
|
||||||
|
}).each([&](int v, ...) {
|
||||||
|
values << v + 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({42, 43, 44}));
|
||||||
|
|
||||||
|
QVector<int> expected{
|
||||||
|
0, 42, 1, 43, 2, 44,
|
||||||
|
42, 43, 44,
|
||||||
|
43, 44, 45,
|
||||||
|
-1, -1, -1,
|
||||||
|
44, 45, 46
|
||||||
|
};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_qpromise_each::emptySequence()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({}).each([&](int v, ...) {
|
||||||
|
values << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>());
|
||||||
|
QCOMPARE(values, QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::preserveValues()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::ignoreResult()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, ...) {
|
||||||
|
values << v + 1;
|
||||||
|
return "Foo";
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::delayedFulfilled()
|
||||||
|
{
|
||||||
|
QMap<int, int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, int index) {
|
||||||
|
return QPromise<void>::resolve().delay(250).then([=, &values]() {
|
||||||
|
values[v] = index;
|
||||||
|
return 42;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(values, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 44) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([](int v, ...) {
|
||||||
|
if (v == 44) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::functorArguments()
|
||||||
|
{
|
||||||
|
QVector<int> values;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).each([&](int v, int i) {
|
||||||
|
values << i << v;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 43, 44}));
|
||||||
|
QCOMPARE(values, QVector<int>({0, 42, 1, 43, 2, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_each::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
4
tests/auto/qtpromise/qpromise/filter/filter.pro
Normal file
4
tests/auto/qtpromise/qpromise/filter/filter.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_filter
|
||||||
|
SOURCES += $$PWD/tst_filter.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
152
tests/auto/qtpromise/qpromise/filter/tst_filter.cpp
Normal file
152
tests/auto/qtpromise/qpromise/filter/tst_filter.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_qpromise_filter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void filterValues();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void preserveOrder();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qpromise_filter)
|
||||||
|
#include "tst_filter.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(Sequence{
|
||||||
|
42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||||
|
}).filter([](int v, ...) {
|
||||||
|
return v > 42 && v < 51;
|
||||||
|
}).filter([](int, int i) {
|
||||||
|
return QPromise<bool>::resolve(i % 2 == 0);
|
||||||
|
}).filter([](int v, ...) {
|
||||||
|
return v != 45;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<Sequence>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, Sequence()), Sequence({43, 47, 49}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
|
||||||
|
void tst_qpromise_filter::emptySequence()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({}).filter([](int v, ...) {
|
||||||
|
return v % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::filterValues()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
|
||||||
|
return v % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::delayedFulfilled()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
|
||||||
|
return QPromise<bool>([&](const QPromiseResolve<bool>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
resolve(v % 2 == 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
|
||||||
|
return QPromise<bool>([&](
|
||||||
|
const QPromiseResolve<bool>& resolve,
|
||||||
|
const QPromiseReject<bool>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 43) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([](int v, ...) {
|
||||||
|
if (v == 43) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::functorArguments()
|
||||||
|
{
|
||||||
|
QMap<int, int> args;
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({42, 43, 44}).filter([&](int v, int i) {
|
||||||
|
args[v] = i;
|
||||||
|
return i % 2 == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 44}));
|
||||||
|
QMap<int, int> expected{{42, 0}, {43, 1}, {44, 2}};
|
||||||
|
QCOMPARE(args, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::preserveOrder()
|
||||||
|
{
|
||||||
|
auto p = QPromise<QVector<int>>::resolve({250, 50, 100, 400, 300}).filter([](int v, ...) {
|
||||||
|
return QPromise<bool>::resolve(v > 200).delay(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({250, 400, 300}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_filter::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
4
tests/auto/qtpromise/qpromise/map/map.pro
Normal file
4
tests/auto/qtpromise/qpromise/map/map.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_map
|
||||||
|
SOURCES += $$PWD/tst_map.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
157
tests/auto/qtpromise/qpromise/map/tst_map.cpp
Normal file
157
tests/auto/qtpromise/qpromise/map/tst_map.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_qpromise_map : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void emptySequence();
|
||||||
|
void modifyValues();
|
||||||
|
void convertValues();
|
||||||
|
void delayedFulfilled();
|
||||||
|
void delayedRejected();
|
||||||
|
void functorThrows();
|
||||||
|
void functorArguments();
|
||||||
|
void preserveOrder();
|
||||||
|
void sequenceTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qpromise_map)
|
||||||
|
#include "tst_map.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(Sequence{42, 43, 44}).map([](int v, ...) {
|
||||||
|
return QString::number(v + 1);
|
||||||
|
}).map([](const QString& v, int i) {
|
||||||
|
return QtPromise::qPromise(QString("%1:%2").arg(i).arg(v));
|
||||||
|
}).map([](const QString& v, ...) {
|
||||||
|
return QtPromise::qPromise((v + "!").toUtf8());
|
||||||
|
}).map([](const QByteArray& v, ...) {
|
||||||
|
return QString::fromUtf8(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"0:43!", "1:44!", "2:45!"}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_qpromise_map::emptySequence()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{}).map([](int v, ...) {
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::modifyValues()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::convertValues()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||||
|
return QString::number(v + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<QString>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<QString>()), QVector<QString>({"43", "44", "45"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::delayedFulfilled()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||||
|
return QPromise<int>([&](const QPromiseResolve<int>& resolve) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
resolve(v + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({43, 44, 45}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::delayedRejected()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||||
|
return QPromise<int>([&](
|
||||||
|
const QPromiseResolve<int>& resolve,
|
||||||
|
const QPromiseReject<int>& reject) {
|
||||||
|
QtPromisePrivate::qtpromise_defer([=]() {
|
||||||
|
if (v == 43) {
|
||||||
|
reject(QString("foo"));
|
||||||
|
}
|
||||||
|
resolve(v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::functorThrows()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{42, 43, 44}).map([](int v, ...) {
|
||||||
|
if (v == 43) {
|
||||||
|
throw QString("foo");
|
||||||
|
}
|
||||||
|
return v + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForError(p, QString()), QString("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::functorArguments()
|
||||||
|
{
|
||||||
|
auto p1 = QtPromise::qPromise(QVector<int>{42, 42, 42}).map([](int v, int i) {
|
||||||
|
return v * i;
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p1), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p1, QVector<int>()), QVector<int>({0, 42, 84}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::preserveOrder()
|
||||||
|
{
|
||||||
|
auto p = QtPromise::qPromise(QVector<int>{250, 500, 100}).map([](int v, ...) {
|
||||||
|
return QtPromise::qPromise(v + 1).delay(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int>>>::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({251, 501, 101}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_map::sequenceTypes()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<int>>::exec();
|
||||||
|
SequenceTester<QVector<int>>::exec();
|
||||||
|
SequenceTester<std::list<int>>::exec();
|
||||||
|
SequenceTester<std::vector<int>>::exec();
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
all \
|
|
||||||
construct \
|
construct \
|
||||||
delay \
|
delay \
|
||||||
|
each \
|
||||||
fail \
|
fail \
|
||||||
|
filter \
|
||||||
finally \
|
finally \
|
||||||
|
map \
|
||||||
operators \
|
operators \
|
||||||
reject \
|
|
||||||
resolve \
|
|
||||||
tap \
|
tap \
|
||||||
tapfail \
|
tapfail \
|
||||||
then \
|
then \
|
||||||
|
@ -87,6 +87,10 @@ void tst_qpromise_timeout::timeout()
|
|||||||
QCOMPARE(waitForValue(p, -1), -1);
|
QCOMPARE(waitForValue(p, -1), -1);
|
||||||
QCOMPARE(p.isRejected(), true);
|
QCOMPARE(p.isRejected(), true);
|
||||||
QCOMPARE(failed, true);
|
QCOMPARE(failed, true);
|
||||||
QVERIFY(elapsed >= 2000 * 0.95); // Qt::CoarseTimer (default) Coarse timers try to
|
|
||||||
QVERIFY(elapsed <= 2000 * 1.05); // keep accuracy within 5% of the desired interval.
|
// Qt::CoarseTimer (default) Coarse timers try to
|
||||||
|
// keep accuracy within 5% of the desired interval.
|
||||||
|
// Require accuracy within 6% for passing the test.
|
||||||
|
QVERIFY(elapsed >= 2000 * 0.94);
|
||||||
|
QVERIFY(elapsed <= 2000 * 1.06);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user