1/* 2 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18*/ 19 20#include "config.h" 21 22#include <QMetaEnum> 23#include <QMetaMethod> 24#include <QMetaObject> 25#include <QMetaProperty> 26#include <QMetaType> 27#include <QtTest/QtTest> 28#include <private/qquickwebview_p.h> 29#include <private/qwebloadrequest_p.h> 30#include <private/qwebnavigationrequest_p.h> 31 32class tst_publicapi : public QObject { 33 Q_OBJECT 34private Q_SLOTS: 35 void publicAPI(); 36}; 37 38static QList<const QMetaObject*> typesToCheck = QList<const QMetaObject*>() 39 << &QQuickWebView::staticMetaObject 40 << &QWebLoadRequest::staticMetaObject 41 << &QWebNavigationRequest::staticMetaObject; 42 43static QStringList expectedAPI = QStringList() 44 << "QQuickWebView.AcceptRequest --> NavigationRequestAction" 45 << "QQuickWebView.IgnoreRequest --> NavigationRequestAction" 46 << "QQuickWebView.LoadStartedStatus --> LoadStatus" 47 << "QQuickWebView.LoadStoppedStatus --> LoadStatus" 48 << "QQuickWebView.LoadSucceededStatus --> LoadStatus" 49 << "QQuickWebView.LoadFailedStatus --> LoadStatus" 50 << "QQuickWebView.NoErrorDomain --> ErrorDomain" 51 << "QQuickWebView.InternalErrorDomain --> ErrorDomain" 52 << "QQuickWebView.NetworkErrorDomain --> ErrorDomain" 53 << "QQuickWebView.HttpErrorDomain --> ErrorDomain" 54 << "QQuickWebView.DownloadErrorDomain --> ErrorDomain" 55 << "QQuickWebView.LinkClickedNavigation --> NavigationType" 56 << "QQuickWebView.FormSubmittedNavigation --> NavigationType" 57 << "QQuickWebView.BackForwardNavigation --> NavigationType" 58 << "QQuickWebView.ReloadNavigation --> NavigationType" 59 << "QQuickWebView.FormResubmittedNavigation --> NavigationType" 60 << "QQuickWebView.OtherNavigation --> NavigationType" 61 << "QQuickWebView.title --> QString" 62 << "QQuickWebView.url --> QUrl" 63 << "QQuickWebView.icon --> QUrl" 64 << "QQuickWebView.canGoBack --> bool" 65 << "QQuickWebView.canGoForward --> bool" 66 << "QQuickWebView.loading --> bool" 67 << "QQuickWebView.loadProgress --> int" 68 << "QQuickWebView.titleChanged() --> void" 69 << "QQuickWebView.navigationHistoryChanged() --> void" 70 << "QQuickWebView.loadingChanged(QWebLoadRequest*) --> void" 71 << "QQuickWebView.loadProgressChanged() --> void" 72 << "QQuickWebView.urlChanged() --> void" 73 << "QQuickWebView.iconChanged() --> void" 74 << "QQuickWebView.linkHovered(QUrl,QString) --> void" 75 << "QQuickWebView.navigationRequested(QWebNavigationRequest*) --> void" 76 << "QQuickWebView.loadHtml(QString,QUrl,QUrl) --> void" 77 << "QQuickWebView.loadHtml(QString,QUrl) --> void" 78 << "QQuickWebView.loadHtml(QString) --> void" 79 << "QQuickWebView.goBack() --> void" 80 << "QQuickWebView.goForward() --> void" 81 << "QQuickWebView.stop() --> void" 82 << "QQuickWebView.reload() --> void" 83 << "QWebLoadRequest.url --> QUrl" 84 << "QWebLoadRequest.status --> QQuickWebView::LoadStatus" 85 << "QWebLoadRequest.errorString --> QString" 86 << "QWebLoadRequest.errorDomain --> QQuickWebView::ErrorDomain" 87 << "QWebLoadRequest.errorCode --> int" 88 << "QWebNavigationRequest.url --> QUrl" 89 << "QWebNavigationRequest.mouseButton --> int" 90 << "QWebNavigationRequest.keyboardModifiers --> int" 91 << "QWebNavigationRequest.action --> QQuickWebView::NavigationRequestAction" 92 << "QWebNavigationRequest.navigationType --> QQuickWebView::NavigationType" 93 << "QWebNavigationRequest.actionChanged() --> void" 94 ; 95 96static bool isCheckedEnum(const QByteArray& typeName) 97{ 98 QList<QByteArray> tokens = typeName.split(':'); 99 if (tokens.size() == 3) { 100 QByteArray& enumClass = tokens[0]; 101 QByteArray& enumName = tokens[2]; 102 foreach (const QMetaObject* mo, typesToCheck) { 103 if (mo->className() != enumClass) 104 continue; 105 for (int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) 106 if (mo->enumerator(i).name() == enumName) 107 return true; 108 } 109 } 110 return false; 111} 112 113static bool isCheckedClass(const QByteArray& typeName) 114{ 115 foreach (const QMetaObject* mo, typesToCheck) { 116 QByteArray moTypeName(mo->className()); 117 if (moTypeName == typeName || moTypeName + "*" == typeName) 118 return true; 119 } 120 return false; 121} 122 123static void checkKnownType(const QByteArray& typeName) 124{ 125 if ((typeName != "void" && !QMetaType::type(typeName)) || QMetaType::type(typeName) >= QMetaType::User) { 126 bool knownEnum = isCheckedEnum(typeName); 127 bool knownClass = isCheckedClass(typeName); 128 QVERIFY2(knownEnum || knownClass, qPrintable(QString("The API uses an unknown type [%1], you might have to add it to the typesToCheck list.").arg(typeName.constData()))); 129 } 130} 131 132static void gatherAPI(const QString& prefix, const QMetaEnum& metaEnum, QStringList* output) 133{ 134 for (int i = 0; i < metaEnum.keyCount(); ++i) 135 *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(metaEnum.key(i)).arg(metaEnum.name()); 136} 137 138static void gatherAPI(const QString& prefix, const QMetaProperty& property, QStringList* output) 139{ 140 *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(property.name()).arg(property.typeName()); 141 checkKnownType(property.typeName()); 142} 143 144static void gatherAPI(const QString& prefix, const QMetaMethod& method, QStringList* output) 145{ 146 if (method.access() != QMetaMethod::Private) { 147 const char* methodTypeName = !!strlen(method.typeName()) ? method.typeName() : "void"; 148 *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(QString::fromLatin1(method.methodSignature())).arg(QString::fromLatin1(methodTypeName)); 149 150 checkKnownType(methodTypeName); 151 foreach (QByteArray paramType, method.parameterTypes()) 152 checkKnownType(paramType); 153 } 154} 155 156static void gatherAPI(const QString& prefix, const QMetaObject* meta, QStringList* output) 157{ 158 // *Offset points us only at the leaf class members, we don't have inheritance in our API yet anyway. 159 for (int i = meta->enumeratorOffset(); i < meta->enumeratorCount(); ++i) 160 gatherAPI(prefix, meta->enumerator(i), output); 161 for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i) 162 gatherAPI(prefix, meta->property(i), output); 163 for (int i = meta->methodOffset(); i < meta->methodCount(); ++i) 164 gatherAPI(prefix, meta->method(i), output); 165} 166 167void tst_publicapi::publicAPI() 168{ 169 QStringList actualAPI; 170 foreach (const QMetaObject* meta, typesToCheck) 171 gatherAPI(QString::fromLatin1(meta->className()) + ".", meta, &actualAPI); 172 173 // Uncomment to print the actual API. 174 // foreach(QString actual, actualAPI) 175 // printf(" << \"%s\"\n", qPrintable(actual)); 176 177 // Make sure that nothing slips in the public API unintentionally. 178 foreach (QString actual, actualAPI) 179 QVERIFY2(expectedAPI.contains(actual), qPrintable(actual)); 180 // Make sure that the expected list is up-to-date with intentionally added APIs. 181 foreach (QString expected, expectedAPI) 182 QVERIFY2(actualAPI.contains(expected), qPrintable(expected)); 183} 184 185QTEST_MAIN(tst_publicapi) 186 187#include "tst_publicapi.moc" 188