diff options
-rw-r--r-- | src/enginio_client/enginioclient.cpp | 15 | ||||
-rw-r--r-- | src/enginio_client/enginioclient_p.h | 71 | ||||
-rw-r--r-- | tests/auto/enginioclient/tst_enginioclient.cpp | 86 |
3 files changed, 101 insertions, 71 deletions
diff --git a/src/enginio_client/enginioclient.cpp b/src/enginio_client/enginioclient.cpp index 6a47696..3d1b888 100644 --- a/src/enginio_client/enginioclient.cpp +++ b/src/enginio_client/enginioclient.cpp @@ -262,6 +262,21 @@ QNetworkRequest EnginioClientConnectionPrivate::prepareRequest(const QUrl &url) return req; } +bool EnginioClientConnectionPrivate::appendIdToPathIfPossible(QString *path, const QString &id, QByteArray *errorMsg, EnginioClientConnectionPrivate::PathOptions flags, QByteArray errorMessageHint) +{ + Q_ASSERT(path && errorMsg); + if (id.isEmpty()) { + if (flags == RequireIdInPath) { + *errorMsg = constructErrorMessage(errorMessageHint); + return false; + } + return true; + } + path->append('/'); + path->append(id); + return true; +} + EnginioClientConnectionPrivate::EnginioClientConnectionPrivate() : _identity(), _serviceUrl(EnginioString::apiEnginIo), diff --git a/src/enginio_client/enginioclient_p.h b/src/enginio_client/enginioclient_p.h index 93ce864..286a30c 100644 --- a/src/enginio_client/enginioclient_p.h +++ b/src/enginio_client/enginioclient_p.h @@ -87,11 +87,11 @@ QT_BEGIN_NAMESPACE CHECK_AND_SET_URL_PATH_IMPL(Url, Object, Operation, EnginioClientConnectionPrivate::Default) #define CHECK_AND_SET_PATH_WITH_ID(Url, Object, Operation) \ - CHECK_AND_SET_URL_PATH_IMPL(Url, Object, Operation, EnginioClientConnectionPrivate::IncludeIdInPath) + CHECK_AND_SET_URL_PATH_IMPL(Url, Object, Operation, EnginioClientConnectionPrivate::RequireIdInPath) class ENGINIOCLIENT_EXPORT EnginioClientConnectionPrivate : public QObjectPrivate { - enum PathOptions { Default, IncludeIdInPath = 1}; + enum PathOptions { Default, RequireIdInPath = 1}; struct ENGINIOCLIENT_EXPORT GetPathReturnValue : public QPair<bool, QString> { @@ -105,6 +105,8 @@ class ENGINIOCLIENT_EXPORT EnginioClientConnectionPrivate : public QObjectPrivat operator QString() const { return second; } }; + static bool appendIdToPathIfPossible(QString *path, const QString &id, QByteArray *errorMsg, PathOptions flags, QByteArray errorMessageHint = EnginioString::Requested_operation_requires_non_empty_id_value); + template<class T> static GetPathReturnValue getPath(const T &object, int operation, QString *path, QByteArray *errorMsg, PathOptions flags = Default) { @@ -114,6 +116,7 @@ class ENGINIOCLIENT_EXPORT EnginioClientConnectionPrivate : public QObjectPrivat QString &result = *path; result.reserve(96); result.append(QStringLiteral("/v1/")); + QString id = object[EnginioString::id].toString(); switch (operation) { case Enginio::ObjectOperation: { @@ -122,8 +125,9 @@ class ENGINIOCLIENT_EXPORT EnginioClientConnectionPrivate : public QObjectPrivat msg = constructErrorMessage(EnginioString::Requested_object_operation_requires_non_empty_objectType_value); return GetPathReturnValue(Failed); } - result.append(objectType.replace('.', '/')); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; } case Enginio::AccessControlOperation: @@ -133,83 +137,65 @@ class ENGINIOCLIENT_EXPORT EnginioClientConnectionPrivate : public QObjectPrivat msg = constructErrorMessage(EnginioString::Requested_object_acl_operation_requires_non_empty_objectType_value); return GetPathReturnValue(Failed); } - result.append(objectType.replace('.', '/')); - QString id = object[EnginioString::id].toString(); - if (id.isEmpty()) { - msg = constructErrorMessage(EnginioString::Requested_object_acl_operation_requires_non_empty_id_value); + if (!appendIdToPathIfPossible(path, id, errorMsg, RequireIdInPath, EnginioString::Requested_object_acl_operation_requires_non_empty_id_value)) return GetPathReturnValue(Failed); - } - result.append('/'); - result.append(id); result.append('/'); result.append(EnginioString::access); return GetPathReturnValue(true, EnginioString::access); } case Enginio::FileOperation: { result.append(EnginioString::files); - // if we have a fileID, it becomes "view", otherwise it is up/download - QString fileId = object[EnginioString::id].toString(); - if (!fileId.isEmpty()) { - result.append('/'); - result.append(fileId); - } + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; } case Enginio::FileGetDownloadUrlOperation: { result.append(EnginioString::files); - QString fileId = object[EnginioString::id].toString(); - if (fileId.isEmpty()) { - msg = constructErrorMessage(EnginioString::Download_operation_requires_non_empty_fileId_value); + if (!appendIdToPathIfPossible(path, id, errorMsg, RequireIdInPath, EnginioString::Download_operation_requires_non_empty_fileId_value)) return GetPathReturnValue(Failed); - } - result.append(QLatin1Char('/') + fileId + QStringLiteral("/download_url")); + result.append(QStringLiteral("/download_url")); break; } case Enginio::FileChunkUploadOperation: { - const QString fileId = object[EnginioString::id].toString(); - Q_ASSERT(!fileId.isEmpty()); - result.append(EnginioString::files + QLatin1Char('/') + fileId + QStringLiteral("/chunk")); + Q_ASSERT(!id.isEmpty()); + result.append(EnginioString::files); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); + result.append(QStringLiteral("/chunk")); break; } case Enginio::SearchOperation: result.append(EnginioString::search); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; case Enginio::SessionOperation: result.append(EnginioString::session); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; case Enginio::UserOperation: result.append(EnginioString::users); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; case Enginio::UsergroupOperation: result.append(EnginioString::usergroups); + if (!appendIdToPathIfPossible(path, id, errorMsg, flags)) + return GetPathReturnValue(Failed); break; case Enginio::UsergroupMembersOperation: { - QString id = object[EnginioString::id].toString(); - if (id.isEmpty()) { - msg = constructErrorMessage(EnginioString::Requested_usergroup_member_operation_requires_non_empty_id_value); - return GetPathReturnValue(Failed); - } result.append(EnginioString::usergroups); - result.append('/'); - result.append(id); + if (!appendIdToPathIfPossible(path, id, errorMsg, RequireIdInPath, EnginioString::Requested_usergroup_member_operation_requires_non_empty_id_value)) + return GetPathReturnValue(Failed); result.append('/'); result.append(EnginioString::members); return GetPathReturnValue(true, EnginioString::member); } } - if (flags & IncludeIdInPath) { - QString id = object[EnginioString::id].toString(); - if (id.isEmpty()) { - msg = constructErrorMessage(EnginioString::Requested_operation_requires_non_empty_id_value); - return GetPathReturnValue(Failed); - } - result.append('/'); - result.append(id); - } - return GetPathReturnValue(true, QString()); } @@ -557,7 +543,6 @@ public: url.setQuery(urlQuery); QNetworkRequest req = prepareRequest(url); - return networkManager()->get(req); } @@ -565,7 +550,7 @@ public: QNetworkReply *downloadUrl(const ObjectAdaptor<T> &object) { QUrl url(_serviceUrl); - CHECK_AND_SET_PATH(url, object, Enginio::FileGetDownloadUrlOperation); + CHECK_AND_SET_PATH_WITH_ID(url, object, Enginio::FileGetDownloadUrlOperation); if (object.contains(EnginioString::variant)) { QString variant = object[EnginioString::variant].toString(); QUrlQuery query; diff --git a/tests/auto/enginioclient/tst_enginioclient.cpp b/tests/auto/enginioclient/tst_enginioclient.cpp index aafebbe..d1f25cc 100644 --- a/tests/auto/enginioclient/tst_enginioclient.cpp +++ b/tests/auto/enginioclient/tst_enginioclient.cpp @@ -140,6 +140,49 @@ void tst_EnginioClient::initTestCase() prepareForSearch(); EnginioTests::prepareTestUsersAndUserGroups(_backendId); + + // create some todos objects + QJsonObject todos; + todos["name"] = QStringLiteral("todos"); + + QJsonObject title; + title["name"] = QStringLiteral("title"); + title["type"] = QStringLiteral("string"); + title["indexed"] = true; + QJsonObject completed; + completed["name"] = QStringLiteral("completed"); + completed["type"] = QStringLiteral("boolean"); + completed["indexed"] = false; + QJsonObject count; + count["name"] = QStringLiteral("count"); + count["type"] = QStringLiteral("number"); + count["indexed"] = false; + + QJsonArray properties; + properties.append(title); + properties.append(completed); + properties.append(count); + todos["properties"] = properties; + + QVERIFY(_backendManager.createObjectType(_backendName, EnginioTests::TESTAPP_ENV, todos)); + { + EnginioClient client; + QObject::connect(&client, SIGNAL(error(EnginioReply *)), this, SLOT(error(EnginioReply *))); + client.setBackendId(_backendId); + client.setServiceUrl(EnginioTests::TESTAPP_URL); + + QJsonObject object; + object["objectType"] = QString::fromUtf8("objects.todos"); + object["title"] = QString::fromUtf8("init todo 1"); + object["completed"] = false; + EnginioReply* reply1 = client.create(object); + object["title"] = QString::fromUtf8("init todo 2"); + EnginioReply* reply2 = client.create(object); + QTRY_VERIFY(reply1->isFinished()); + CHECK_NO_ERROR(reply1); + QTRY_VERIFY(reply2->isFinished()); + CHECK_NO_ERROR(reply2); + } } void tst_EnginioClient::cleanupTestCase() @@ -177,20 +220,31 @@ void tst_EnginioClient::query_todos() QSignalSpy spy(&client, SIGNAL(finished(EnginioReply *))); QSignalSpy spyError(&client, SIGNAL(error(EnginioReply*))); //![query-todo] - QJsonObject object; - object["objectType"] = QString::fromUtf8("objects.todos"); - const EnginioReply* reply = client.query(object); + QJsonObject query; + query["objectType"] = QString::fromUtf8("objects.todos"); + EnginioReply *reply = client.query(query); //![query-todo] QVERIFY(reply); QTRY_COMPARE(spy.count(), 1); QCOMPARE(spyError.count(), 0); - const EnginioReply *response = spy[0][0].value<EnginioReply*>(); + EnginioReply *response = spy[0][0].value<EnginioReply*>(); QCOMPARE(response, reply); CHECK_NO_ERROR(response); QVERIFY(!response->data().isEmpty()); QVERIFY(!response->data()["results"].isUndefined()); + + { // try to query the object with an id + QJsonArray results = reply->data()["results"].toArray(); + QVERIFY(results.count() > 1); // the test assumes that querying by id will return less items. + QString id = results[0].toObject()["id"].toString(); + query["id"] = id; + reply = client.query(query); + QTRY_VERIFY(reply->isFinished()); + CHECK_NO_ERROR(reply); + QCOMPARE(reply->data()["id"].toString(), id); + } } void tst_EnginioClient::query_todos_filter() @@ -882,30 +936,6 @@ void tst_EnginioClient::deleteReply() void tst_EnginioClient::create_todos() { - QJsonObject todos; - todos["name"] = QStringLiteral("todos"); - - QJsonObject title; - title["name"] = QStringLiteral("title"); - title["type"] = QStringLiteral("string"); - title["indexed"] = true; - QJsonObject completed; - completed["name"] = QStringLiteral("completed"); - completed["type"] = QStringLiteral("boolean"); - completed["indexed"] = false; - QJsonObject count; - count["name"] = QStringLiteral("count"); - count["type"] = QStringLiteral("number"); - count["indexed"] = false; - - QJsonArray properties; - properties.append(title); - properties.append(completed); - properties.append(count); - todos["properties"] = properties; - - QVERIFY(_backendManager.createObjectType(_backendName, EnginioTests::TESTAPP_ENV, todos)); - EnginioClient client; QObject::connect(&client, SIGNAL(error(EnginioReply *)), this, SLOT(error(EnginioReply *))); client.setBackendId(_backendId); |