summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/CMakeLists.txt15
-rw-r--r--tests/auto/auto.pro10
-rw-r--r--tests/auto/cmake/CMakeLists.txt44
-rw-r--r--tests/auto/cmake/cmake.pro5
-rw-r--r--tests/auto/cmake/test_modules/CMakeLists.txt7
-rw-r--r--tests/auto/cmake/test_modules/container/CMakeLists.txt24
-rw-r--r--tests/auto/cmake/test_modules/container/axcontainer.cpp29
-rw-r--r--tests/auto/cmake/test_modules/server/CMakeLists.txt24
-rw-r--r--tests/auto/cmake/test_modules/server/axserver.cpp29
-rw-r--r--tests/auto/cmake/test_target_typelibs/CMakeLists.txt12
-rw-r--r--tests/auto/cmake/test_target_typelibs/main.cpp11
-rw-r--r--tests/auto/cmake/test_target_typelibs_absolute/CMakeLists.txt12
-rw-r--r--tests/auto/cmake/test_target_typelibs_absolute/main.cpp11
-rw-r--r--tests/auto/cmake/test_target_typelibs_empty_libs/CMakeLists.txt12
-rw-r--r--tests/auto/cmake/test_target_typelibs_empty_libs/main.cpp11
-rw-r--r--tests/auto/cmake/test_target_typelibs_non_existing_libs/CMakeLists.txt12
-rw-r--r--tests/auto/cmake/test_target_typelibs_non_existing_libs/main.cpp11
-rw-r--r--tests/auto/cmake/test_target_typelibs_out_dir/CMakeLists.txt15
-rw-r--r--tests/auto/cmake/test_target_typelibs_out_dir/main.cpp11
-rw-r--r--tests/auto/conversion/CMakeLists.txt17
-rw-r--r--tests/auto/conversion/comutil_p.h250
-rw-r--r--tests/auto/conversion/conversion.pro3
-rw-r--r--tests/auto/conversion/testutil_p.h60
-rw-r--r--tests/auto/conversion/tst_conversion.cpp349
-rw-r--r--tests/auto/dumpcpp/CMakeLists.txt20
-rw-r--r--tests/auto/dumpcpp/dumpcpp.pro11
-rw-r--r--tests/auto/dumpcpp/tst_dumpcpp.cpp119
-rw-r--r--tests/auto/qaxobject/CMakeLists.txt15
-rw-r--r--tests/auto/qaxobject/qaxobject.pro3
-rw-r--r--tests/auto/qaxobject/tst_qaxobject.cpp29
-rw-r--r--tests/auto/qaxobjectcom/CMakeLists.txt33
-rw-r--r--tests/auto/qaxobjectcom/testserver/CMakeLists.txt47
-rw-r--r--tests/auto/qaxobjectcom/testserver/testserver.cpp132
-rw-r--r--tests/auto/qaxobjectcom/testserver/testserver.def3
-rw-r--r--tests/auto/qaxobjectcom/testserver/testserver.h43
-rw-r--r--tests/auto/qaxobjectcom/testserver/testserver.rc1
-rw-r--r--tests/auto/qaxobjectcom/testserver/testserverlib.idl33
-rw-r--r--tests/auto/qaxobjectcom/tst_qaxobjectcom.cpp87
-rw-r--r--tests/auto/qaxobjectcom/tst_qaxobjectcom.exe.manifest.in12
-rw-r--r--tests/auto/qaxscript/CMakeLists.txt15
-rw-r--r--tests/auto/qaxscript/qaxscript.pro3
-rw-r--r--tests/auto/qaxscript/tst_qaxscript.cpp175
-rw-r--r--tests/auto/qaxscriptmanager/CMakeLists.txt19
-rw-r--r--tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp188
-rw-r--r--tests/auto/qbstr/CMakeLists.txt15
-rw-r--r--tests/auto/qbstr/tst_qbstr.cpp138
46 files changed, 1838 insertions, 287 deletions
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index 8537f4f..2f384ae 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -1,9 +1,18 @@
-# Generated from auto.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(conversion)
add_subdirectory(qaxobject)
-# add_subdirectory(dumpcpp) (needs typelib target) # special case
-#add_subdirectory(cmake) # special case
+add_subdirectory(dumpcpp)
+add_subdirectory(cmake)
+add_subdirectory(qbstr)
+
+find_program(midl midl.exe)
+if (midl)
+ add_subdirectory(qaxobjectcom)
+endif()
+
if(NOT GCC)
add_subdirectory(qaxscript)
+ add_subdirectory(qaxscriptmanager)
endif()
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
deleted file mode 100644
index 0b43b0d..0000000
--- a/tests/auto/auto.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS += \
- conversion \
- qaxobject \
- qaxscript \
- dumpcpp \
- cmake
-
-*g++*: SUBDIRS -= \
- qaxscript \
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 4f15a69..3611659 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -1,12 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
-cmake_minimum_required(VERSION 2.8)
-project(qmake_cmake_files)
+cmake_minimum_required(VERSION 3.16)
+
+project(qtactivetqt_cmake_tests)
enable_testing()
-find_package(Qt5Core REQUIRED)
+set(required_packages Core)
+set(optional_packages Widgets Gui)
+
+# Setup the test when called as a completely standalone project.
+if(TARGET Qt6::Core)
+ # Tests are built as part of the qtactiveqt build tree.
+ # Setup paths so that the Qt packages are found.
+ qt_internal_set_up_build_dir_package_paths()
+endif()
+
+find_package(Qt6 REQUIRED COMPONENTS ${required_packages})
+find_package(Qt6 OPTIONAL_COMPONENTS ${optional_packages})
+
+# Setup common test variables which were previously set by ctest_testcase_common.prf.
+set(CMAKE_MODULES_UNDER_TEST "${required_packages}" "${optional_packages}")
+
+foreach(qt_package ${CMAKE_MODULES_UNDER_TEST})
+ set(package_name "${QT_CMAKE_EXPORT_NAMESPACE}${qt_package}")
+ if(${package_name}_FOUND)
+ set(CMAKE_${qt_package}_MODULE_MAJOR_VERSION "${${package_name}_VERSION_MAJOR}")
+ set(CMAKE_${qt_package}_MODULE_MINOR_VERSION "${${package_name}_VERSION_MINOR}")
+ set(CMAKE_${qt_package}_MODULE_PATCH_VERSION "${${package_name}_VERSION_PATCH}")
+ endif()
+endforeach()
-include("${_Qt5CTestMacros}")
+include("${_Qt6CTestMacros}")
-expect_pass(test_modules)
+if(TARGET Qt6::Widgets AND TARGET Qt6::Gui)
+ _qt_internal_test_expect_pass(test_target_typelibs)
+ _qt_internal_test_expect_pass(test_target_typelibs_absolute)
+ _qt_internal_test_expect_fail(test_target_typelibs_empty_libs)
+ _qt_internal_test_expect_fail(test_target_typelibs_non_existing_libs)
+ _qt_internal_test_expect_pass(test_target_typelibs_out_dir)
+ _qt_internal_test_expect_pass(test_modules/container)
+ _qt_internal_test_expect_pass(test_modules/server)
+endif()
diff --git a/tests/auto/cmake/cmake.pro b/tests/auto/cmake/cmake.pro
deleted file mode 100644
index bf2dbcb..0000000
--- a/tests/auto/cmake/cmake.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-
-# Cause make to do nothing.
-TEMPLATE = subdirs
-
-CONFIG += ctest_testcase
diff --git a/tests/auto/cmake/test_modules/CMakeLists.txt b/tests/auto/cmake/test_modules/CMakeLists.txt
deleted file mode 100644
index 4336ad4..0000000
--- a/tests/auto/cmake/test_modules/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-cmake_minimum_required(VERSION 2.8)
-
-project(test_modules)
-
-add_subdirectory(server)
-add_subdirectory(container)
diff --git a/tests/auto/cmake/test_modules/container/CMakeLists.txt b/tests/auto/cmake/test_modules/container/CMakeLists.txt
index 6d04576..999e241 100644
--- a/tests/auto/cmake/test_modules/container/CMakeLists.txt
+++ b/tests/auto/cmake/test_modules/container/CMakeLists.txt
@@ -1,24 +1,10 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.16)
project(cmake_axcontainer)
-find_package(Qt5Core REQUIRED)
-find_package(Qt5Gui REQUIRED)
-find_package(Qt5Widgets REQUIRED)
-
-find_package(Qt5AxContainer REQUIRED)
-
-include_directories(
- ${Qt5AxContainer_INCLUDE_DIRS}
-)
-
-add_definitions(${Qt5AxContainer_DEFINITIONS})
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
-
+find_package(Qt6 COMPONENTS Core Gui Widgets AxContainer CONFIG REQUIRED)
add_executable(axcontainerapp axcontainer.cpp)
-
-target_link_libraries(axcontainerapp
- ${Qt5AxContainer_LIBRARIES}
-)
+target_link_libraries(axcontainerapp Qt6::Core Qt6::Gui Qt6::Widgets Qt6::AxContainer)
diff --git a/tests/auto/cmake/test_modules/container/axcontainer.cpp b/tests/auto/cmake/test_modules/container/axcontainer.cpp
index e16bddb..73d8ebb 100644
--- a/tests/auto/cmake/test_modules/container/axcontainer.cpp
+++ b/tests/auto/cmake/test_modules/container/axcontainer.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** 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 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qt_windows.h>
#include <QtAxContainer/QAxWidget>
diff --git a/tests/auto/cmake/test_modules/server/CMakeLists.txt b/tests/auto/cmake/test_modules/server/CMakeLists.txt
index f553990..0a8d420 100644
--- a/tests/auto/cmake/test_modules/server/CMakeLists.txt
+++ b/tests/auto/cmake/test_modules/server/CMakeLists.txt
@@ -1,24 +1,10 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.16)
project(cmake_axserver)
-find_package(Qt5Core REQUIRED)
-find_package(Qt5Gui REQUIRED)
-find_package(Qt5Widgets REQUIRED)
-
-find_package(Qt5AxServer REQUIRED)
-
-include_directories(
- ${Qt5AxServer_INCLUDE_DIRS}
-)
-
-add_definitions(${Qt5AxServer_DEFINITIONS})
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
-
+find_package(Qt6 COMPONENTS Core Gui Widgets AxServer CONFIG REQUIRED)
add_executable(axserverapp WIN32 axserver.cpp)
-
-target_link_libraries(axserverapp
- ${Qt5AxServer_LIBRARIES}
-)
+target_link_libraries(axserverapp Qt6::Core Qt6::Gui Qt6::Widgets Qt6::AxServer)
diff --git a/tests/auto/cmake/test_modules/server/axserver.cpp b/tests/auto/cmake/test_modules/server/axserver.cpp
index b31014c..6dabc17 100644
--- a/tests/auto/cmake/test_modules/server/axserver.cpp
+++ b/tests/auto/cmake/test_modules/server/axserver.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
-** 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 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qt_windows.h>
#include <QAxFactory>
diff --git a/tests/auto/cmake/test_target_typelibs/CMakeLists.txt b/tests/auto/cmake/test_target_typelibs/CMakeLists.txt
new file mode 100644
index 0000000..528aa08
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_typelibs)
+
+find_package(Qt6 COMPONENTS AxContainer Gui Widgets CONFIG REQUIRED)
+
+add_executable(tst_typelibs main.cpp)
+target_link_libraries(tst_typelibs PRIVATE Qt6::AxContainer Qt6::Gui Qt6::Widgets)
+
+qt6_target_typelibs(tst_typelibs LIBRARIES "ieframe.dll")
diff --git a/tests/auto/cmake/test_target_typelibs/main.cpp b/tests/auto/cmake/test_target_typelibs/main.cpp
new file mode 100644
index 0000000..4b69f66
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs/main.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "ieframe.h"
+
+int main(int argc, char *argv[])
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ delete webBrowser;
+ return 0;
+}
diff --git a/tests/auto/cmake/test_target_typelibs_absolute/CMakeLists.txt b/tests/auto/cmake/test_target_typelibs_absolute/CMakeLists.txt
new file mode 100644
index 0000000..942fa54
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_absolute/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_typelibs)
+
+find_package(Qt6 COMPONENTS AxContainer Gui Widgets CONFIG REQUIRED)
+
+add_executable(tst_typelibs main.cpp)
+target_link_libraries(tst_typelibs PRIVATE Qt6::AxContainer Qt6::Gui Qt6::Widgets)
+
+qt6_target_typelibs(tst_typelibs LIBRARIES "$ENV{SystemRoot}/System32/ieframe.dll")
diff --git a/tests/auto/cmake/test_target_typelibs_absolute/main.cpp b/tests/auto/cmake/test_target_typelibs_absolute/main.cpp
new file mode 100644
index 0000000..4b69f66
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_absolute/main.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "ieframe.h"
+
+int main(int argc, char *argv[])
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ delete webBrowser;
+ return 0;
+}
diff --git a/tests/auto/cmake/test_target_typelibs_empty_libs/CMakeLists.txt b/tests/auto/cmake/test_target_typelibs_empty_libs/CMakeLists.txt
new file mode 100644
index 0000000..2971c1b
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_empty_libs/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_typelibs)
+
+find_package(Qt6 COMPONENTS AxContainer Gui Widgets CONFIG REQUIRED)
+
+add_executable(tst_typelibs main.cpp)
+target_link_libraries(tst_typelibs PRIVATE Qt6::AxContainer Qt6::Gui Qt6::Widgets)
+
+qt6_target_typelibs(tst_typelibs)
diff --git a/tests/auto/cmake/test_target_typelibs_empty_libs/main.cpp b/tests/auto/cmake/test_target_typelibs_empty_libs/main.cpp
new file mode 100644
index 0000000..4b69f66
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_empty_libs/main.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "ieframe.h"
+
+int main(int argc, char *argv[])
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ delete webBrowser;
+ return 0;
+}
diff --git a/tests/auto/cmake/test_target_typelibs_non_existing_libs/CMakeLists.txt b/tests/auto/cmake/test_target_typelibs_non_existing_libs/CMakeLists.txt
new file mode 100644
index 0000000..aaca1c9
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_non_existing_libs/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_typelibs)
+
+find_package(Qt6 COMPONENTS AxContainer Gui Widgets CONFIG REQUIRED)
+
+add_executable(tst_typelibs main.cpp)
+target_link_libraries(tst_typelibs PRIVATE Qt6::AxContainer Qt6::Gui Qt6::Widgets)
+
+qt6_target_typelibs(tst_typelibs LIBRARIES "ieframe.dll" "qt100notexistinglib.dll")
diff --git a/tests/auto/cmake/test_target_typelibs_non_existing_libs/main.cpp b/tests/auto/cmake/test_target_typelibs_non_existing_libs/main.cpp
new file mode 100644
index 0000000..4b69f66
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_non_existing_libs/main.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "ieframe.h"
+
+int main(int argc, char *argv[])
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ delete webBrowser;
+ return 0;
+}
diff --git a/tests/auto/cmake/test_target_typelibs_out_dir/CMakeLists.txt b/tests/auto/cmake/test_target_typelibs_out_dir/CMakeLists.txt
new file mode 100644
index 0000000..d1c38ae
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_out_dir/CMakeLists.txt
@@ -0,0 +1,15 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(tst_typelibs)
+
+find_package(Qt6 COMPONENTS AxContainer Gui Widgets CONFIG REQUIRED)
+
+add_executable(tst_typelibs main.cpp)
+target_link_libraries(tst_typelibs PRIVATE Qt6::AxContainer Qt6::Gui Qt6::Widgets)
+target_include_directories(tst_typelibs PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
+
+qt6_target_typelibs(tst_typelibs LIBRARIES "ieframe.dll"
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/typelibs"
+)
diff --git a/tests/auto/cmake/test_target_typelibs_out_dir/main.cpp b/tests/auto/cmake/test_target_typelibs_out_dir/main.cpp
new file mode 100644
index 0000000..a2f659a
--- /dev/null
+++ b/tests/auto/cmake/test_target_typelibs_out_dir/main.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "typelibs/ieframe.h"
+
+int main(int argc, char *argv[])
+{
+ SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ delete webBrowser;
+ return 0;
+}
diff --git a/tests/auto/conversion/CMakeLists.txt b/tests/auto/conversion/CMakeLists.txt
index 4aab821..1e25aeb 100644
--- a/tests/auto/conversion/CMakeLists.txt
+++ b/tests/auto/conversion/CMakeLists.txt
@@ -1,13 +1,24 @@
-# Generated from conversion.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## conversion Test:
#####################################################################
-qt_add_test(conversion
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(conversion LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(conversion
SOURCES
tst_conversion.cpp
- PUBLIC_LIBRARIES
+ INCLUDE_DIRECTORIES
+ ../../../src/activeqt/shared/
+ LIBRARIES
Qt::AxContainer
Qt::Gui
+ Qt::AxBasePrivate
+ Qt::CorePrivate
)
diff --git a/tests/auto/conversion/comutil_p.h b/tests/auto/conversion/comutil_p.h
new file mode 100644
index 0000000..e722ed5
--- /dev/null
+++ b/tests/auto/conversion/comutil_p.h
@@ -0,0 +1,250 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef COMUTIL_P_H
+#define COMUTIL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QtGlobal>
+#include <QtAxBase/private/qbstr_p.h>
+#include <comdef.h>
+#include <type_traits>
+#include <oleauto.h>
+#include <wrl/client.h>
+
+using Microsoft::WRL::ComPtr;
+
+template<typename T>
+ComPtr<T> makeComObject()
+{
+ ComPtr<T> ptr;
+ *ptr.GetAddressOf() = new T;
+ return ptr;
+}
+
+template<typename T>
+constexpr VARTYPE ValueType()
+{
+ using ValueType = std::remove_cv_t<std::remove_pointer_t<T>>;
+
+ constexpr VARTYPE maybeByref = std::is_pointer_v<T> ? VT_BYREF : VT_EMPTY;
+ if constexpr (std::is_same_v<ValueType, bool>)
+ return VT_BOOL | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, char>)
+ return VT_I1 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, unsigned char>)
+ return VT_UI1 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, short>)
+ return VT_I2 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, unsigned short>)
+ return VT_UI2 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, int>)
+ return VT_I4 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, unsigned int>)
+ return VT_UI4 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, long long>)
+ return VT_I8 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, unsigned long long>)
+ return VT_UI8 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, float>)
+ return VT_R4 | maybeByref;
+ else if constexpr (std::is_same_v<ValueType, double>)
+ return VT_R8 | maybeByref;
+ else if constexpr (std::is_same_v<const ValueType *, const wchar_t *>)
+ return VT_BSTR;
+ else if constexpr (std::is_base_of_v<IDispatch, ValueType>)
+ return VT_DISPATCH;
+ else if constexpr (std::is_base_of_v<IUnknown, ValueType>)
+ return VT_UNKNOWN;
+ else
+ return VT_EMPTY;
+};
+
+template<typename T>
+constexpr auto ValueField()
+{
+ using Type = std::remove_const_t<T>;
+ if constexpr (std::is_same_v<Type, bool>)
+ return &VARIANT::boolVal;
+ else if constexpr (std::is_same_v<Type, bool *>)
+ return &VARIANT::pboolVal;
+ else if constexpr (std::is_same_v<Type, char>)
+ return &VARIANT::cVal;
+ else if constexpr (std::is_same_v<Type, char *>)
+ return &VARIANT::pcVal;
+ else if constexpr (std::is_same_v<Type, unsigned char>)
+ return &VARIANT::bVal;
+ else if constexpr (std::is_same_v<Type, unsigned char *>)
+ return &VARIANT::pbVal;
+ else if constexpr (std::is_same_v<Type, short>)
+ return &VARIANT::iVal;
+ else if constexpr (std::is_same_v<Type, short *>)
+ return &VARIANT::piVal;
+ else if constexpr (std::is_same_v<Type, unsigned short>)
+ return &VARIANT::uiVal;
+ else if constexpr (std::is_same_v<Type, unsigned short *>)
+ return &VARIANT::puiVal;
+ else if constexpr (std::is_same_v<Type, int>)
+ return &VARIANT::intVal;
+ else if constexpr (std::is_same_v<Type, int *>)
+ return &VARIANT::pintVal;
+ else if constexpr (std::is_same_v<Type, unsigned int>)
+ return &VARIANT::uintVal;
+ else if constexpr (std::is_same_v<Type, unsigned int *>)
+ return &VARIANT::puintVal;
+ else if constexpr (std::is_same_v<Type, long long>)
+ return &VARIANT::llVal;
+ else if constexpr (std::is_same_v<Type, long long *>)
+ return &VARIANT::pllVal;
+ else if constexpr (std::is_same_v<Type, unsigned long long>)
+ return &VARIANT::ullVal;
+ else if constexpr (std::is_same_v<Type, unsigned long long *>)
+ return &VARIANT::pullVal;
+ else if constexpr (std::is_same_v<Type, float>)
+ return &VARIANT::fltVal;
+ else if constexpr (std::is_same_v<Type, float *>)
+ return &VARIANT::pfltVal;
+ else if constexpr (std::is_same_v<Type, double>)
+ return &VARIANT::dblVal;
+ else if constexpr (std::is_same_v<Type, double *>)
+ return &VARIANT::pdblVal;
+ else if constexpr (std::is_same_v<T, const wchar_t *>)
+ return &VARIANT::bstrVal;
+ else if constexpr (std::is_base_of_v<IDispatch, std::remove_pointer_t<Type>>)
+ return &VARIANT::pdispVal;
+ else if constexpr (std::is_base_of_v<IUnknown, std::remove_pointer_t<Type>>)
+ return &VARIANT::punkVal;
+}
+
+class ComVariant : public tagVARIANT
+{
+public:
+ ComVariant() noexcept : VARIANT{} { ::VariantInit(this); }
+
+ ~ComVariant()
+ {
+ const HRESULT hr = ::VariantClear(this);
+ Q_ASSERT(hr == S_OK);
+ Q_UNUSED(hr)
+ }
+
+ ComVariant(const ComVariant &src) : ComVariant() { copy(&src); }
+ ComVariant(const VARIANT &src) noexcept : ComVariant() { copy(&src); }
+ ComVariant(const QBStr &src) noexcept : ComVariant() { copy(src.bstr()); }
+
+ template<typename T>
+ ComVariant(const T &value) : ComVariant()
+ {
+ assign(value);
+ }
+
+ ComVariant &operator=(const ComVariant &rhs) noexcept
+ {
+ if (this == &rhs)
+ return *this;
+
+ clear();
+ copy(&rhs);
+
+ return *this;
+ }
+
+ template<typename T>
+ ComVariant &operator=(const T &rhs)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ void clear()
+ {
+ const HRESULT hr = ::VariantClear(this);
+
+ Q_ASSERT(hr == S_OK);
+ Q_UNUSED(hr)
+ }
+
+ void copy(const VARIANT *src)
+ {
+ vt = VT_EMPTY;
+ const HRESULT hr = ::VariantCopy(this, const_cast<VARIANT *>(src));
+
+ Q_ASSERT(hr == S_OK);
+ Q_UNUSED(hr)
+ }
+
+ void copy(const BSTR &src)
+ {
+ vt = VT_EMPTY;
+ if (!src)
+ return;
+
+ vt = VT_BSTR;
+ bstrVal = ::SysAllocStringByteLen(reinterpret_cast<const char *>(src),
+ ::SysStringByteLen(src));
+
+ Q_ASSERT(bstrVal);
+ }
+
+ bool operator==(const ComVariant &rhs) const
+ {
+ auto *lhs = const_cast<tagVARIANT *>(static_cast<const tagVARIANT *>(this));
+ auto *other = const_cast<tagVARIANT *>(static_cast<const tagVARIANT *>(&rhs));
+ return compare(lhs, other, LOCALE_USER_DEFAULT, 0) == static_cast<HRESULT>(VARCMP_EQ);
+ }
+
+private:
+ template<typename T>
+ void assign(const T &value)
+ {
+ constexpr VARTYPE valueType = ValueType<T>();
+ static_assert(valueType != VT_EMPTY, "Invalid type for ComVariant");
+
+ vt = valueType;
+
+ constexpr auto VARIANT::*field = ValueField<T>();
+ if constexpr (valueType == VT_BSTR)
+ this->*field = QBStr{ value }.release();
+ else
+ this->*field = value;
+
+ if constexpr (valueType == VT_UNKNOWN || valueType == VT_DISPATCH)
+ value->AddRef();
+ }
+
+ static HRESULT compare(VARIANT *lhs, VARIANT *rhs, LCID lcid, ULONG flags)
+ {
+ // Workaround missing support for VT_I1, VT_UI2, VT_UI4 and VT_UI8 in VarCmp
+ switch (lhs->vt) {
+ case VT_I1:
+ if (lhs->cVal == rhs->cVal)
+ return VARCMP_EQ;
+ return lhs->cVal > rhs->cVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI2:
+ if (lhs->uiVal == rhs->uiVal)
+ return VARCMP_EQ;
+ return lhs->uiVal > rhs->uiVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI4:
+ if (lhs->uintVal == rhs->uintVal)
+ return VARCMP_EQ;
+ return lhs->uintVal > rhs->uintVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI8:
+ if (lhs->ullVal == rhs->ullVal)
+ return VARCMP_EQ;
+ return lhs->ullVal > rhs->ullVal ? VARCMP_GT : VARCMP_LT;
+ }
+ return ::VarCmp(lhs, rhs, lcid, flags);
+ }
+};
+
+#endif
diff --git a/tests/auto/conversion/conversion.pro b/tests/auto/conversion/conversion.pro
deleted file mode 100644
index 47f0699..0000000
--- a/tests/auto/conversion/conversion.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG += testcase
-QT += axcontainer testlib
-SOURCES += tst_conversion.cpp
diff --git a/tests/auto/conversion/testutil_p.h b/tests/auto/conversion/testutil_p.h
new file mode 100644
index 0000000..572e3d1
--- /dev/null
+++ b/tests/auto/conversion/testutil_p.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TESTUTIL_P_H
+#define TESTUTIL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qtcore/qt_windows.h>
+#include <qtcore/private/qcomobject_p.h>
+#include <qtcore/qtglobal>
+#include <wrl/client.h>
+#include <atomic>
+
+using Microsoft::WRL::ComPtr;
+
+template <typename T>
+ULONG refCount(const ComPtr<T> &p)
+{
+ p->AddRef();
+ return p->Release();
+}
+
+struct IUnknownStub : QComObject<IUnknown>
+{
+};
+
+struct IDispatchStub : QComObject<IDispatch>
+{
+ HRESULT GetTypeInfoCount(UINT * /*pctinfo*/) override { return E_NOTIMPL; }
+
+ HRESULT GetTypeInfo(UINT /*iTInfo*/, LCID /*lcid*/, ITypeInfo ** /*ppTInfo*/) override
+ {
+ return E_NOTIMPL;
+ }
+
+ HRESULT GetIDsOfNames(const IID & /*riid*/, LPOLESTR * /*rgszNames*/, UINT /*cNames*/,
+ LCID /*lcid*/, DISPID * /*rgDispId*/) override
+ {
+ return E_NOTIMPL;
+ }
+
+ HRESULT Invoke(DISPID /*dispIdMember*/, const IID & /*riid*/, LCID /*lcid*/, WORD /*wFlags*/,
+ DISPPARAMS * /*pDispParams*/, VARIANT * /*pVarResult*/,
+ EXCEPINFO * /*pExcepInfo*/, UINT * /*puArgErr*/) override
+ {
+ return E_NOTIMPL;
+ }
+};
+
+#endif
diff --git a/tests/auto/conversion/tst_conversion.cpp b/tests/auto/conversion/tst_conversion.cpp
index 52be69b..ba7bb5d 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
+
+#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,271 @@ 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();
+
+ const ULONG expectedRefCount = refCount(stub);
+
+ const QVariant qVariant = VARIANTToQVariant(value, {});
+
+ QVERIFY(refCount(stub) == expectedRefCount);
+
+ 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;
+
+ const ULONG expectedRefCount = refCount(stub) + 1; // Add one for the VARIANT
+
+ QVERIFY(QVariantToVARIANT(qvar, comVariant));
+
+ QCOMPARE(refCount(stub), expectedRefCount);
+
+ 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();
+
+ const ULONG expectedRefCount = refCount(stub);
+
+ const QVariant qVariant = VARIANTToQVariant(value, "IDispatch*");
+
+ QCOMPARE(refCount(stub), expectedRefCount);
+
+ 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;
+ const auto expectedRefCount = refCount(testFixture.m_iDispatchStub) + 1;
+
+ ComVariant comVariant;
+ QVERIFY(QVariantToVARIANT(testFixture.m_qVariant, comVariant));
+
+ QCOMPARE(refCount(testFixture.m_iDispatchStub), expectedRefCount);
+
+ const ComPtr<IUnknown> recovered = comVariant.pdispVal;
+
+ QCOMPARE(recovered, testFixture.m_iDispatchStub);
+}
+
+void tst_Conversion::VARIANTToQVariant_IncreasesRefCount_WhenCalledWithQVariantTypeName()
+{
+ const IDispatchFixture testFixture;
+ const auto expectedRefCount = refCount(testFixture.m_iDispatchStub) + 1;
+
+ 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(refCount(testFixture.m_iDispatchStub), expectedRefCount);
+
+ // Workaround to ensure cleanup
+ testFixture.m_iDispatchStub->Release();
+}
+
+void tst_Conversion::ObserveThat_VARIANTToQVariant_ReturnsEmptyQVariant_WhenWrappingIDispatchInQAxObjectPtr()
+{
+ const IDispatchFixture testFixture;
+ QCOMPARE(refCount(testFixture.m_iDispatchStub), 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(refCount(testFixture.m_iDispatchStub), 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"
diff --git a/tests/auto/dumpcpp/CMakeLists.txt b/tests/auto/dumpcpp/CMakeLists.txt
index 91da6c3..a5ff2dc 100644
--- a/tests/auto/dumpcpp/CMakeLists.txt
+++ b/tests/auto/dumpcpp/CMakeLists.txt
@@ -1,20 +1,24 @@
-# Generated from dumpcpp.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
## tst_dumpcpp Test:
#####################################################################
-qt_add_test(tst_dumpcpp
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_dumpcpp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_dumpcpp
SOURCES
tst_dumpcpp.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::AxContainer
Qt::Gui
Qt::Widgets
)
-#### Keys ignored in scope 1:.:.:dumpcpp.pro:<TRUE>:
-# TYPELIBS = "$$(SystemRoot)\\system32\\ieframe.dll"
-
-## Scopes:
-#####################################################################
+qt6_target_typelibs(tst_dumpcpp LIBRARIES "ieframe.dll")
+qt6_target_typelibs(tst_dumpcpp LIBRARIES "msxml6.dll")
diff --git a/tests/auto/dumpcpp/dumpcpp.pro b/tests/auto/dumpcpp/dumpcpp.pro
deleted file mode 100644
index aae7bd8..0000000
--- a/tests/auto/dumpcpp/dumpcpp.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-CONFIG += testcase
-QT += widgets axcontainer testlib
-SOURCES += tst_dumpcpp.cpp
-TARGET = tst_dumpcpp
-
-# Assume Web Browser type library is available in all windows installations
-TYPELIBS = $$(SystemRoot)\\system32\\ieframe.dll
-
-!exists($$TYPELIBS) {
- message("Web Browser type library for test not found!")
-}
diff --git a/tests/auto/dumpcpp/tst_dumpcpp.cpp b/tests/auto/dumpcpp/tst_dumpcpp.cpp
index 039c090..66cd158 100644
--- a/tests/auto/dumpcpp/tst_dumpcpp.cpp
+++ b/tests/auto/dumpcpp/tst_dumpcpp.cpp
@@ -1,47 +1,55 @@
-/****************************************************************************
-**
-** 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
#include <QtTest/QtTest>
#include "ieframe.h" // generated header
+#include "msxml6.h" // generated header
#include <QApplication>
+
+struct XmlFixture
+{
+ MSXML2::DOMDocument60 doc;
+ MSXML2::IXMLDOMNodeList *root;
+
+ const QString xml{
+ R"(
+ <root prop="The root property">
+ The value
+ </root>
+ )" };
+};
+
class tst_dumpcpp : public QObject
{
Q_OBJECT
private slots:
+ void init();
void toggleAddressBar();
+ void propertyGetter_ReturnsValue_WhenValueIsInt();
+ void propertyGetter_ReturnsValue_WhenValueIsString();
+ void invokeGetter_ReturnsValue_WhenValueInheritsIDispatch();
+ void propertyGetter_ReturnsValue_WhenValueInheritsIDispatch();
+
+ void propertySetter_SetsValue_WhenValueIsVariantInt();
+ void propertySetter_SetsValue_WhenValueIsString();
+ void invoke_SetsValue_WhenValueDerivesFromIDispatch();
+
+private:
+ XmlFixture m_xml;
};
+void tst_dumpcpp::init()
+{
+ m_xml.doc.loadXML(m_xml.xml);
+ m_xml.root = m_xml.doc.childNodes();
+}
+
// A simple test to verify that an object can be instantiated and interacted with
void tst_dumpcpp::toggleAddressBar()
{
- SHDocVw::WebBrowser* webBrowser = new SHDocVw::WebBrowser;
+ SHDocVw::WebBrowser *webBrowser = new SHDocVw::WebBrowser;
QVERIFY(webBrowser);
bool addressBar = webBrowser->AddressBar();
addressBar = !addressBar;
@@ -50,5 +58,60 @@ void tst_dumpcpp::toggleAddressBar()
delete webBrowser;
}
+void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueIsInt()
+{
+ int length = m_xml.root->length();
+ QVERIFY(length == 1);
+}
+
+void tst_dumpcpp::invokeGetter_ReturnsValue_WhenValueInheritsIDispatch()
+{
+ // item(...) takes an argument and is called as a function invocation
+ MSXML2::IXMLDOMNode *firstChild = m_xml.root->item(0);
+ QVERIFY(firstChild);
+}
+
+void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueInheritsIDispatch()
+{
+ // attributes() takes an argument and is called as property getter
+ MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes();
+ QVERIFY(attributes);
+}
+
+void tst_dumpcpp::propertyGetter_ReturnsValue_WhenValueIsString()
+{
+ MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes();
+
+ // nodeValue is a property getter
+ QVariant p = attributes->getNamedItem("prop")->nodeValue();
+ QCOMPARE(p, "The root property");
+}
+
+void tst_dumpcpp::propertySetter_SetsValue_WhenValueIsVariantInt()
+{
+ MSXML2::IXMLDOMNamedNodeMap *attributes = m_xml.root->item(0)->attributes();
+ MSXML2::IXMLDOMNode *attribNode = attributes->item(0);
+ attribNode->setNodeValue(QVariant { 42 } );
+
+ QVariant p = attributes->getNamedItem("prop")->nodeValue();
+ QCOMPARE(p, 42);
+}
+
+void tst_dumpcpp::propertySetter_SetsValue_WhenValueIsString()
+{
+ m_xml.root->item(0)->setText("The new value");
+ QCOMPARE(m_xml.root->item(0)->text(), "The new value");
+}
+
+void tst_dumpcpp::invoke_SetsValue_WhenValueDerivesFromIDispatch()
+{
+ MSXML2::IXMLDOMNode *node = m_xml.doc.createNode(MSXML2::NODE_ELEMENT, "sometag", "");
+ node->setText("The new text");
+
+ m_xml.root->item(0)->appendChild(node);
+
+ QCOMPARE(m_xml.root->item(0)->childNodes()->item(1)->text(), "The new text");
+}
+
QTEST_MAIN(tst_dumpcpp)
#include "tst_dumpcpp.moc"
diff --git a/tests/auto/qaxobject/CMakeLists.txt b/tests/auto/qaxobject/CMakeLists.txt
index 7c07415..87fe2e1 100644
--- a/tests/auto/qaxobject/CMakeLists.txt
+++ b/tests/auto/qaxobject/CMakeLists.txt
@@ -1,13 +1,20 @@
-# Generated from qaxobject.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
-## qaxobject Test:
+## QAxObject Test:
#####################################################################
-qt_add_test(qaxobject
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qaxobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qaxobject
SOURCES
tst_qaxobject.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::AxContainer
Qt::Gui
)
diff --git a/tests/auto/qaxobject/qaxobject.pro b/tests/auto/qaxobject/qaxobject.pro
deleted file mode 100644
index e6f51a1..0000000
--- a/tests/auto/qaxobject/qaxobject.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG += testcase
-QT += axcontainer testlib
-SOURCES += tst_qaxobject.cpp
diff --git a/tests/auto/qaxobject/tst_qaxobject.cpp b/tests/auto/qaxobject/tst_qaxobject.cpp
index 3955a6c..dfae5f0 100644
--- a/tests/auto/qaxobject/tst_qaxobject.cpp
+++ b/tests/auto/qaxobject/tst_qaxobject.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** 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
#include <QtTest/QtTest>
diff --git a/tests/auto/qaxobjectcom/CMakeLists.txt b/tests/auto/qaxobjectcom/CMakeLists.txt
new file mode 100644
index 0000000..09ce6a1
--- /dev/null
+++ b/tests/auto/qaxobjectcom/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Configure the manifest file to point to the com_server dll
+# because the dll name is different in debug and release
+set(TestServerDll "TestServer${CMAKE_DEBUG_POSTFIX}.dll")
+configure_file(
+ tst_qaxobjectcom.exe.manifest.in
+ tst_qaxobjectcom.exe.manifest
+)
+
+qt_internal_add_test(tst_qaxobjectcom
+ SOURCES
+ tst_qaxobjectcom.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/tst_qaxobjectcom.exe.manifest
+ LIBRARIES
+ Qt::AxContainer
+ Qt::CorePrivate
+ Qt::AxBasePrivate
+)
+
+# Embed the manifest file into the binary for registry free COM
+target_link_options(tst_qaxobjectcom PRIVATE "/MANIFEST")
+
+# Build the com_server automatically
+add_subdirectory(testserver)
+add_dependencies(tst_qaxobjectcom testserver)
+
+# Generate qaxobject COM wrapper for our COM test server
+qt6_target_typelibs(tst_qaxobjectcom
+ LIBRARIES
+ ${CMAKE_CURRENT_BINARY_DIR}/testserver/testserverlib.tlb
+)
diff --git a/tests/auto/qaxobjectcom/testserver/CMakeLists.txt b/tests/auto/qaxobjectcom/testserver/CMakeLists.txt
new file mode 100644
index 0000000..f05ebc0
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Configure file allow execute_process to detect changes to idl file.
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/testserverlib.idl
+ ${CMAKE_CURRENT_BINARY_DIR}/testserverlib.idl
+ COPYONLY
+)
+
+# Run midl at configure time because qt6_target_typelibs checks
+# for presence of tlb file at configure time
+execute_process(
+ COMMAND
+ midl /h testserverlib.h /tlb testserverlib.tlb testserverlib.idl
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND_ERROR_IS_FATAL ANY
+)
+
+qt_add_library(testserver
+SHARED
+ testserver.h
+ testserver.cpp
+ testserver.def
+ testserverlib.idl
+ testserver.rc
+)
+
+# Trigger rebuild of resources if tlb file changed
+set_property(
+ SOURCE
+ testserver.rc
+ PROPERTY
+ OBJECT_DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/testserverlib.tlb
+)
+
+target_include_directories(testserver
+ PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+target_link_libraries(testserver
+ PRIVATE
+ Qt::CorePrivate
+ Qt::AxBasePrivate
+)
diff --git a/tests/auto/qaxobjectcom/testserver/testserver.cpp b/tests/auto/qaxobjectcom/testserver/testserver.cpp
new file mode 100644
index 0000000..1145565
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/testserver.cpp
@@ -0,0 +1,132 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QString>
+#include <QUuid>
+#include <QtCore/qassert.h>
+#include <QtCore/qdebug.h>
+#include "testserverlib.h"
+#include "testserver.h"
+
+extern "C" IMAGE_DOS_HEADER __ImageBase; // Trickery to get path to current dll
+static long s_serverLock = 0;
+
+static const std::array<wchar_t, MAX_PATH> GetModuleFilename()
+{
+ std::array<wchar_t, MAX_PATH> filename;
+ const DWORD length = GetModuleFileName(reinterpret_cast<HMODULE>(&__ImageBase), filename.data(),
+ static_cast<DWORD>(filename.size()));
+
+ if (0 == length || filename.size() == length)
+ return {};
+
+ return filename;
+}
+
+// Create a dispatcher that implements IDispatch for the input owner
+static ComPtr<IUnknown> CreateDispatcher(const QUuid &guid, IUnknown *owner)
+{
+ ComPtr<ITypeLib> typeLib;
+ if (LoadTypeLib(GetModuleFilename().data(), &typeLib) != S_OK)
+ {
+ qCritical("Failed to load type library");
+ return {};
+ }
+
+ ComPtr<ITypeInfo> typeInfo;
+ if (typeLib->GetTypeInfoOfGuid(guid, &typeInfo)
+ != S_OK) {
+ qCritical("Failed to get type info");
+ return {};
+ }
+
+ ComPtr<IUnknown> dispatcher;
+ if (CreateStdDispatch(owner, owner, typeInfo.Get(), &dispatcher) != S_OK) {
+ qCritical("Failed to create standard dispatch");
+ return {};
+ }
+
+ return dispatcher;
+}
+
+TestServer::TestServer()
+{
+ m_unkDisp = CreateDispatcher(__uuidof(IComServer), this);
+ ++s_serverLock;
+}
+
+HRESULT __stdcall TestServer::QueryInterface(IID const &id, void **result)
+{
+ Q_ASSERT(result);
+ if (id == __uuidof(IDispatch)) {
+ ComPtr<IDispatch> disp;
+ m_unkDisp.As(&disp);
+ *result = disp.Detach();
+ return S_OK;
+ }
+ return QComObject::QueryInterface(id, result);
+}
+
+HRESULT TestServer::SetObserver(IUnknown* observer)
+{
+ const ComPtr<IUnknown> rcv{ observer };
+ return rcv.As(&m_receiver);
+}
+
+HRESULT TestServer::VariantIn(VARIANT v)
+{
+ return m_receiver->VariantIn(v);
+}
+
+struct Factory : IClassFactory
+{
+ ULONG __stdcall AddRef() override { return 2; }
+ ULONG __stdcall Release() override { return 1; }
+ HRESULT __stdcall QueryInterface(IID const &id, void **result) override
+ {
+ Q_ASSERT(result);
+
+ if (id == __uuidof(IClassFactory) || id == __uuidof(IUnknown)) {
+ *result = static_cast<IClassFactory *>(this);
+ return S_OK;
+ }
+
+ *result = nullptr;
+ return E_NOINTERFACE;
+ }
+
+ HRESULT __stdcall CreateInstance(IUnknown *outer, IID const &iid, void **result) override
+ {
+ Q_ASSERT(result);
+ Q_ASSERT(!outer);
+
+ const ComPtr<TestServer> server{ new (std::nothrow) TestServer };
+ return server->QueryInterface(iid, result);
+ }
+
+ HRESULT __stdcall LockServer(BOOL lock) override
+ {
+ if (lock)
+ ++s_serverLock;
+ else
+ --s_serverLock;
+
+ return S_OK;
+ }
+};
+
+HRESULT __stdcall DllGetClassObject(CLSID const &clsid, IID const &iid, void **result)
+{
+ if (__uuidof(TestServer) == clsid) {
+ static Factory farm;
+
+ return farm.QueryInterface(iid, result);
+ }
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT __stdcall DllCanUnloadNow()
+{
+ return s_serverLock ? S_FALSE : S_OK;
+}
diff --git a/tests/auto/qaxobjectcom/testserver/testserver.def b/tests/auto/qaxobjectcom/testserver/testserver.def
new file mode 100644
index 0000000..56e1a71
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/testserver.def
@@ -0,0 +1,3 @@
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
diff --git a/tests/auto/qaxobjectcom/testserver/testserver.h b/tests/auto/qaxobjectcom/testserver/testserver.h
new file mode 100644
index 0000000..53663ef
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/testserver.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef TEST_SERVER_H
+#define TEST_SERVER_H
+
+#include <qt_windows.h>
+#include "testserverlib.h"
+#include <wrl/client.h>
+#include <QtCore/private/qcomobject_p.h>
+#include "../../conversion/comutil_p.h"
+
+using Microsoft::WRL::ComPtr;
+
+class __declspec(uuid("af732aba-95cf-4ee7-bd59-8f946b7f82e3"))
+TestServer : public QComObject<IComServer>
+{
+public:
+ TestServer();
+
+ HRESULT __stdcall QueryInterface(IID const &id, void **result) override;
+ HRESULT __stdcall SetObserver(IUnknown *observer) override;
+ HRESULT __stdcall VariantIn(VARIANT v) override;
+
+private:
+ ComPtr<IUnknown> m_unkDisp;
+ ComPtr<IComServer> m_receiver;
+};
+
+struct Receiver : public QComObject<IComServer>
+{
+ HRESULT SetObserver(IUnknown *observer) override { return E_NOTIMPL; }
+
+ HRESULT VariantIn(VARIANT arg) override
+ {
+ lastArg = ComVariant{ arg };
+ return S_OK;
+ }
+
+ ComVariant lastArg{};
+};
+
+#endif
diff --git a/tests/auto/qaxobjectcom/testserver/testserver.rc b/tests/auto/qaxobjectcom/testserver/testserver.rc
new file mode 100644
index 0000000..51dfeed
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/testserver.rc
@@ -0,0 +1 @@
+1 TYPELIB "testserverlib.tlb"
diff --git a/tests/auto/qaxobjectcom/testserver/testserverlib.idl b/tests/auto/qaxobjectcom/testserver/testserverlib.idl
new file mode 100644
index 0000000..00d64ab
--- /dev/null
+++ b/tests/auto/qaxobjectcom/testserver/testserverlib.idl
@@ -0,0 +1,33 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ dual,
+ uuid(f4811a11-3092-415e-a473-38c627544246),
+ oleautomation,
+ pointer_default(unique)
+]
+interface IComServer : IUnknown
+{
+ HRESULT SetObserver([in] IUnknown *observer);
+ HRESULT VariantIn([in] VARIANT arg);
+};
+
+[
+ uuid(104d435f-7504-4786-aae7-b22745450c4c),
+ version(1.0),
+]
+library ComServerLib
+{
+ [
+ uuid(af732aba-95cf-4ee7-bd59-8f946b7f82e3),
+ ]
+ coclass TestServer
+ {
+ interface IComServer;
+ };
+};
diff --git a/tests/auto/qaxobjectcom/tst_qaxobjectcom.cpp b/tests/auto/qaxobjectcom/tst_qaxobjectcom.cpp
new file mode 100644
index 0000000..fec1d8d
--- /dev/null
+++ b/tests/auto/qaxobjectcom/tst_qaxobjectcom.cpp
@@ -0,0 +1,87 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtTest/QtTest>
+#include "testserverlib.h"
+#include <testserver/testserverlib.h>
+#include "testserver/testserver.h"
+#include "../conversion/comutil_p.h"
+#include <QtAxBase/private/qbstr_p.h>
+
+class tst_qaxobjectcom : public QObject
+{
+ Q_OBJECT
+private slots:
+ void comObject_receivesVARIANT_whenCalledWithQVariant_data()
+ {
+ QTest::addColumn<QVariant>("value");
+ QTest::addColumn<ComVariant>("expected");
+
+ QTest::addRow("bool") << QVariant{ true } << ComVariant{ VARIANT_TRUE };
+ QTest::addRow("short") << QVariant{ static_cast<short>(3) } << ComVariant{ static_cast<int>(3) }; // TODO: Fixme
+ QTest::addRow("unsigned short") << QVariant{ static_cast<ushort>(3) } << ComVariant{ static_cast<int>(3) }; // TODO: Fixme
+ QTest::addRow("int") << QVariant{ 3 } << ComVariant{ 3 };
+ QTest::addRow("unsigned int") << QVariant{ 3u } << ComVariant{ 3u };
+ QTest::addRow("long long") << QVariant{ 3ll } << ComVariant{ 3ll };
+ QTest::addRow("unsigned long long") << QVariant{ 3ull } << ComVariant{ 3ull };
+ QTest::addRow("float") << QVariant{ 3.3f } << ComVariant{ 3.3f };
+ QTest::addRow("double") << QVariant{ 3.3 } << ComVariant{ 3.3 };
+ }
+
+ void comObject_receivesVARIANT_whenCalledWithQVariant()
+ {
+ QFETCH(const QVariant, value);
+ QFETCH(const ComVariant, expected);
+
+ // Arrange
+ ComServerLib::TestServer server;
+ const ComPtr<Receiver> observer = makeComObject<Receiver>();
+ server.SetObserver(observer.Get());
+
+ // Act
+ server.VariantIn(value);
+
+ // Assert
+ QCOMPARE_EQ(observer->lastArg, expected);
+ }
+
+ void comObject_receivesVARIANT_whenCalledWithVariantStringList()
+ {
+ const QVariant value{ QList{ QVariant{ "A" }, QVariant{ "BC" } } };
+
+ // Arrange
+ ComServerLib::TestServer server;
+ const ComPtr<Receiver> observer = makeComObject<Receiver>();
+ server.SetObserver(observer.Get());
+
+ // Act
+ server.VariantIn(value);
+
+ // Assert
+ QVERIFY(V_ISARRAY(&observer->lastArg));
+
+ LPSAFEARRAY safeArray = V_ARRAY(&observer->lastArg);
+
+ VARTYPE itemType;
+ if (SUCCEEDED(SafeArrayGetVartype(safeArray, &itemType)))
+
+ QCOMPARE_EQ(itemType, VT_VARIANT);
+
+ LPVOID data;
+ QCOMPARE_EQ(SafeArrayAccessData(safeArray, &data), S_OK);
+
+ const auto *pItems = static_cast<const VARIANT*>(data);
+ ComVariant item1{ pItems[0] };
+ ComVariant item2{ pItems[1] };
+
+ QCOMPARE_EQ(item1, ComVariant{ QBStr{ L"A" } });
+ QCOMPARE_EQ(item2, ComVariant{ QBStr{ L"BC" } });
+
+ // end accessing data
+ QCOMPARE_EQ(SafeArrayUnaccessData(safeArray), S_OK);
+
+ }
+};
+
+QTEST_MAIN(tst_qaxobjectcom)
+#include "tst_qaxobjectcom.moc"
diff --git a/tests/auto/qaxobjectcom/tst_qaxobjectcom.exe.manifest.in b/tests/auto/qaxobjectcom/tst_qaxobjectcom.exe.manifest.in
new file mode 100644
index 0000000..7d6ef11
--- /dev/null
+++ b/tests/auto/qaxobjectcom/tst_qaxobjectcom.exe.manifest.in
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity version="1.0.0.0" name="tst_qaxobjectcom.app"/>
+ <file name="testserver/${TestServerDll}">
+ <comClass
+ description="Com Server"
+ clsid="{af732aba-95cf-4ee7-bd59-8f946b7f82e3}"
+ progid="Qt.TestServer"
+ threadingModel = "Both"
+ />
+ </file>
+</assembly>
diff --git a/tests/auto/qaxscript/CMakeLists.txt b/tests/auto/qaxscript/CMakeLists.txt
index 4312217..351ab2f 100644
--- a/tests/auto/qaxscript/CMakeLists.txt
+++ b/tests/auto/qaxscript/CMakeLists.txt
@@ -1,12 +1,19 @@
-# Generated from qaxscript.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
#####################################################################
-## qaxscript Test:
+## tst_QAxScript Test:
#####################################################################
-qt_add_test(qaxscript
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qaxscript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qaxscript
SOURCES
tst_qaxscript.cpp
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::AxContainer
)
diff --git a/tests/auto/qaxscript/qaxscript.pro b/tests/auto/qaxscript/qaxscript.pro
deleted file mode 100644
index 704b2cd..0000000
--- a/tests/auto/qaxscript/qaxscript.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG += testcase
-QT = core axcontainer testlib
-SOURCES += tst_qaxscript.cpp
diff --git a/tests/auto/qaxscript/tst_qaxscript.cpp b/tests/auto/qaxscript/tst_qaxscript.cpp
index 3b3ab88..1eb4258 100644
--- a/tests/auto/qaxscript/tst_qaxscript.cpp
+++ b/tests/auto/qaxscript/tst_qaxscript.cpp
@@ -1,57 +1,162 @@
-/****************************************************************************
-**
-** 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
#include <QtTest/QtTest>
#include <QAxScriptManager>
#include <QAxScript>
+using namespace Qt::StringLiterals;
+
class tst_QAxScript : public QObject
{
Q_OBJECT
private slots:
+ void call();
void scriptReturnValue();
+ void scriptOutParameters();
+ void error_data();
+ void error();
};
+void tst_QAxScript::call()
+{
+ QAxScriptManager scriptManager;
+ const auto scriptCode_js = uR"JS(
+ function test1() {
+ return 'JScript';
+ }
+ )JS"_s;
+ const auto scriptCode_vb = uR"VB(
+ Function test2()
+ test2 = "VBScript"
+ End Function
+ )VB"_s;
+ QAxScript *jsscript = scriptManager.load(scriptCode_js, u"JS"_s, u"JScript"_s);
+ QVERIFY2(jsscript, "Unable to load script (CoInitializeEx() called?)");
+ QVERIFY(jsscript->scriptEngine()->hasIntrospection());
+ QAxScript *vbscript = scriptManager.load(scriptCode_vb, u"VB"_s, u"VBScript"_s);
+ QVERIFY2(vbscript, "Unable to load script (CoInitializeEx() called?)");
+ QVERIFY(vbscript->scriptEngine()->hasIntrospection());
+
+ QCOMPARE(jsscript->call("test1()"), "JScript");
+ QTest::ignoreMessage(QtWarningMsg, "QAxBase::dynamicCallHelper: test1(): No such method in [unknown]");
+ QTest::ignoreMessage(QtWarningMsg, "\tCandidates are:");
+ QCOMPARE(vbscript->call("test1()"), QVariant());
+ QCOMPARE(vbscript->call("test2()"), "VBScript");
+ QTest::ignoreMessage(QtWarningMsg, "QAxBase::dynamicCallHelper: test2(): No such method in [unknown]");
+ QTest::ignoreMessage(QtWarningMsg, "\tCandidates are:");
+ QCOMPARE(jsscript->call("test2()"), QVariant());
+}
+
void tst_QAxScript::scriptReturnValue()
{
QAxScriptManager scriptManager;
- const char scriptCode[] =
- "function foo() {\n"
- " return 'test';\n"
- "}\n"; // QTBUG-42289, fails when DISPATCH_PROPERTYGET is used.
- QAxScript *script = scriptManager.load(QLatin1String(scriptCode),
- QStringLiteral("Test"),
- QStringLiteral("JScript"));
+ const auto scriptCode = uR"JS(
+ function foo() {
+ return 'test';
+ }
+ )JS"_s; // QTBUG-42289, fails when DISPATCH_PROPERTYGET is used.
+ QAxScript *script = scriptManager.load(scriptCode, u"Test"_s, u"JScript"_s);
QVERIFY2(script, "Unable to load script (CoInitializeEx() called?)");
const QVariant result = script->call("foo()");
- QCOMPARE(result, QVariant(QStringLiteral("test")));
+ QCOMPARE(result, QVariant(u"test"_s));
+}
+
+void tst_QAxScript::scriptOutParameters()
+{
+ QAxScriptManager scriptManager;
+ const auto scriptCode = uR"VB(
+ Function GetProductName(ByRef manufacturer, ByRef name, ByRef version)
+ manufacturer = "The Qt Company"
+ name = "ActiveQt"
+ version = 650
+ On Error Resume Next
+ GetProductName = 42
+ End Function
+ )VB"_s;
+
+ QAxScript *script = scriptManager.load(scriptCode, u"Test"_s, u"VBScript"_s);
+ QVERIFY2(script, "Unable to load script (CoInitializeEx() called?)");
+
+ QVariant returnValue;
+ QList<QVariant> results = {{}, {}, {}};
+
+ returnValue = script->scriptEngine()->dynamicCall("GetProductName(QVariant&,QVariant&,QVariant&)", results);
+ QCOMPARE(returnValue, 42);
+ QCOMPARE(results.size(), 3);
+ QCOMPARE(results.at(0), "The Qt Company");
+ QCOMPARE(results.at(1), "ActiveQt");
+ QCOMPARE(results.at(2), 650);
+
+ results = {{}, {}, {}};
+ returnValue = script->call("GetProductName(QVariant&,QVariant&,QVariant&)", results);
+ QCOMPARE(returnValue, 42);
+ QCOMPARE(results.size(), 3);
+ QCOMPARE(results.at(0), "The Qt Company");
+ QCOMPARE(results.at(1), "ActiveQt");
+ QCOMPARE(results.at(2), 650);
+}
+
+void tst_QAxScript::error_data()
+{
+ QTest::addColumn<QString>("scriptCode");
+ QTest::addColumn<QString>("language");
+ QTest::addColumn<int>("expectedErrorCode");
+ QTest::addColumn<QString>("expectedDescription");
+ QTest::addColumn<int>("expectedSourcePosition");
+ QTest::addColumn<QString>("expectedSourceText");
+
+ QTest::addRow("JS syntax error")
+ << "function foo {}"
+ << "JScript"
+ << 0 << "Expected '('" << 0 << "function foo {}";
+
+ QTest::addRow("VB syntax error")
+ << "Funktion test"
+ << "VBScript"
+ << 0 << "Type mismatch: 'Funktion'" << 0 << "";
+}
+
+void tst_QAxScript::error()
+{
+ QFETCH(QString, scriptCode);
+ QFETCH(QString, language);
+ QFETCH(int, expectedErrorCode);
+ QFETCH(QString, expectedDescription);
+ QFETCH(int, expectedSourcePosition);
+ QFETCH(QString, expectedSourceText);
+
+ QAxScriptManager scriptManager;
+ QAxScript script(u"Test"_s, &scriptManager);
+
+ QAxScript *actualScript = nullptr;
+ int actualCode;
+ QString actualDescription;
+ int actualSourcePosition;
+ QString actualSourceText;
+
+ connect(&scriptManager, &QAxScriptManager::error,
+ this, [&](QAxScript *script){
+ actualScript = script;
+ });
+
+ connect(&script, &QAxScript::error,
+ this, [&](int code, const QString &description, int sourcePosition, const QString &sourceText){
+ actualCode = code;
+ actualDescription = description;
+ actualSourcePosition = sourcePosition;
+ actualSourceText = sourceText.trimmed();
+ });
+
+ script.load(scriptCode, language);
+
+ QCOMPARE(actualScript, &script);
+ QCOMPARE(actualCode, expectedErrorCode);
+ QCOMPARE(actualDescription, expectedDescription);
+ QCOMPARE(actualSourcePosition, expectedSourcePosition);
+ QCOMPARE(actualSourceText, expectedSourceText);
}
QTEST_MAIN(tst_QAxScript)
diff --git a/tests/auto/qaxscriptmanager/CMakeLists.txt b/tests/auto/qaxscriptmanager/CMakeLists.txt
new file mode 100644
index 0000000..37b83ab
--- /dev/null
+++ b/tests/auto/qaxscriptmanager/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## QAxScriptManager Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qaxscriptmanager LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qaxscriptmanager
+ SOURCES
+ tst_qaxscriptmanager.cpp
+ LIBRARIES
+ Qt::AxContainer
+)
diff --git a/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp
new file mode 100644
index 0000000..9ecb7c2
--- /dev/null
+++ b/tests/auto/qaxscriptmanager/tst_qaxscriptmanager.cpp
@@ -0,0 +1,188 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+
+#include <QtTest/QtTest>
+#include <QAxScriptManager>
+#include <QAxScript>
+
+using namespace Qt::StringLiterals;
+
+class tst_QAxScriptManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ struct Script {
+ QString language;
+ QString name;
+ QString code;
+ };
+
+private slots:
+ void functions_data();
+ void functions();
+
+ void scriptNames_data();
+ void scriptNames();
+
+ void script_data();
+ void script();
+
+ void call_data();
+ void call();
+};
+
+void tst_QAxScriptManager::functions_data()
+{
+ const auto scriptCode_js = Script{u"JScript"_s, u"test1"_s, uR"JS(
+ function js1() {
+ return 'JScript 1';
+ }
+ function js2(value) {
+ return 'JScript 2';
+ }
+ )JS"_s};
+ const auto scriptCode_vb = Script{u"VBScript"_s, u"test2"_s, uR"VB(
+ Function vb1()
+ vb1 = "VBScript 1"
+ End Function
+
+ Function vb2(value)
+ vb2 = "VBScript 2"
+ End Function
+ )VB"_s};
+
+ QTest::addColumn<QList<Script>>("scripts");
+ QTest::addColumn<QStringList>("functions");
+ QTest::addColumn<QStringList>("signatures");
+
+ QTest::addRow("js") << QList{scriptCode_js}
+ << QStringList{"js1", "js2"}
+ << QStringList{"js1()", "js2(QVariant)"};
+ QTest::addRow("vb") << QList{scriptCode_vb}
+ << QStringList{"vb1", "vb2"}
+ << QStringList{"vb1()", "vb2(QVariant)"};
+ QTest::addRow("both") << QList{scriptCode_js, scriptCode_vb}
+ << QStringList{"js1", "js2", "vb1", "vb2"}
+ << QStringList{"js1()", "js2(QVariant)", "vb1()", "vb2(QVariant)"};
+}
+
+void tst_QAxScriptManager::functions()
+{
+ // QStringList functions(QAxScript::FunctionFlags = QAxScript::FunctionNames) const;
+
+ QFETCH(QList<Script>, scripts);
+ QFETCH(QStringList, functions);
+ QFETCH(QStringList, signatures);
+
+ QAxScriptManager scriptManager;
+ for (const auto &script : scripts) {
+ QVERIFY2(scriptManager.load(script.code, script.name, script.language),
+ "Unable to load script (CoInitializeEx() called?)");
+ }
+ functions.sort();
+ QStringList actualFunctions = scriptManager.functions();
+ actualFunctions.sort();
+ QCOMPARE(actualFunctions, functions);
+
+ QStringList actualSignatures = scriptManager.functions(QAxScript::FunctionSignatures);
+ actualSignatures.sort();
+ QCOMPARE(actualSignatures, signatures);
+}
+
+void tst_QAxScriptManager::scriptNames_data()
+{
+ functions_data();
+}
+
+void tst_QAxScriptManager::scriptNames()
+{
+ // QStringList scriptNames() const;
+ QFETCH(QList<Script>, scripts);
+ QFETCH(QStringList, functions);
+
+ QAxScriptManager scriptManager;
+ QStringList expectedNames;
+ for (const auto &script : scripts) {
+ expectedNames << script.name;
+ QVERIFY2(scriptManager.load(script.code, script.name, script.language),
+ "Unable to load script (CoInitializeEx() called?)");
+ }
+ expectedNames.sort();
+ QStringList actualNames = scriptManager.scriptNames();
+ actualNames.sort();
+ QCOMPARE(actualNames, expectedNames);
+}
+
+void tst_QAxScriptManager::script_data()
+{
+ functions_data();
+}
+
+void tst_QAxScriptManager::script()
+{
+ QFETCH(QList<Script>, scripts);
+ QFETCH(QStringList, functions);
+
+ QAxScriptManager scriptManager;
+ QStringList expectedNames;
+ for (const auto &script : scripts) {
+ expectedNames << script.name;
+ QVERIFY2(scriptManager.load(script.code, script.name, script.language),
+ "Unable to load script (CoInitializeEx() called?)");
+ }
+
+ for (const auto &script : scripts) {
+ QAxScript *axscript = scriptManager.script(script.name);
+ QVERIFY(axscript);
+ QVERIFY(axscript->scriptEngine());
+ QVERIFY(axscript->scriptEngine()->isValid());
+ const auto scriptFunctions = axscript->functions();
+ for (const auto &scriptFunction : scriptFunctions) {
+ auto index = functions.indexOf(scriptFunction);
+ QCOMPARE_NE(index, -1);
+ functions.remove(index);
+ }
+
+ QCOMPARE(axscript->scriptEngine()->scriptLanguage(), script.language);
+ }
+
+ // verify that all functions were found across the different QAxScript objects
+ QVERIFY(functions.isEmpty());
+}
+
+void tst_QAxScriptManager::call_data()
+{
+ functions_data();
+}
+
+void tst_QAxScriptManager::call()
+{
+ QFETCH(QList<Script>, scripts);
+ QFETCH(QStringList, functions);
+ QFETCH(QStringList, signatures);
+
+ QAxScriptManager scriptManager;
+ for (const auto &script : scripts) {
+ QAxScript *axScript = scriptManager.load(script.code, script.name, script.language);
+
+ QVERIFY2(axScript, "Unable to load script (CoInitializeEx() called?)");
+ QVERIFY(axScript->scriptEngine());
+ QVERIFY(axScript->scriptEngine()->hasIntrospection());
+ }
+
+ // QAxScriptManager::call finds the script based on function name...
+ for (const auto &function : std::as_const(functions)) {
+ QVariant result = scriptManager.call(function);
+ QCOMPARE(result.metaType(), QMetaType::fromType<QString>());
+ }
+ // ...or fully qualified function signature
+ for (const auto &function : std::as_const(signatures)) {
+ QVariant result = scriptManager.call(function);
+ QCOMPARE(result.metaType(), QMetaType::fromType<QString>());
+ }
+}
+
+QTEST_MAIN(tst_QAxScriptManager)
+#include "tst_qaxscriptmanager.moc"
diff --git a/tests/auto/qbstr/CMakeLists.txt b/tests/auto/qbstr/CMakeLists.txt
new file mode 100644
index 0000000..65a49a6
--- /dev/null
+++ b/tests/auto/qbstr/CMakeLists.txt
@@ -0,0 +1,15 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qbstr LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qbstr
+ SOURCES
+ tst_qbstr.cpp
+ LIBRARIES
+ Qt::AxBasePrivate
+)
diff --git a/tests/auto/qbstr/tst_qbstr.cpp b/tests/auto/qbstr/tst_qbstr.cpp
new file mode 100644
index 0000000..3a757f6
--- /dev/null
+++ b/tests/auto/qbstr/tst_qbstr.cpp
@@ -0,0 +1,138 @@
+// 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 <QtTest/QtTest>
+#include <QtAxBase/private/qbstr_p.h>
+
+QT_USE_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+typedef int (*SETOANOCACHE)(void);
+
+void DisableBSTRCache()
+{
+ const HINSTANCE hLib = LoadLibraryA("OLEAUT32.DLL");
+ if (hLib != nullptr) {
+ const SETOANOCACHE SetOaNoCache =
+ reinterpret_cast<SETOANOCACHE>(GetProcAddress(hLib, "SetOaNoCache"));
+ if (SetOaNoCache != nullptr)
+ SetOaNoCache();
+ FreeLibrary(hLib);
+ }
+}
+
+class tst_qbstr : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase() { DisableBSTRCache(); }
+ void constructor_nullInitializes()
+ {
+ const QBStr str;
+ QVERIFY(!str.bstr());
+ }
+
+ void constructor_initializes_withLiteral()
+ {
+ const QBStr str{ L"hello world" };
+ QCOMPARE_EQ(str.bstr(), "hello world"_L1);
+ }
+
+ void constructor_initializes_withQString()
+ {
+ const QString expected{ "hello world"_L1 };
+ QBStr str{ expected };
+ QCOMPARE_EQ(QStringView{ str.bstr() }, expected);
+ }
+
+ void copyConstructor_initializes_withNullString()
+ {
+ const QBStr null;
+ const QBStr dest = null;
+ QCOMPARE_EQ(dest.bstr(), nullptr);
+ }
+
+ void copyConstructor_initializes_withValidString()
+ {
+ const QBStr expected{ L"hello world" };
+ const QBStr dest = expected;
+ QCOMPARE_EQ(QStringView{ dest.bstr() }, expected.bstr());
+ }
+
+ void moveConstructor_initializes_withNullString()
+ {
+ const QBStr str{ QBStr{} };
+ QCOMPARE_EQ(str.bstr(), nullptr);
+ }
+
+ void moveConstructor_initializes_withValidString()
+ {
+ QBStr source { L"hello world" };
+ const QBStr str{ std::move(source) };
+ QCOMPARE_EQ(str.bstr(), "hello world"_L1);
+ }
+
+ void assignment_assigns_withNullString()
+ {
+ const QBStr source{};
+ const QBStr dest = source;
+ QCOMPARE_EQ(dest.bstr(), nullptr);
+ }
+
+ void assignment_assigns_withValidString()
+ {
+ const QBStr source{ L"hello world" };
+ const QBStr dest = source;
+ QCOMPARE_EQ(dest.bstr(), "hello world"_L1);
+ }
+
+ void moveAssignment_assigns_withNullString()
+ {
+ QBStr source{};
+ const QBStr dest = std::move(source);
+ QCOMPARE_EQ(dest.bstr(), nullptr);
+ }
+
+ void moveAssignment_assigns_withValidString()
+ {
+ QBStr source{ L"hello world" };
+ const QBStr dest = std::move(source);
+ QCOMPARE_EQ(dest.bstr(), "hello world"_L1);
+ }
+
+ void release_returnsStringAndClearsValue()
+ {
+ QBStr str{ L"hello world" };
+ BSTR val = str.release();
+ QCOMPARE_EQ(str.bstr(), nullptr);
+ QCOMPARE_EQ(val, "hello world"_L1);
+ SysFreeString(val);
+ }
+
+ void str_returnsQString_withNullString()
+ {
+ const QBStr bstr{};
+ const QString str = bstr.str();
+ QVERIFY(str.isEmpty());
+ }
+
+ void str_returnsQString_withValidString()
+ {
+ const QBStr bstr{L"hello world"};
+ const QString str = bstr.str();
+ QCOMPARE_EQ(str, "hello world");
+ }
+
+ void operatorBool_returnsFalse_withNullString() {
+ QVERIFY(!QBStr{});
+ }
+
+ void operatorBool_returnsTrue_withValidString()
+ {
+ QVERIFY(QBStr{ "hello world" });
+ }
+};
+
+QTEST_MAIN(tst_qbstr)
+#include "tst_qbstr.moc"