Avoid potential negative array index access to cached text.
[LibreOffice.git] / toolkit / qa / cppunit / a11y / XAccessibleComponentTester.cxx
blobfa5fb9f7054f811d2687cc70a7a1d0c204e1294c
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 "XAccessibleComponentTester.hxx"
22 #include <cppunit/TestAssert.h>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/accessibility/XAccessible.hpp>
26 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
27 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
28 #include <com/sun/star/awt/Point.hpp>
29 #include <com/sun/star/uno/Reference.hxx>
31 #include <tools/color.hxx>
33 #include <test/a11y/AccessibilityTools.hxx>
35 using namespace css;
37 /**
38 * @brief Checks the component's bounds
40 * Checks the X and Y coordinates are non-negative, and that the width and
41 * height are greater than 0.
43 * Coherence with @c getLocation() is tested in the test for the
44 * latter.
46 void XAccessibleComponentTester::testBounds()
48 auto bounds = mxComponent->getBounds();
49 std::cout << "bounds: " << bounds.Width << "x" << bounds.Height << std::showpos << bounds.X
50 << bounds.Y << std::noshowpos << std::endl;
51 CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), bounds.X);
52 CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), bounds.Y);
53 CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), bounds.Width);
54 CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), bounds.Height);
57 /**
58 * @brief Tests results of XAccessibleComponent::getSize()
60 * Succeeds if the size is the same as in bounds.
62 void XAccessibleComponentTester::testSize()
64 auto bounds = mxComponent->getBounds();
65 auto size = mxComponent->getSize();
66 CPPUNIT_ASSERT_EQUAL(bounds.Width, size.Width);
67 CPPUNIT_ASSERT_EQUAL(bounds.Height, size.Height);
70 /**
71 * @brief Tests results of XAccessibleComponent::getBounds()
73 * First checks 4 inner bounds (upper, lower, left and right) of component
74 * bounding box to contain at least one point of the component. Second 4 outer
75 * bounds are checked to not contain any component points.
77 * Succeeds if inner bounds contain component points and outer bounds don't
78 * contain any component points.
80 void XAccessibleComponentTester::testContainsPoint()
82 auto bounds = mxComponent->getBounds();
84 /* upper end */
85 int curX = 0;
86 while (!mxComponent->containsPoint(awt::Point(curX, 0)) && curX < bounds.Width)
87 curX++;
88 CPPUNIT_ASSERT_MESSAGE("Upper bound of box contains no component points", curX < bounds.Width);
89 std::cout << "Upper bound of box contains point (" << curX << ",0)" << std::endl;
90 /* lower end */
91 curX = 0;
92 while (!mxComponent->containsPoint(awt::Point(curX, bounds.Height - 1)) && curX < bounds.Width)
93 curX++;
94 CPPUNIT_ASSERT_MESSAGE("Lower bound of box contains no component points", curX < bounds.Width);
95 std::cout << "Lower bound of box contains point (" << curX << "," << (bounds.Height - 1) << ")"
96 << std::endl;
97 /* left end */
98 int curY = 0;
99 while (!mxComponent->containsPoint(awt::Point(0, curY)) && curY < bounds.Height)
100 curY++;
101 CPPUNIT_ASSERT_MESSAGE("Left bound of box contains no component points", curY < bounds.Height);
102 std::cout << "Left bound of box contains point (0," << curY << ")" << std::endl;
103 /* right end */
104 curY = 0;
105 while (!mxComponent->containsPoint(awt::Point(bounds.Width - 1, curY)) && curY < bounds.Height)
106 curY++;
107 CPPUNIT_ASSERT_MESSAGE("Right bound of box contains no component points", curY < bounds.Height);
108 std::cout << "Right bound of box contains point (" << (bounds.Width - 1) << "," << curY << ")"
109 << std::endl;
110 /* no match outside the bounds */
111 for (int x = -1; x <= bounds.Width; x++)
113 CPPUNIT_ASSERT_MESSAGE("Outer upper bound CONTAINS a component point",
114 !mxComponent->containsPoint(awt::Point(x, -1)));
115 CPPUNIT_ASSERT_MESSAGE("Outer lower bound CONTAINS a component point",
116 !mxComponent->containsPoint(awt::Point(x, bounds.Height)));
118 for (int y = -1; y <= bounds.Height; y++)
120 CPPUNIT_ASSERT_MESSAGE("Outer left bound CONTAINS a component point",
121 !mxComponent->containsPoint(awt::Point(-1, y)));
122 CPPUNIT_ASSERT_MESSAGE("Outer right bound CONTAINS a component point",
123 !mxComponent->containsPoint(awt::Point(bounds.Width, y)));
128 * @brief Tests results of XAccessibleComponent::getAccessibleAtPoint()
130 * Iterates through all children which implement
131 * <code>XAccessibleComponent</code> (if they exist) determines their
132 * boundaries and tries to get each child by <code>getAccessibleAtPoint</code>
133 * passing point which belongs to the child.
134 * Also the point is checked which doesn't belong to child boundary box.
136 * Succeeds if in the first cases the right children are returned, and in the
137 * second <code>null</code> or another child is returned.
139 void XAccessibleComponentTester::testAccessibleAtPoint()
141 sal_Int64 count = mxContext->getAccessibleChildCount();
142 std::cout << "Found " << count << " children" << std::endl;
143 for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++)
145 auto child = mxContext->getAccessibleChild(i);
146 uno::Reference<accessibility::XAccessibleContext> childContext(
147 child->getAccessibleContext(), uno::UNO_SET_THROW);
148 std::cout << "* Found child: " << AccessibilityTools::debugString(child) << std::endl;
149 std::cout << " states: "
150 << AccessibilityTools::debugAccessibleStateSet(
151 childContext->getAccessibleStateSet())
152 << std::endl;
153 uno::Reference<accessibility::XAccessibleComponent> xChildComponent(childContext,
154 uno::UNO_QUERY);
155 std::cout << " component: " << xChildComponent << std::endl;
156 if (!xChildComponent)
157 continue;
159 auto childBounds = xChildComponent->getBounds();
160 if (childBounds.X == -1)
161 continue;
162 std::cout << " bounds: " << childBounds.Width << "x" << childBounds.Height << std::showpos
163 << childBounds.X << childBounds.Y << std::noshowpos << std::endl;
165 std::cout << "finding the point which lies on the component" << std::endl;
166 int curX = 0;
167 int curY = 0;
168 while (!xChildComponent->containsPoint(awt::Point(curX, curY)) && curX < childBounds.Width)
170 curX++;
171 curY++;
173 if (curX >= childBounds.Width)
175 std::cout << "Couldn't find a point with contains" << std::endl;
176 continue;
178 else
180 std::cout << "Child found at point +" << childBounds.X + curX << "+"
181 << childBounds.Y + curY << std::endl;
184 // trying the point laying on child
185 auto xAccAtPoint
186 = mxComponent->getAccessibleAtPoint(awt::Point(childBounds.X, childBounds.Y));
187 CPPUNIT_ASSERT_MESSAGE("Child not found at point", xAccAtPoint.is());
188 if (!AccessibilityTools::equals(child, xAccAtPoint))
190 auto idxExpected = childContext->getAccessibleIndexInParent();
191 auto idxResult = xAccAtPoint->getAccessibleContext()->getAccessibleIndexInParent();
192 std::cout << "The child found (" << AccessibilityTools::debugString(xAccAtPoint)
193 << ") is not the expected one (" << AccessibilityTools::debugString(child)
194 << ")" << std::endl;
195 if (idxExpected < idxResult)
197 std::cout << "-- it probably is hidden behind? Skipping." << std::endl;
199 else
201 CPPUNIT_ASSERT_EQUAL_MESSAGE("The child found is NOT the expected one", child,
202 xAccAtPoint);
206 // trying the point NOT laying on child
207 xAccAtPoint
208 = mxComponent->getAccessibleAtPoint(awt::Point(childBounds.X - 1, childBounds.Y - 1));
209 if (xAccAtPoint.is())
211 CPPUNIT_ASSERT_MESSAGE("Child found OUTSIDE its bounds",
212 !AccessibilityTools::equals(child, xAccAtPoint));
218 * @brief Tests results of XAccessibleComponent::getLocation()
220 * Succeeds if the location is the same as location of boundary obtained by
221 * the <code>getBounds()</code> method.
223 void XAccessibleComponentTester::testLocation()
225 auto bounds = mxComponent->getBounds();
226 auto location = mxComponent->getLocation();
227 CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid X location", bounds.X, location.X);
228 CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid Y location", bounds.Y, location.Y);
232 * @brief Tests results of XAccessibleComponent::getLocationOnScreen()
233 * @returns @c true on success.
235 * Get the screen location of the component and its parent
236 * (if it exists and supports <code>XAccessibleComponent</code>).
238 * Succeeds component screen location equals to screen location of its parent
239 * plus location of the component relative to the parent.
241 void XAccessibleComponentTester::testLocationOnScreen()
243 auto location = mxComponent->getLocationOnScreen();
244 std::cout << "location on screen: +" << location.X << "+" << location.Y << std::endl;
246 auto xParent = mxContext->getAccessibleParent();
247 if (!xParent.is())
248 std::cout << "No parent" << std::endl;
249 else
251 std::cout << "Found parent: " << AccessibilityTools::debugString(xParent) << std::endl;
252 uno::Reference<accessibility::XAccessibleComponent> xParentComponent(
253 xParent->getAccessibleContext(), uno::UNO_QUERY);
254 if (!xParentComponent.is())
255 std::cout << "Parent is not a Component" << std::endl;
256 else
258 auto bounds = mxComponent->getBounds();
259 auto parentLocation = xParentComponent->getLocationOnScreen();
260 CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid X screen location", parentLocation.X + bounds.X,
261 location.X);
262 CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid Y screen location", parentLocation.Y + bounds.Y,
263 location.Y);
269 * Just calls the method.
271 void XAccessibleComponentTester::testGrabFocus() { mxComponent->grabFocus(); }
274 * Just calls the method.
276 void XAccessibleComponentTester::testGetForeground()
278 auto color = mxComponent->getForeground();
279 std::cout << "foreground color: " << Color(ColorAlpha, color) << std::endl;
283 * Just calls the method.
285 void XAccessibleComponentTester::testGetBackground()
287 auto color = mxComponent->getBackground();
288 std::cout << "background color: " << Color(ColorAlpha, color) << std::endl;
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */