From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- framework/qa/cppunit/dispatchtest.cxx | 219 ++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 framework/qa/cppunit/dispatchtest.cxx (limited to 'framework/qa/cppunit/dispatchtest.cxx') diff --git a/framework/qa/cppunit/dispatchtest.cxx b/framework/qa/cppunit/dispatchtest.cxx new file mode 100644 index 000000000..16a4ecb51 --- /dev/null +++ b/framework/qa/cppunit/dispatchtest.cxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-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/. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Sample interception implementation that asserts getInterceptedURLs() and queryDispatch() is in sync. +class MyInterceptor + : public cppu::WeakImplHelper +{ + uno::Reference m_xMaster; + uno::Reference m_xSlave; + uno::Sequence m_aDisabledCommands; + int m_nExpected; + int m_nUnexpected; + +public: + MyInterceptor(); + + /// Number of queryDispatch() calls that operate on a command advertised by getInterceptedURLs(). + int getExpected(); + /// Number of queryDispatch() calls that operate on a command not advertised by getInterceptedURLs(). + int getUnexpected(); + + // frame::XInterceptorInfo + virtual uno::Sequence SAL_CALL getInterceptedURLs() override; + + // frame::XDispatchProviderInterceptor + virtual void SAL_CALL setMasterDispatchProvider( + const uno::Reference& xNewSupplier) override; + virtual uno::Reference SAL_CALL getMasterDispatchProvider() override; + virtual void SAL_CALL + setSlaveDispatchProvider(const uno::Reference& xNewSupplier) override; + virtual uno::Reference SAL_CALL getSlaveDispatchProvider() override; + + // frame::XDispatchProvider + virtual uno::Sequence> SAL_CALL + queryDispatches(const uno::Sequence& rRequests) override; + virtual uno::Reference + SAL_CALL queryDispatch(const util::URL& rURL, const OUString& rTargetFrameName, + sal_Int32 SearchFlags) override; +}; + +MyInterceptor::MyInterceptor() + : m_aDisabledCommands{ ".uno:Bold" } + , m_nExpected(0) + , m_nUnexpected(0) +{ +} + +int MyInterceptor::getExpected() +{ + int nRet = m_nExpected; + m_nExpected = 0; + return nRet; +} + +int MyInterceptor::getUnexpected() +{ + int nRet = m_nUnexpected; + m_nUnexpected = 0; + return nRet; +} + +uno::Sequence MyInterceptor::getInterceptedURLs() { return m_aDisabledCommands; } + +void MyInterceptor::setMasterDispatchProvider( + const uno::Reference& xNewSupplier) +{ + m_xMaster = xNewSupplier; +} + +uno::Reference MyInterceptor::getMasterDispatchProvider() +{ + return m_xMaster; +} + +void MyInterceptor::setSlaveDispatchProvider( + const uno::Reference& xNewSupplier) +{ + m_xSlave = xNewSupplier; +} + +uno::Reference MyInterceptor::getSlaveDispatchProvider() +{ + return m_xSlave; +} + +uno::Sequence> +MyInterceptor::queryDispatches(const uno::Sequence& rRequests) +{ + uno::Sequence> aResult(rRequests.getLength()); + auto aResultRange = asNonConstRange(aResult); + + for (sal_Int32 i = 0; i < rRequests.getLength(); ++i) + { + aResultRange[i] = queryDispatch(rRequests[i].FeatureURL, rRequests[i].FrameName, + rRequests[i].SearchFlags); + } + + return aResult; +} + +uno::Reference MyInterceptor::queryDispatch(const util::URL& rURL, + const OUString& /*rTargetFrameName*/, + sal_Int32 /*SearchFlags*/) +{ + if (std::find(std::cbegin(m_aDisabledCommands), std::cend(m_aDisabledCommands), rURL.Complete) + != std::cend(m_aDisabledCommands)) + ++m_nExpected; + else + ++m_nUnexpected; + + return uno::Reference(); +} + +/// Tests how InterceptionHelper invokes a registered interceptor. +class DispatchTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +protected: + uno::Reference mxComponent; + +public: + virtual void setUp() override; + virtual void tearDown() override; +}; + +void DispatchTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void DispatchTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +CPPUNIT_TEST_FIXTURE(DispatchTest, testInterception) +{ + mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"); + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xModel.is()); + + uno::Reference xRegistration( + xModel->getCurrentController()->getFrame(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xRegistration.is()); + + rtl::Reference pInterceptor(new MyInterceptor()); + xRegistration->registerDispatchProviderInterceptor(pInterceptor); + + dispatchCommand(mxComponent, ".uno:Bold", {}); + CPPUNIT_ASSERT_EQUAL(1, pInterceptor->getExpected()); + CPPUNIT_ASSERT_EQUAL(0, pInterceptor->getUnexpected()); + dispatchCommand(mxComponent, ".uno:Italic", {}); + CPPUNIT_ASSERT_EQUAL(1, pInterceptor->getExpected()); + // This was 1: MyInterceptor::queryDispatch() was called for .uno:Italic. + CPPUNIT_ASSERT_EQUAL(0, pInterceptor->getUnexpected()); +} + +constexpr OUStringLiteral DATA_DIRECTORY = u"/framework/qa/cppunit/data/"; + +CPPUNIT_TEST_FIXTURE(DispatchTest, testSfxOfficeDispatchDispose) +{ + // this test doesn't work with a new document because of aURL.Main check in SfxBaseController::dispatch() + mxComponent = loadFromDesktop(m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.fodp", + "com.sun.star.presentation.PresentationDocument"); + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xModel.is()); + uno::Reference xController(xModel->getCurrentController()); + CPPUNIT_ASSERT(xController.is()); + uno::Reference xFrame(xController->getFrame(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xFrame.is()); + + uno::Reference xParser(util::URLTransformer::create(mxComponentContext)); + util::URL url; + url.Complete = xModel->getURL() + "#dummy"; + xParser->parseStrict(url); + + uno::Reference xDisp(xFrame->queryDispatch(url, "", 0)); + CPPUNIT_ASSERT(xDisp.is()); + + mxComponent->dispose(); + + util::URL urlSlot; + urlSlot.Complete = "slot:5598"; + xParser->parseStrict(urlSlot); + // crashed with UAF + xDisp->dispatch(urlSlot, {}); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3