diff options
Diffstat (limited to 'tests/auto/conversion/tst_conversion.cpp')
-rw-r--r-- | tests/auto/conversion/tst_conversion.cpp | 345 |
1 files changed, 309 insertions, 36 deletions
diff --git a/tests/auto/conversion/tst_conversion.cpp b/tests/auto/conversion/tst_conversion.cpp index 52be69b..61ffb85 100644 --- a/tests/auto/conversion/tst_conversion.cpp +++ b/tests/auto/conversion/tst_conversion.cpp @@ -1,30 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "comutil_p.h" +#include "testutil_p.h" + +#include <qaxtypes_p.h> +#include <ActiveQt/qaxobject.h> #include <QtTest/QtTest> #include <QtCore/QVariant> @@ -32,18 +13,13 @@ #include <QtCore/QMetaType> #include <qt_windows.h> +#include <wrl/client.h> -QT_BEGIN_NAMESPACE - -// Conversion functions from statically linked library (axtypes.h) -bool QVariantToVARIANT_container(const QVariant &var, VARIANT &arg, - const QByteArray &typeName = QByteArray(), - bool out = false); +using Microsoft::WRL::ComPtr; -QVariant VARIANTToQVariant_container(const VARIANT &arg, const QByteArray &typeName, - uint type = 0); +QT_BEGIN_NAMESPACE -QT_END_NAMESPACE +using namespace Qt::StringLiterals; class tst_Conversion : public QObject { @@ -52,6 +28,36 @@ class tst_Conversion : public QObject private slots: void conversion_data(); void conversion(); + + void VARIANTToQVariant_ReturnsBool_WhenCalledWithVariantBool(); + void QVariantToVARIANT_ReturnsVariantBool_WhenCalledWithBool(); + + void VARIANTToQVariant_ReturnsString_WhenCalledWithString_data(); + void VARIANTToQVariant_ReturnsString_WhenCalledWithString(); + + void QVariantToVARIANT_ReturnsString_WhenCalledWithString_data(); + void QVariantToVARIANT_ReturnsString_WhenCalledWithString(); + + void VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer_data(); + void VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer(); + + void QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue_data(); + void QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue(); + + void VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIUnknown(); + void QVariantToVARIANT_RecoversIUnknown_WhenQVariantHasIUnknown(); + + void VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIDispatch(); + void QVariantToVARIANT_RecoversIDispatch_WhenQVariantHasIDispatch(); + + void VARIANTToQVariant_IncreasesRefCount_WhenCalledWithQVariantTypeName(); + + void ObserveThat_VARIANTToQVariant_ReturnsEmptyQVariant_WhenWrappingIDispatchInQAxObjectPtr(); + void VARIANTToQVariant_CreatesQAxObject_WhenCalledWithMetaTypeId(); + +private: + template<typename T> + static void addScalarMaxValueRow(); }; enum Mode { @@ -170,6 +176,11 @@ void tst_Conversion::conversion_data() << qvar << uint(VT_DATE | VT_BYREF) << typeName << ByReference; QTest::newRow("datetime-out") << qvar << uint(VT_DATE | VT_BYREF) << typeName << OutParameter; + + // QTBUG-122762; do not create a 2-dimensional array from a string (sequence). + qvar = QVariant(QVariantList{QVariant(QString("test"_L1)), QVariant(42)}); + QTest::newRow("list") + << qvar << uint(VT_VARIANT | VT_ARRAY | VT_BYREF) << typeName << OutParameter; } void tst_Conversion::conversion() @@ -195,5 +206,267 @@ void tst_Conversion::conversion() delete variant.pullVal; } +void tst_Conversion::VARIANTToQVariant_ReturnsBool_WhenCalledWithVariantBool() +{ + { + const ComVariant v = true; + const QVariant result = VARIANTToQVariant(v, "canBeAnything"); + QVERIFY(result == true); + } + + { + const ComVariant v = false; + const QVariant result = VARIANTToQVariant(v, "canBeAnything"); + QVERIFY(result == false); + } +} + +void tst_Conversion::QVariantToVARIANT_ReturnsVariantBool_WhenCalledWithBool() +{ + { + const QVariant v = true; + ComVariant result; + QVERIFY(QVariantToVARIANT(v, result)); + QVERIFY(result.vt == VT_BOOL); + QVERIFY(result.boolVal == VARIANT_TRUE); + } + + { + const QVariant v = false; + ComVariant result; + QVERIFY(QVariantToVARIANT(v, result)); + QVERIFY(result.vt == VT_BOOL); + QVERIFY(result.boolVal == VARIANT_FALSE); + } +} + +void tst_Conversion::VARIANTToQVariant_ReturnsString_WhenCalledWithString_data() +{ + QTest::addColumn<QString>("text"); + QTest::newRow("empty") << QString{ "" }; + QTest::newRow("nonempty") << QString{ "Some Latin 1 text" }; +} + +void tst_Conversion::VARIANTToQVariant_ReturnsString_WhenCalledWithString() +{ + QFETCH(QString, text); + + const ComVariant comVariant = text.toStdWString().c_str(); + const QVariant actual = VARIANTToQVariant(comVariant, {}); + + QCOMPARE(actual, text); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsString_WhenCalledWithString_data() +{ + QTest::addColumn<QString>("text"); + QTest::newRow("empty") << QString{ "" }; + QTest::newRow("nonempty") << QString{ "Some Latin 1 text" }; +} + +void tst_Conversion::QVariantToVARIANT_ReturnsString_WhenCalledWithString() +{ + QFETCH(QString, text); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(text, comVariant)); + + const QString actual = QString::fromWCharArray(comVariant.bstrVal); + + QCOMPARE(actual, text); +} + +void tst_Conversion:: + VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer_data() +{ + QTest::addColumn<ComVariant>("comVariant"); + QTest::addColumn<QVariant>("qvariant"); + + addScalarMaxValueRow<char>(); + addScalarMaxValueRow<unsigned char>(); + addScalarMaxValueRow<short>(); + addScalarMaxValueRow<unsigned short>(); + addScalarMaxValueRow<int>(); + addScalarMaxValueRow<unsigned int>(); + addScalarMaxValueRow<long long>(); + addScalarMaxValueRow<unsigned long long>(); + addScalarMaxValueRow<float>(); + addScalarMaxValueRow<double>(); + + addScalarMaxValueRow<char *>(); + addScalarMaxValueRow<unsigned char *>(); + addScalarMaxValueRow<short *>(); + addScalarMaxValueRow<unsigned short *>(); + addScalarMaxValueRow<int *>(); + addScalarMaxValueRow<unsigned int *>(); + addScalarMaxValueRow<long long *>(); + addScalarMaxValueRow<unsigned long long *>(); + addScalarMaxValueRow<float *>(); + addScalarMaxValueRow<double *>(); +} + +void tst_Conversion::VARIANTToQVariant_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValueOrPointer() +{ + QFETCH(ComVariant, comVariant); + QFETCH(QVariant, qvariant); + + const QVariant actual = VARIANTToQVariant(comVariant, qvariant.typeName()); + + QCOMPARE(actual, qvariant); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue_data() +{ + QTest::addColumn<ComVariant>("comVariant"); + QTest::addColumn<QVariant>("qvariant"); + + addScalarMaxValueRow<int>(); + addScalarMaxValueRow<unsigned int>(); + addScalarMaxValueRow<long long>(); + addScalarMaxValueRow<unsigned long long>(); + addScalarMaxValueRow<float>(); + addScalarMaxValueRow<double>(); +} + +void tst_Conversion::QVariantToVARIANT_ReturnsCopyOfValue_WhenCalledWithMaxPossibleValue() +{ + QFETCH(ComVariant, comVariant); + QFETCH(QVariant, qvariant); + + ComVariant actual; + QVERIFY(QVariantToVARIANT(qvariant, actual)); + + QCOMPARE(actual, comVariant); +} + +void tst_Conversion::VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIUnknown() +{ + const auto stub = makeComObject<IUnknownStub>(); + + const ComVariant value = stub.Get(); + + QVERIFY(stub->m_refCount == 2u); + + const QVariant qVariant = VARIANTToQVariant(value, {}); + + QVERIFY(stub->m_refCount == 2u); + + Q_UNUSED(qVariant); +} + +void tst_Conversion::QVariantToVARIANT_RecoversIUnknown_WhenQVariantHasIUnknown() +{ + const auto stub = makeComObject<IUnknownStub>(); + const ComVariant value = stub.Get(); + + const QVariant qvar = VARIANTToQVariant(value, {}); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(qvar, comVariant)); + + QCOMPARE(stub->m_refCount, 3u); + + const ComPtr<IUnknown> recovered = comVariant.punkVal; + + QCOMPARE(recovered, stub); +} + +void tst_Conversion::VARIANTToQVariant_DoesNotIncreaseRefCount_WhenGivenAnIDispatch() +{ + const auto stub = makeComObject<IDispatchStub>(); + + const ComVariant value = stub.Get(); + + QCOMPARE(stub->m_refCount, 2u); + const QVariant qVariant = VARIANTToQVariant(value, "IDispatch*"); + + QCOMPARE(stub->m_refCount, 2u); + + Q_UNUSED(qVariant); +} + +struct IDispatchFixture +{ + const ComPtr<IDispatchStub> m_iDispatchStub = makeComObject<IDispatchStub>(); + const ComVariant m_comVariant = m_iDispatchStub.Get(); + const QVariant m_qVariant = VARIANTToQVariant(m_comVariant, "IDispatch*"); +}; + +void tst_Conversion::QVariantToVARIANT_RecoversIDispatch_WhenQVariantHasIDispatch() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + ComVariant comVariant; + QVERIFY(QVariantToVARIANT(testFixture.m_qVariant, comVariant)); + + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 3u); + + const ComPtr<IUnknown> recovered = comVariant.pdispVal; + + QCOMPARE(recovered, testFixture.m_iDispatchStub); +} + +void tst_Conversion::VARIANTToQVariant_IncreasesRefCount_WhenCalledWithQVariantTypeName() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QVariant"); + qVariant = {}; + + // Observe that IDispatch interface is leaked here, since + // the QVariant destructor does not decrement the refcount + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 3u); + + // Workaround to ensure cleanup + testFixture.m_iDispatchStub->Release(); +} + +void tst_Conversion::ObserveThat_VARIANTToQVariant_ReturnsEmptyQVariant_WhenWrappingIDispatchInQAxObjectPtr() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + qRegisterMetaType<QAxObject *>("QAxObject*"); + qRegisterMetaType<QAxObject>("QAxObject"); + + const QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QAxObject*"); + QVERIFY(qVariant.isNull()); +} + +void tst_Conversion::VARIANTToQVariant_CreatesQAxObject_WhenCalledWithMetaTypeId() +{ + const IDispatchFixture testFixture; + QCOMPARE(testFixture.m_iDispatchStub->m_refCount, 2u); + + qRegisterMetaType<QAxObject *>("QAxObject*"); + qRegisterMetaType<QAxObject>("QAxObject"); + + const QVariant qVariant = VARIANTToQVariant(testFixture.m_comVariant, "QAxObject*", QMetaType::fromType<QAxObject*>().id()); + + QAxObject *recovered = qVariant.value<QAxObject *>(); + QVERIFY(recovered != nullptr); +} + +template<typename T> +void tst_Conversion::addScalarMaxValueRow() +{ + using ValueType = std::remove_pointer_t<T>; + static ValueType v = std::numeric_limits<ValueType>::max(); + + ComVariant comVariant; + if constexpr (std::is_pointer_v<T>) + comVariant = &v; + else + comVariant = v; + + const char *typeName = QMetaType::fromType<T>().name(); + QTest::newRow(typeName) << comVariant << QVariant{ v }; +} + QTEST_MAIN(tst_Conversion) + +QT_END_NAMESPACE + #include "tst_conversion.moc" |