From b74e0adf3e376f668802767a20f8e1e66e932733 Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 14 Jul 2016 00:34:01 +0200 Subject: [PATCH] Add unittest for FolderTreeWidget. This includes testing for: - showing folders for the initial resources from the unittest env - creating resources, they should appear in the tree - creating a search folder, should create "Search / search123456" - deleting that search folder, both should disappear, and things shouldn't get corrupted (kitemmodels bug, fix pending, test disabled until KF 5.26) The dummykernel from src/filter/tests is moved up to autotests/ for sharing. --- CMakeLists.txt | 1 + autotests/CMakeLists.txt | 7 + .../tests => autotests}/dummykernel.cpp | 0 {src/filter/tests => autotests}/dummykernel.h | 0 autotests/foldertreewidgettest.cpp | 236 ++++++++++++++++++ autotests/unittestenv/config-sqlite-db.xml | 8 + .../akonadi/akonadiserverrc | 10 + .../unittestenv/xdgconfig/akonadi-firstrunrc | 4 + .../xdgconfig/akonadi_knut_resource_0rc | 4 + .../xdgconfig/akonadi_knut_resource_1rc | 4 + .../xdgconfig/akonadi_knut_resource_2rc | 4 + .../unittestenv/xdglocal/testdata-res1.xml | 4 + .../unittestenv/xdglocal/testdata-res2.xml | 4 + .../unittestenv/xdglocal/testdata-res3.xml | 4 + src/filter/tests/CMakeLists.txt | 2 +- src/filter/tests/kmfilterdialogtestgui.cpp | 2 +- 16 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 autotests/CMakeLists.txt rename {src/filter/tests => autotests}/dummykernel.cpp (100%) rename {src/filter/tests => autotests}/dummykernel.h (100%) create mode 100644 autotests/foldertreewidgettest.cpp create mode 100644 autotests/unittestenv/config-sqlite-db.xml create mode 100644 autotests/unittestenv/xdgconfig-sqlite.db/akonadi/akonadiserverrc create mode 100644 autotests/unittestenv/xdgconfig/akonadi-firstrunrc create mode 100644 autotests/unittestenv/xdgconfig/akonadi_knut_resource_0rc create mode 100644 autotests/unittestenv/xdgconfig/akonadi_knut_resource_1rc create mode 100644 autotests/unittestenv/xdgconfig/akonadi_knut_resource_2rc create mode 100644 autotests/unittestenv/xdglocal/testdata-res1.xml create mode 100644 autotests/unittestenv/xdglocal/testdata-res2.xml create mode 100644 autotests/unittestenv/xdglocal/testdata-res3.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a693a7..0ad7260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,5 +112,6 @@ install(FILES ) add_subdirectory(src) +add_subdirectory(autotests) install( FILES mailcommon.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt new file mode 100644 index 0000000..fa48fec --- /dev/null +++ b/autotests/CMakeLists.txt @@ -0,0 +1,7 @@ +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) +set(KDEPIMLIBS_RUN_ISOLATED_TESTS TRUE) +set(KDEPIMLIBS_RUN_SQLITE_ISOLATED_TESTS TRUE) + +add_akonadi_isolated_test(foldertreewidgettest.cpp) +target_link_libraries(foldertreewidgettest KF5::Mime KF5::AkonadiWidgets KF5::MailCommon) + diff --git a/src/filter/tests/dummykernel.cpp b/autotests/dummykernel.cpp similarity index 100% rename from src/filter/tests/dummykernel.cpp rename to autotests/dummykernel.cpp diff --git a/src/filter/tests/dummykernel.h b/autotests/dummykernel.h similarity index 100% rename from src/filter/tests/dummykernel.h rename to autotests/dummykernel.h diff --git a/autotests/foldertreewidgettest.cpp b/autotests/foldertreewidgettest.cpp new file mode 100644 index 0000000..9ba423f --- /dev/null +++ b/autotests/foldertreewidgettest.cpp @@ -0,0 +1,236 @@ +/* + Copyright (c) 2016 David Faure + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#undef QT_NO_CAST_FROM_ASCII + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "folder/entitycollectionorderproxymodel.h" +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "dummykernel.cpp" + +using namespace Akonadi; + +class FolderTreeWidgetTest : public QObject +{ + Q_OBJECT +public: + +private slots: + void initTestCase() + { + AkonadiTest::checkTestIsIsolated(); + + DummyKernel *kernel = new DummyKernel(0); + CommonKernel->registerKernelIf(kernel); + CommonKernel->registerSettingsIf(kernel); + + mFolderTreeWidget = new MailCommon::FolderTreeWidget(0); + const QStringList resourceOrder{"akonadi_knut_resource_2", "akonadi_knut_resource_0"}; // _1 isn't specified so it goes at the end + mFolderTreeWidget->entityOrderProxy()->setTopLevelOrder(resourceOrder); + + mCollectionModel = KernelIf->collectionModel(); + mTopModel = mFolderTreeWidget->folderTreeView()->model(); + + // One knut resource is already defined in the unittestenv, so that it's below "Search" in the ETM. + QTRY_COMPARE(mCollectionModel->rowCount(), 2); + QCOMPARE(mTopModel->rowCount(), 1); // Search doesn't appear yet + mFolderNames = QStringList{"res1"}; + QCOMPARE(collectNames(mTopModel), mFolderNames); + } + + void createAndDeleteSearchCollection() // testCreateResources must have been called before + { +#if KITEMMODELS_VERSION <= QT_VERSION_CHECK(5, 25, 0) + QSKIP("This test requires a fix in kitemmodels' KRecursiveFilterProxyModel"); +#endif +#ifdef SHOW_WIDGET + mFolderTreeWidget->resize(1000, 1000); + mFolderTreeWidget->show(); +#endif + + // Create search folder + Akonadi::SearchQuery query; + query.addTerm(Akonadi::SearchTerm(QStringLiteral("plugin"), 1)); + SearchCreateJob *create = new SearchCreateJob(QStringLiteral("search123456"), query, this); + create->setSearchMimeTypes({KMime::Message::mimeType()}); + create->setRemoteSearchEnabled(false); + AKVERIFYEXEC(create); + const Collection searchCol = create->createdCollection(); + QVERIFY(searchCol.isValid()); + + // Check it appeared in the tree, under a Search toplevel item + QTRY_COMPARE(mCollectionModel->rowCount(), 2); + QTRY_COMPARE(mTopModel->rowCount(), 2); + const QStringList names = collectNames(mTopModel); + QCOMPARE(names, QStringList() << "res1" << "Search"); + const int rowOfSearch = names.indexOf("Search"); + const QModelIndex searchParent = mTopModel->index(rowOfSearch, 0); + QCOMPARE(mTopModel->rowCount(searchParent), 1); // the actual child search folder + +#ifdef SHOW_WIDGET + QTest::qWait(500); +#endif + + QSignalSpy rATBRSpy_CollectionModel(mCollectionModel, &QAbstractItemModel::rowsAboutToBeRemoved); + QSignalSpy rATBRSpy_FolderTreeProxyModel(mFolderTreeWidget->folderTreeWidgetProxyModel(), &QAbstractItemModel::rowsAboutToBeRemoved); + QSignalSpy rATBRSpy_TopModel(mTopModel, &QAbstractItemModel::rowsAboutToBeRemoved); + + // Now delete it + Akonadi::CollectionDeleteJob *delJob = new Akonadi::CollectionDeleteJob(searchCol); + AKVERIFYEXEC(delJob); + + // Check it disappeared from the tree, as well as the toplevel item + QTRY_COMPARE(mTopModel->rowCount(), 1); + QCOMPARE(collectNames(mTopModel), mFolderNames); + QCOMPARE(collectNames(mFolderTreeWidget->entityOrderProxy()), mFolderNames); + + QCOMPARE(rATBRSpy_CollectionModel.count(), 2); // one for the child, one for the parent + QCOMPARE(rATBRSpy_FolderTreeProxyModel.count(), 2); // one for the child, one for the parent + QCOMPARE(rATBRSpy_TopModel.count(), 2); // one for the child, one for the parent + + checkMailFolders(mTopModel->index(0, 0)); + +#ifdef SHOW_WIDGET + QTest::qWait(1000); +#endif + } + + void testCreateResources() + { + // Test creating more knut resources. + // This tests that ETM and proxies on top update correctly, and it tests toplevel collection order. + const QVector numFolders{ 1, 5, 2 }; + QVector topLevelCollections; + const AgentType agentType = AgentManager::self()->type(QStringLiteral("akonadi_knut_resource")); + QVERIFY(agentType.isValid()); + mFolderNames = QStringList{"res3", "res1", "res2"}; // according to resourceOrder above (the folder names are defined in testdata-res*.xml) + + // Create resources + const int numResources = numFolders.count(); + for (int i = 1 /*first one already created*/ ; i < numResources ; ++i ) { + AgentInstanceCreateJob *agentCreateJob = new AgentInstanceCreateJob(agentType); + AKVERIFYEXEC(agentCreateJob); + const QString identifier = agentCreateJob->instance().identifier(); + + QTRY_COMPARE(mCollectionModel->rowCount(), i + 1); + QTRY_COMPARE(mTopModel->rowCount(), i + 1); + + Collection topLevelCollection; + QTRY_VERIFY((topLevelCollection = topLevelCollectionForResource(identifier)).isValid()); + topLevelCollections.append(topLevelCollection); + + // Now create some folders + for (int number = 0 ; number < numFolders[i] ; ++number) { + Collection mailCollection; + mailCollection.setParentCollection(topLevelCollection); + mailCollection.setName(QStringLiteral("mailCollection_%1_%2").arg(i).arg(number)); + CollectionCreateJob *collCreateJob = new CollectionCreateJob(mailCollection); + AKVERIFYEXEC(collCreateJob); + } + const int resourceRow = collectNames(mTopModel).indexOf("res" + QString::number(i+1)); + QModelIndex parent = mTopModel->index(resourceRow, 0); + QTRY_COMPARE(mTopModel->rowCount(parent), numFolders[i]); + + checkMailFolders(parent); + } + QCOMPARE(collectNames(mTopModel), mFolderNames); + } + +private: + static Collection topLevelCollectionForResource(const QString &identifier) + { + // Find out the collection for the resource (as defined in unittestenv/xdglocal/testdata-res*.xml) + CollectionFetchJob *job = new CollectionFetchJob(Collection::root(), CollectionFetchJob::FirstLevel); + if (job->exec()) { + const Collection::List collections = job->collections(); + foreach (const Collection &col, collections) { + //qDebug() << col.resource() << col.mimeType(); + if (col.resource() == identifier) { + return col; + } + } + } else { + qWarning() << job->errorString(); + } + return Collection(); + } + + // Check that every child of @p parent has a valid CollectionRole. + static void checkMailFolders(const QModelIndex &parent) + { + const QAbstractItemModel *model = parent.model(); + for (int row = 0; row < model->rowCount(parent); ++row) { + QModelIndex idx = model->index(row, 0, parent); + QModelIndex col1idx = model->index(row, 1, parent); + QCOMPARE(col1idx.sibling(col1idx.row(), 0), idx); + Collection collection = idx.data(EntityTreeModel::CollectionRole).value(); + QVERIFY2(collection.isValid(), qPrintable(idx.data().toString())); + } + } + + + static QStringList collectNames(QAbstractItemModel *model); + EntityMimeTypeFilterModel *mCollectionModel; + QAbstractItemModel *mTopModel; + MailCommon::FolderTreeWidget *mFolderTreeWidget; + QStringList mFolderNames; +}; + + +QStringList FolderTreeWidgetTest::collectNames(QAbstractItemModel *model) +{ + QStringList ret; + for (int row = 0 ; row < model->rowCount() ; ++row) { + ret.append(model->index(row, 0).data().toString()); + } + return ret; +} + +QTEST_AKONADIMAIN(FolderTreeWidgetTest) + +#include "foldertreewidgettest.moc" diff --git a/autotests/unittestenv/config-sqlite-db.xml b/autotests/unittestenv/config-sqlite-db.xml new file mode 100644 index 0000000..c36076f --- /dev/null +++ b/autotests/unittestenv/config-sqlite-db.xml @@ -0,0 +1,8 @@ + + kdehome + xdgconfig-sqlite.db + xdglocal + akonadi_knut_resource + true + sqlite + diff --git a/autotests/unittestenv/xdgconfig-sqlite.db/akonadi/akonadiserverrc b/autotests/unittestenv/xdgconfig-sqlite.db/akonadi/akonadiserverrc new file mode 100644 index 0000000..33e7f81 --- /dev/null +++ b/autotests/unittestenv/xdgconfig-sqlite.db/akonadi/akonadiserverrc @@ -0,0 +1,10 @@ +[%General] +# This is a slightly adjusted version of the QSQLITE driver from Qt +# It is provided by akonadi itself +Driver=QSQLITE3 + +[Debug] +Tracer=null + +[Search] +Manager=Dummy diff --git a/autotests/unittestenv/xdgconfig/akonadi-firstrunrc b/autotests/unittestenv/xdgconfig/akonadi-firstrunrc new file mode 100644 index 0000000..c5e90d8 --- /dev/null +++ b/autotests/unittestenv/xdgconfig/akonadi-firstrunrc @@ -0,0 +1,4 @@ +[ProcessedDefaults] +defaultaddressbook=done +defaultcalendar=done +defaultnotebook=done diff --git a/autotests/unittestenv/xdgconfig/akonadi_knut_resource_0rc b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_0rc new file mode 100644 index 0000000..0d9e3cf --- /dev/null +++ b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_0rc @@ -0,0 +1,4 @@ +[General] +DataFile[$e]=$XDG_DATA_HOME/testdata-res1.xml +FileWatchingEnabled=false + diff --git a/autotests/unittestenv/xdgconfig/akonadi_knut_resource_1rc b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_1rc new file mode 100644 index 0000000..05b752e --- /dev/null +++ b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_1rc @@ -0,0 +1,4 @@ +[General] +DataFile[$e]=$XDG_DATA_HOME/testdata-res2.xml +FileWatchingEnabled=false + diff --git a/autotests/unittestenv/xdgconfig/akonadi_knut_resource_2rc b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_2rc new file mode 100644 index 0000000..85773a4 --- /dev/null +++ b/autotests/unittestenv/xdgconfig/akonadi_knut_resource_2rc @@ -0,0 +1,4 @@ +[General] +DataFile[$e]=$XDG_DATA_HOME/testdata-res3.xml +FileWatchingEnabled=false + diff --git a/autotests/unittestenv/xdglocal/testdata-res1.xml b/autotests/unittestenv/xdglocal/testdata-res1.xml new file mode 100644 index 0000000..100336f --- /dev/null +++ b/autotests/unittestenv/xdglocal/testdata-res1.xml @@ -0,0 +1,4 @@ + + + + diff --git a/autotests/unittestenv/xdglocal/testdata-res2.xml b/autotests/unittestenv/xdglocal/testdata-res2.xml new file mode 100644 index 0000000..3673c33 --- /dev/null +++ b/autotests/unittestenv/xdglocal/testdata-res2.xml @@ -0,0 +1,4 @@ + + + + diff --git a/autotests/unittestenv/xdglocal/testdata-res3.xml b/autotests/unittestenv/xdglocal/testdata-res3.xml new file mode 100644 index 0000000..916ef47 --- /dev/null +++ b/autotests/unittestenv/xdglocal/testdata-res3.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/filter/tests/CMakeLists.txt b/src/filter/tests/CMakeLists.txt index 47c4cdb..620126b 100644 --- a/src/filter/tests/CMakeLists.txt +++ b/src/filter/tests/CMakeLists.txt @@ -30,7 +30,7 @@ target_link_libraries(mndadvicedialoggui ) -set(kmfilterdialogtestgui_SRCS kmfilterdialogtestgui.cpp dummykernel.cpp) +set(kmfilterdialogtestgui_SRCS kmfilterdialogtestgui.cpp ../../../autotests/dummykernel.cpp) add_executable(kmfilterdialogtestgui ${kmfilterdialogtestgui_SRCS}) ecm_mark_as_test(kmfilterdialogtestgui) target_link_libraries(kmfilterdialogtestgui diff --git a/src/filter/tests/kmfilterdialogtestgui.cpp b/src/filter/tests/kmfilterdialogtestgui.cpp index 748e1af..866b703 100644 --- a/src/filter/tests/kmfilterdialogtestgui.cpp +++ b/src/filter/tests/kmfilterdialogtestgui.cpp @@ -16,7 +16,7 @@ */ #include "kmfilterdialogtestgui.h" -#include "dummykernel.h" +#include "../../../autotests/dummykernel.h" #include "../kernel/mailkernel.h" #include "../kmfilterdialog.h"