diff options
author | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2012-06-05 16:14:06 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-08 12:02:21 +0200 |
commit | 72eb7cda976c05c67616e93403750442175af430 (patch) | |
tree | a6821c982796ae590c1b0438624c32e593a27452 | |
parent | c85268e04d2f52d2aaecba9e927c1025a0f4648d (diff) |
Fixed created QJsonDbWatcher with invalid state number
if the state number is too far in the future, or the partition is not
available, or the watcher spans multiple object tables, report an error to the
caller.
Change-Id: I4b1e4fa2859b1e781f5b3d70e639c70fab1ae2db
Reviewed-by: Jamey Hicks <jamey.hicks@nokia.com>
-rw-r--r-- | src/daemon/dbserver.cpp | 49 | ||||
-rw-r--r-- | tests/auto/qjsondbwatcher/partitions.json | 3 | ||||
-rw-r--r-- | tests/auto/qjsondbwatcher/testqjsondbwatcher.cpp | 53 | ||||
-rw-r--r-- | tests/shared/testhelper.cpp | 6 |
4 files changed, 104 insertions, 7 deletions
diff --git a/src/daemon/dbserver.cpp b/src/daemon/dbserver.cpp index fc3fa29..8cdc646 100644 --- a/src/daemon/dbserver.cpp +++ b/src/daemon/dbserver.cpp @@ -818,7 +818,7 @@ void DBServer::createNotification(const JsonDbObject &object, ClientJsonStream * JsonDbQuery parsedQuery = parser.result(); JsonDbNotification *n = new JsonDbNotification(getOwner(stream), parsedQuery, actions); - if (object.contains("initialStateNumber") && object.value("initialStateNumber").isDouble()) + if (object.value("initialStateNumber").isDouble()) n->setInitialStateNumber(static_cast<qint32>(object.value("initialStateNumber").toDouble())); stream->addNotification(uuid, n); @@ -865,14 +865,53 @@ JsonDbError::ErrorCode DBServer::validateNotification(const JsonDbObject ¬ifi return JsonDbError::MissingQuery; } - if (notificationDef.contains(JsonDbString::kPartitionStr) && - notificationDef.value(JsonDbString::kPartitionStr).toString() != mEphemeralPartition->name()) { - QString partitionName = notificationDef.value(JsonDbString::kPartitionStr).toString(); + QString partitionName = mDefaultPartition->partitionSpec().name; + QJsonValue v = notificationDef.value(JsonDbString::kPartitionStr); + if (!v.isUndefined()) { + if (!v.isString()) { + message = QStringLiteral("invalid partition specified"); + return JsonDbError::InvalidPartition; + } else if (!v.toString().isEmpty()) { + partitionName = v.toString(); + } + } + v = notificationDef.value(QStringLiteral("initialStateNumber")); + if (!v.isUndefined() && !v.isDouble()) { + message = QStringLiteral("invalid initial state number specified"); + return JsonDbError::InvalidStateNumber; + } + quint32 initialStateNumber = static_cast<quint32>(v.toDouble(0)); + + if (partitionName != mEphemeralPartition->name()) { JsonDbPartition *partition = findPartition(partitionName); if (!partition) { - message = QString::fromLatin1("Invalid partition specified: %1").arg(partitionName); + message = QStringLiteral("Invalid partition specified: %1").arg(partitionName); + return JsonDbError::InvalidPartition; + } + if (!partition->isOpen()) { + message = QStringLiteral("Partition '%1' is not currently available").arg(partitionName); return JsonDbError::InvalidPartition; } + JsonDbObjectTable *table = 0; + QSet<QString> matchedTypes = query.matchedTypes(); + if (!matchedTypes.isEmpty()) { + foreach (const QString &type, matchedTypes) { + JsonDbObjectTable *viewtable = partition->findObjectTable(type); + if (table && viewtable && table != viewtable) { + message = QStringLiteral("Cannot create a watcher for multiple object tables"); + return JsonDbError::MissingQuery; + } + table = viewtable; + } + } + if (!table) + table = partition->mainObjectTable(); + if (initialStateNumber != static_cast<quint32>(-1)) { + if (initialStateNumber > table->stateNumber()) { + message = QStringLiteral("Too new state number specified"); + return JsonDbError::InvalidStateNumber; + } + } } return JsonDbError::NoError; diff --git a/tests/auto/qjsondbwatcher/partitions.json b/tests/auto/qjsondbwatcher/partitions.json index f8a7c87..4619bc6 100644 --- a/tests/auto/qjsondbwatcher/partitions.json +++ b/tests/auto/qjsondbwatcher/partitions.json @@ -1,3 +1,4 @@ [ - { "name" :"com.qt-project.shared", "path":".", "default" : true } + { "name" :"com.qt-project.shared", "path":".", "default" : true }, + { "name" :"com.qt-project.removable", "path":"/nonexistentdir", "removable" : true } ] diff --git a/tests/auto/qjsondbwatcher/testqjsondbwatcher.cpp b/tests/auto/qjsondbwatcher/testqjsondbwatcher.cpp index 66ff74a..cb465cc 100644 --- a/tests/auto/qjsondbwatcher/testqjsondbwatcher.cpp +++ b/tests/auto/qjsondbwatcher/testqjsondbwatcher.cpp @@ -870,6 +870,59 @@ void TestQJsonDbWatcher::invalid() mConnection->addWatcher(&watcher3); QVERIFY(waitForError(&watcher3, QJsonDbWatcher::InvalidPartition)); mConnection->removeWatcher(&watcher3); + + // invalid initial state number + QJsonDbWatcher watcher4; + watcher4.setQuery(QStringLiteral("[?_type=\"Contact\"]")); + watcher4.setInitialStateNumber(1234567); + mConnection->addWatcher(&watcher4); + QVERIFY(waitForError(&watcher4, QJsonDbWatcher::InvalidStateNumber)); + mConnection->removeWatcher(&watcher4); + + // unavailable partition + QJsonDbWatcher watcher5; + watcher5.setQuery(QStringLiteral("[?_type=\"Contact\"]")); + watcher5.setPartition(QStringLiteral("com.qt-project.removable")); + mConnection->addWatcher(&watcher5); + QVERIFY(waitForError(&watcher5, QJsonDbWatcher::InvalidPartition)); + mConnection->removeWatcher(&watcher5); + + // watcher over multiple object tables + { + static const char schemaJson[] = +"{ \ + \"_type\": \"_schemaType\", \ + \"name\": \"invalidMapType\", \ + \"schema\": { \ + \"type\": \"object\", \ + \"extends\": {\"$ref\": \"View\"} \ + } \ +}"; + QJsonDbObject schema = QJsonDocument::fromJson(QByteArray(schemaJson)).object(); + + QJsonDbObject map; + map.insert(QLatin1String("_type"), QLatin1String("Map")); + map.insert(QLatin1String("targetType"), QLatin1String("invalidMapType")); + QJsonObject submap; + submap.insert(QLatin1String("com.test.indextest"), QLatin1String("function (o) { jsondb.emit(o); }")); + map.insert(QLatin1String("join"), submap); + + QJsonDbCreateRequest request(QList<QJsonObject>() << schema << map); + QVERIFY(mConnection->send(&request)); + QVERIFY(waitForResponse(&request)); + QJsonDbWatcher watcher6; + watcher6.setQuery(QStringLiteral("[?_type=\"Contact\" | _type = \"invalidMapType\"]")); + mConnection->addWatcher(&watcher6); + QVERIFY(waitForError(&watcher6, QJsonDbWatcher::MissingQuery)); + mConnection->removeWatcher(&watcher6); + } + + // watcher over multiple types in the same object table + QJsonDbWatcher watcher7; + watcher7.setQuery(QStringLiteral("[?_type in [\"Contact\", \"AnotherContact\"]]")); + mConnection->addWatcher(&watcher7); + QVERIFY(waitForStatus(&watcher7, QJsonDbWatcher::Active)); + mConnection->removeWatcher(&watcher7); } void TestQJsonDbWatcher::privatePartition() diff --git a/tests/shared/testhelper.cpp b/tests/shared/testhelper.cpp index b0dcd7c..346c4bb 100644 --- a/tests/shared/testhelper.cpp +++ b/tests/shared/testhelper.cpp @@ -376,7 +376,11 @@ bool TestHelper::waitForStatus(QJsonDbWatcher *watcher, QJsonDbWatcher::Status s connect(watcher, SIGNAL(statusChanged(QtJsonDb::QJsonDbWatcher::Status)), this, SLOT(watcherStatusChanged(QtJsonDb::QJsonDbWatcher::Status))); + connect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + this, SLOT(watcherError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); blockWithTimeout(); + disconnect(watcher, SIGNAL(error(QtJsonDb::QJsonDbWatcher::ErrorCode,QString)), + this, SLOT(watcherError(QtJsonDb::QJsonDbWatcher::ErrorCode,QString))); disconnect(watcher, SIGNAL(statusChanged(QtJsonDb::QJsonDbWatcher::Status)), this, SLOT(watcherStatusChanged(QtJsonDb::QJsonDbWatcher::Status))); @@ -519,7 +523,7 @@ void TestHelper::watcherLastStateNumberChanged(int stateNumber) void TestHelper::watcherError(QtJsonDb::QJsonDbWatcher::ErrorCode code, QString msg) { - qWarning() << "Watcher error:" << code << msg; + Q_UNUSED(msg); mReceivedError = code; if (code == mExpectedError) mEventLoop.quit(); |