void MemEventModelTest::deleteEvent()
{
    EventModel *model = new EventModel();

    Event event;

    event.setType(Event::IMEvent);
    event.setDirection(Event::Inbound);
    event.setGroupId(group.id());
    event.setStartTime(QDateTime::fromString("2009-08-26T09:37:47Z", Qt::ISODate));
    event.setEndTime(QDateTime::fromString("2009-08-26T09:37:47Z", Qt::ISODate));
    event.setLocalUid("/org/freedesktop/Telepathy/Account/gabble/jabber/dut_40localhost0");
    event.setRemoteUid("td@localhost");
    event.setFreeText("deletetest");

    QSignalSpy eventsCommitted(model, SIGNAL(eventsCommitted(const QList<CommHistory::Event>&, bool)));

    QVERIFY(model->addEvent(event));
    QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));

    QVERIFY(model->deleteEvent(event));
    QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));

    QTest::qWait(CALM_TIMEOUT);

    delete model;
}
void MemEventModelTest::addEvent()
{
    MALLINFO_DUMP("start");

    EventModel *model = new EventModel();

    MALLINFO_DUMP("model ready");

    Event e1;
    e1.setGroupId(group.id());
    e1.setType(Event::IMEvent);
    e1.setDirection(Event::Outbound);
    e1.setStartTime(QDateTime::fromString("2010-01-08T13:37:00Z", Qt::ISODate));
    e1.setEndTime(QDateTime::fromString("2010-01-08T13:37:00Z", Qt::ISODate));
    e1.setLocalUid("/org/freedesktop/Telepathy/Account/gabble/jabber/dut_40localhost0");
    e1.setRemoteUid("td@localhost");
    e1.setFreeText("addEvents 1");

    QVERIFY(model->addEvent(e1));
    QSignalSpy eventsCommitted(model, SIGNAL(eventsCommitted(const QList<CommHistory::Event>&, bool)));

    QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));

    QTest::qWait(CALM_TIMEOUT);

    MALLINFO_DUMP("query done");

    delete model;

    MALLINFO_DUMP("done");
}
bool  SyncModelTest::modifyEvent( int itemId, int parentId, int groupId, const QDateTime &lastModTime,
                                  const QString& localId, const QString& remoteId, const QString& text, bool read)
{
    Q_UNUSED(lastModTime);
    EventModel model;
    watcher.setModel(&model);
    Event e;
    e.setType(Event::SMSEvent);
    e.setId(itemId);
    e.setParentId(parentId);

    if (parentId == ::INBOX ||  parentId >= ::MYFOLDER) {
        e.setDirection(Event::Inbound);
    }  else {
        e.setDirection(Event::Outbound);
    }
    e.setGroupId(groupId);
    e.setLocalUid(localId);
    e.setRemoteUid(remoteId);
    e.setFreeText(text);
    e.setIsRead(read);

    bool    ret = model.modifyEvent(e);
    watcher.waitForSignals(1, 1);
    return ret;
}
void MemEventModelTest::modifyEvent()
{
    EventModel *model = new EventModel();

    Event im;
    im.setType(Event::IMEvent);
    im.setDirection(Event::Outbound);
    im.setGroupId(group.id());
    im.setStartTime(QDateTime::fromString("2009-08-26T09:37:47Z", Qt::ISODate));
    im.setEndTime(QDateTime::fromString("2009-08-26T09:37:47Z", Qt::ISODate));
    im.setLocalUid("/org/freedesktop/Telepathy/Account/gabble/jabber/dut_40localhost0");
    im.setRemoteUid("td@localhost");
    im.setFreeText("imtest");

    QSignalSpy eventsCommitted(model, SIGNAL(eventsCommitted(const QList<CommHistory::Event>&, bool)));
    QVERIFY(model->addEvent(im));

    QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));

    im.resetModifiedProperties();
    im.setFreeText("imtest \"q\" modified\t tabs");
    im.setStartTime(QDateTime::currentDateTime());
    im.setEndTime(QDateTime::currentDateTime());
    im.setIsRead(false);
    // should we actually test more properties?
    QVERIFY(model->modifyEvent(im));
    QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));

    QTest::qWait(CALM_TIMEOUT);

    delete model;
}
//Private functions
bool SyncModelTest::addEvent(int parentId, int groupId, const QDateTime& sentReceivedTime,
                             const QString& localId, const QString& remoteId, const QString& text, bool read)
{
    EventModel model;
    watcher.setModel(&model);
    Event e;
    e.setType(Event::SMSEvent);
    e.setParentId(parentId);

    if (parentId == ::INBOX ||  parentId >= ::MYFOLDER) {
        e.setDirection(Event::Inbound);
    }  else {
        e.setDirection(Event::Outbound);
    }
    e.setGroupId(groupId);
    e.setStartTime(sentReceivedTime);
    e.setEndTime(sentReceivedTime);
    e.setLocalUid(localId);
    e.setRemoteUid(remoteId);
    e.setFreeText(text);
    e.setIsRead(read);

    bool ret_val =  model.addEvent(e);
    watcher.waitForSignals(1, 1);
    itemId = e.id();
    return ret_val;
}
void MemEventModelTest::addEvents()
{
    MALLINFO_DUMP("start");

    MALLINFO_DUMP("model ready");
    int mem=0;
    int lastMem=0;

    for (int i = 0; i < 100; i++) {
        EventModel *model = new EventModel();
        Event e1;

        e1.setGroupId(group.id());
        e1.setType(Event::IMEvent);
        e1.setDirection(Event::Outbound);
        e1.setStartTime(QDateTime::fromString("2010-01-08T13:37:00Z", Qt::ISODate));
        e1.setEndTime(QDateTime::fromString("2010-01-08T13:37:00Z", Qt::ISODate));
        e1.setLocalUid("/org/freedesktop/Telepathy/Account/gabble/jabber/dut_40localhost0");
        e1.setRemoteUid("td@localhost");
        e1.setFreeText(QString("addEvents %1").arg(i));

        QVERIFY(model->addEvent(e1));
        QSignalSpy eventsCommitted(model, SIGNAL(eventsCommitted(const QList<CommHistory::Event>&, bool)));

        QVERIFY(waitSignal(eventsCommitted, WAIT_TIMEOUT));
        waitWithDeletes(100);

        delete model;

        waitWithDeletes(100);
        MALLINFO_DUMP("query done");
        struct mallinfo m = mallinfo();

        if (i >= 50)
            mem += m.uordblks - lastMem;
        lastMem = m.uordblks;
    }

    QTest::qWait(CALM_TIMEOUT);

    MALLINFO_DUMP("ALL DONE");

    qDebug() << "AVG LEAK" << mem/50;

    MALLINFO_DUMP("done");
}
int DeclarativeGroupManager::createOutgoingMessageEvent(int groupId, const QString &localUid,
                                                        const QString &remoteUid, const QString &text)
{
    if (groupId < 0) {
        // Try to find an appropriate group
        GroupObject *group = findGroup(localUid, remoteUid);
        if (group) {
            groupId = group->id();
        } else {
            Group g;
            g.setLocalUid(localUid);
            g.setRemoteUids(QStringList() << remoteUid);
            g.setChatType(Group::ChatTypeP2P);
            DEBUG() << Q_FUNC_INFO << "Creating group for" << localUid << remoteUid;
            if (!addGroup(g)) {
                qWarning() << Q_FUNC_INFO << "Failed creating group";
                return -1;
            }
            groupId = g.id();
        }
    }

    Event event;
    if (localUid.indexOf("/ring/tel/") >= 0)
        event.setType(Event::SMSEvent);
    else
        event.setType(Event::IMEvent);

    event.setDirection(Event::Outbound);
    event.setIsRead(true);
    event.setLocalUid(localUid);
    event.setRemoteUid(remoteUid);
    event.setFreeText(text);
    event.setStartTime(QDateTime::currentDateTime());
    event.setEndTime(event.startTime());
    event.setStatus(Event::SendingStatus);
    event.setGroupId(groupId);

    DEBUG() << Q_FUNC_INFO << groupId << localUid << remoteUid << text;
    EventModel model;
    if (model.addEvent(event))
        return event.id();

    qWarning() << Q_FUNC_INFO << "Failed creating event";
    return -1;
}
void ConversationModelTest::sorting()
{
    EventModel model;
    model.setQueryMode(EventModel::StreamedAsyncQuery);
    model.setFirstChunkSize(5);
    model.enableContactChanges(false);
    watcher.setModel(&model);

    //add events with the same timestamp
    QDateTime now = QDateTime::currentDateTime();
    QDateTime future = now.addSecs(10);

    addTestEvent(model, Event::SMSEvent, Event::Inbound, ACCOUNT1,
                 group1.id(), "I", false, false, now);
    addTestEvent(model, Event::SMSEvent, Event::Inbound, ACCOUNT1,
                 group1.id(), "II", false, false, now);
    addTestEvent(model, Event::SMSEvent, Event::Inbound, ACCOUNT1,
                 group1.id(), "III", false, false, future);
    addTestEvent(model, Event::SMSEvent, Event::Inbound, ACCOUNT1,
                 group1.id(), "IV", false, false, future);
    addTestEvent(model, Event::SMSEvent, Event::Inbound, ACCOUNT1,
                 group1.id(), "V", false, false, future);

    watcher.waitForSignals(5, 5);

    ConversationModel conv;
    conv.setQueryMode(EventModel::StreamedAsyncQuery);
    conv.setFirstChunkSize(5);
    conv.enableContactChanges(false);
    QSignalSpy rowsInserted(&conv, SIGNAL(rowsInserted(const QModelIndex &, int, int)));

    QVERIFY(conv.getEvents(group1.id()));

    QVERIFY(waitSignal(rowsInserted));

    QVERIFY(conv.rowCount() >= 5 );

    QCOMPARE(conv.event(conv.index(0, 0)).freeText(), QLatin1String("V"));
    QCOMPARE(conv.event(conv.index(1, 0)).freeText(), QLatin1String("IV"));
    QCOMPARE(conv.event(conv.index(2, 0)).freeText(), QLatin1String("III"));
    QCOMPARE(conv.event(conv.index(3, 0)).freeText(), QLatin1String("II"));
    QCOMPARE(conv.event(conv.index(4, 0)).freeText(), QLatin1String("I"));
}
Example #9
0
QString MmsHandler::messageNotification(const QString &imsi, const QString &from,
        const QString &subject, uint expiry, const QByteArray &data)
{
    Event event;
    event.setType(Event::MMSEvent);
    event.setStartTime(QDateTime::currentDateTime());
    event.setEndTime(event.startTime());
    event.setDirection(Event::Inbound);
    event.setLocalUid(RING_ACCOUNT_PATH);
    event.setRemoteUid(from);
    event.setSubject(subject);
    event.setExtraProperty("mms-notification-imsi", imsi);
    event.setExtraProperty("mms-expiry", expiry);
    event.setExtraProperty("mms-push-data", data.toBase64());

    bool manualDownload = isDataProhibited();
    event.setStatus(manualDownload ? Event::ManualNotificationStatus : Event::WaitingStatus);

    if (!setGroupForEvent(event)) {
        qCritical() << "Failed to handle group for MMS notification event; message dropped:" << event.toString();
        return QString();
    }

    EventModel model;
    if (!model.addEvent(event)) {
        qCritical() << "Failed to save MMS notification event; message dropped" << event.toString();
        return QString();
    }

    if (!manualDownload) {
        m_activeEvents.append(event.id());
    } else {
        // Show a notification when manual download is needed
        NotificationManager::instance()->showNotification(event, from, Group::ChatTypeP2P);
    }

    DEBUG() << "Created MMS notification event:" << event.toString();
    return manualDownload ? QString() : QString::number(event.id());
}
Example #10
0
int addTestEvent(EventModel &model,
                 Event::EventType type,
                 Event::EventDirection direction,
                 const QString &account,
                 int groupId,
                 const QString &text,
                 bool isDraft,
                 bool isMissedCall,
                 const QDateTime &when,
                 const QString &remoteUid,
                 bool toModelOnly,
                 const QString messageToken)
{
    Event event;
    event.setType(type);
    event.setDirection(direction);
    event.setGroupId(groupId);
    event.setStartTime(when);
    if (type == Event::CallEvent)
        event.setEndTime(when.addSecs(100));
    else
        event.setEndTime(event.startTime());
    event.setLocalUid(account);
    if (remoteUid.isEmpty()) {
        event.setRemoteUid(type == Event::SMSEvent ? "555123456" : "td@localhost");
    } else {
        event.setRemoteUid(remoteUid);
    }
    event.setFreeText(text);
    event.setIsDraft( isDraft );
    event.setIsMissedCall( isMissedCall );
    event.setMessageToken(messageToken);
    if (model.addEvent(event, toModelOnly)) {
        addedEventIds.insert(event.id());
        return event.id();
    }
    return -1;
}
Example #11
0
void Util::importSMS(QTextStream &in) {
    QString line;
    GroupModel groupModel;
    groupModel.enableContactChanges(false);
    groupModel.setQueryMode(EventModel::SyncQuery);
    QList<Event> events;
    int count = 0;
    int groupId;
    QMap<QString, int> phoneGroupMap;
    while (!(line = in.readLine()).isNull()) {
        count ++;
        std::cout << "Handling " << count << " messages" << std::endl;
        QStringList stringList = line.split(QChar(','));

        QString remoteUid = stringList.at(0);

        QString localUid = RING_ACCOUNT;

        QDateTime startTime = QDateTime::fromString(stringList.at(2), "yyyy-MM-dd hh:mm:ss");
        QDateTime endTime = startTime;

        if (!phoneGroupMap.contains(remoteUid)) {
            if (!groupModel.getGroups(RING_ACCOUNT, QString(remoteUid))) {
                std::cout << "Error getting groups!";
                return;
            } else {
                if (groupModel.rowCount() >= 1) {
                    groupId = groupModel.group(groupModel.index(0, 0)).id();
                } else {
                    // new group
                    Group group;
                    group.setLocalUid(localUid);
                    QStringList remoteUids;
                    remoteUids << remoteUid;
                    group.setRemoteUids(remoteUids);
                    if (!groupModel.addGroup(group)) {
                        qCritical() << "Error adding group";
                        return;
                    }
                    groupId = group.id();
                }
                phoneGroupMap.insert(remoteUid, groupId);
            }
        } else {
            groupId = phoneGroupMap[remoteUid];
        }

        Event::EventDirection direction = Event::UnknownDirection;
        if (stringList.at(1) == QString("1"))
            direction = Event::Inbound;
        else
            direction = Event::Outbound;

        Event e;
        e.setDirection(direction);
        e.setType(Event::SMSEvent);
        e.setLocalUid(localUid);
        e.setMessageToken(QUuid::createUuid().toString());

        e.setStartTime(startTime);
        e.setEndTime(endTime);
        e.setIsRead(true);
        e.setStatus(Event::DeliveredStatus);
        e.setBytesReceived(0);
        e.setGroupId(groupId);
        e.setRemoteUid(remoteUid);

        QString freeText = QStringList(stringList.mid(3)).join(QString(","));
        if (freeText.count(QChar('"')) % 2 != 0)
        {
            QString nextLine;
            while (!(nextLine = in.readLine()).isNull()) {
                freeText += "\n" + nextLine;
                if (nextLine.count(QChar('"')) % 2 != 0) {
                    break;
                }
            }
        }
        freeText = freeText.mid(1, freeText.length() - 2);
        freeText.replace(QString("\"\""), QChar('"'));
        e.setFreeText(freeText);

        events.append(e);

        std::cout << "Handled " << count << " messages" << std::endl;
    }
    if (events.count() > 0) {
        std::cout << "About to commit the changes" << std::endl;
        EventModel model;
        Catcher c(&model);
        if (!model.addEvents(events, false)) {
            qCritical() << "Error adding events";
            return;
        }

        c.waitCommit(events.count());
    }
    
}
void ConversationModelPerfTest::getEvents()
{
    QFETCH(int, messages);
    QFETCH(int, contacts);
    QFETCH(int, limit);

    qRegisterMetaType<QModelIndex>("QModelIndex");

    QDateTime startTime = QDateTime::currentDateTime();

    addTestGroups( group1, group2 );

    int commitBatchSize = 75;
    #ifdef PERF_BATCH_SIZE
    commitBatchSize = PERF_BATCH_SIZE;
    #endif

    EventModel addModel;
    QDateTime when = QDateTime::currentDateTime();
    QList<QString> remoteUids;

    qDebug() << __FUNCTION__ << "- Creating" << contacts << "new contacts";

    int ci = 0;
    while(ci < contacts) {
        ci++;
        QString phoneNumber = QString().setNum(qrand() % 10000000);
        remoteUids << phoneNumber;
        addTestContact(QString("Test Contact %1").arg(ci), phoneNumber);

        if(ci % commitBatchSize == 0 && ci < contacts) {
            qDebug() << __FUNCTION__ << "- adding" << commitBatchSize
                << "contacts (" << ci << "/" << contacts << ")";
            waitForIdle(5000);
        }
    }
    qDebug() << __FUNCTION__ << "- adding rest of the contacts ("
        << ci << "/" << contacts << ")";
    waitForIdle(5000);
    QTest::qWait(TIMEOUT);

    qDebug() << __FUNCTION__ << "- Creating" << messages << "new messages";

    QList<Event> eventList;

    int ei = 0;
    while(ei < messages) {
        ei++;

        Event::EventDirection direction;
        direction = qrand() % 2 > 0 ? Event::Inbound : Event::Outbound;

        Event e;
        e.setType(Event::SMSEvent);
        e.setDirection(direction);
        e.setGroupId(group1.id());
        e.setStartTime(when.addSecs(ei));
        e.setEndTime(when.addSecs(ei));
        e.setLocalUid(ACCOUNT1);
        e.setRemoteUid(remoteUids.at(0));
        e.setFreeText(randomMessage(qrand() % 49 + 1)); // Max 50 words / message
        e.setIsDraft(false);
        e.setIsMissedCall(false);

        eventList << e;

        if(ei % commitBatchSize == 0 && ei != messages) {
            qDebug() << __FUNCTION__ << "- adding" << commitBatchSize
                << "messages (" << ei << "/" << messages << ")";
            QVERIFY(addModel.addEvents(eventList, false));
            eventList.clear();
            waitForIdle();
        }
    }

    QVERIFY(addModel.addEvents(eventList, false));
    qDebug() << __FUNCTION__ << "- adding rest of the messages ("
        << ei << "/" << messages << ")";
    eventList.clear();
    waitForIdle();

    int iterations = 10;
    int sum = 0;
    QList<int> times;

    #ifdef PERF_ITERATIONS
    iterations = PERF_ITERATIONS;
    #endif

    char *iterVar = getenv("PERF_ITERATIONS");
    if (iterVar) {
        int iters = QString::fromAscii(iterVar).toInt();
        if (iters > 0) {
            iterations = iters;
        }
    }

    QTest::qWait(TIMEOUT);

    qDebug() << __FUNCTION__ << "- Fetching messages." << iterations << "iterations";
    for(int i = 0; i < iterations; i++) {

        ConversationModel fetchModel;
        bool result = false;

        QSignalSpy rowsInserted(&fetchModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)));

        if (limit < 0) {
            fetchModel.setQueryMode(EventModel::SyncQuery);
        } else {
            fetchModel.setQueryMode(EventModel::StreamedAsyncQuery);
            fetchModel.setFirstChunkSize(limit);
            fetchModel.setChunkSize(limit);
        }

        QTime time;
        time.start();
        result = fetchModel.getEvents(group1.id());

        if(limit >= 0) {
            while (time.elapsed() < 10000 && rowsInserted.isEmpty())
            QCoreApplication::processEvents();
        }

        int elapsed = time.elapsed();
        times << elapsed;
        sum += elapsed;
        qDebug("Time elapsed: %d ms", elapsed);

        QVERIFY(result);
        QVERIFY(fetchModel.rowCount() > 0);

        // With 1000 messages deleting model right away results in segfault
        waitForIdle();
    }

    if(logFile) {
        QTextStream out(logFile);

        out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << ": "
            << metaObject()->className() << "::" << QTest::currentTestFunction() << "("
            << QTest::currentDataTag() << ", " << iterations << " iterations)"
            << "\n";

        for (int i = 0; i < times.size(); i++) {
            out << times.at(i) << " ";
        }
        out << "\n";
    }

    qSort(times);
    float median = 0.0;
    if(iterations % 2 > 0) {
        median = times[(int)(iterations / 2)];
    } else {
        median = (times[iterations / 2] + times[iterations / 2 - 1]) / 2.0f;
    }

    float mean = sum / (float)iterations;
    int testSecs = startTime.secsTo(QDateTime::currentDateTime());

    qDebug("##### Mean: %.1f; Median: %.1f; Test time: %dsec", mean, median, testSecs);

    if(logFile) {
        QTextStream out(logFile);
        out << "Median average: " << (int)median << " ms. Test time: ";
        if (testSecs > 3600) { out << (testSecs / 3600) << "h "; }
        if (testSecs > 60) { out << ((testSecs % 3600) / 60) << "m "; }
        out << ((testSecs % 3600) % 60) << "s\n";
    }
}
void CallModelPerfTest::getEvents()
{
    QFETCH(int, events);
    QFETCH(int, contacts);

    QDateTime startTime = QDateTime::currentDateTime();

    int commitBatchSize = 75;
    #ifdef PERF_BATCH_SIZE
    commitBatchSize = PERF_BATCH_SIZE;
    #endif


    EventModel addModel;
    QDateTime when = QDateTime::currentDateTime();
    QList<QString> remoteUids;

    qDebug() << __FUNCTION__ << "- Creating" << contacts << "new contacts";

    int ci = 0;
    while(ci < contacts) {
        ci++;
        QString phoneNumber = QString().setNum(qrand() % 10000000);
        remoteUids << phoneNumber;
        addTestContact(QString("Test Contact %1").arg(ci), phoneNumber);

        if(ci % commitBatchSize == 0 && ci < contacts) {
            qDebug() << __FUNCTION__ << "- adding" << commitBatchSize
                << "contacts (" << ci << "/" << contacts << ")";
            waitForIdle(5000);
        }
    }
    qDebug() << __FUNCTION__ << "- adding rest of the contacts ("
        << ci << "/" << contacts << ")";

    waitForIdle(5000);
    QTest::qWait(TIMEOUT);

    qDebug() << __FUNCTION__ << "- Creating" << events << "new events";

    QList<Event> eventList;

    int ei = 0;
    while(ei < events) {
        ei++;

        Event::EventDirection direction;
        bool isMissed = false;

        if(qrand() % 2 > 0) {
            direction = Event::Inbound;
            isMissed = (qrand() % 2 > 0);
        } else {
            direction = Event::Outbound;
        }

        Event e;
        e.setType(Event::CallEvent);
        e.setDirection(direction);
        e.setGroupId(-1);
        e.setStartTime(when.addSecs(ei));
        e.setEndTime(when.addSecs(ei));
        e.setLocalUid(ACCOUNT1);
        e.setRemoteUid(remoteUids.at(qrand() % contacts));
        e.setFreeText("");
        e.setIsDraft(false);
        e.setIsMissedCall(isMissed);

        eventList << e;

        if(ei % commitBatchSize == 0 && ei != events) {
            qDebug() << __FUNCTION__ << "- adding" << commitBatchSize
                << "events (" << ei << "/" << events << ")";
            QVERIFY(addModel.addEvents(eventList, false));
            eventList.clear();
            waitForIdle();
        }
    }

    QVERIFY(addModel.addEvents(eventList, false));
    qDebug() << __FUNCTION__ << "- adding rest of the events ("
        << ei << "/" << events << ")";
    eventList.clear();
    waitForIdle();

    int iterations = 10;
    int sum = 0;
    QList<int> times;

    #ifdef PERF_ITERATIONS
    iterations = PERF_ITERATIONS;
    #endif

    char *iterVar = getenv("PERF_ITERATIONS");
    if (iterVar) {
        int iters = QString::fromAscii(iterVar).toInt();
        if (iters > 0) {
            iterations = iters;
        }
    }

    QTest::qWait(TIMEOUT);

    qDebug() << __FUNCTION__ << "- Fetching events." << iterations << "iterations";
    for(int i = 0; i < iterations; i++) {

        CallModel fetchModel;
        bool result = false;

        fetchModel.setQueryMode(EventModel::SyncQuery);
        fetchModel.setFilter(CallModel::SortByContact);

        QTime time;
        time.start();
        result = fetchModel.getEvents();
        int elapsed = time.elapsed();
        times << elapsed;
        sum += elapsed;
        qDebug("Time elapsed: %d ms", elapsed);

        QVERIFY(result);
        QVERIFY(fetchModel.rowCount() > 0);

        waitForIdle();
    }

    if(logFile) {
        QTextStream out(logFile);

        out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << ": "
            << metaObject()->className() << "::" << QTest::currentTestFunction() << "("
            << QTest::currentDataTag() << ", " << iterations << " iterations)"
            << "\n";

        for (int i = 0; i < times.size(); i++) {
            out << times.at(i) << " ";
        }
        out << "\n";
    }

    qSort(times);
    float median = 0.0;
    if(iterations % 2 > 0) {
        median = times[(int)(iterations / 2)];
    } else {
        median = (times[iterations / 2] + times[iterations / 2 - 1]) / 2.0f;
    }

    float mean = sum / (float)iterations;
    int testSecs = startTime.secsTo(QDateTime::currentDateTime());

    qDebug("##### Mean: %.1f; Median: %.1f; Test time: %dsec", mean, median, testSecs);

    if(logFile) {
        QTextStream out(logFile);
        out << "Median average: " << (int)median << " ms. Test time: ";
        if (testSecs > 3600) { out << (testSecs / 3600) << "h "; }
        if (testSecs > 60) { out << ((testSecs % 3600) / 60) << "m "; }
        out << ((testSecs % 3600) % 60) << "s\n";
    }
}