Revision control
// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
// Copyright (C) 2019 Menlo Systems GmbH, author Arno Rehn <a.rehn@menlosystems.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_WEBCHANNEL_H
#define TST_WEBCHANNEL_H
#include <QObject>
#include <QProperty>
#include <QVariant>
#include <QList>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
#if QT_CONFIG(future)
#include <QFuture>
#endif
#include <QtDebug>
#include <QtWebChannel/QWebChannelAbstractTransport>
struct TestStruct
{
TestStruct(int foo = 0, int bar = 0)
: foo(foo)
, bar(bar)
{}
int foo;
int bar;
operator QString() const {
return QStringLiteral("TestStruct(foo=%1, bar=%2)").arg(foo).arg(bar);
}
};
inline bool operator==(const TestStruct &a, const TestStruct &b)
{
return a.foo == b.foo && a.bar == b.bar;
}
inline QDebug operator<<(QDebug &dbg, const TestStruct &ts)
{
QDebugStateSaver dbgState(dbg);
dbg.noquote() << static_cast<QString>(ts);
return dbg;
}
Q_DECLARE_METATYPE(TestStruct)
using TestStructVector = std::vector<TestStruct>;
Q_DECLARE_METATYPE(TestStructVector)
QT_BEGIN_NAMESPACE
class DummyTransport : public QWebChannelAbstractTransport
{
Q_OBJECT
public:
explicit DummyTransport(QObject *parent = nullptr)
: QWebChannelAbstractTransport(parent)
{}
~DummyTransport() {};
void emitMessageReceived(const QJsonObject &message)
{
emit messageReceived(message, this);
}
QList<QJsonObject> messagesSent() const { return mMessagesSent; }
+ void clearMessages() { mMessagesSent.clear(); }
+
public slots:
void sendMessage(const QJsonObject &message) override
{
mMessagesSent.push_back(message);
}
private:
QList<QJsonObject> mMessagesSent;
};
class TestObject : public QObject
{
Q_OBJECT
Q_PROPERTY(Foo foo READ foo CONSTANT)
Q_PROPERTY(int asdf READ asdf NOTIFY asdfChanged)
Q_PROPERTY(QString bar READ bar NOTIFY theBarHasChanged)
Q_PROPERTY(QObject * objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectPropertyChanged)
Q_PROPERTY(TestObject * returnedObject READ returnedObject WRITE setReturnedObject NOTIFY returnedObjectChanged)
Q_PROPERTY(QString prop READ prop WRITE setProp NOTIFY propChanged)
Q_PROPERTY(QString stringProperty READ readStringProperty WRITE setStringProperty BINDABLE bindableStringProperty)
public:
explicit TestObject(QObject *parent = nullptr)
: QObject(parent)
, mObjectProperty(nullptr)
, mReturnedObject(nullptr)
{ }
enum Foo {
Bar,
Asdf
};
Q_ENUM(Foo)
enum TestFlag : quint16 {
FirstFlag = 0x1,
SecondFlag = 0x2
};
Q_DECLARE_FLAGS(TestFlags, TestFlag)
Q_FLAG(TestFlags)
Foo foo() const {return Bar;}
int asdf() const {return 42;}
QString bar() const {return QString();}
QObject *objectProperty() const
{
return mObjectProperty;
}
TestObject *returnedObject() const
{
return mReturnedObject;
}
QString prop() const
{
return mProp;
}
QString readStringProperty() const { return mStringProperty; }
Q_INVOKABLE void method1() {}
#if QT_CONFIG(future)
Q_INVOKABLE QFuture<int> futureIntResult() const;
Q_INVOKABLE QFuture<int> futureDelayedIntResult() const;
#ifdef WEBCHANNEL_TESTS_CAN_USE_CONCURRENT
Q_INVOKABLE QFuture<int> futureIntResultFromThread() const;
#endif
Q_INVOKABLE QFuture<void> futureVoidResult() const;
Q_INVOKABLE QFuture<QString> futureStringResult() const;
Q_INVOKABLE QFuture<int> cancelledFuture() const;
Q_INVOKABLE QFuture<int> failedFuture() const;
#endif
protected:
Q_INVOKABLE void method2() {}
private:
Q_INVOKABLE void method3() {}
signals:
void sig1();
void sig2(const QString&);
void asdfChanged();
void theBarHasChanged();
void objectPropertyChanged();
void returnedObjectChanged();
void propChanged(const QString&);
void replay();
void overloadSignal(int);
void overloadSignal(float);
public slots:
void slot1() {}
void slot2(const QString&) {}
void setReturnedObject(TestObject *obj)
{
mReturnedObject = obj;
emit returnedObjectChanged();
}
void setObjectProperty(QObject *object)
{
mObjectProperty = object;
emit objectPropertyChanged();
}
void setProp(const QString&prop) {emit propChanged(mProp=prop);}
void fire() {emit replay();}
double overload(double d) { return d + 1; }
int overload(int i) { return i * 2; }
QObject *overload(QObject *object) { return object; }
QString overload(const QString &str) { return str.toUpper(); }
QString overload(const QString &str, int i) { return str.toUpper() + QString::number(i + 1); }
QString overload(const QJsonArray &v) { return QString::number(v[1].toInt()) + v[0].toString(); }
void setStringProperty(const QString &v) { mStringProperty = v; }
QBindable<QString> bindableStringProperty() { return &mStringProperty; }
QString getStringProperty() const { return mStringProperty; }
void bindStringPropertyToStringProperty2() { bindableStringProperty().setBinding(Qt::makePropertyBinding(mStringProperty2)); }
void setStringProperty2(const QString &string) { mStringProperty2 = string; }
protected slots:
void slot3() {}
private slots:
void slot4() {}
public:
QObject *mObjectProperty;
TestObject *mReturnedObject;
QString mProp;
Q_OBJECT_BINDABLE_PROPERTY(TestObject, QString, mStringProperty);
QProperty<QString> mStringProperty2;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(TestObject::TestFlags)
class TestWebChannel : public QObject
{
Q_OBJECT
Q_PROPERTY(int lastInt READ readInt WRITE setInt NOTIFY lastIntChanged);
Q_PROPERTY(bool lastBool READ readBool WRITE setBool NOTIFY lastBoolChanged);
Q_PROPERTY(double lastDouble READ readDouble WRITE setDouble NOTIFY lastDoubleChanged);
Q_PROPERTY(QVariant lastVariant READ readVariant WRITE setVariant NOTIFY lastVariantChanged);
Q_PROPERTY(QJsonValue lastJsonValue READ readJsonValue WRITE setJsonValue NOTIFY lastJsonValueChanged);
Q_PROPERTY(QJsonObject lastJsonObject READ readJsonObject WRITE setJsonObject NOTIFY lastJsonObjectChanged);
Q_PROPERTY(QJsonArray lastJsonArray READ readJsonArray WRITE setJsonArray NOTIFY lastJsonArrayChanged);
public:
explicit TestWebChannel(QObject *parent = 0);
virtual ~TestWebChannel();
public slots:
int readInt() const;
void setInt(int i);
bool readBool() const;
void setBool(bool b);
double readDouble() const;
void setDouble(double d);
void setIntDouble(int i, double d);
QVariant readVariant() const;
void setVariant(const QVariant &v);
QJsonValue readJsonValue() const;
void setJsonValue(const QJsonValue &v);
QJsonObject readJsonObject() const;
void setJsonObject(const QJsonObject &v);
QJsonArray readJsonArray() const;
void setJsonArray(const QJsonArray &v);
QUrl readUrl() const;
void setUrl(const QUrl &u);
int readOverload(int i);
QString readOverload(const QString &arg);
QString readOverload(const QString &arg, int i);
signals:
void lastIntChanged();
void lastBoolChanged();
void lastDoubleChanged();
void lastVariantChanged();
void lastJsonValueChanged();
void lastJsonObjectChanged();
void lastJsonArrayChanged();
private slots:
void testRegisterObjects();
void testDeregisterObjects();
void testDeregisterObjectAtStart();
void testInfoForObject();
void testInvokeMethodConversion();
void testFunctionOverloading();
void testSetPropertyConversion();
void testInvokeMethodOverloadResolution();
void testDisconnect();
void testWrapRegisteredObject();
void testUnwrapObject();
void testTransportWrapObjectProperties();
void testRemoveUnusedTransports();
void testPassWrappedObjectBack();
void testWrapValues_data();
void testWrapValues();
void testWrapObjectWithMultipleTransports();
void testJsonToVariant_data();
void testJsonToVariant();
void testInfiniteRecursion();
void testAsyncObject();
void testQProperty();
void testPropertyUpdateInterval_data();
void testPropertyUpdateInterval();
void testPropertyMultipleTransports();
void testQPropertyBlockUpdates();
void testBindings();
void testDeletionDuringMethodInvocation_data();
void testDeletionDuringMethodInvocation();
void testRejectsMissingArguments();
void testRejectsUnresolvableObjectId();
void testRejectsUnresolvableObjectIdInMethodCall();
void testAcceptsExplicitNullForObjectPointer();
void testRejectsMismatchedObjectClass();
void testRejectsMismatchedObjectClassByName();
void testRejectsMismatchedObjectClassByIndex();
void testRejectsUnconvertibleArgument();
+ void testRejectsNonSignalIndex();
#if QT_CONFIG(future)
void testAsyncMethodReturningFuture_data();
void testAsyncMethodReturningFuture();
#endif
void qtbug46548_overriddenProperties();
void qtbug62388_wrapObjectMultipleTransports();
void qtbug150200_transportStateRemovedOnDestroy();
void qtbug150200_transportStateRemovedOnDisconnect();
void qtbug150200_newTransportDoesNotInheritState();
private:
DummyTransport *m_dummyTransport;
int m_lastInt;
bool m_lastBool;
double m_lastDouble;
QVariant m_lastVariant;
QJsonValue m_lastJsonValue;
QJsonObject m_lastJsonObject;
QJsonArray m_lastJsonArray;
QUrl m_lastUrl;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(TestObject::Foo)
#endif // TST_WEBCHANNEL_H