Avoid potential negative array index access to cached text.
[LibreOffice.git] / toolkit / qa / cppunit / a11y / XAccessibleEventBroadcasterTester.cxx
blob852c91c341be07fe4f6bc5acb78ca1794e82a1ab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "XAccessibleEventBroadcasterTester.hxx"
22 #include <iostream>
24 #include <cppunit/TestAssert.h>
26 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
30 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
31 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
32 #include <com/sun/star/awt/PosSize.hpp>
33 #include <com/sun/star/awt/Rectangle.hpp>
34 #include <com/sun/star/awt/XWindow.hpp>
35 #include <com/sun/star/lang/EventObject.hpp>
37 #include <cppuhelper/implbase.hxx>
38 #include <rtl/ref.hxx>
39 #include <sal/log.hxx>
41 #include <test/a11y/AccessibilityTools.hxx>
43 using namespace css;
45 namespace
47 class EvListener : public cppu::WeakImplHelper<accessibility::XAccessibleEventListener>
49 public:
50 bool mbGotEvent;
52 EvListener()
53 : mbGotEvent(false)
57 // XEventListener
58 virtual void SAL_CALL disposing(const lang::EventObject&) override {}
60 // XAccessibleEventListener
61 virtual void SAL_CALL notifyEvent(const accessibility::AccessibleEventObject& aEvent) override
63 std::cout << "Listener got event: " << AccessibilityTools::debugString(aEvent) << std::endl;
64 uno::Reference<accessibility::XAccessible> xOld(aEvent.OldValue, uno::UNO_QUERY);
65 if (xOld.is())
66 std::cout << "Old: " << AccessibilityTools::debugString(xOld) << std::endl;
68 uno::Reference<accessibility::XAccessible> xNew(aEvent.NewValue, uno::UNO_QUERY);
69 if (xNew.is())
70 std::cout << "New: " << AccessibilityTools::debugString(xNew) << std::endl;
72 mbGotEvent = true;
77 XAccessibleEventBroadcasterTester::XAccessibleEventBroadcasterTester(
78 const uno::Reference<accessibility::XAccessibleEventBroadcaster>& xBroadcaster,
79 const uno::Reference<awt::XWindow>& xWindow)
80 : mxBroadcaster(xBroadcaster)
81 , mxWindow(xWindow)
85 bool XAccessibleEventBroadcasterTester::isTransient(
86 const uno::Reference<accessibility::XAccessibleEventBroadcaster> xBroadcaster)
88 uno::Reference<accessibility::XAccessibleContext> xCtx(xBroadcaster, uno::UNO_QUERY_THROW);
89 return isTransient(xCtx);
92 bool XAccessibleEventBroadcasterTester::isTransient(
93 const uno::Reference<accessibility::XAccessibleContext> xCtx)
95 return ((xCtx->getAccessibleStateSet() & accessibility::AccessibleStateType::TRANSIENT)
96 && (xCtx->getAccessibleParent()->getAccessibleContext()->getAccessibleStateSet()
97 & accessibility::AccessibleStateType::MANAGES_DESCENDANTS));
101 * @brief Generates an event on @c mxBroadcaster.
103 * This method indirectly alters the state of @c mxBroadcaster so that an
104 * accessible event will be fired for it. It can be called as many times as
105 * needed and triggers an event each time.
107 void XAccessibleEventBroadcasterTester::fireEvent()
109 awt::Rectangle newPosSize = mxWindow->getPosSize();
110 newPosSize.Width = newPosSize.Width - 20;
111 newPosSize.Height = newPosSize.Height - 20;
112 newPosSize.X = newPosSize.X + 20;
113 newPosSize.Y = newPosSize.Y + 20;
114 mxWindow->setPosSize(newPosSize.X, newPosSize.Y, newPosSize.Width, newPosSize.Height,
115 awt::PosSize::POSSIZE);
119 * @brief Adds a listener and fires events by mean of object relation.
121 * Asserts that the listener was properly called.
123 void XAccessibleEventBroadcasterTester::testAddEventListener()
125 rtl::Reference<EvListener> xListener(new EvListener);
126 mxBroadcaster->addAccessibleEventListener(xListener);
127 bool transient = isTransient(mxBroadcaster);
129 std::cout << "firing event" << std::endl;
130 fireEvent();
132 AccessibilityTools::Await([&xListener]() { return xListener->mbGotEvent; });
134 if (!transient)
135 CPPUNIT_ASSERT_MESSAGE("listener wasn't called", xListener->mbGotEvent);
136 else
137 CPPUNIT_ASSERT_MESSAGE("Object is Transient, listener isn't expected to be called",
138 !xListener->mbGotEvent);
140 mxBroadcaster->removeAccessibleEventListener(xListener);
144 * @brief Similar to @c testAddEventListener() but also removes the listener
146 * Adds an event listener just like @c testAddEventListener(), and then removes it and verifies an
147 * event doesn't trigger the supposedly removed listener.
149 * @see testAddEventListener()
151 void XAccessibleEventBroadcasterTester::testRemoveEventListener()
153 /* there is nothing we can really test for transient objects */
154 if (isTransient(mxBroadcaster))
156 std::cerr << "could not test removing listener on transient object " << mxBroadcaster
157 << std::endl;
158 return;
161 rtl::Reference<EvListener> xListener(new EvListener);
162 mxBroadcaster->addAccessibleEventListener(xListener);
164 std::cout << "firing event (with listener)" << std::endl;
165 fireEvent();
167 AccessibilityTools::Await([&xListener]() { return xListener->mbGotEvent; });
169 CPPUNIT_ASSERT_MESSAGE("listener wasn't called", xListener->mbGotEvent);
171 /* reset listener, remove it and try again */
172 xListener->mbGotEvent = false;
174 std::cout << "removing listener" << std::endl;
175 mxBroadcaster->removeAccessibleEventListener(xListener);
177 std::cout << "firing event (without listener)" << std::endl;
178 fireEvent();
180 AccessibilityTools::Wait(500);
182 CPPUNIT_ASSERT_MESSAGE("removed listener was called", !xListener->mbGotEvent);
185 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */