summaryrefslogtreecommitdiffstats
path: root/tests/clientapitest.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-01-31 17:32:45 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-01-31 19:38:57 +0100
commit546d86aae7cd0b9766f3a0ea73f3777334d55814 (patch)
tree58667b891038926e732e1b6fd9b50a8433bf465b /tests/clientapitest.cpp
parent871a048580d5a464fb697713a5e0e2c52dee5208 (diff)
downloadsink-546d86aae7cd0b9766f3a0ea73f3777334d55814.tar.gz
sink-546d86aae7cd0b9766f3a0ea73f3777334d55814.zip
A model stress test to try to crash the result emitter when used with
threads.
Diffstat (limited to 'tests/clientapitest.cpp')
-rw-r--r--tests/clientapitest.cpp59
1 files changed, 42 insertions, 17 deletions
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 @@
9#include "resultprovider.h" 9#include "resultprovider.h"
10#include "facadefactory.h" 10#include "facadefactory.h"
11#include "test.h" 11#include "test.h"
12#include "asyncutils.h"
12 13
13template <typename T> 14template <typename T>
14class TestDummyResourceFacade : public Sink::StoreFacade<T> 15class TestDummyResourceFacade : public Sink::StoreFacade<T>
@@ -53,38 +54,41 @@ public:
53 }; 54 };
54 QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr> load(const Sink::Query &query, const Sink::Log::Context &ctx) Q_DECL_OVERRIDE 55 QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename T::Ptr>::Ptr> load(const Sink::Query &query, const Sink::Log::Context &ctx) Q_DECL_OVERRIDE
55 { 56 {
56 auto resultProvider = new Sink::ResultProvider<typename T::Ptr>(); 57 auto resultProvider = QSharedPointer<Sink::ResultProvider<typename T::Ptr>>::create();
57 resultProvider->onDone([resultProvider,ctx]() { 58 resultProvider->onDone([resultProvider,ctx]() {
58 SinkTraceCtx(ctx) << "Result provider is done"; 59 SinkTraceCtx(ctx) << "Result provider is done";
59 delete resultProvider;
60 }); 60 });
61 // We have to do it this way, otherwise we're not setting the fetcher right 61 // We have to do it this way, otherwise we're not setting the fetcher right
62 auto emitter = resultProvider->emitter(); 62 auto emitter = resultProvider->emitter();
63 63
64 resultProvider->setFetcher([query, resultProvider, this, ctx](const typename T::Ptr &parent) { 64 resultProvider->setFetcher([query, resultProvider, this, ctx](const typename T::Ptr &parent) {
65 if (parent) { 65 async::run<int>([=] {
66 SinkTraceCtx(ctx) << "Running the fetcher " << parent->identifier(); 66 if (parent) {
67 } else { 67 SinkTraceCtx(ctx) << "Running the fetcher " << parent->identifier();
68 SinkTraceCtx(ctx) << "Running the fetcher."; 68 } else {
69 } 69 SinkTraceCtx(ctx) << "Running the fetcher.";
70 SinkTraceCtx(ctx) << "-------------------------.";
71 for (const auto &res : results) {
72 SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray();
73 auto parentProperty = res->getProperty("parent").toByteArray();
74 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) {
75 SinkTraceCtx(ctx) << "Found a hit" << res->identifier();
76 resultProvider->add(res);
77 } 70 }
78 } 71 SinkTraceCtx(ctx) << "-------------------------.";
79 resultProvider->initialResultSetComplete(parent, true); 72 for (const auto &res : results) {
73 // SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray();
74 auto parentProperty = res->getProperty("parent").toByteArray();
75 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) {
76 // SinkTraceCtx(ctx) << "Found a hit" << res->identifier();
77 resultProvider->add(res);
78 }
79 }
80 resultProvider->initialResultSetComplete(parent, true);
81 return 0;
82 }, runAsync).exec();
80 }); 83 });
81 auto job = KAsync::syncStart<void>([query, resultProvider]() {}); 84 auto job = KAsync::syncStart<void>([query, resultProvider]() {});
82 mResultProvider = resultProvider; 85 mResultProvider = resultProvider.data();
83 return qMakePair(job, emitter); 86 return qMakePair(job, emitter);
84 } 87 }
85 88
86 QList<typename T::Ptr> results; 89 QList<typename T::Ptr> results;
87 Sink::ResultProviderInterface<typename T::Ptr> *mResultProvider; 90 Sink::ResultProviderInterface<typename T::Ptr> *mResultProvider;
91 bool runAsync = false;
88}; 92};
89 93
90 94
@@ -280,6 +284,27 @@ private slots:
280 QVERIFY(!result.errorCode()); 284 QVERIFY(!result.errorCode());
281 QVERIFY(gotValue); 285 QVERIFY(gotValue);
282 } 286 }
287
288 void testModelStress()
289 {
290 auto facade = TestDummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade();
291 facade->runAsync = true;
292 for (int i = 0; i < 100; i++) {
293 facade->results << QSharedPointer<Sink::ApplicationDomain::Folder>::create("resource", "id" + QByteArray::number(i), 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create());
294 }
295 ResourceConfig::addResource("dummyresource.instance1", "dummyresource");
296
297 Sink::Query query;
298 query.resourceFilter("dummyresource.instance1");
299
300 for (int i = 0; i < 100; i++) {
301 auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query);
302 model->fetchMore(QModelIndex());
303 QTest::qWait(1);
304 }
305 QTest::qWait(100);
306 }
307
283}; 308};
284 309
285QTEST_MAIN(ClientAPITest) 310QTEST_MAIN(ClientAPITest)