offapi/UnoApi_offapi.mk | 3 offapi/org/libreoffice/embindtest/ExplicitConstructors.idl | 21 +++ offapi/org/libreoffice/embindtest/ImplicitConstructor.idl | 18 ++ offapi/org/libreoffice/embindtest/XArgumentStore.idl | 18 ++ pyuno/PythonTest_pyuno_pytests_embindtest.mk | 1 pyuno/qa/pytests/serviceconstructors.py | 82 +++++++++++++ uitest/uitest/test.py | 7 - unotest/Library_embindtest.mk | 1 unotest/source/embindtest/embindtest.component | 6 unotest/source/embindtest/serviceconstructors.cxx | 62 +++++++++ 10 files changed, 215 insertions(+), 4 deletions(-)
New commits: commit 7930a07d76d7708b69372fd54133675af0e0ec9e Author: Neil Roberts <[email protected]> AuthorDate: Tue Feb 10 20:50:10 2026 +0100 Commit: Stephan Bergmann <[email protected]> CommitDate: Wed Mar 4 13:53:16 2026 +0100 uitest: Use the new service constructors to create the Toolkit Instead of explicitly calling createInstance we can use the implicit service constructor on the Toolkit type for a slightly nicer way to construct it. Change-Id: Ia06000afc0cde27209966854704ca8dd61375adf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199106 Reviewed-by: Stephan Bergmann <[email protected]> Tested-by: Jenkins diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py index 98ede61a6cf1..42fb2abb575c 100644 --- a/uitest/uitest/test.py +++ b/uitest/uitest/test.py @@ -12,6 +12,7 @@ from contextlib import contextmanager from uitest.uihelper.common import get_state_as_dict, select_by_text from com.sun.star.uno import RuntimeException +from com.sun.star.awt import Toolkit from libreoffice.uno.eventlistener import EventListener from libreoffice.uno.propertyvalue import mkPropertyValues @@ -197,8 +198,7 @@ class UITest(object): self._xUITest.executeCommandForProvider(".uno:CloseWin", frame) # Closing the window will happen asynchronously on the main thread so let’s wait # until the close actually completes. - xToolkit = self._xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit') - xToolkit.waitUntilAllIdlesDispatched() + Toolkit.create(self._xContext).waitUntilAllIdlesDispatched() # Calls UITest.close_doc at exit @contextmanager @@ -301,8 +301,7 @@ class UITest(object): # execute_dialog_through_command will end up dispatching the command asynchronously # on the main thread. The Base code seems to have a few race conditions so to avoid # that let’s wait to make sure the close completes before continuing - xToolkit = self._xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit') - xToolkit.waitUntilAllIdlesDispatched() + Toolkit.create(self._xContext).waitUntilAllIdlesDispatched() else: self._xUITest.executeCommand(".uno:CloseDoc") frames = desktop.getFrames() commit 2cd17a11484904845dc386315026882c72696543 Author: Neil Roberts <[email protected]> AuthorDate: Tue Feb 10 22:52:57 2026 +0100 Commit: Stephan Bergmann <[email protected]> CommitDate: Wed Mar 4 13:53:05 2026 +0100 Add a PythonTest for service constructors in pyuno This leverages the existing framework for embindtest to add interfaces and services to test with. Hopefully that means the tests will run on the CI without ending up in the final release builds because they are only enabled with --enable-embindtest-uno. Change-Id: Idd394e616ad14943cecd60bf3a3e228d93166e34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199105 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <[email protected]> diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index eabe9d8a07e7..356e97893dcc 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -4391,10 +4391,13 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,org/libreoffice/embindtest, \ Constants \ Enum \ Exception \ + ExplicitConstructors \ + ImplicitConstructor \ Struct \ StructLong \ StructString \ Template \ + XArgumentStore \ XAttributes \ XTest \ )) diff --git a/offapi/org/libreoffice/embindtest/ExplicitConstructors.idl b/offapi/org/libreoffice/embindtest/ExplicitConstructors.idl new file mode 100644 index 000000000000..d2034f2660cd --- /dev/null +++ b/offapi/org/libreoffice/embindtest/ExplicitConstructors.idl @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +service ExplicitConstructors: org::libreoffice::embindtest::XArgumentStore +{ + multipleArguments([in] long a, [in] string b, [in] float c); + interfaceArgument([in] com::sun::star::uno::XInterface a); + restArgument([in] any... rest); +}; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/ImplicitConstructor.idl b/offapi/org/libreoffice/embindtest/ImplicitConstructor.idl new file mode 100644 index 000000000000..56067fa0c5ec --- /dev/null +++ b/offapi/org/libreoffice/embindtest/ImplicitConstructor.idl @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +// This should make an implicit default constructor that only takes +// the component context as an argument. +service ImplicitConstructor: org::libreoffice::embindtest::XArgumentStore; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/offapi/org/libreoffice/embindtest/XArgumentStore.idl b/offapi/org/libreoffice/embindtest/XArgumentStore.idl new file mode 100644 index 000000000000..22cfd1ec5eb2 --- /dev/null +++ b/offapi/org/libreoffice/embindtest/XArgumentStore.idl @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module org { module libreoffice { module embindtest { + +interface XArgumentStore { + sequence<any> getArguments(); +}; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/pyuno/PythonTest_pyuno_pytests_embindtest.mk b/pyuno/PythonTest_pyuno_pytests_embindtest.mk index 8f8341f7c50e..053b05f1d2d1 100644 --- a/pyuno/PythonTest_pyuno_pytests_embindtest.mk +++ b/pyuno/PythonTest_pyuno_pytests_embindtest.mk @@ -11,6 +11,7 @@ $(eval $(call gb_PythonTest_PythonTest,pyuno_pytests_embindtest)) $(eval $(call gb_PythonTest_add_modules,pyuno_pytests_embindtest,$(SRCDIR)/pyuno/qa/pytests, \ embindtest \ + serviceconstructors \ )) # vim: set noet sw=4 ts=4: diff --git a/pyuno/qa/pytests/serviceconstructors.py b/pyuno/qa/pytests/serviceconstructors.py new file mode 100644 index 000000000000..ce742ef9b54f --- /dev/null +++ b/pyuno/qa/pytests/serviceconstructors.py @@ -0,0 +1,82 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +import unittest +import org.libreoffice.unotest +from org.libreoffice.embindtest import ImplicitConstructor +from org.libreoffice.embindtest import ExplicitConstructors +from com.sun.star.script import CannotConvertException + +class ServiceConstructorsTest(unittest.TestCase): + def test_implicit_constructor(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + obj = ImplicitConstructor.create(ctx) + self.assertEqual(obj.getArguments(), tuple()) + + def test_multiple_arguments(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + obj = ExplicitConstructors.multipleArguments(ctx, 42, " is half of ", 84.0) + self.assertEqual(obj.getArguments(), (42, " is half of ", 84.0)) + + def test_interface_argument(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + obj = ExplicitConstructors.interfaceArgument(ctx, ctx) + self.assertEqual(obj.getArguments(), (ctx, )) + + # None should be coerced into a null reference even though + # normally it’s supposed to represent the void type + obj = ExplicitConstructors.interfaceArgument(ctx, None) + self.assertEqual(obj.getArguments(), (None, )) + + def test_rest_arguments(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + + obj = ExplicitConstructors.restArgument(ctx) + self.assertEqual(obj.getArguments(), tuple()) + + obj = ExplicitConstructors.restArgument(ctx, 1, 2, "buckle my shoe") + self.assertEqual(obj.getArguments(), (1, 2, "buckle my shoe")) + + def test_invalid_arguments(self): + ctx = org.libreoffice.unotest.pyuno.getComponentContext() + + with self.assertRaises(AttributeError) as cm: + ImplicitConstructor.create() + self.assertEqual(str(cm.exception), + "org.libreoffice.embindtest.ImplicitConstructor::create " + "requires 1 argument") + + with self.assertRaises(AttributeError) as cm: + ExplicitConstructors.interfaceArgument() + self.assertEqual(str(cm.exception), + "org.libreoffice.embindtest.ExplicitConstructors::interfaceArgument " + "requires 2 arguments") + + with self.assertRaises(AttributeError) as cm: + ExplicitConstructors.interfaceArgument(1, 2, 3) + self.assertEqual(str(cm.exception), + "org.libreoffice.embindtest.ExplicitConstructors::interfaceArgument " + "requires 2 arguments") + + with self.assertRaises(AttributeError) as cm: + ExplicitConstructors.restArgument() + self.assertEqual(str(cm.exception), + "org.libreoffice.embindtest.ExplicitConstructors::restArgument " + "requires at least 1 argument") + + with self.assertRaises(AttributeError) as cm: + ImplicitConstructor.create(True) + self.assertEqual(str(cm.exception), + "First argument to a service constructor must be an " + "XComponentContext") + + with self.assertRaises(CannotConvertException): + ExplicitConstructors.interfaceArgument(ctx, 12) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/unotest/Library_embindtest.mk b/unotest/Library_embindtest.mk index 439b711c3a2c..4c7a92f4d5c1 100644 --- a/unotest/Library_embindtest.mk +++ b/unotest/Library_embindtest.mk @@ -11,6 +11,7 @@ $(eval $(call gb_Library_Library,embindtest)) $(eval $(call gb_Library_add_exception_objects,embindtest, \ unotest/source/embindtest/embindtest \ + unotest/source/embindtest/serviceconstructors \ )) $(eval $(call gb_Library_set_componentfile,embindtest,unotest/source/embindtest/embindtest,services)) diff --git a/unotest/source/embindtest/embindtest.component b/unotest/source/embindtest/embindtest.component index 9391811ce2d0..30bdc5c3f68f 100644 --- a/unotest/source/embindtest/embindtest.component +++ b/unotest/source/embindtest/embindtest.component @@ -22,4 +22,10 @@ name="org.libreoffice.comp.embindtest.Test"> <service name="org.libreoffice.embindtest.Test"/> </implementation> + <implementation + constructor="org_libreoffice_comp_embindtest_Constructors_get_implementation" + name="org.libreoffice.comp.embindtest.Constructors"> + <service name="org.libreoffice.embindtest.ImplicitConstructor"/> + <service name="org.libreoffice.embindtest.ExplicitConstructors"/> + </implementation> </component> diff --git a/unotest/source/embindtest/serviceconstructors.cxx b/unotest/source/embindtest/serviceconstructors.cxx new file mode 100644 index 000000000000..c5feed409840 --- /dev/null +++ b/unotest/source/embindtest/serviceconstructors.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <org/libreoffice/embindtest/XArgumentStore.hpp> + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace +{ +class ConstructorsTest : public cppu::WeakImplHelper<org::libreoffice::embindtest::XArgumentStore, + css::lang::XServiceInfo> +{ +public: + explicit ConstructorsTest(css::uno::Sequence<css::uno::Any> const& args) + : m_aArgs(args) + { + } + + OUString SAL_CALL getImplementationName() override + { + return u"org.libreoffice.comp.embindtest.Constructors"_ustr; + } + + sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return { u"org.libreoffice.embindtest.ImplicitConstructor"_ustr, + u"org.libreoffice.embindtest.ExplicitConstructors"_ustr }; + } + + css::uno::Sequence<css::uno::Any> SAL_CALL getArguments() override { return m_aArgs; } + +private: + css::uno::Sequence<css::uno::Any> m_aArgs; +}; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +org_libreoffice_comp_embindtest_Constructors_get_implementation( + css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const& args) +{ + return cppu::acquire(new ConstructorsTest(args)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
