[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [sink/develop] /: A model stress test to try to crash the result emitter when used with
From: Christian Mollekopf <null () kde ! org>
Date: 2017-01-31 19:33:31
Message-ID: E1cYeBH-0005xb-Jh () code ! kde ! org
[Download RAW message or body]
Git commit 546d86aae7cd0b9766f3a0ea73f3777334d55814 by Christian Mollekopf.
Committed on 31/01/2017 at 18:38.
Pushed by cmollekopf into branch 'develop'.
A model stress test to try to crash the result emitter when used with
threads.
M +16 -10 common/asyncutils.h
M +42 -17 tests/clientapitest.cpp
https://commits.kde.org/sink/546d86aae7cd0b9766f3a0ea73f3777334d55814
diff --git a/common/asyncutils.h b/common/asyncutils.h
index 2cf010e..6cbcee8 100644
--- a/common/asyncutils.h
+++ b/common/asyncutils.h
@@ -25,17 +25,23 @@
namespace async {
template <typename T>
-KAsync::Job<T> run(const std::function<T()> &f)
+KAsync::Job<T> run(const std::function<T()> &f, bool runAsync = true)
{
- return KAsync::start<T>([f](KAsync::Future<T> &future) {
- auto result = QtConcurrent::run(f);
- auto watcher = new QFutureWatcher<T>;
- watcher->setFuture(result);
- QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, [&future, \
watcher]() {
- future.setValue(watcher->future().result());
- delete watcher;
- future.setFinished();
+ if (runAsync) {
+ return KAsync::start<T>([f](KAsync::Future<T> &future) {
+ auto result = QtConcurrent::run(f);
+ auto watcher = new QFutureWatcher<T>;
+ watcher->setFuture(result);
+ QObject::connect(watcher, &QFutureWatcher<T>::finished, watcher, \
[&future, watcher]() { + future.setValue(watcher->future().result());
+ delete watcher;
+ future.setFinished();
+ });
});
- });
+ } else {
+ return KAsync::syncStart<T>([f]() {
+ return f();
+ });
+ }
}
}
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp
index 159789f..55fdcfc 100644
--- a/tests/clientapitest.cpp
+++ b/tests/clientapitest.cpp
@@ -9,6 +9,7 @@
#include "resultprovider.h"
#include "facadefactory.h"
#include "test.h"
+#include "asyncutils.h"
template <typename T>
class TestDummyResourceFacade : public Sink::StoreFacade<T>
@@ -53,38 +54,41 @@ public:
};
QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr> \
load(const Sink::Query &query, const Sink::Log::Context &ctx) Q_DECL_OVERRIDE {
- auto resultProvider = new Sink::ResultProvider<typename T::Ptr>();
+ auto resultProvider = QSharedPointer<Sink::ResultProvider<typename \
T::Ptr>>::create(); resultProvider->onDone([resultProvider,ctx]() {
SinkTraceCtx(ctx) << "Result provider is done";
- delete resultProvider;
});
// We have to do it this way, otherwise we're not setting the fetcher right
auto emitter = resultProvider->emitter();
resultProvider->setFetcher([query, resultProvider, this, ctx](const typename \
T::Ptr &parent) {
- if (parent) {
- SinkTraceCtx(ctx) << "Running the fetcher " << parent->identifier();
- } else {
- SinkTraceCtx(ctx) << "Running the fetcher.";
- }
- SinkTraceCtx(ctx) << "-------------------------.";
- for (const auto &res : results) {
- SinkTraceCtx(ctx) << "Parent filter " << \
query.getFilter("parent").value.toByteArray() << res->identifier() << \
res->getProperty("parent").toByteArray();
- auto parentProperty = res->getProperty("parent").toByteArray();
- if ((!parent && parentProperty.isEmpty()) || (parent && \
parentProperty == parent->identifier()) || \
query.parentProperty().isEmpty()) {
- SinkTraceCtx(ctx) << "Found a hit" << res->identifier();
- resultProvider->add(res);
+ async::run<int>([=] {
+ if (parent) {
+ SinkTraceCtx(ctx) << "Running the fetcher " << \
parent->identifier(); + } else {
+ SinkTraceCtx(ctx) << "Running the fetcher.";
}
- }
- resultProvider->initialResultSetComplete(parent, true);
+ SinkTraceCtx(ctx) << "-------------------------.";
+ for (const auto &res : results) {
+ // SinkTraceCtx(ctx) << "Parent filter " << \
query.getFilter("parent").value.toByteArray() << res->identifier() << \
res->getProperty("parent").toByteArray(); + auto parentProperty = \
res->getProperty("parent").toByteArray(); + if ((!parent && \
parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || \
query.parentProperty().isEmpty()) { + // SinkTraceCtx(ctx) << \
"Found a hit" << res->identifier(); + \
resultProvider->add(res); + }
+ }
+ resultProvider->initialResultSetComplete(parent, true);
+ return 0;
+ }, runAsync).exec();
});
auto job = KAsync::syncStart<void>([query, resultProvider]() {});
- mResultProvider = resultProvider;
+ mResultProvider = resultProvider.data();
return qMakePair(job, emitter);
}
QList<typename T::Ptr> results;
Sink::ResultProviderInterface<typename T::Ptr> *mResultProvider;
+ bool runAsync = false;
};
@@ -280,6 +284,27 @@ private slots:
QVERIFY(!result.errorCode());
QVERIFY(gotValue);
}
+
+ void testModelStress()
+ {
+ auto facade = \
TestDummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); + \
facade->runAsync = true; + for (int i = 0; i < 100; i++) {
+ facade->results << \
QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id" + \
QByteArray::number(i), 0, \
QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); + }
+ ResourceConfig::addResource("dummyresource.instance1", "dummyresource");
+
+ Sink::Query query;
+ query.resourceFilter("dummyresource.instance1");
+
+ for (int i = 0; i < 100; i++) {
+ auto model = \
Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query); + \
model->fetchMore(QModelIndex()); + QTest::qWait(1);
+ }
+ QTest::qWait(100);
+ }
+
};
QTEST_MAIN(ClientAPITest)
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic