diff options
author | Christian Franke <nobody@nowhere.ws> | 2012-03-21 12:52:37 (GMT) |
---|---|---|
committer | Christian Franke <nobody@nowhere.ws> | 2012-03-21 13:12:45 (GMT) |
commit | 4a0c4288e7d832f8cd72eefde6afe8fc535f5e73 (patch) | |
tree | 7dea186a9bcbac75fa06e3cc121ba0c6511e3250 | |
parent | 179da0310ec3df51b1e95492fca04ab273fa70ac (diff) |
Use upstream opensearch code
All arora specific code has been moved from src/opensearch/ to src/
so now, src/opensearch is a direct clone of the qopensearch tree at
http://gitorious.org/qopensearch/qopensearch
56 files changed, 1978 insertions, 299 deletions
diff --git a/src/opensearch/.gitignore b/src/opensearch/.gitignore new file mode 100644 index 0000000..45950ba --- /dev/null +++ b/src/opensearch/.gitignore @@ -0,0 +1,9 @@ +build +Makefile* +.ui +.moc +.obj +.rcc +.qm +.gdb_history +*~ diff --git a/src/opensearch/build.pri b/src/opensearch/build.pri new file mode 100644 index 0000000..d7aac97 --- /dev/null +++ b/src/opensearch/build.pri @@ -0,0 +1,7 @@ +BUILDDIR = $$PWD/build +TEMPDIR = $$BUILDDIR/tmp + +RCC_DIR = $$TEMPDIR +UI_DIR = $$TEMPDIR +MOC_DIR = $$TEMPDIR +OBJECTS_DIR = $$TEMPDIR diff --git a/src/opensearch/examples/examples.pro b/src/opensearch/examples/examples.pro new file mode 100644 index 0000000..7f43581 --- /dev/null +++ b/src/opensearch/examples/examples.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = suggestions + +CONFIG += ordered diff --git a/src/opensearch/examples/suggestions/helperobject.h b/src/opensearch/examples/suggestions/helperobject.h new file mode 100644 index 0000000..69b0508 --- /dev/null +++ b/src/opensearch/examples/suggestions/helperobject.h @@ -0,0 +1,34 @@ +#include <qobject.h> + +#include <qapplication.h> +#include <qstringlist.h> +#include <qtextstream.h> +#include <qtimer.h> + +class HelperObject : public QObject +{ + Q_OBJECT + +public: + HelperObject(QObject *parent, QTextStream *stream) + : QObject(parent) + , m_stream(stream) + { + } + +public slots: + void printSuggestions(const QStringList &suggestions) + { + Q_ASSERT(m_stream); + if (suggestions.isEmpty()) + *m_stream << "No suggestions." << "\n"; + else + *m_stream << suggestions.join("\n") << "\n"; + + QApplication *app = static_cast<QApplication*>(parent()); + QTimer::singleShot(0, app, SLOT(quit())); + } + +private: + QTextStream *m_stream; +}; diff --git a/src/opensearch/examples/suggestions/main.cpp b/src/opensearch/examples/suggestions/main.cpp new file mode 100644 index 0000000..7030667 --- /dev/null +++ b/src/opensearch/examples/suggestions/main.cpp @@ -0,0 +1,65 @@ +#include <qapplication.h> + +#include "opensearchengine.h" +#include "opensearchreader.h" +#include "helperobject.h" + +#include <qfile.h> +#include <qnetworkaccessmanager.h> +#include <qobject.h> +#include <qtextstream.h> +#include <qtimer.h> + +#include <cstdio> + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + QStringList args = app.arguments(); + + QTextStream stream(stdout); + + if (args.count() < 3) { + stream << QString("Usage: %1 filepath searchterm").arg(args.at(0)) << '\n'; + return 1; + } + + QString filePath = args.at(1); + QString searchTerm = args.at(2); + + if (!QFile::exists(filePath)) { + stream << QString("File %1 does not exist.").arg(filePath) << '\n'; + return 1; + } + + QFile file(filePath); + file.open(QIODevice::ReadOnly); + + QNetworkAccessManager manager; + + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(&file); + if (reader.hasError()) { + stream << QString("Error: %1").arg(reader.errorString()) << '\n'; + return 1; + } + + if (!engine->isValid()) { + stream << "The OpenSearch description is invalid." << '\n'; + return 1; + } + + QTimer timer; + timer.setSingleShot(true); + timer.setInterval(10 * 1000); + + HelperObject helper(&app, &stream); + engine->setNetworkAccessManager(&manager); + engine->requestSuggestions(searchTerm); + timer.start(); + QObject::connect(engine, SIGNAL(suggestions(const QStringList &)), + &helper, SLOT(printSuggestions(const QStringList &))); + QObject::connect(&timer, SIGNAL(timeout()), + &app, SLOT(quit())); + app.exec(); +}
\ No newline at end of file diff --git a/src/opensearch/examples/suggestions/suggestions.pro b/src/opensearch/examples/suggestions/suggestions.pro new file mode 100644 index 0000000..896a2ea --- /dev/null +++ b/src/opensearch/examples/suggestions/suggestions.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +QT += network + +include(../../build.pri) +include(../../src/opensearch.pri) +DESTDIR = $$BUILDDIR/examples + +SOURCES += main.cpp +HEADERS += helperobject.h diff --git a/src/opensearch/opensearchreader.cpp b/src/opensearch/opensearchreader.cpp deleted file mode 100644 index 7b88578..0000000 --- a/src/opensearch/opensearchreader.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> - * - * 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 - */ - -#include "opensearchreader.h" - -#include "opensearchengine.h" - -#include <qiodevice.h> - -/*! - \class OpenSearchReader - \brief A class reading a search engine description from an external source - - OpenSearchReader is a class that can be used to read search engine descriptions - formed using the OpenSearch format. - - It inherits QXmlStreamReader and thus provides additional functions, such as - QXmlStreamReader::error(), QXmlStreamReader::hasError() that can be used to make sure - the reading procedure succeeded. - - For more information see: - http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_description_document - - \sa OpenSearchEngine, OpenSearchWriter -*/ - -/*! - Constructs a new reader. - - \note One instance can be used to read multiple files, one by one. -*/ -OpenSearchReader::OpenSearchReader() - : QXmlStreamReader() -{ -} - -/*! - Reads an OpenSearch engine from the \a device and returns an OpenSearchEngine object, - filled in with all the data that has been retrieved from the document. - - If the \a device is closed, it will be opened. - - To make sure if the procedure succeeded, check QXmlStreamReader::error(). - - \return a new constructed OpenSearchEngine object - - \note The function returns an object of the OpenSearchEngine class even if the document - is bad formed or doesn't conform to the specification. It needs to be manually - deleted afterwards, if intended. - \note The lifetime of the returned OpenSearchEngine object is up to the user. - The object should be deleted once it is not used anymore to avoid memory leaks. -*/ -OpenSearchEngine *OpenSearchReader::read(QIODevice *device) -{ - clear(); - - if (!device->isOpen()) - device->open(QIODevice::ReadOnly); - - setDevice(device); - return read(); -} - -OpenSearchEngine *OpenSearchReader::read() -{ - OpenSearchEngine *engine = new OpenSearchEngine(); - - while (!isStartElement() && !atEnd()) - readNext(); - - if (name() != QLatin1String("OpenSearchDescription") - || namespaceUri() != QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) { - raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); - return engine; - } - - while (!atEnd()) { - readNext(); - - if (!isStartElement()) - continue; - - if (name() == QLatin1String("ShortName")) { - engine->setName(readElementText()); - } else if (name() == QLatin1String("Description")) { - engine->setDescription(readElementText()); - } else if (name() == QLatin1String("Url")) { - - QString type = attributes().value(QLatin1String("type")).toString(); - QString url = attributes().value(QLatin1String("template")).toString(); - QString method = attributes().value(QLatin1String("method")).toString(); - - if (type == QLatin1String("application/x-suggestions+json") - && !engine->suggestionsUrlTemplate().isEmpty()) - continue; - - if ((type.isEmpty() - || type == QLatin1String("text/html") - || type == QLatin1String("application/xhtml+xml")) - && !engine->searchUrlTemplate().isEmpty()) - continue; - - if (url.isEmpty()) - continue; - - QList<OpenSearchEngine::Parameter> parameters; - - readNext(); - - while (!(isEndElement() && name() == QLatin1String("Url"))) { - if (!isStartElement() || (name() != QLatin1String("Param") && name() != QLatin1String("Parameter"))) { - readNext(); - continue; - } - - QString key = attributes().value(QLatin1String("name")).toString(); - QString value = attributes().value(QLatin1String("value")).toString(); - - if (!key.isEmpty() && !value.isEmpty()) - parameters.append(OpenSearchEngine::Parameter(key, value)); - - while (!isEndElement()) - readNext(); - } - - if (type == QLatin1String("application/x-suggestions+json")) { - engine->setSuggestionsUrlTemplate(url); - engine->setSuggestionsParameters(parameters); - engine->setSuggestionsMethod(method); - } else if (type.isEmpty() || type == QLatin1String("text/html") || type == QLatin1String("application/xhtml+xml")) { - engine->setSearchUrlTemplate(url); - engine->setSearchParameters(parameters); - engine->setSearchMethod(method); - } - - } else if (name() == QLatin1String("Image")) { - engine->setImageUrl(readElementText()); - } - - if (!engine->name().isEmpty() - && !engine->description().isEmpty() - && !engine->suggestionsUrlTemplate().isEmpty() - && !engine->searchUrlTemplate().isEmpty() - && !engine->imageUrl().isEmpty()) - break; - } - - return engine; -} - diff --git a/src/opensearch/qopensearch.pro b/src/opensearch/qopensearch.pro new file mode 100644 index 0000000..95f3807 --- /dev/null +++ b/src/opensearch/qopensearch.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = src/opensearch.pro tests examples + +CONFIG += ordered diff --git a/src/opensearch/src/opensearch-nolib.pri b/src/opensearch/src/opensearch-nolib.pri new file mode 100644 index 0000000..9c69a66 --- /dev/null +++ b/src/opensearch/src/opensearch-nolib.pri @@ -0,0 +1,16 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +QT += network script + +HEADERS += \ + opensearchengine.h \ + opensearchenginedelegate.h \ + opensearchreader.h \ + opensearchwriter.h + +SOURCES += \ + opensearchengine.cpp \ + opensearchenginedelegate.cpp \ + opensearchreader.cpp \ + opensearchwriter.cpp diff --git a/src/opensearch/src/opensearch.pri b/src/opensearch/src/opensearch.pri new file mode 100644 index 0000000..e9a120c --- /dev/null +++ b/src/opensearch/src/opensearch.pri @@ -0,0 +1,6 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +LIBS += -L$$BUILDDIR \ + -Wl,-rpath,$$BUILDDIR \ + -lqopensearch diff --git a/src/opensearch/opensearch.pri b/src/opensearch/src/opensearch.pro index dbace74..cbd1499 100644 --- a/src/opensearch/opensearch.pri +++ b/src/opensearch/src/opensearch.pro @@ -1,26 +1,23 @@ +TEMPLATE = lib +TARGET = qopensearch +CONFIG += dll + +include(../build.pri) +DESTDIR = $$BUILDDIR + INCLUDEPATH += $$PWD DEPENDPATH += $$PWD +QT += network script + HEADERS += \ - opensearchdialog.h \ opensearchengine.h \ opensearchenginedelegate.h \ - opensearchengineaction.h \ - opensearchenginemodel.h \ - opensearchmanager.h \ opensearchreader.h \ opensearchwriter.h SOURCES += \ - opensearchdialog.cpp \ opensearchengine.cpp \ opensearchenginedelegate.cpp \ - opensearchengineaction.cpp \ - opensearchenginemodel.cpp \ - opensearchmanager.cpp \ opensearchreader.cpp \ opensearchwriter.cpp - -FORMS += opensearchdialog.ui - -QT += script diff --git a/src/opensearch/opensearchengine.cpp b/src/opensearch/src/opensearchengine.cpp index 0332fc1..a0dfa6d 100644 --- a/src/opensearch/opensearchengine.cpp +++ b/src/opensearch/src/opensearchengine.cpp @@ -24,6 +24,7 @@ #include <qbuffer.h> #include <qcoreapplication.h> #include <qlocale.h> +#include <qnetworkaccessmanager.h> #include <qnetworkrequest.h> #include <qnetworkreply.h> #include <qregexp.h> @@ -31,6 +32,45 @@ #include <qscriptvalue.h> #include <qstringlist.h> +class OpenSearchEnginePrivate +{ +public: + OpenSearchEnginePrivate(); + + QString name; + QString description; + + QString imageUrl; + QImage image; + + QStringList tags; + + QString searchUrlTemplate; + QString suggestionsUrlTemplate; + OpenSearchEngine::Parameters searchParameters; + OpenSearchEngine::Parameters suggestionsParameters; + QString searchMethod; + QString suggestionsMethod; + + QMap<QString, QNetworkAccessManager::Operation> requestMethods; + + QNetworkAccessManager *networkAccessManager; + QNetworkReply *suggestionsReply; + + QScriptEngine *scriptEngine; + + OpenSearchEngineDelegate *delegate; +}; + +OpenSearchEnginePrivate::OpenSearchEnginePrivate() + : searchMethod(QLatin1String("get")) + , suggestionsMethod(QLatin1String("get")) + , networkAccessManager(0) + , suggestionsReply(0) + , scriptEngine(0) + , delegate(0) +{} + /*! \class OpenSearchEngine \brief A class representing a single search engine described in OpenSearch format @@ -83,15 +123,10 @@ */ OpenSearchEngine::OpenSearchEngine(QObject *parent) : QObject(parent) - , m_searchMethod(QLatin1String("get")) - , m_suggestionsMethod(QLatin1String("get")) - , m_networkAccessManager(0) - , m_suggestionsReply(0) - , m_scriptEngine(0) - , m_delegate(0) + , d(new OpenSearchEnginePrivate()) { - m_requestMethods.insert(QLatin1String("get"), QNetworkAccessManager::GetOperation); - m_requestMethods.insert(QLatin1String("post"), QNetworkAccessManager::PostOperation); + d->requestMethods.insert(QLatin1String("get"), QNetworkAccessManager::GetOperation); + d->requestMethods.insert(QLatin1String("post"), QNetworkAccessManager::PostOperation); } /*! @@ -99,8 +134,9 @@ OpenSearchEngine::OpenSearchEngine(QObject *parent) */ OpenSearchEngine::~OpenSearchEngine() { - if (m_scriptEngine) - m_scriptEngine->deleteLater(); + if (d->scriptEngine) + d->scriptEngine->deleteLater(); + delete d; } QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString &searchTemplate) @@ -130,12 +166,12 @@ QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString */ QString OpenSearchEngine::name() const { - return m_name; + return d->name; } void OpenSearchEngine::setName(const QString &name) { - m_name = name; + d->name = name; } /*! @@ -146,12 +182,12 @@ void OpenSearchEngine::setName(const QString &name) */ QString OpenSearchEngine::description() const { - return m_description; + return d->description; } void OpenSearchEngine::setDescription(const QString &description) { - m_description = description; + d->description = description; } /*! @@ -162,12 +198,12 @@ void OpenSearchEngine::setDescription(const QString &description) */ QString OpenSearchEngine::searchUrlTemplate() const { - return m_searchUrlTemplate; + return d->searchUrlTemplate; } void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate) { - m_searchUrlTemplate = searchUrlTemplate; + d->searchUrlTemplate = searchUrlTemplate; } /*! @@ -202,14 +238,14 @@ void OpenSearchEngine::setSearchUrlTemplate(const QString &searchUrlTemplate) */ QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const { - if (m_searchUrlTemplate.isEmpty()) + if (d->searchUrlTemplate.isEmpty()) return QUrl(); - QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_searchUrlTemplate).toUtf8()); + QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, d->searchUrlTemplate).toUtf8()); - if (m_searchMethod != QLatin1String("post")) { - Parameters::const_iterator end = m_searchParameters.constEnd(); - Parameters::const_iterator i = m_searchParameters.constBegin(); + if (d->searchMethod != QLatin1String("post")) { + Parameters::const_iterator end = d->searchParameters.constEnd(); + Parameters::const_iterator i = d->searchParameters.constBegin(); for (; i != end; ++i) retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); } @@ -223,7 +259,7 @@ QUrl OpenSearchEngine::searchUrl(const QString &searchTerm) const */ bool OpenSearchEngine::providesSuggestions() const { - return !m_suggestionsUrlTemplate.isEmpty(); + return !d->suggestionsUrlTemplate.isEmpty(); } /*! @@ -234,12 +270,12 @@ bool OpenSearchEngine::providesSuggestions() const */ QString OpenSearchEngine::suggestionsUrlTemplate() const { - return m_suggestionsUrlTemplate; + return d->suggestionsUrlTemplate; } void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTemplate) { - m_suggestionsUrlTemplate = suggestionsUrlTemplate; + d->suggestionsUrlTemplate = suggestionsUrlTemplate; } /*! @@ -254,14 +290,14 @@ void OpenSearchEngine::setSuggestionsUrlTemplate(const QString &suggestionsUrlTe */ QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const { - if (m_suggestionsUrlTemplate.isEmpty()) + if (d->suggestionsUrlTemplate.isEmpty()) return QUrl(); - QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, m_suggestionsUrlTemplate).toUtf8()); + QUrl retVal = QUrl::fromEncoded(parseTemplate(searchTerm, d->suggestionsUrlTemplate).toUtf8()); - if (m_suggestionsMethod != QLatin1String("post")) { - Parameters::const_iterator end = m_suggestionsParameters.constEnd(); - Parameters::const_iterator i = m_suggestionsParameters.constBegin(); + if (d->suggestionsMethod != QLatin1String("post")) { + Parameters::const_iterator end = d->suggestionsParameters.constEnd(); + Parameters::const_iterator i = d->suggestionsParameters.constBegin(); for (; i != end; ++i) retVal.addQueryItem(i->first, parseTemplate(searchTerm, i->second)); } @@ -278,12 +314,12 @@ QUrl OpenSearchEngine::suggestionsUrl(const QString &searchTerm) const */ OpenSearchEngine::Parameters OpenSearchEngine::searchParameters() const { - return m_searchParameters; + return d->searchParameters; } void OpenSearchEngine::setSearchParameters(const Parameters &searchParameters) { - m_searchParameters = searchParameters; + d->searchParameters = searchParameters; } /*! @@ -295,12 +331,12 @@ void OpenSearchEngine::setSearchParameters(const Parameters &searchParameters) */ OpenSearchEngine::Parameters OpenSearchEngine::suggestionsParameters() const { - return m_suggestionsParameters; + return d->suggestionsParameters; } void OpenSearchEngine::setSuggestionsParameters(const Parameters &suggestionsParameters) { - m_suggestionsParameters = suggestionsParameters; + d->suggestionsParameters = suggestionsParameters; } /*! @@ -309,16 +345,16 @@ void OpenSearchEngine::setSuggestionsParameters(const Parameters &suggestionsPar */ QString OpenSearchEngine::searchMethod() const { - return m_searchMethod; + return d->searchMethod; } void OpenSearchEngine::setSearchMethod(const QString &method) { QString requestMethod = method.toLower(); - if (!m_requestMethods.contains(requestMethod)) + if (!d->requestMethods.contains(requestMethod)) return; - m_searchMethod = requestMethod; + d->searchMethod = requestMethod; } /*! @@ -327,16 +363,16 @@ void OpenSearchEngine::setSearchMethod(const QString &method) */ QString OpenSearchEngine::suggestionsMethod() const { - return m_suggestionsMethod; + return d->suggestionsMethod; } void OpenSearchEngine::setSuggestionsMethod(const QString &method) { QString requestMethod = method.toLower(); - if (!m_requestMethods.contains(requestMethod)) + if (!d->requestMethods.contains(requestMethod)) return; - m_suggestionsMethod = requestMethod; + d->suggestionsMethod = requestMethod; } /*! @@ -353,20 +389,20 @@ void OpenSearchEngine::setSuggestionsMethod(const QString &method) */ QString OpenSearchEngine::imageUrl() const { - return m_imageUrl; + return d->imageUrl; } void OpenSearchEngine::setImageUrl(const QString &imageUrl) { - m_imageUrl = imageUrl; + d->imageUrl = imageUrl; } void OpenSearchEngine::loadImage() const { - if (!m_networkAccessManager || m_imageUrl.isEmpty()) + if (!d->networkAccessManager || d->imageUrl.isEmpty()) return; - QNetworkReply *reply = m_networkAccessManager->get(QNetworkRequest(QUrl::fromEncoded(m_imageUrl.toUtf8()))); + QNetworkReply *reply = d->networkAccessManager->get(QNetworkRequest(QUrl::fromEncoded(d->imageUrl.toUtf8()))); connect(reply, SIGNAL(finished()), this, SLOT(imageObtained())); } @@ -385,7 +421,7 @@ void OpenSearchEngine::imageObtained() if (response.isEmpty()) return; - m_image.loadFromData(response); + d->image.loadFromData(response); emit imageChanged(); } @@ -400,49 +436,63 @@ void OpenSearchEngine::imageObtained() */ QImage OpenSearchEngine::image() const { - if (m_image.isNull()) + if (d->image.isNull()) loadImage(); - return m_image; + return d->image; } void OpenSearchEngine::setImage(const QImage &image) { - if (m_imageUrl.isEmpty()) { + if (d->imageUrl.isEmpty()) { QBuffer imageBuffer; imageBuffer.open(QBuffer::ReadWrite); if (image.save(&imageBuffer, "PNG")) { - m_imageUrl = QString(QLatin1String("data:image/png;base64,%1")) + d->imageUrl = QString(QLatin1String("data:image/png;base64,%1")) .arg(QLatin1String(imageBuffer.buffer().toBase64())); } } - m_image = image; + d->image = image; emit imageChanged(); } /*! + \property tags + \brief a set of words that are used as keywords to identify and categorize this search content +*/ +QStringList OpenSearchEngine::tags() const +{ + return d->tags; +} + +void OpenSearchEngine::setTags(const QStringList &tags) +{ + d->tags = tags; +} + +/*! \property valid \brief indicates whether the engine is valid i.e. the description was properly formed and included all necessary information */ bool OpenSearchEngine::isValid() const { - return (!m_name.isEmpty() && !m_searchUrlTemplate.isEmpty()); + return (!d->name.isEmpty() && !d->searchUrlTemplate.isEmpty()); } bool OpenSearchEngine::operator==(const OpenSearchEngine &other) const { - return (m_name == other.m_name - && m_description == other.m_description - && m_imageUrl == other.m_imageUrl - && m_searchUrlTemplate == other.m_searchUrlTemplate - && m_suggestionsUrlTemplate == other.m_suggestionsUrlTemplate - && m_searchParameters == other.m_searchParameters - && m_suggestionsParameters == other.m_suggestionsParameters); + return (d->name == other.d->name + && d->description == other.d->description + && d->imageUrl == other.d->imageUrl + && d->searchUrlTemplate == other.d->searchUrlTemplate + && d->suggestionsUrlTemplate == other.d->suggestionsUrlTemplate + && d->searchParameters == other.d->searchParameters + && d->suggestionsParameters == other.d->suggestionsParameters); } bool OpenSearchEngine::operator<(const OpenSearchEngine &other) const { - return (m_name < other.m_name); + return (d->name < other.d->name); } /*! @@ -460,33 +510,33 @@ void OpenSearchEngine::requestSuggestions(const QString &searchTerm) if (searchTerm.isEmpty() || !providesSuggestions()) return; - Q_ASSERT(m_networkAccessManager); + Q_ASSERT(d->networkAccessManager); - if (!m_networkAccessManager) + if (!d->networkAccessManager) return; - if (m_suggestionsReply) { - m_suggestionsReply->disconnect(this); - m_suggestionsReply->abort(); - m_suggestionsReply->deleteLater(); - m_suggestionsReply = 0; + if (d->suggestionsReply) { + d->suggestionsReply->disconnect(this); + d->suggestionsReply->abort(); + d->suggestionsReply->deleteLater(); + d->suggestionsReply = 0; } - Q_ASSERT(m_requestMethods.contains(m_suggestionsMethod)); - if (m_suggestionsMethod == QLatin1String("get")) { - m_suggestionsReply = m_networkAccessManager->get(QNetworkRequest(suggestionsUrl(searchTerm))); + Q_ASSERT(d->requestMethods.contains(d->suggestionsMethod)); + if (d->suggestionsMethod == QLatin1String("get")) { + d->suggestionsReply = d->networkAccessManager->get(QNetworkRequest(suggestionsUrl(searchTerm))); } else { QStringList parameters; - Parameters::const_iterator end = m_suggestionsParameters.constEnd(); - Parameters::const_iterator i = m_suggestionsParameters.constBegin(); + Parameters::const_iterator end = d->suggestionsParameters.constEnd(); + Parameters::const_iterator i = d->suggestionsParameters.constBegin(); for (; i != end; ++i) parameters.append(i->first + QLatin1String("=") + i->second); QByteArray data = parameters.join(QLatin1String("&")).toUtf8(); - m_suggestionsReply = m_networkAccessManager->post(QNetworkRequest(suggestionsUrl(searchTerm)), data); + d->suggestionsReply = d->networkAccessManager->post(QNetworkRequest(suggestionsUrl(searchTerm)), data); } - connect(m_suggestionsReply, SIGNAL(finished()), this, SLOT(suggestionsObtained())); + connect(d->suggestionsReply, SIGNAL(finished()), this, SLOT(suggestionsObtained())); } /*! @@ -501,36 +551,36 @@ void OpenSearchEngine::requestSuggestions(const QString &searchTerm) */ void OpenSearchEngine::requestSearchResults(const QString &searchTerm) { - if (!m_delegate || searchTerm.isEmpty()) + if (!d->delegate || searchTerm.isEmpty()) return; - Q_ASSERT(m_requestMethods.contains(m_searchMethod)); + Q_ASSERT(d->requestMethods.contains(d->searchMethod)); QNetworkRequest request(QUrl(searchUrl(searchTerm))); QByteArray data; - QNetworkAccessManager::Operation operation = m_requestMethods.value(m_searchMethod); + QNetworkAccessManager::Operation operation = d->requestMethods.value(d->searchMethod); if (operation == QNetworkAccessManager::PostOperation) { QStringList parameters; - Parameters::const_iterator end = m_searchParameters.constEnd(); - Parameters::const_iterator i = m_searchParameters.constBegin(); + Parameters::const_iterator end = d->searchParameters.constEnd(); + Parameters::const_iterator i = d->searchParameters.constBegin(); for (; i != end; ++i) parameters.append(i->first + QLatin1String("=") + i->second); data = parameters.join(QLatin1String("&")).toUtf8(); } - m_delegate->performSearchRequest(request, operation, data); + d->delegate->performSearchRequest(request, operation, data); } void OpenSearchEngine::suggestionsObtained() { - QString response(QString::fromUtf8(m_suggestionsReply->readAll())); + QString response(QString::fromUtf8(d->suggestionsReply->readAll())); response = response.trimmed(); - m_suggestionsReply->close(); - m_suggestionsReply->deleteLater(); - m_suggestionsReply = 0; + d->suggestionsReply->close(); + d->suggestionsReply->deleteLater(); + d->suggestionsReply = 0; if (response.isEmpty()) return; @@ -538,14 +588,14 @@ void OpenSearchEngine::suggestionsObtained() if (!response.startsWith(QLatin1Char('[')) || !response.endsWith(QLatin1Char(']'))) return; - if (!m_scriptEngine) - m_scriptEngine = new QScriptEngine(); + if (!d->scriptEngine) + d->scriptEngine = new QScriptEngine(); // Evaluate the JSON response using QtScript. - if (!m_scriptEngine->canEvaluate(response)) + if (!d->scriptEngine->canEvaluate(response)) return; - QScriptValue responseParts = m_scriptEngine->evaluate(response); + QScriptValue responseParts = d->scriptEngine->evaluate(response); if (!responseParts.property(1).isArray()) return; @@ -565,12 +615,12 @@ void OpenSearchEngine::suggestionsObtained() */ QNetworkAccessManager *OpenSearchEngine::networkAccessManager() const { - return m_networkAccessManager; + return d->networkAccessManager; } void OpenSearchEngine::setNetworkAccessManager(QNetworkAccessManager *networkAccessManager) { - m_networkAccessManager = networkAccessManager; + d->networkAccessManager = networkAccessManager; } /*! @@ -582,12 +632,12 @@ void OpenSearchEngine::setNetworkAccessManager(QNetworkAccessManager *networkAcc */ OpenSearchEngineDelegate *OpenSearchEngine::delegate() const { - return m_delegate; + return d->delegate; } void OpenSearchEngine::setDelegate(OpenSearchEngineDelegate *delegate) { - m_delegate = delegate; + d->delegate = delegate; } /*! diff --git a/src/opensearch/opensearchengine.h b/src/opensearch/src/opensearchengine.h index 3ec63d2..6197f38 100644 --- a/src/opensearch/opensearchengine.h +++ b/src/opensearch/src/opensearchengine.h @@ -23,14 +23,16 @@ #include <qpair.h> #include <qimage.h> #include <qmap.h> -#include <qnetworkaccessmanager.h> #include <qstring.h> +#include <qstringlist.h> #include <qurl.h> +class QNetworkAccessManager; class QNetworkReply; class QScriptEngine; class OpenSearchEngineDelegate; +class OpenSearchEnginePrivate; class OpenSearchEngine : public QObject { Q_OBJECT @@ -53,8 +55,9 @@ public: Q_PROPERTY(QString suggestionsMethod READ suggestionsMethod WRITE setSuggestionsMethod) Q_PROPERTY(bool providesSuggestions READ providesSuggestions) Q_PROPERTY(QString imageUrl READ imageUrl WRITE setImageUrl) + Q_PROPERTY(QStringList tags READ tags WRITE setTags) Q_PROPERTY(bool valid READ isValid) - Q_PROPERTY(QNetworkAccessManager *networkAccessManager READ networkAccessManager WRITE setNetworkAccessManager) + Q_PROPERTY(QNetworkAccessManager* networkAccessManager READ networkAccessManager WRITE setNetworkAccessManager) OpenSearchEngine(QObject *parent = 0); ~OpenSearchEngine(); @@ -93,6 +96,9 @@ public: QImage image() const; void setImage(const QImage &image); + QStringList tags() const; + void setTags(const QStringList &tags); + bool isValid() const; QNetworkAccessManager *networkAccessManager() const; @@ -117,28 +123,7 @@ private slots: void suggestionsObtained(); private: - QString m_name; - QString m_description; - - QString m_imageUrl; - QImage m_image; - - QString m_searchUrlTemplate; - QString m_suggestionsUrlTemplate; - Parameters m_searchParameters; - Parameters m_suggestionsParameters; - QString m_searchMethod; - QString m_suggestionsMethod; - - QMap<QString, QNetworkAccessManager::Operation> m_requestMethods; - - QNetworkAccessManager *m_networkAccessManager; - QNetworkReply *m_suggestionsReply; - - QScriptEngine *m_scriptEngine; - - OpenSearchEngineDelegate *m_delegate; + OpenSearchEnginePrivate *d; }; #endif // OPENSEARCHENGINE_H - diff --git a/src/opensearch/opensearchenginedelegate.cpp b/src/opensearch/src/opensearchenginedelegate.cpp index d31569a..d31569a 100644 --- a/src/opensearch/opensearchenginedelegate.cpp +++ b/src/opensearch/src/opensearchenginedelegate.cpp diff --git a/src/opensearch/opensearchenginedelegate.h b/src/opensearch/src/opensearchenginedelegate.h index 5de3c59..5de3c59 100644 --- a/src/opensearch/opensearchenginedelegate.h +++ b/src/opensearch/src/opensearchenginedelegate.h diff --git a/src/opensearch/src/opensearchreader.cpp b/src/opensearch/src/opensearchreader.cpp new file mode 100644 index 0000000..c758434 --- /dev/null +++ b/src/opensearch/src/opensearchreader.cpp @@ -0,0 +1,229 @@ +/* + * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> + * + * 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 + */ + +#include "opensearchreader.h" + +#include "opensearchengine.h" + +#include <qiodevice.h> + +/*! + \class OpenSearchReader + \brief A class reading a search engine description from an external source + + OpenSearchReader is a class that can be used to read search engine descriptions + formed using the OpenSearch format. + + It inherits QXmlStreamReader and thus provides additional functions, such as + QXmlStreamReader::error(), QXmlStreamReader::hasError() that can be used to make sure + the reading procedure succeeded. + + For more information see: + http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_description_document + + \sa OpenSearchEngine, OpenSearchWriter +*/ + +/*! + Constructs a new reader. + + \note One instance can be used to read multiple files, one by one. +*/ +OpenSearchReader::OpenSearchReader() + : QXmlStreamReader() + , m_engine(0) +{ +} + +/*! + Reads an OpenSearch engine from the \a device and returns an OpenSearchEngine object, + filled in with all the data that has been retrieved from the document. + + If the \a device is closed, it will be opened. + + To make sure if the procedure succeeded, check QXmlStreamReader::error(). + + \return a new constructed OpenSearchEngine object + + \note The function returns an object of the OpenSearchEngine class even if the document + is bad formed or doesn't conform to the specification. It needs to be manually + deleted afterwards, if intended. + \note The lifetime of the returned OpenSearchEngine object is up to the user. + The object should be deleted once it is not used anymore to avoid memory leaks. +*/ +OpenSearchEngine *OpenSearchReader::read(QIODevice *device) +{ + m_engine = 0; + clear(); + + if (!device->isOpen()) + device->open(QIODevice::ReadOnly); + + setDevice(device); + readDocument(); + return m_engine; +} + +#include <qdebug.h> + +void OpenSearchReader::readDocument() +{ + m_engine = new OpenSearchEngine(); + + while (!isStartElement() && !atEnd()) + readNext(); + + if (name() != QLatin1String("OpenSearchDescription") + || namespaceUri() != QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) { + raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); + return; + } + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (!isStartElement()) + continue; + + if (name() == QLatin1String("ShortName")) + readName(); + else if (name() == QLatin1String("Description")) + readDescription(); + else if (name() == QLatin1String("Url")) + readUrl(); + else if (name() == QLatin1String("Image")) + readImage(); + else if (name() == QLatin1String("Tags")) + readTags(); + else + skipSubtree(); + } +} + +void OpenSearchReader::readName() +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("ShortName")); + m_engine->setName(readElementText()); +} + +void OpenSearchReader::readDescription() +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("Description")); + m_engine->setDescription(readElementText()); +} + +void OpenSearchReader::readUrl() +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("Url")); + + QString type = attributes().value(QLatin1String("type")).toString(); + QString url = attributes().value(QLatin1String("template")).toString(); + QString method = attributes().value(QLatin1String("method")).toString(); + + if (type.isEmpty() || type == QLatin1String("application/xhtml+xml")) + type = QLatin1String("text/html"); + + if (url.isEmpty()) { + skipSubtree(); + return; + } + + if (type == QLatin1String("application/x-suggestions+json") + && !m_engine->suggestionsUrlTemplate().isEmpty()) { + skipSubtree(); + return; + } + + if (type == QLatin1String("text/html") + && !m_engine->searchUrlTemplate().isEmpty()) { + skipSubtree(); + return; + } + + OpenSearchEngine::Parameters parameters; + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (!isStartElement()) + continue; + + if (name() == QLatin1String("Param") || name() == QLatin1String("Parameter")) + readParameter(¶meters); + else + skipSubtree(); + } + + if (type == QLatin1String("application/x-suggestions+json")) { + m_engine->setSuggestionsUrlTemplate(url); + m_engine->setSuggestionsParameters(parameters); + m_engine->setSuggestionsMethod(method); + } else if (type == QLatin1String("text/html")) { + m_engine->setSearchUrlTemplate(url); + m_engine->setSearchParameters(parameters); + m_engine->setSearchMethod(method); + } +} + +void OpenSearchReader::readParameter(OpenSearchEngine::Parameters *parameters) +{ + Q_ASSERT(isStartElement() && (name() == QLatin1String("Param") || name() == QLatin1String("Parameter"))); + + QString key = attributes().value(QLatin1String("name")).toString(); + QString value = attributes().value(QLatin1String("value")).toString(); + + if (key.isEmpty() || value.isEmpty()) + return; + + parameters->append(OpenSearchEngine::Parameter(key, value)); + readNext(); +} + +void OpenSearchReader::readImage() +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("Image")); + m_engine->setImageUrl(readElementText()); +} + +void OpenSearchReader::readTags() +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("Tags")); + m_engine->setTags(readElementText().split(QLatin1Char(' '), QString::SkipEmptyParts)); +} + +void OpenSearchReader::skipSubtree() +{ + Q_ASSERT(isStartElement()); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + skipSubtree(); + } +} diff --git a/src/opensearch/opensearchreader.h b/src/opensearch/src/opensearchreader.h index a4f11bc..fadcbc6 100644 --- a/src/opensearch/opensearchreader.h +++ b/src/opensearch/src/opensearchreader.h @@ -22,19 +22,26 @@ #include <qxmlstream.h> -class OpenSearchEngine; +#include "opensearchengine.h" class OpenSearchReader : public QXmlStreamReader { public: OpenSearchReader(); - OpenSearchEngine *read(QIODevice *device); private: - OpenSearchEngine *read(); + void readDocument(); + void readName(); + void readDescription(); + void readUrl(); + void readParameter(OpenSearchEngine::Parameters *parameters); + void readImage(); + void readTags(); + void skipSubtree(); +private: + OpenSearchEngine *m_engine; }; #endif // OPENSEARCHREADER_H - diff --git a/src/opensearch/opensearchwriter.cpp b/src/opensearch/src/opensearchwriter.cpp index 10b7c54..3877006 100644 --- a/src/opensearch/opensearchwriter.cpp +++ b/src/opensearch/src/opensearchwriter.cpp @@ -130,6 +130,9 @@ void OpenSearchWriter::write(OpenSearchEngine *engine) if (!engine->imageUrl().isEmpty()) writeTextElement(QLatin1String("Image"), engine->imageUrl()); + if (!engine->tags().isEmpty()) + writeTextElement(QLatin1String("Tags"), engine->tags().join(QLatin1String(" "))); + writeEndElement(); writeEndDocument(); } diff --git a/src/opensearch/opensearchwriter.h b/src/opensearch/src/opensearchwriter.h index ab7fd61..fdd552f 100644 --- a/src/opensearch/opensearchwriter.h +++ b/src/opensearch/src/opensearchwriter.h @@ -37,4 +37,3 @@ private: }; #endif // OPENSEARCHWRITER_H - diff --git a/src/opensearch/tests/opensearchengine/.gitignore b/src/opensearch/tests/opensearchengine/.gitignore new file mode 100644 index 0000000..b4eb4cd --- /dev/null +++ b/src/opensearch/tests/opensearchengine/.gitignore @@ -0,0 +1 @@ +tst_opensearchengine diff --git a/src/opensearch/tests/opensearchengine/opensearchengine.pro b/src/opensearch/tests/opensearchengine/opensearchengine.pro new file mode 100644 index 0000000..0c5f37b --- /dev/null +++ b/src/opensearch/tests/opensearchengine/opensearchengine.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = tst_opensearchengine + +QT += network + +include(../tests.pri) +include(../../src/opensearch.pri) + +SOURCES += \ + tst_opensearchengine.cpp + +RESOURCES += \ + opensearchengine.qrc diff --git a/src/opensearch/tests/opensearchengine/opensearchengine.qrc b/src/opensearch/tests/opensearchengine/opensearchengine.qrc new file mode 100644 index 0000000..8d254e0 --- /dev/null +++ b/src/opensearch/tests/opensearchengine/opensearchengine.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>suggestions.txt</file> +</qresource> +</RCC> diff --git a/src/opensearch/tests/opensearchengine/suggestions.txt b/src/opensearch/tests/opensearchengine/suggestions.txt new file mode 100644 index 0000000..73a1e67 --- /dev/null +++ b/src/opensearch/tests/opensearchengine/suggestions.txt @@ -0,0 +1 @@ +["sea", ["sears", "search engines", "search engine", "search", "sears.com", "seattle times"], ["7,390,000 results", "17,900,000 results", "25,700,000 results", "1,220,000,000 results", "1 result", "17,600,000 results"], ["http://example.com?q=sears", "http://example.com?q=search+engines", "http://example.com?q=search+engine", "http://example.com?q=search", "http://example.com?q=sears.com", "http://example.com?q=seattle+times"]]
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp b/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp new file mode 100644 index 0000000..5bf3e05 --- /dev/null +++ b/src/opensearch/tests/opensearchengine/tst_opensearchengine.cpp @@ -0,0 +1,910 @@ +/* + * Copyright 2009 Benjamin C. Meyer <ben@meyerhome.net> + * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> + * + * 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 + */ + +#include <qtest.h> +#include "qtry.h" +#include "opensearchengine.h" +#include "opensearchenginedelegate.h" + +#include <qbuffer.h> +#include <qfile.h> +#include <qlocale.h> +#include <qnetworkaccessmanager.h> +#include <qnetworkreply.h> +#include <qnetworkrequest.h> +#include <qsignalspy.h> +#include <qtimer.h> + +typedef OpenSearchEngine::Parameters Parameters; +typedef OpenSearchEngine::Parameter Parameter; + +class tst_OpenSearchEngine : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void opensearchengine_data(); + void opensearchengine(); + + void description_data(); + void description(); + void image(); + void imageUrl_data(); + void imageUrl(); + void isValid_data(); + void isValid(); + void name_data(); + void name(); + void operatorlessthan(); + void operatorequal_data(); + void operatorequal(); + void providesSuggestions_data(); + void providesSuggestions(); + void requestSuggestions_data(); + void requestSuggestions(); + void requestSuggestionsCrash(); + void searchParameters_data(); + void searchParameters(); + void searchUrl_data(); + void searchUrl(); + void searchUrlTemplate_data(); + void searchUrlTemplate(); + void suggestionsParameters_data(); + void suggestionsParameters(); + void suggestionsUrl_data(); + void suggestionsUrl(); + void suggestionsUrlTemplate_data(); + void suggestionsUrlTemplate(); + void parseTemplate_data(); + void parseTemplate(); + void languageCodes_data(); + void languageCodes(); + void requestMethods(); + void delegate(); +}; + +// Subclass that exposes the protected functions. +class SubOpenSearchEngine : public OpenSearchEngine +{ +public: + void call_imageChanged() + { return SubOpenSearchEngine::imageChanged(); } + + void call_loadImage() const + { return SubOpenSearchEngine::loadImage(); } + + QString call_parseTemplate(QString const &searchTerm, QString const &searchTemplate) const + { return SubOpenSearchEngine::parseTemplate(searchTerm, searchTemplate); } + + void call_suggestions(QStringList const &suggestions) + { return SubOpenSearchEngine::suggestions(suggestions); } +}; + +class SuggestionsTestNetworkReply : public QNetworkReply +{ + Q_OBJECT + +public: + SuggestionsTestNetworkReply(const QNetworkRequest &request, QObject *parent = 0) + : QNetworkReply(parent) + { + setOperation(QNetworkAccessManager::GetOperation); + setRequest(request); + setUrl(request.url()); + setOpenMode(QIODevice::ReadOnly); + + expectedResult.setFileName(":/suggestions.txt"); + expectedResult.open(QIODevice::ReadOnly); + setError(QNetworkReply::NoError, tr("No Error")); + + QTimer::singleShot(50, this, SLOT(sendSuggestions())); + } + + ~SuggestionsTestNetworkReply() + { + close(); + } + + qint64 bytesAvailable() const + { + return expectedResult.bytesAvailable() + QNetworkReply::bytesAvailable(); + } + + void close() + { + expectedResult.close(); + } + + qint64 readData(char *data, qint64 maxSize) + { + return expectedResult.read(data, maxSize); + } + + void abort() + { + } + +private slots: + void sendSuggestions() + { + // Publish result + setHeader(QNetworkRequest::ContentTypeHeader, QByteArray("text/html")); + setHeader(QNetworkRequest::ContentLengthHeader, expectedResult.bytesAvailable()); + setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200); + setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, QByteArray("Ok")); + + emit metaDataChanged(); + emit readyRead(); + emit downloadProgress(expectedResult.size(), expectedResult.size()); + emit finished(); + } + +private: + QFile expectedResult; +}; + +class SuggestionsTestNetworkAccessManager : public QNetworkAccessManager +{ +public: + SuggestionsTestNetworkAccessManager(QObject *parent = 0) + : QNetworkAccessManager(parent) + { + } + + QNetworkRequest lastRequest; + Operation lastOperation; + bool lastOutgoingData; + +protected: + QNetworkReply *createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *outgoingData = 0) + { + lastOperation = operation; + lastRequest = request; + lastOutgoingData = (bool)outgoingData; + + return new SuggestionsTestNetworkReply(request, 0); + } +}; + +class Delegate : public OpenSearchEngineDelegate +{ + public: + Delegate() + : OpenSearchEngineDelegate() + , callsCount(0) + { + } + + ~Delegate() + { + } + + void performSearchRequest(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation, + const QByteArray &data) + { + ++callsCount; + lastRequest = request; + lastOperation = operation; + lastData = data; + } + + QNetworkRequest lastRequest; + QNetworkAccessManager::Operation lastOperation; + QByteArray lastData; + int callsCount; +}; + +// This will be called before the first test function is executed. +// It is only called once. +void tst_OpenSearchEngine::initTestCase() +{ + QCoreApplication::setApplicationName("tst_opensearchengine"); +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_OpenSearchEngine::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_OpenSearchEngine::init() +{ +} + +// This will be called after every test function. +void tst_OpenSearchEngine::cleanup() +{ +} + +void tst_OpenSearchEngine::opensearchengine_data() +{ +} + +void tst_OpenSearchEngine::opensearchengine() +{ + SubOpenSearchEngine engine; + QCOMPARE(engine.description(), QString()); + QCOMPARE(engine.image(), QImage()); + QCOMPARE(engine.imageUrl(), QString()); + QCOMPARE(engine.isValid(), false); + QCOMPARE(engine.name(), QString()); + OpenSearchEngine other; + QCOMPARE(engine.operator<(other), false); + QCOMPARE(engine.operator==(other), true); + QCOMPARE(engine.providesSuggestions(), false); + engine.requestSuggestions(QString()); + QCOMPARE(engine.searchParameters(), QList<Parameter>()); + QCOMPARE(engine.searchUrl(QString()), QUrl()); + QCOMPARE(engine.searchUrlTemplate(), QString()); + engine.setDescription(QString()); + engine.setImage(QImage()); + engine.setImageUrl(QString()); + engine.setName(QString()); + engine.setSearchParameters(QList<Parameter>()); + engine.setSearchUrlTemplate(QString()); + engine.setSuggestionsParameters(QList<Parameter>()); + engine.setSuggestionsUrlTemplate(QString()); + QCOMPARE(engine.suggestionsParameters(), QList<Parameter>()); + QCOMPARE(engine.suggestionsUrl(QString()), QUrl()); + QCOMPARE(engine.suggestionsUrlTemplate(), QString()); + QCOMPARE(engine.tags(), QStringList()); + engine.setTags(QStringList() << "foo" << "bar"); + QCOMPARE(engine.tags(), QStringList() << "foo" << "bar"); + engine.call_imageChanged(); + engine.call_loadImage(); + QVERIFY(!engine.networkAccessManager()); + QNetworkAccessManager manager; + engine.setNetworkAccessManager(&manager); + QCOMPARE(engine.networkAccessManager(), &manager); + QCOMPARE(engine.call_parseTemplate(QString(), QString()), QString()); + engine.call_suggestions(QStringList()); +} + +void tst_OpenSearchEngine::description_data() +{ + QTest::addColumn<QString>("description"); + QTest::newRow("null") << QString(); + QTest::newRow("foo") << QString("foo"); +} + +// public QString description() const +void tst_OpenSearchEngine::description() +{ + QFETCH(QString, description); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setDescription(description); + QCOMPARE(engine.description(), description); + QCOMPARE(engine.property("description").toString(), description); + engine.setProperty("description", QString()); + QCOMPARE(engine.property("description").toString(), QString()); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +// public QImage image() const +void tst_OpenSearchEngine::image() +{ + SubOpenSearchEngine engine; + + QNetworkAccessManager manager; + engine.setNetworkAccessManager(&manager); + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + QBuffer imageBuffer; + imageBuffer.open(QBuffer::ReadWrite); + QPixmap image(1, 1); + image.fill(); + image.save(&imageBuffer, "PNG"); + QString imageUrl = QString("data:image/png;base64,").append(imageBuffer.buffer().toBase64()); + engine.setImageUrl(imageUrl); + QCOMPARE(engine.image(), QImage()); + + QTRY_COMPARE(spy0.count(), 1); + QCOMPARE(spy1.count(), 0); + QVERIFY(engine.image() != QImage()); + + SubOpenSearchEngine engine2; + QSignalSpy spy2(&engine2, SIGNAL(imageChanged())); + + QVERIFY(engine2.imageUrl().isEmpty()); + engine2.setImage(engine.image()); + QCOMPARE(engine2.imageUrl(), imageUrl); + + QCOMPARE(spy2.count(), 1); +} + +void tst_OpenSearchEngine::imageUrl_data() +{ + QTest::addColumn<QString>("imageUrl"); + QTest::newRow("null") << QString(); + QTest::newRow("foo") << QString("foo"); +} + +// public QString imageUrl() const +void tst_OpenSearchEngine::imageUrl() +{ + QFETCH(QString, imageUrl); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setImageUrl(imageUrl); + QCOMPARE(engine.imageUrl(), imageUrl); + QCOMPARE(engine.property("imageUrl").toString(), imageUrl); + engine.setProperty("imageUrl", QString()); + QCOMPARE(engine.property("imageUrl").toString(), QString()); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::isValid_data() +{ + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::addColumn<bool>("isValid"); + QTest::newRow("false-0") << QString() << QString() << false; + QTest::newRow("false-1") << QString() << QString("x") << false; + QTest::newRow("false-2") << QString("x") << QString() << false; + QTest::newRow("true") << QString("x") << QString("y") << true; +} + +// public bool isValid() const +void tst_OpenSearchEngine::isValid() +{ + QFETCH(QString, name); + QFETCH(QString, searchUrlTemplate); + QFETCH(bool, isValid); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setName(name); + engine.setSearchUrlTemplate(searchUrlTemplate); + QCOMPARE(engine.isValid(), isValid); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::name_data() +{ + QTest::addColumn<QString>("name"); + QTest::newRow("null") << QString(); + QTest::newRow("foo") << QString("foo"); +} + +// public QString name() const +void tst_OpenSearchEngine::name() +{ + QFETCH(QString, name); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setName(name); + QCOMPARE(engine.name(), name); + QCOMPARE(engine.property("name").toString(), name); + engine.setProperty("name", QString()); + QCOMPARE(engine.property("name").toString(), QString()); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +// public bool operator<(OpenSearchEngine const &other) const +void tst_OpenSearchEngine::operatorlessthan() +{ + SubOpenSearchEngine engine1; + engine1.setName("a"); + SubOpenSearchEngine engine2; + engine2.setName("b"); + + QVERIFY(engine1 < engine2); +} + +Q_DECLARE_METATYPE(Parameters) +void tst_OpenSearchEngine::operatorequal_data() +{ + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("description"); + QTest::addColumn<QString>("imageUrl"); + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::addColumn<Parameters>("searchParameters"); + QTest::addColumn<Parameters>("suggestionsParameters"); + QTest::addColumn<bool>("operatorequal"); + QTest::newRow("null") << QString() << QString() << QString() << QString() << QString() + << Parameters() << Parameters() + << true; + QTest::newRow("name") << QString("x") << QString() << QString() << QString() << QString() + << Parameters() << Parameters() + << false; + QTest::newRow("description") << QString() << QString("x") << QString() << QString() << QString() + << Parameters() << Parameters() + << false; + QTest::newRow("imageUrl") << QString() << QString() << QString("x") << QString() << QString() + << Parameters() << Parameters() + << false; + QTest::newRow("parameters") << QString() << QString() << QString() << QString() << QString() + << (Parameters() << Parameter("a", "b")) << Parameters() + << false; +} + +// public bool operator==(OpenSearchEngine const &other) const +void tst_OpenSearchEngine::operatorequal() +{ + QFETCH(QString, name); + QFETCH(QString, description); + QFETCH(QString, imageUrl); + QFETCH(QString, searchUrlTemplate); + QFETCH(QString, suggestionsUrlTemplate); + QFETCH(Parameters, searchParameters); + QFETCH(Parameters, suggestionsParameters); + QFETCH(bool, operatorequal); + + SubOpenSearchEngine engine; + SubOpenSearchEngine other; + other.setName(name); + other.setDescription(description); + other.setImageUrl(imageUrl); + other.setSearchUrlTemplate(searchUrlTemplate); + other.setSuggestionsUrlTemplate(suggestionsUrlTemplate); + other.setSearchParameters(searchParameters); + other.setSuggestionsParameters(suggestionsParameters); + + QCOMPARE(engine.operator==(other), operatorequal); +} + +void tst_OpenSearchEngine::providesSuggestions_data() +{ + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::addColumn<bool>("providesSuggestions"); + QTest::newRow("false") << QString() << false; + QTest::newRow("true") << QString("foo") << true; +} + +// public bool providesSuggestions() const +void tst_OpenSearchEngine::providesSuggestions() +{ + QFETCH(QString, suggestionsUrlTemplate); + QFETCH(bool, providesSuggestions); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate); + QCOMPARE(engine.providesSuggestions(), providesSuggestions); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::requestSuggestions_data() +{ + QTest::addColumn<QString>("searchTerm"); + QTest::addColumn<QString>("method"); + QTest::addColumn<QNetworkAccessManager::Operation>("lastOperation"); + QTest::newRow("null") << QString() << QString() << QNetworkAccessManager::GetOperation; + QTest::newRow("foo") << QString("foo") << QString("get") << QNetworkAccessManager::GetOperation; + QTest::newRow("bar") << QString("bar") << QString("post") << QNetworkAccessManager::PostOperation; + QTest::newRow("baz") << QString("baz") << QString("put") << QNetworkAccessManager::GetOperation; +} + +Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) +// public void requestSuggestions(QString const &searchTerm) +void tst_OpenSearchEngine::requestSuggestions() +{ + QFETCH(QString, searchTerm); + QFETCH(QString, method); + QFETCH(QNetworkAccessManager::Operation, lastOperation); + + SuggestionsTestNetworkAccessManager manager; + SubOpenSearchEngine engine; + engine.setNetworkAccessManager(&manager); + engine.setSuggestionsMethod(method); + engine.setSuggestionsUrlTemplate("http://foobar.baz"); + engine.setSuggestionsParameters(Parameters() << Parameter("a", "b")); + + QVERIFY(engine.providesSuggestions()); + + QSignalSpy spy(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.requestSuggestions(searchTerm); + + if (searchTerm.isEmpty()) { + QTest::qWait(200); + QCOMPARE(spy.count(), 0); + } else { + QTRY_COMPARE(spy.count(), 1); + + QStringList suggestions; + suggestions << "sears" << "search engines" << "search engine" << "search" << "sears.com" << "seattle times"; + QCOMPARE(spy.at(0).at(0).toStringList(), suggestions); + + QCOMPARE(manager.lastOperation, lastOperation); + QCOMPARE(manager.lastOutgoingData, lastOperation == QNetworkAccessManager::PostOperation); + } +} + +void tst_OpenSearchEngine::requestSuggestionsCrash() +{ + SuggestionsTestNetworkAccessManager manager; + SubOpenSearchEngine engine; + engine.setNetworkAccessManager(&manager); + engine.setSuggestionsUrlTemplate("http://foobar.baz"); + + QVERIFY(engine.providesSuggestions()); + + QSignalSpy spy(&engine, SIGNAL(suggestions(QStringList const&))); + + QStringList colors = QColor::colorNames(); + + for (int i = 0; i < colors.count(); ++i) + engine.requestSuggestions(colors.at(i)); + + QTRY_COMPARE(spy.count(), 1); + + QStringList suggestions; + suggestions << "sears" << "search engines" << "search engine" << "search" << "sears.com" << "seattle times"; + QCOMPARE(spy.at(0).at(0).toStringList(), suggestions); +} + +void tst_OpenSearchEngine::searchParameters_data() +{ + QTest::addColumn<Parameters>("searchParameters"); + QTest::newRow("null") << QList<Parameter>(); + QTest::newRow("something") << (Parameters() << Parameter("a", "b")); +} + +// public QList<Parameter> searchParameters() const +void tst_OpenSearchEngine::searchParameters() +{ + QFETCH(Parameters, searchParameters); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setSearchParameters(searchParameters); + QCOMPARE(engine.searchParameters(), searchParameters); + QCOMPARE(qvariant_cast<Parameters>(engine.property("searchParameters")), searchParameters); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::searchUrl_data() +{ + QTest::addColumn<QString>("searchTerm"); + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::addColumn<Parameters>("parameters"); + QTest::addColumn<QUrl>("searchUrl"); + QTest::newRow("null") << QString() << QString() << Parameters() << QUrl(); + QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}") + << Parameters() << QUrl(QString("http://foobar.baz/?q=foo")); + QTest::newRow("empty") << QString() << QString("http://foobar.baz/?q={searchTerms}") + << Parameters() << QUrl(QString("http://foobar.baz/?q=")); + QTest::newRow("parameters") << QString("baz") << QString("http://foobar.baz/?q={searchTerms}") + << (Parameters() << Parameter("abc", "{searchTerms}") << Parameter("x", "yz")) + << QUrl(QString("http://foobar.baz/?q=baz&abc=baz&x=yz")); +} + +// public QUrl searchUrl(QString const &searchTerm) const +void tst_OpenSearchEngine::searchUrl() +{ + QFETCH(QString, searchTerm); + QFETCH(QString, searchUrlTemplate); + QFETCH(Parameters, parameters); + QFETCH(QUrl, searchUrl); + + SubOpenSearchEngine engine; + engine.setSearchParameters(parameters); + engine.setSearchUrlTemplate(searchUrlTemplate); + + QCOMPARE(engine.searchUrl(searchTerm), searchUrl); +} + +void tst_OpenSearchEngine::searchUrlTemplate_data() +{ + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::newRow("null") << QString(); + QTest::newRow("foo") << QString("foo"); +} + +// public QString searchUrlTemplate() const +void tst_OpenSearchEngine::searchUrlTemplate() +{ + QFETCH(QString, searchUrlTemplate); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setSearchUrlTemplate(searchUrlTemplate); + QCOMPARE(engine.property("searchUrlTemplate").toString(), searchUrlTemplate); + engine.setProperty("searchUrlTemplate", QString()); + QCOMPARE(engine.property("searchUrlTemplate").toString(), QString()); + engine.setProperty("searchUrlTemplate", searchUrlTemplate); + QCOMPARE(engine.searchUrlTemplate(), searchUrlTemplate); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::suggestionsParameters_data() +{ + QTest::addColumn<Parameters>("suggestionsParameters"); + QTest::newRow("null") << QList<Parameter>(); + QTest::newRow("something") << (Parameters() << Parameter("a", "b")); +} + +// public QList<Parameter> suggestionsParameters() const +void tst_OpenSearchEngine::suggestionsParameters() +{ + QFETCH(Parameters, suggestionsParameters); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setSuggestionsParameters(suggestionsParameters); + QCOMPARE(engine.suggestionsParameters(), suggestionsParameters); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::suggestionsUrl_data() +{ + QTest::addColumn<QString>("searchTerm"); + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::addColumn<Parameters>("parameters"); + QTest::addColumn<QUrl>("suggestionsUrl"); + QTest::newRow("null") << QString() << QString() << Parameters() << QUrl(); + QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}") + << Parameters() << QUrl(QString("http://foobar.baz/?q=foo")); + QTest::newRow("empty") << QString() << QString("http://foobar.baz/?q={searchTerms}") + << Parameters() << QUrl(QString("http://foobar.baz/?q=")); + QTest::newRow("parameters") << QString("baz") << QString("http://foobar.baz/?q={searchTerms}") + << (Parameters() << Parameter("a", "bc")) + << QUrl(QString("http://foobar.baz/?q=baz&a=bc")); +} + +// public QUrl suggestionsUrl(QString const &searchTerm) const +void tst_OpenSearchEngine::suggestionsUrl() +{ + QFETCH(QString, searchTerm); + QFETCH(QString, suggestionsUrlTemplate); + QFETCH(Parameters, parameters); + QFETCH(QUrl, suggestionsUrl); + + SubOpenSearchEngine engine; + engine.setSuggestionsParameters(parameters); + engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate); + + QCOMPARE(engine.suggestionsUrl(searchTerm), suggestionsUrl); +} + +void tst_OpenSearchEngine::suggestionsUrlTemplate_data() +{ + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::newRow("null") << QString(); + QTest::newRow("foo") << QString("foo"); +} + +// public QString suggestionsUrlTemplate() const +void tst_OpenSearchEngine::suggestionsUrlTemplate() +{ + QFETCH(QString, suggestionsUrlTemplate); + + SubOpenSearchEngine engine; + + QSignalSpy spy0(&engine, SIGNAL(imageChanged())); + QSignalSpy spy1(&engine, SIGNAL(suggestions(QStringList const&))); + + engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate); + QCOMPARE(engine.suggestionsUrlTemplate(), suggestionsUrlTemplate); + + QCOMPARE(spy0.count(), 0); + QCOMPARE(spy1.count(), 0); +} + +void tst_OpenSearchEngine::parseTemplate_data() +{ + QString lang = QLocale().name().replace(QLatin1Char('_'), QLatin1Char('-')); + + QTest::addColumn<QString>("searchTerm"); + QTest::addColumn<QString>("searchTemplate"); + QTest::addColumn<QString>("parseTemplate"); + QTest::addColumn<bool>("valid"); + QTest::newRow("null") << QString() << QString() << QString() << false; + QTest::newRow("foo") << QString("foo") << QString("http://foobar.baz/?q={searchTerms}") + << QString("http://foobar.baz/?q=foo") << true; + QTest::newRow("allParameters") << QString("bar") + << QString("http://foobar.baz/?st={searchTerms}&c={count}" + "&si={startIndex}&sp={startPage}&l={language}" + "&ie={inputEncoding}&oe={outputEncoding}") + << QString("http://foobar.baz/?st=bar&c=20&si=0&" + "sp=0&l=%1&ie=UTF-8&oe=UTF-8").arg(lang) + << true; + QTest::newRow("tricky") << QString("{count}") << QString("http://foobar.baz/q={searchTerms}&count={count}") + << QString("http://foobar.baz/q=%7Bcount%7D&count=20") << true; + QTest::newRow("multiple") << QString("abc") << QString("http://foobar.baz/?q={searchTerms}&x={searchTerms}") + << QString("http://foobar.baz/?q=abc&x=abc") << true; + QTest::newRow("referrer") << QString("foo") + << QString("http://foobar.baz/?q={searchTerms}&a={source}&b={ref:source}&c={referrer:source?}") + << QString("http://foobar.baz/?q=foo&a=tst_opensearchengine" + "&b=tst_opensearchengine&c=tst_opensearchengine") + << true; + QTest::newRow("inputEncoding") << QString("c++") << QString("http://foobar.baz/?q={searchTerms}") + << QString("http://foobar.baz/?q=c%2B%2B") << true; +} + +// protected QString parseTemplate(QString const &searchTerm, QString const &searchTemplate) const +void tst_OpenSearchEngine::parseTemplate() +{ + QFETCH(QString, searchTerm); + QFETCH(QString, searchTemplate); + QFETCH(QString, parseTemplate); + QFETCH(bool, valid); + + SubOpenSearchEngine engine; + QString url = engine.call_parseTemplate(searchTerm, searchTemplate); + QCOMPARE(url, parseTemplate); + QCOMPARE(QUrl(url).isValid(), valid); +} + +void tst_OpenSearchEngine::languageCodes_data() +{ + QTest::addColumn<QString>("languageCode"); + QTest::addColumn<QString>("url"); + + QTest::newRow("es") << QString("es") << QString("http://foobar.baz/?l=es-ES"); + QTest::newRow("pt_BR") << QString("pt_BR") << QString("http://foobar.baz/?l=pt-BR"); +} + +void tst_OpenSearchEngine::languageCodes() +{ + QFETCH(QString, languageCode); + QFETCH(QString, url); + + QLocale::setDefault(QLocale(languageCode)); + + SubOpenSearchEngine engine; + QCOMPARE(engine.call_parseTemplate(QString("foo"), QString("http://foobar.baz/?l={language}")), url); +} + +void tst_OpenSearchEngine::requestMethods() +{ + SubOpenSearchEngine engine; + + QCOMPARE(engine.searchMethod(), QString("get")); + QCOMPARE(engine.suggestionsMethod(), QString("get")); + + engine.setSearchMethod("post"); + QCOMPARE(engine.searchMethod(), QString("post")); + QCOMPARE(engine.suggestionsMethod(), QString("get")); + + engine.setSearchMethod("get"); + QCOMPARE(engine.searchMethod(), QString("get")); + QCOMPARE(engine.suggestionsMethod(), QString("get")); + + engine.setSuggestionsMethod("PoSt"); + QCOMPARE(engine.searchMethod(), QString("get")); + QCOMPARE(engine.suggestionsMethod(), QString("post")); + + engine.setSearchMethod("foo"); + QCOMPARE(engine.searchMethod(), QString("get")); + QCOMPARE(engine.suggestionsMethod(), QString("post")); + + engine.setSuggestionsMethod("bar"); + QCOMPARE(engine.searchMethod(), QString("get")); + QCOMPARE(engine.suggestionsMethod(), QString("post")); +} + +void tst_OpenSearchEngine::delegate() +{ + SubOpenSearchEngine engine; + engine.setName(QString("foo")); + engine.setDescription(QString("bar")); + engine.setSearchUrlTemplate(QString("http://foobar.baz/?q={searchTerms}")); + + QCOMPARE(engine.delegate(), (Delegate*)0); + engine.setDelegate(0); + QCOMPARE(engine.delegate(), (Delegate*)0); + engine.requestSearchResults(QString("baz")); + + Delegate delegate; + engine.setDelegate(&delegate); + QCOMPARE(engine.delegate(), &delegate); + engine.requestSearchResults(QString("baz")); + + QCOMPARE(delegate.callsCount, 1); + QCOMPARE(delegate.lastOperation, QNetworkAccessManager::GetOperation); + QCOMPARE(delegate.lastData, QByteArray()); + QNetworkRequest request(QUrl(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate()))); + QCOMPARE(delegate.lastRequest, request); + QVERIFY(delegate.lastRequest.url().hasQueryItem("q")); + QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz")); + + engine.setSearchParameters(Parameters() << Parameter("a", "b") << Parameter("b", "c")); + engine.requestSearchResults(QString("baz")); + + QCOMPARE(delegate.callsCount, 2); + QCOMPARE(delegate.lastOperation, QNetworkAccessManager::GetOperation); + QCOMPARE(delegate.lastData, QByteArray()); + + QVERIFY(delegate.lastRequest.url().hasQueryItem("a")); + QCOMPARE(delegate.lastRequest.url().queryItemValue("a"), QString("b")); + QVERIFY(delegate.lastRequest.url().hasQueryItem("b")); + QCOMPARE(delegate.lastRequest.url().queryItemValue("b"), QString("c")); + QVERIFY(delegate.lastRequest.url().hasQueryItem("q")); + QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz")); + + QUrl url(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate())); + QCOMPARE(delegate.lastRequest.url().toString(QUrl::RemoveQuery), url.toString(QUrl::RemoveQuery)); + + engine.setSearchMethod(QString("post")); + engine.requestSearchResults(QString("baz")); + + QCOMPARE(delegate.callsCount, 3); + QCOMPARE(delegate.lastOperation, QNetworkAccessManager::PostOperation); + request = QNetworkRequest(QUrl(engine.call_parseTemplate(QString("baz"), engine.searchUrlTemplate()))); + QCOMPARE(delegate.lastRequest, request); + QVERIFY(delegate.lastRequest.url().hasQueryItem("q")); + QCOMPARE(delegate.lastRequest.url().queryItemValue("q"), QString("baz")); + + QVERIFY(!delegate.lastData.isEmpty()); + QStringList query = QString(delegate.lastData).split('&'); + QCOMPARE(query.count(), 2); + QCOMPARE(query, QStringList() << "a=b" << "b=c"); +} + +QTEST_MAIN(tst_OpenSearchEngine) +#include "tst_opensearchengine.moc" + diff --git a/src/opensearch/tests/opensearchreader/.gitignore b/src/opensearch/tests/opensearchreader/.gitignore new file mode 100644 index 0000000..bcc3fd0 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/.gitignore @@ -0,0 +1 @@ +tst_opensearchreader diff --git a/src/opensearch/tests/opensearchreader/opensearchreader.pro b/src/opensearch/tests/opensearchreader/opensearchreader.pro new file mode 100644 index 0000000..cb17f92 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/opensearchreader.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = tst_opensearchreader + +include(../tests.pri) +include(../../src/opensearch.pri) + +SOURCES += \ + tst_opensearchreader.cpp + +RESOURCES += \ + opensearchreader.qrc diff --git a/src/opensearch/tests/opensearchreader/opensearchreader.qrc b/src/opensearch/tests/opensearchreader/opensearchreader.qrc new file mode 100644 index 0000000..ad2044c --- /dev/null +++ b/src/opensearch/tests/opensearchreader/opensearchreader.qrc @@ -0,0 +1,12 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>testfile1.xml</file> + <file>testfile2.xml</file> + <file>testfile3.xml</file> + <file>testfile4.xml</file> + <file>testfile5.xml</file> + <file>testfile6.xml</file> + <file>testfile7.xml</file> + <file>testfile8.xml</file> +</qresource> +</RCC> diff --git a/src/opensearch/tests/opensearchreader/testfile1.xml b/src/opensearch/tests/opensearchreader/testfile1.xml new file mode 100644 index 0000000..ee1ed1c --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile1.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Wikipedia (en)</ShortName> + <Description >Full text search in the English Wikipedia</Description> + <Url method="get" type="application/rss+xml" template="http://en.wikipedia.org/rss" /> + <Url method="post" type="text/html" template="http://en.wikipedia.org/bar" /> + <Url method="get" type="application/x-suggestions+json" template="http://en.wikipedia.org/foo" /> + <Url method="get" template="http://en.wikipedia.org/baz" /> + <Image width="16" height="16">http://en.wikipedia.org/favicon.ico</Image> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile2.xml b/src/opensearch/tests/opensearchreader/testfile2.xml new file mode 100644 index 0000000..0a620b4 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile2.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Wikipedia (en)</ShortName> + <Url method="get" type="application/x-suggestions+json" template="http://en.wikipedia.org/foo" /> + <Image width="16" height="16">http://en.wikipedia.org/favicon.ico</Image> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile3.xml b/src/opensearch/tests/opensearchreader/testfile3.xml new file mode 100644 index 0000000..c778e26 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile3.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>GitHub</ShortName> + <Description>Search GitHub</Description> + <Url type="text/html" method="get" template="http://github.com/search"> + <Param name="q" value="{searchTerms}"/> + <Parameter name="b" value="foo"/> + </Url> + <Url method="post" type="application/x-suggestions+json" template="http://github.com/suggestions"> + <Parameter name="bar" value="baz"/> + </Url> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile4.xml b/src/opensearch/tests/opensearchreader/testfile4.xml new file mode 100644 index 0000000..9c484a2 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile4.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Google</ShortName> + <Description>Google Web Search</Description> + <Url method="get" type="text/html" template="http://www.google.com/search?bar" /> + <Url method="get" type="application/x-suggestions+json" template="http://suggestqueries.google.com/complete/foo" /> + <Image width="16" height="16">http://www.google.com/favicon.ico</Image> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile5.xml b/src/opensearch/tests/opensearchreader/testfile5.xml new file mode 100644 index 0000000..266e4b1 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile5.xml @@ -0,0 +1 @@ +<foo><bar></bar></foo>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile6.xml b/src/opensearch/tests/opensearchreader/testfile6.xml new file mode 100644 index 0000000..4495beb --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile6.xml @@ -0,0 +1,5 @@ +<OpenSearchDescription> + <ShortName>Google</ShortName> + <Description>Google Web Search</Description> + <Url method="get" type="text/html" template="http://www.google.com/search?bar" /> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/testfile7.xml b/src/opensearch/tests/opensearchreader/testfile7.xml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile7.xml diff --git a/src/opensearch/tests/opensearchreader/testfile8.xml b/src/opensearch/tests/opensearchreader/testfile8.xml new file mode 100644 index 0000000..c203851 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/testfile8.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Web Search</ShortName> + <Description>Use Example.com to search the Web.</Description> + <Tags>example web</Tags> + <!-- <Contact>admin@example.com</Contact> --> + <Url type="text/html" template="http://example.com/"/> +</OpenSearchDescription>
\ No newline at end of file diff --git a/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp b/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp new file mode 100644 index 0000000..8b0f677 --- /dev/null +++ b/src/opensearch/tests/opensearchreader/tst_opensearchreader.cpp @@ -0,0 +1,163 @@ +/* + * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> + * + * 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 + */ + +#include <QtTest/QtTest> + +#include "opensearchreader.h" +#include "opensearchengine.h" + +typedef OpenSearchEngine::Parameters Parameters; +typedef OpenSearchEngine::Parameter Parameter; + +class tst_OpenSearchReader : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void read_data(); + void read(); +}; + +// This will be called before the first test function is executed. +// It is only called once. +void tst_OpenSearchReader::initTestCase() +{ +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_OpenSearchReader::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_OpenSearchReader::init() +{ +} + +// This will be called after every test function. +void tst_OpenSearchReader::cleanup() +{ +} + +Q_DECLARE_METATYPE(Parameters) +void tst_OpenSearchReader::read_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<bool>("valid"); + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("description"); + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::addColumn<QString>("imageUrl"); + QTest::addColumn<Parameters>("searchParameters"); + QTest::addColumn<Parameters>("suggestionsParameters"); + QTest::addColumn<QString>("searchMethod"); + QTest::addColumn<QString>("suggestionsMethod"); + QTest::addColumn<QStringList>("tags"); + + QTest::newRow("null") << QString(":/doesNotExist") << false << QString() << QString() << QString() << QString() + << QString() << Parameters() << Parameters() << QString("get") + << QString("get") << QStringList(); + + QTest::newRow("testfile1") << QString(":/testfile1.xml") << true << QString("Wikipedia (en)") + << QString("Full text search in the English Wikipedia") << QString("http://en.wikipedia.org/bar") + << QString("http://en.wikipedia.org/foo") << QString("http://en.wikipedia.org/favicon.ico") + << Parameters() << Parameters() << QString("post") + << QString("get") << QStringList(); + + QTest::newRow("testfile2") << QString(":/testfile2.xml") << false << QString("Wikipedia (en)") + << QString() << QString() << QString("http://en.wikipedia.org/foo") << QString("http://en.wikipedia.org/favicon.ico") + << Parameters() << Parameters() << QString("get") + << QString("get") << QStringList(); + + QTest::newRow("testfile3") << QString(":/testfile3.xml") << true << QString("GitHub") << QString("Search GitHub") + << QString("http://github.com/search") << QString("http://github.com/suggestions") << QString() + << (Parameters() << Parameter(QString("q"), QString("{searchTerms}")) + << Parameter(QString("b"), QString("foo"))) + << (Parameters() << Parameter(QString("bar"), QString("baz"))) + << QString("get") << QString("post") << QStringList(); + + QTest::newRow("testfile4") << QString(":/testfile4.xml") << true << QString("Google") << QString("Google Web Search") + << QString("http://www.google.com/search?bar") << QString("http://suggestqueries.google.com/complete/foo") + << QString("http://www.google.com/favicon.ico") << Parameters() + << Parameters() << QString("get") << QString("get") << QStringList(); + + QTest::newRow("testfile5") << QString(":/testfile5.xml") << false << QString() << QString() << QString() << QString() + << QString() << Parameters() << Parameters() << QString("get") + << QString("get") << QStringList(); + + QTest::newRow("testfile6") << QString(":/testfile6.xml") << false << QString() << QString() << QString() << QString() + << QString() << Parameters() << Parameters() << QString("get") + << QString("get") << QStringList(); + + QTest::newRow("testfile7") << QString(":/testfile7.xml") << false << QString() << QString() << QString() << QString() + << QString() << Parameters() << Parameters() << QString("get") + << QString("get") << QStringList(); + + QTest::newRow("testfile8") << QString(":/testfile8.xml") << true << QString("Web Search") << QString("Use Example.com to search the Web.") + << QString("http://example.com/") << QString() << QString() << Parameters() << Parameters() << QString("get") + << QString("get") << (QStringList() << "example" << "web"); +} + +void tst_OpenSearchReader::read() +{ + QFETCH(QString, fileName); + QFETCH(bool, valid); + QFETCH(QString, name); + QFETCH(QString, description); + QFETCH(QString, searchUrlTemplate); + QFETCH(QString, suggestionsUrlTemplate); + QFETCH(QString, imageUrl); + QFETCH(Parameters, searchParameters); + QFETCH(Parameters, suggestionsParameters); + QFETCH(QString, searchMethod); + QFETCH(QString, suggestionsMethod); + QFETCH(QStringList, tags); + + QFile file(fileName); + file.open(QIODevice::ReadOnly); + OpenSearchReader reader; + OpenSearchEngine *engine = reader.read(&file); + + QCOMPARE(engine->isValid(), valid); + QCOMPARE(engine->name(), name); + QCOMPARE(engine->description(), description); + QCOMPARE(engine->searchUrlTemplate(), searchUrlTemplate); + QCOMPARE(engine->suggestionsUrlTemplate(), suggestionsUrlTemplate); + QCOMPARE(engine->searchParameters(), searchParameters); + QCOMPARE(engine->suggestionsParameters(), suggestionsParameters); + QCOMPARE(engine->imageUrl(), imageUrl); + QCOMPARE(engine->searchMethod(), searchMethod); + QCOMPARE(engine->suggestionsMethod(), suggestionsMethod); + QCOMPARE(engine->tags(), tags); + + delete engine; +} + +QTEST_MAIN(tst_OpenSearchReader) + +#include "tst_opensearchreader.moc" + diff --git a/src/opensearch/tests/opensearchwriter/.gitignore b/src/opensearch/tests/opensearchwriter/.gitignore new file mode 100644 index 0000000..a2db00e --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/.gitignore @@ -0,0 +1 @@ +tst_opensearchwriter diff --git a/src/opensearch/tests/opensearchwriter/opensearchwriter.pro b/src/opensearch/tests/opensearchwriter/opensearchwriter.pro new file mode 100644 index 0000000..c88b532 --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/opensearchwriter.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = tst_opensearchwriter + +include(../tests.pri) +include(../../src/opensearch.pri) + +SOURCES += \ + tst_opensearchwriter.cpp + +RESOURCES += \ + opensearchwriter.qrc diff --git a/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc b/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc new file mode 100644 index 0000000..0c9fde0 --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/opensearchwriter.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>testfile1.xml</file> + <file>testfile2.xml</file> + <file>testfile3.xml</file> +</qresource> +</RCC> diff --git a/src/opensearch/tests/opensearchwriter/testfile1.xml b/src/opensearch/tests/opensearchwriter/testfile1.xml new file mode 100644 index 0000000..04c05a3 --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/testfile1.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Foo Bar</ShortName> + <Description>Bar Foo</Description> + <Url method="get" type="text/html" template="http://foobar.barfoo/search"/> +</OpenSearchDescription> diff --git a/src/opensearch/tests/opensearchwriter/testfile2.xml b/src/opensearch/tests/opensearchwriter/testfile2.xml new file mode 100644 index 0000000..78e4360 --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/testfile2.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Arora!</ShortName> + <Description>a cross platform web browser built using Qt and WebKit</Description> + <Url method="get" type="text/html" template="http://foobar.barfoo/search"/> + <Url method="post" type="application/x-suggestions+json" template="http://foobar.barfoo/suggest"/> + <Tags>foo bar</Tags> +</OpenSearchDescription> diff --git a/src/opensearch/tests/opensearchwriter/testfile3.xml b/src/opensearch/tests/opensearchwriter/testfile3.xml new file mode 100644 index 0000000..058f5ea --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/testfile3.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Foo Bar</ShortName> + <Description>Bar Foo</Description> + <Url method="post" type="text/html" template="http://foobar.barfoo/search" xmlns:p="http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"> + <p:Parameter name="q" value="{searchTerms}"/> + <p:Parameter name="a" value="foo"/> + </Url> + <Url method="get" type="application/x-suggestions+json" template="http://foobar.barfoo/suggest" xmlns:p="http://a9.com/-/spec/opensearch/extensions/parameters/1.0/"> + <p:Parameter name="q" value="{searchTerms}"/> + </Url> +</OpenSearchDescription> diff --git a/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp b/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp new file mode 100644 index 0000000..a87f0df --- /dev/null +++ b/src/opensearch/tests/opensearchwriter/tst_opensearchwriter.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2009 Jakub Wieczorek <faw217@gmail.com> + * + * 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 + */ + +#include <QtTest/QtTest> + +#include "opensearchwriter.h" +#include "opensearchengine.h" + +class tst_OpenSearchWriter : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void write_data(); + void write(); +}; + +// This will be called before the first test function is executed. +// It is only called once. +void tst_OpenSearchWriter::initTestCase() +{ +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_OpenSearchWriter::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_OpenSearchWriter::init() +{ +} + +// This will be called after every test function. +void tst_OpenSearchWriter::cleanup() +{ +} + +Q_DECLARE_METATYPE(OpenSearchEngine::Parameters) +void tst_OpenSearchWriter::write_data() +{ + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("description"); + QTest::addColumn<QString>("searchUrlTemplate"); + QTest::addColumn<QString>("suggestionsUrlTemplate"); + QTest::addColumn<QString>("imageUrl"); + QTest::addColumn<OpenSearchEngine::Parameters>("searchParameters"); + QTest::addColumn<OpenSearchEngine::Parameters>("suggestionsParameters"); + QTest::addColumn<QString>("searchMethod"); + QTest::addColumn<QString>("suggestionsMethod"); + QTest::addColumn<QStringList>("tags"); + QTest::addColumn<QString>("fileName"); + + QTest::newRow("testfile1") << QString("Foo Bar") << QString("Bar Foo") << QString("http://foobar.barfoo/search") << QString() + << QString() << OpenSearchEngine::Parameters() << OpenSearchEngine::Parameters() + << QString() << QString("get") << QStringList() << QString(":/testfile1.xml"); + + QTest::newRow("testfile2") << QString("Arora!") << QString("a cross platform web browser built using Qt and WebKit") + << QString("http://foobar.barfoo/search") << QString("http://foobar.barfoo/suggest") << QString() + << OpenSearchEngine::Parameters() << OpenSearchEngine::Parameters() << QString("get") << QString("post") + << (QStringList() << "foo" << "bar") << QString(":/testfile2.xml"); + + QTest::newRow("testile3") << QString("Foo Bar") << QString("Bar Foo") << QString("http://foobar.barfoo/search") + << QString("http://foobar.barfoo/suggest") << QString() + << (OpenSearchEngine::Parameters() << OpenSearchEngine::Parameter("q", "{searchTerms}") << OpenSearchEngine::Parameter("a", "foo")) + << (OpenSearchEngine::Parameters() << OpenSearchEngine::Parameter("q", "{searchTerms}")) + << QString("post") << QString("foo") << QStringList() << QString(":/testfile3.xml"); +} + +void tst_OpenSearchWriter::write() +{ + QFETCH(QString, name); + QFETCH(QString, description); + QFETCH(QString, searchUrlTemplate); + QFETCH(QString, suggestionsUrlTemplate); + QFETCH(QString, imageUrl); + QFETCH(OpenSearchEngine::Parameters, searchParameters); + QFETCH(OpenSearchEngine::Parameters, suggestionsParameters); + QFETCH(QString, searchMethod); + QFETCH(QString, suggestionsMethod); + QFETCH(QStringList, tags); + QFETCH(QString, fileName); + + OpenSearchEngine engine; + OpenSearchWriter writer; + + engine.setName(name); + engine.setDescription(description); + engine.setSearchUrlTemplate(searchUrlTemplate); + engine.setSuggestionsUrlTemplate(suggestionsUrlTemplate); + engine.setImageUrl(imageUrl); + engine.setSearchParameters(searchParameters); + engine.setSuggestionsParameters(suggestionsParameters); + engine.setSearchMethod(searchMethod); + engine.setSuggestionsMethod(suggestionsMethod); + engine.setTags(tags); + + QByteArray output; + QBuffer buffer(&output); + writer.write(&buffer, &engine); + + QFile expected(fileName); + expected.open(QIODevice::ReadOnly); + + QCOMPARE(output, expected.readAll()); +} + +QTEST_MAIN(tst_OpenSearchWriter) + +#include "tst_opensearchwriter.moc" + diff --git a/src/opensearch/tests/qtry.h b/src/opensearch/tests/qtry.h new file mode 100644 index 0000000..4d9b712 --- /dev/null +++ b/src/opensearch/tests/qtry.h @@ -0,0 +1,49 @@ +/* + * Copyright 2008-2009 Benjamin C. Meyer <ben@meyerhome.net> + * + * 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 + */ + +#ifndef QTRY_H +#define QTRY_H + +#include <qtest.h> + +#ifndef QTRY_COMPARE + +#define __TRY_TIMEOUT__ 5000 +#define __TRY_STEP__ 50 + +#define __QTRY(__expression__, __functionToCall__) \ + do { \ + int __i = 0; \ + while (!(__expression__) && __i < __TRY_TIMEOUT__) { \ + QTest::qWait(__TRY_STEP__); \ + __i += __TRY_STEP__; \ + } \ + __functionToCall__; \ + } while(0) + +#define QTRY_COMPARE(__expression__, __expected__) \ + __QTRY((__expression__ == __expected__), QCOMPARE(__expression__, __expected__)); + +#define QTRY_VERIFY(__expression__) \ + __QTRY(__expression__, QVERIFY(__expression__)); + +#endif // QTRY_COMPARE + +#endif // QTRY_H + diff --git a/src/opensearch/tests/tests.pri b/src/opensearch/tests/tests.pri new file mode 100644 index 0000000..096f22a --- /dev/null +++ b/src/opensearch/tests/tests.pri @@ -0,0 +1,12 @@ +win32: CONFIG += console +mac:CONFIG -= app_bundle + +CONFIG += qtestlib + +HEADERS += qtry.h + +include(../build.pri) +DESTDIR = $$BUILDDIR/tests + +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD diff --git a/src/opensearch/tests/tests.pro b/src/opensearch/tests/tests.pro new file mode 100644 index 0000000..0660b2c --- /dev/null +++ b/src/opensearch/tests/tests.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = opensearchengine opensearchreader opensearchwriter + +CONFIG += ordered diff --git a/src/opensearch/opensearchdialog.cpp b/src/opensearchdialog.cpp index 94fdf8d..94fdf8d 100644 --- a/src/opensearch/opensearchdialog.cpp +++ b/src/opensearchdialog.cpp diff --git a/src/opensearch/opensearchdialog.h b/src/opensearchdialog.h index 5f50e97..5f50e97 100644 --- a/src/opensearch/opensearchdialog.h +++ b/src/opensearchdialog.h diff --git a/src/opensearch/opensearchdialog.ui b/src/opensearchdialog.ui index 1e503e5..1e503e5 100644 --- a/src/opensearch/opensearchdialog.ui +++ b/src/opensearchdialog.ui diff --git a/src/opensearch/opensearchengineaction.cpp b/src/opensearchengineaction.cpp index 6674022..6674022 100644 --- a/src/opensearch/opensearchengineaction.cpp +++ b/src/opensearchengineaction.cpp diff --git a/src/opensearch/opensearchengineaction.h b/src/opensearchengineaction.h index aeb93b2..aeb93b2 100644 --- a/src/opensearch/opensearchengineaction.h +++ b/src/opensearchengineaction.h diff --git a/src/opensearch/opensearchenginemodel.cpp b/src/opensearchenginemodel.cpp index a35f1bb..a35f1bb 100644 --- a/src/opensearch/opensearchenginemodel.cpp +++ b/src/opensearchenginemodel.cpp diff --git a/src/opensearch/opensearchenginemodel.h b/src/opensearchenginemodel.h index 23001cf..23001cf 100644 --- a/src/opensearch/opensearchenginemodel.h +++ b/src/opensearchenginemodel.h diff --git a/src/opensearch/opensearchmanager.cpp b/src/opensearchmanager.cpp index d9bb0a2..d9bb0a2 100644 --- a/src/opensearch/opensearchmanager.cpp +++ b/src/opensearchmanager.cpp diff --git a/src/opensearch/opensearchmanager.h b/src/opensearchmanager.h index 1d3f33c..1d3f33c 100644 --- a/src/opensearch/opensearchmanager.h +++ b/src/opensearchmanager.h diff --git a/src/src.pri b/src/src.pri index 7c1a0e3..0b602da 100644 --- a/src/src.pri +++ b/src/src.pri @@ -7,7 +7,7 @@ win32|os2 : Debug : CONFIG += console INCLUDEPATH += $$PWD DEPENDPATH += $$PWD -QT += webkit network +QT += webkit network script # Share object files for faster compiling RCC_DIR = $$PWD/.rcc @@ -30,6 +30,7 @@ FORMS += \ acceptlanguagedialog.ui \ downloaditem.ui \ downloads.ui \ + opensearchdialog.ui \ searchbanner.ui \ settings.ui @@ -46,6 +47,10 @@ HEADERS += \ downloadmanager.h \ modelmenu.h \ modeltoolbar.h \ + opensearchdialog.h \ + opensearchengineaction.h \ + opensearchenginemodel.h \ + opensearchmanager.h \ plaintexteditsearch.h \ searchbar.h \ searchbutton.h \ @@ -74,6 +79,10 @@ SOURCES += \ downloadmanager.cpp \ modelmenu.cpp \ modeltoolbar.cpp \ + opensearchdialog.cpp \ + opensearchengineaction.cpp \ + opensearchenginemodel.cpp \ + opensearchmanager.cpp \ plaintexteditsearch.cpp \ searchbar.cpp \ searchbutton.cpp \ @@ -94,7 +103,7 @@ include(bookmarks/bookmarks.pri) include(history/history.pri) include(locationbar/locationbar.pri) include(network/network.pri) -include(opensearch/opensearch.pri) +include(opensearch/src/opensearch-nolib.pri) include(qwebplugins/qwebplugins.pri) include(utils/utils.pri) include(useragent/useragent.pri) |