diff --git a/akonadi/collectionutils_p.h b/akonadi/collectionutils_p.h index 19279de9c..5070e84d3 100644 --- a/akonadi/collectionutils_p.h +++ b/akonadi/collectionutils_p.h @@ -1,90 +1,99 @@ /* Copyright (c) 2008 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COLLECTIONUTILS_P_H #define AKONADI_COLLECTIONUTILS_P_H #include namespace Akonadi { /** * @internal */ namespace CollectionUtils { inline bool isVirtualParent( const Collection &collection ) { return (collection.parentCollection() == Collection::root() && collection.resource() == QLatin1String( "akonadi_search_resource" )); } inline bool isVirtual( const Collection &collection ) { return (collection.resource() == QLatin1String( "akonadi_search_resource" )); } inline bool isResource( const Collection &collection ) { return (collection.parentCollection() == Collection::root()); } inline bool isStructural( const Collection &collection ) { return collection.contentMimeTypes().isEmpty(); } inline bool isFolder( const Collection &collection ) { return (collection.parentCollection() != Collection::root() && collection.resource() != QLatin1String( "akonadi_search_resource" ) && !collection.contentMimeTypes().isEmpty()); } inline QString defaultIconName( const Collection &col ) { if ( CollectionUtils::isVirtualParent( col ) ) return QLatin1String( "edit-find" ); if ( CollectionUtils::isVirtual( col ) ) return QLatin1String( "document-preview" ); if ( CollectionUtils::isResource( col ) ) return QLatin1String( "network-server" ); if ( CollectionUtils::isStructural( col ) ) return QLatin1String( "folder-grey" ); const QStringList content = col.contentMimeTypes(); if ( content.size() == 1 || (content.size() == 2 && content.contains( Collection::mimeType() )) ) { if ( content.contains( QLatin1String( "text/x-vcard" ) ) || content.contains( QLatin1String( "text/directory" ) ) || content.contains( QLatin1String( "text/vcard" ) ) ) return QLatin1String( "x-office-address-book" ); // TODO: add all other content types and/or fix their mimetypes if ( content.contains( QLatin1String( "akonadi/event" ) ) || content.contains( QLatin1String( "text/ical" ) ) ) return QLatin1String( "view-pim-calendar" ); if ( content.contains( QLatin1String( "akonadi/task" ) ) ) return QLatin1String( "view-pim-tasks" ); } else if ( content.isEmpty() ) { return QLatin1String( "folder-grey" ); } return QLatin1String( "folder" ); } + + inline bool hasValidHierarchicalRID( const Collection &col ) + { + if ( col == Collection::root() ) + return true; + if ( col.remoteId().isEmpty() ) + return false; + return hasValidHierarchicalRID( col.parentCollection() ); + } } } #endif diff --git a/akonadi/protocolhelper.cpp b/akonadi/protocolhelper.cpp index 6a40163f3..a51686ada 100644 --- a/akonadi/protocolhelper.cpp +++ b/akonadi/protocolhelper.cpp @@ -1,253 +1,263 @@ /* Copyright (c) 2008 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "protocolhelper_p.h" #include "attributefactory.h" #include "collectionstatistics.h" #include "exception.h" #include #include #include #include #include #include #include using namespace Akonadi; int ProtocolHelper::parseCachePolicy(const QByteArray & data, CachePolicy & policy, int start) { QVarLengthArray params; int end = Akonadi::ImapParser::parseParenthesizedList( data, params, start ); for ( int i = 0; i < params.count() - 1; i += 2 ) { const QByteArray key = params[i]; const QByteArray value = params[i + 1]; if ( key == "INHERIT" ) policy.setInheritFromParent( value == "true" ); else if ( key == "INTERVAL" ) policy.setIntervalCheckTime( value.toInt() ); else if ( key == "CACHETIMEOUT" ) policy.setCacheTimeout( value.toInt() ); else if ( key == "SYNCONDEMAND" ) policy.setSyncOnDemand( value == "true" ); else if ( key == "LOCALPARTS" ) { QVarLengthArray tmp; QStringList parts; Akonadi::ImapParser::parseParenthesizedList( value, tmp ); for ( int j=0; j ancestors; ImapParser::parseParenthesizedList( data, ancestors ); Entity* current = entity; foreach ( const QByteArray &uidRidPair, ancestors ) { QList parentIds; ImapParser::parseParenthesizedList( uidRidPair, parentIds ); if ( parentIds.size() != 2 ) break; const Collection::Id uid = parentIds.at( 0 ).toLongLong(); const QString rid = QString::fromUtf8( parentIds.at( 1 ) ); if ( uid == Collection::root().id() ) { current->setParentCollection( Collection::root() ); break; } current->parentCollection().setId( uid ); current->parentCollection().setRemoteId( rid ); current = ¤t->parentCollection(); } } int ProtocolHelper::parseCollection(const QByteArray & data, Collection & collection, int start) { int pos = start; // collection and parent id Collection::Id colId = -1; bool ok = false; pos = ImapParser::parseNumber( data, colId, &ok, pos ); if ( !ok || colId <= 0 ) { kDebug() << "Could not parse collection id from response:" << data; return start; } Collection::Id parentId = -1; pos = ImapParser::parseNumber( data, parentId, &ok, pos ); if ( !ok || parentId < 0 ) { kDebug() << "Could not parse parent id from response:" << data; return start; } collection = Collection( colId ); collection.setParentCollection( Collection( parentId ) ); // attributes QVarLengthArray attributes; pos = ImapParser::parseParenthesizedList( data, attributes, pos ); for ( int i = 0; i < attributes.count() - 1; i += 2 ) { const QByteArray key = attributes[i]; const QByteArray value = attributes[i + 1]; if ( key == "NAME" ) { collection.setName( QString::fromUtf8( value ) ); } else if ( key == "REMOTEID" ) { collection.setRemoteId( QString::fromUtf8( value ) ); } else if ( key == "RESOURCE" ) { collection.setResource( QString::fromUtf8( value ) ); } else if ( key == "MIMETYPE" ) { QVarLengthArray ct; ImapParser::parseParenthesizedList( value, ct ); QStringList ct2; for ( int j = 0; j < ct.size(); j++ ) ct2 << QString::fromLatin1( ct[j] ); collection.setContentMimeTypes( ct2 ); } else if ( key == "MESSAGES" ) { CollectionStatistics s = collection.statistics(); s.setCount( value.toLongLong() ); collection.setStatistics( s ); } else if ( key == "UNSEEN" ) { CollectionStatistics s = collection.statistics(); s.setUnreadCount( value.toLongLong() ); collection.setStatistics( s ); } else if ( key == "SIZE" ) { CollectionStatistics s = collection.statistics(); s.setSize( value.toLongLong() ); collection.setStatistics( s ); } else if ( key == "CACHEPOLICY" ) { CachePolicy policy; ProtocolHelper::parseCachePolicy( value, policy ); collection.setCachePolicy( policy ); } else if ( key == "ANCESTORS" ) { parseAncestors( value, &collection ); } else { Attribute* attr = AttributeFactory::createAttribute( key ); Q_ASSERT( attr ); attr->deserialize( value ); collection.addAttribute( attr ); } } return pos; } QByteArray ProtocolHelper::attributesToByteArray(const Entity & entity, bool ns ) { QList l; foreach ( const Attribute *attr, entity.attributes() ) { l << encodePartIdentifier( ns ? PartAttribute : PartGlobal, attr->type() ); l << ImapParser::quote( attr->serialized() ); } return ImapParser::join( l, " " ); } QByteArray ProtocolHelper::encodePartIdentifier(PartNamespace ns, const QByteArray & label, int version ) { const QByteArray versionString( version != 0 ? '[' + QByteArray::number( version ) + ']' : "" ); switch ( ns ) { case PartGlobal: return label + versionString; case PartPayload: return "PLD:" + label + versionString; case PartAttribute: return "ATR:" + label + versionString; default: Q_ASSERT( false ); } return QByteArray(); } QByteArray ProtocolHelper::decodePartIdentifier( const QByteArray &data, PartNamespace & ns ) { if ( data.startsWith( "PLD:" ) ) { //krazy:exclude=strings ns = PartPayload; return data.mid( 4 ); } else if ( data.startsWith( "ATR:" ) ) { //krazy:exclude=strings ns = PartAttribute; return data.mid( 4 ); } else { ns = PartGlobal; return data; } } QByteArray ProtocolHelper::itemSetToByteArray( const Item::List &_items, const QByteArray &command ) { if ( _items.isEmpty() ) throw Exception( "No items specified" ); Item::List items( _items ); QByteArray rv; std::sort( items.begin(), items.end(), boost::bind( &Item::id, _1 ) < boost::bind( &Item::id, _2 ) ); if ( items.first().isValid() ) { // all items have a uid set rv += " " AKONADI_CMD_UID " "; rv += command; rv += ' '; QList uids; foreach ( const Item &item, items ) uids << item.id(); ImapSet set; set.add( uids ); rv += set.toImapSequenceSet(); } else { // check if all items have a remote id QList rids; foreach ( const Item &item, items ) { if ( item.remoteId().isEmpty() ) throw Exception( i18n( "No remote identifier specified" ) ); rids << ImapParser::quote( item.remoteId().toUtf8() ); } rv += " " AKONADI_CMD_RID " "; rv += command; rv += " ("; rv += ImapParser::join( rids, " " ); rv += ')'; } return rv; } + +QByteArray ProtocolHelper::hierarchicalRidToByteArray( const Collection &col ) +{ + if ( col == Collection::root() ) + return QByteArray("(0 \"\")"); + if ( col.remoteId().isEmpty() ) + return QByteArray(); + const QByteArray parentHrid = hierarchicalRidToByteArray( col.parentCollection() ); + return '(' + QByteArray::number( col.id() ) + ' ' + ImapParser::quote( col.remoteId().toUtf8() ) + ") " + parentHrid; +} diff --git a/akonadi/protocolhelper_p.h b/akonadi/protocolhelper_p.h index c64767234..b87819774 100644 --- a/akonadi/protocolhelper_p.h +++ b/akonadi/protocolhelper_p.h @@ -1,99 +1,105 @@ /* Copyright (c) 2008 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_PROTOCOLHELPER_P_H #define AKONADI_PROTOCOLHELPER_P_H #include #include #include namespace Akonadi { /** @internal Helper methods for converting between libakonadi objects and their protocol representation. @todo Add unit tests for this. @todo Use exceptions for a useful error handling */ class ProtocolHelper { public: /** Part namespaces. */ enum PartNamespace { PartGlobal, PartPayload, PartAttribute }; /** Parse a cache policy definition. @param data The input data. @param policy The parsed cache policy. @param start Start of the data, ie. postion after the label. @returns Position in data after the cache policy description. */ static int parseCachePolicy( const QByteArray &data, CachePolicy &policy, int start = 0 ); /** Convert a cache policy object into its protocol representation. */ static QByteArray cachePolicyToByteArray( const CachePolicy &policy ); /** Convert a ancestor chain from its protocol representation into an Entity object. */ static void parseAncestors( const QByteArray &data, Entity *entity, int start = 0 ); /** Parse a collection description. @param data The input data. @param collection The parsed collection. @param start Start of the data. @returns Position in data after the collection description. */ static int parseCollection( const QByteArray &data, Collection &collection, int start = 0 ); /** Convert attributes to their protocol representation. */ static QByteArray attributesToByteArray( const Entity &entity, bool ns = false ); /** Encodes part label and namespace. */ static QByteArray encodePartIdentifier( PartNamespace ns, const QByteArray &label, int version = 0 ); /** Decode part label and namespace. */ static QByteArray decodePartIdentifier( const QByteArray &data, PartNamespace &ns ); /** Converts the given set of items into a protocol representation. @throws A Akonadi::Exception if the item set contains items with missing/invalid identifiers. */ static QByteArray itemSetToByteArray( const Item::List &items, const QByteArray &command ); + + /** + Converts the given collection's hierarchical RID into a protocol representation. + Assumes @p col has a valid hierarchical RID, so check that before! + */ + static QByteArray hierarchicalRidToByteArray( const Collection &col ); }; } #endif diff --git a/akonadi/tests/CMakeLists.txt b/akonadi/tests/CMakeLists.txt index 2d7576566..a7d3538db 100644 --- a/akonadi/tests/CMakeLists.txt +++ b/akonadi/tests/CMakeLists.txt @@ -1,129 +1,130 @@ if(${EXECUTABLE_OUTPUT_PATH}) set( PREVIOUS_EXEC_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH} ) else(${EXECUTABLE_OUTPUT_PATH}) set( PREVIOUS_EXEC_OUTPUT_PATH . ) endif(${EXECUTABLE_OUTPUT_PATH}) set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) include_directories( ${CMAKE_SOURCE_DIR}/akonadi ${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../ ${Boost_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR}/akonadi/private ) # add testrunner (application for managing a self-contained test # environment) add_subdirectory(testrunner) # add benchmarker add_subdirectory(benchmarker) # convenience macro to add akonadi demo application macro(add_akonadi_demo _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_executable(${_name} TEST ${_test}) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS}) endmacro(add_akonadi_demo) # convenience macro to add akonadi qtestlib unit-tests macro(add_akonadi_test _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_unit_test(${_name} TESTNAME akonadi-${_name} ${_test} fakesession.cpp fakemonitor.cpp fakeserver.cpp) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) endmacro(add_akonadi_test) # convenience macro to add akonadi testrunner unit-tests macro(add_akonadi_isolated_test _source) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) kde4_add_executable(${_name} TEST ${_test}) target_link_libraries(${_name} akonadi-kde akonadi-kmime ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) # based on kde4_add_unit_test if (WIN32) get_target_property( _loc ${_name} LOCATION ) set(_executable ${_loc}.bat) set(_testrunner ${PREVIOUS_EXEC_OUTPUT_PATH}/akonaditest.bat) else (WIN32) set(_executable ${EXECUTABLE_OUTPUT_PATH}/${_name}) set(_testrunner ${PREVIOUS_EXEC_OUTPUT_PATH}/akonaditest) endif (WIN32) if (UNIX) set(_executable ${_executable}.shell) set(_testrunner ${_testrunner}.shell) endif (UNIX) add_test( akonadi-mysql-db-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-mysql-db.xml ${_executable} ) add_test( akonadi-mysql-fs-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-mysql-fs.xml ${_executable} ) #add_test( akonadi-postgresql-fs-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-postgresql-fs.xml ${_executable} ) #add_test( akonadi-postgresql-fs-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-postgresql-fs.xml ${_executable} ) #add_test( akonadi-sqlite-${_name} ${_testrunner} -c ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config-sqlite.xml ${_executable} ) endmacro(add_akonadi_isolated_test) # demo applications add_akonadi_demo(itemdumper.cpp) add_akonadi_demo(subscriber.cpp) add_akonadi_demo(headfetcher.cpp) add_akonadi_demo(agentinstancewidgettest.cpp) add_akonadi_demo(agenttypewidgettest.cpp) add_akonadi_demo(pluginloadertest.cpp) add_akonadi_demo(selftester.cpp) kde4_add_executable( akonadi-firstrun TEST ../firstrun.cpp firstrunner.cpp ) target_link_libraries( akonadi-firstrun akonadi-kde ${KDE4_KDEUI_LIBS} ) # qtestlib unit tests add_akonadi_test(imapparsertest.cpp) add_akonadi_test(imapsettest.cpp) add_akonadi_test(itemhydratest.cpp) add_akonadi_test(itemtest.cpp) add_akonadi_test(itemserializertest.cpp) add_akonadi_test(mimetypecheckertest.cpp) add_akonadi_test(protocolhelpertest.cpp) add_akonadi_test(entitytreemodeltest.cpp) +add_akonadi_test(collectionutilstest.cpp) # qtestlib tests that need non-exported stuff from akonadi-kde kde4_add_unit_test(resourceschedulertest TESTNAME akonadi-resourceschedulertest resourceschedulertest.cpp ../resourcescheduler.cpp) target_link_libraries(resourceschedulertest akonadi-kde ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDECORE_LIBS} ${AKONADI_COMMON_LIBRARIES}) # testrunner tests add_akonadi_isolated_test(testenvironmenttest.cpp) add_akonadi_isolated_test(autoincrementtest.cpp) add_akonadi_isolated_test(attributefactorytest.cpp) add_akonadi_isolated_test(collectionjobtest.cpp) add_akonadi_isolated_test(collectionpathresolvertest.cpp) add_akonadi_isolated_test(collectionattributetest.cpp) add_akonadi_isolated_test(itemfetchtest.cpp) add_akonadi_isolated_test(itemappendtest.cpp) add_akonadi_isolated_test(itemstoretest.cpp) add_akonadi_isolated_test(itemdeletetest.cpp) add_akonadi_isolated_test(entitycachetest.cpp) add_akonadi_isolated_test(monitortest.cpp) add_akonadi_isolated_test(searchjobtest.cpp) add_akonadi_isolated_test(changerecordertest.cpp) add_akonadi_isolated_test(resourcetest.cpp) add_akonadi_isolated_test(subscriptiontest.cpp) add_akonadi_isolated_test(transactiontest.cpp) add_akonadi_isolated_test(filteractiontest.cpp) add_akonadi_isolated_test(itemcopytest.cpp) add_akonadi_isolated_test(itemmovetest.cpp) add_akonadi_isolated_test(collectioncopytest.cpp) add_akonadi_isolated_test(collectionmovetest.cpp) add_akonadi_isolated_test(collectionsynctest.cpp) add_akonadi_isolated_test(itemsynctest.cpp) add_akonadi_isolated_test(linktest.cpp) add_akonadi_isolated_test(cachetest.cpp) add_akonadi_isolated_test(servermanagertest.cpp) add_akonadi_isolated_test(collectioncreator.cpp) add_akonadi_isolated_test(itembenchmark.cpp) diff --git a/akonadi/tests/collectionutilstest.cpp b/akonadi/tests/collectionutilstest.cpp new file mode 100644 index 000000000..75ce75c7f --- /dev/null +++ b/akonadi/tests/collectionutilstest.cpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2009 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "entitycache.cpp" + +#include +#include +#include "../collectionutils_p.h" + +using namespace Akonadi; + +class CollectionUtilsTest : public QObject +{ + Q_OBJECT + private slots: + void testHasValidHierarchicalRID_data() + { + QTest::addColumn( "collection" ); + QTest::addColumn( "isHRID" ); + + QTest::newRow( "empty" ) << Collection() << false; + QTest::newRow( "root" ) << Collection::root() << true; + Collection c; + c.setParentCollection( Collection::root() ); + QTest::newRow( "one level not ok" ) << c << false; + c.setRemoteId( "r1" ); + QTest::newRow( "one level ok" ) << c << true; + Collection c2; + c2.setParentCollection( c ); + QTest::newRow( "two level not ok" ) << c2 << false; + c2.setRemoteId( "r2" ); + QTest::newRow( "two level ok" ) << c2 << true; + c2.parentCollection().setRemoteId( QString() ); + QTest::newRow( "mid RID missing" ) << c2 << false; + } + + void testHasValidHierarchicalRID() + { + QFETCH( Collection, collection ); + QFETCH( bool, isHRID ); + QCOMPARE( CollectionUtils::hasValidHierarchicalRID( collection ), isHRID ); + } +}; + +QTEST_AKONADIMAIN( CollectionUtilsTest, NoGUI ) + +#include "collectionutilstest.moc" diff --git a/akonadi/tests/protocolhelpertest.cpp b/akonadi/tests/protocolhelpertest.cpp index b595b0e2c..85488f444 100644 --- a/akonadi/tests/protocolhelpertest.cpp +++ b/akonadi/tests/protocolhelpertest.cpp @@ -1,116 +1,141 @@ /* Copyright (c) 2009 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "test_utils.h" #include "protocolhelper.cpp" using namespace Akonadi; class ProtocolHelperTest : public QObject { Q_OBJECT private slots: void testItemSetToByteArray_data() { QTest::addColumn( "items" ); QTest::addColumn( "result" ); QTest::addColumn( "shouldThrow" ); Item u1; u1.setId( 1 ); Item u2; u2.setId( 2 ); Item u3; u3.setId( 3 ); Item r1; r1.setRemoteId( "A" ); Item r2; r2.setRemoteId( "B" ); QTest::newRow( "empty" ) << Item::List() << QByteArray() << true; QTest::newRow( "single uid" ) << (Item::List() << u1) << QByteArray( " UID CMD 1" ) << false; QTest::newRow( "multi uid" ) << (Item::List() << u1 << u3) << QByteArray( " UID CMD 1,3" ) << false; QTest::newRow( "block uid" ) << (Item::List() << u1 << u2 << u3) << QByteArray( " UID CMD 1:3" ) << false; QTest::newRow( "single rid" ) << (Item::List() << r1) << QByteArray( " RID CMD (\"A\")" ) << false; QTest::newRow( "multi rid" ) << (Item::List() << r1 << r2) << QByteArray( " RID CMD (\"A\" \"B\")" ) << false; QTest::newRow( "invalid" ) << (Item::List() << Item()) << QByteArray() << true; QTest::newRow( "mixed" ) << (Item::List() << u1 << r1) << QByteArray() << true; } void testItemSetToByteArray() { QFETCH( Item::List, items ); QFETCH( QByteArray, result ); QFETCH( bool, shouldThrow ); bool didThrow = false; try { const QByteArray r = ProtocolHelper::itemSetToByteArray( items, "CMD" ); QCOMPARE( r, result ); } catch ( const std::exception &e ) { qDebug() << e.what(); didThrow = true; } QCOMPARE( didThrow, shouldThrow ); } void testCollectionParsing_data() { QTest::addColumn( "input" ); QTest::addColumn( "collection" ); const QByteArray b1 = "2 1 (REMOTEID \"r2\" NAME \"n2\")"; Collection c1; c1.setId( 2 ); c1.setRemoteId( "r2" ); c1.parentCollection().setId( 1 ); c1.setName( "n2" ); QTest::newRow( "no ancestors" ) << b1 << c1; const QByteArray b2 = "3 2 (REMOTEID \"r3\" ANCESTORS ((2 \"r2\") (1 \"r1\") (0 \"\")))"; Collection c2; c2.setId( 3 ); c2.setRemoteId( "r3" ); c2.parentCollection().setId( 2 ); c2.parentCollection().setRemoteId( "r2" ); c2.parentCollection().parentCollection().setId( 1 ); c2.parentCollection().parentCollection().setRemoteId( "r1" ); c2.parentCollection().parentCollection().setParentCollection( Collection::root() ); QTest::newRow( "ancestors" ) << b2 << c2; } void testCollectionParsing() { QFETCH( QByteArray, input ); QFETCH( Collection, collection ); Collection parsedCollection; ProtocolHelper::parseCollection( input, parsedCollection ); QCOMPARE( parsedCollection.name(), collection.name() ); while ( collection.isValid() || parsedCollection.isValid() ) { QCOMPARE( parsedCollection.id(), collection.id() ); QCOMPARE( parsedCollection.remoteId(), collection.remoteId() ); const Collection p1( parsedCollection.parentCollection() ); const Collection p2( collection.parentCollection() ); parsedCollection = p1; collection = p2; } } + + void testHRidToByteArray_data() + { + QTest::addColumn( "collection" ); + QTest::addColumn( "result" ); + + QTest::newRow( "empty" ) << Collection() << QByteArray(); + QTest::newRow( "root" ) << Collection::root() << QByteArray( "(0 \"\")" ); + Collection c; + c.setParentCollection( Collection::root() ); + c.setRemoteId( "r1" ); + QTest::newRow( "one level" ) << c << QByteArray( "(-14 \"r1\") (0 \"\")" ); + Collection c2; + c2.setParentCollection( c ); + c2.setRemoteId( "r2" ); + QTest::newRow( "two level ok" ) << c2 << QByteArray( "(-15 \"r2\") (-14 \"r1\") (0 \"\")" ); + } + + void testHRidToByteArray() + { + QFETCH( Collection, collection ); + QFETCH( QByteArray, result ); + qDebug() << ProtocolHelper::hierarchicalRidToByteArray( collection ) << result; + QCOMPARE( ProtocolHelper::hierarchicalRidToByteArray( collection ), result ); + } }; QTEST_KDEMAIN( ProtocolHelperTest, NoGUI ) #include "protocolhelpertest.moc"