LibreOffice Module test (master) 1
xpropertyset.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
11
12#include <com/sun/star/beans/Property.hpp>
13#include <com/sun/star/beans/PropertyAttribute.hpp>
14#include <com/sun/star/beans/PropertyChangeEvent.hpp>
15#include <com/sun/star/beans/XPropertyChangeListener.hpp>
16#include <com/sun/star/beans/XPropertySet.hpp>
17#include <com/sun/star/beans/XVetoableChangeListener.hpp>
18#include <com/sun/star/lang/EventObject.hpp>
19#include <com/sun/star/util/DateTime.hpp>
20
21#include <com/sun/star/uno/Any.hxx>
22#include <com/sun/star/uno/Reference.hxx>
23#include <com/sun/star/uno/Type.h>
24
26#include <rtl/ref.hxx>
27
28#include <cppunit/TestAssert.h>
29
30using namespace css;
31using namespace css::uno;
32
33namespace apitest
34{
36 : initialized(false)
37{
38}
39
40namespace
41{
42class MockedPropertyChangeListener : public ::cppu::WeakImplHelper<beans::XPropertyChangeListener>
43{
44public:
45 MockedPropertyChangeListener()
46 : m_bListenerCalled(false)
47 {
48 }
49
51
52 virtual void SAL_CALL propertyChange(const beans::PropertyChangeEvent& /* xEvent */) override
53 {
54 m_bListenerCalled = true;
55 }
56
57 virtual void SAL_CALL disposing(const lang::EventObject& /* xEventObj */) override {}
58};
59
60class MockedVetoableChangeListener : public ::cppu::WeakImplHelper<beans::XVetoableChangeListener>
61{
62public:
63 MockedVetoableChangeListener()
64 : m_bListenerCalled(false)
65 {
66 }
67
69
70 virtual void SAL_CALL vetoableChange(const beans::PropertyChangeEvent& /* xEvent */) override
71 {
72 m_bListenerCalled = true;
73 }
74
75 virtual void SAL_CALL disposing(const lang::EventObject& /* xEventObj */) override {}
76};
77}
78
80{
81 uno::Reference<beans::XPropertySet> xPropSet(init(), uno::UNO_QUERY_THROW);
82 uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropSet->getPropertySetInfo();
83 fillPropsToTest(xPropInfo);
84
85 for (const auto& aName : maPropsToTest.bound)
86 {
87 rtl::Reference<MockedPropertyChangeListener> xListener = new MockedPropertyChangeListener();
88 xPropSet->addPropertyChangeListener(
89 aName, uno::Reference<beans::XPropertyChangeListener>(xListener));
91 continue;
92
93 CPPUNIT_ASSERT(xListener->m_bListenerCalled);
94
95 xListener->m_bListenerCalled = false;
96 xPropSet->removePropertyChangeListener(
97 aName, uno::Reference<beans::XPropertyChangeListener>(xListener));
99 CPPUNIT_ASSERT(!xListener->m_bListenerCalled);
100 }
101}
102
104{
105 uno::Reference<beans::XPropertySet> xPropSet(init(), uno::UNO_QUERY_THROW);
106 uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropSet->getPropertySetInfo();
107 fillPropsToTest(xPropInfo);
108
109 for (const auto& aName : maPropsToTest.bound)
110 {
111 rtl::Reference<MockedVetoableChangeListener> xListener = new MockedVetoableChangeListener();
112 xPropSet->addVetoableChangeListener(
113 aName, uno::Reference<beans::XVetoableChangeListener>(xListener));
115 continue;
116
117 CPPUNIT_ASSERT(xListener->m_bListenerCalled);
118
119 xListener->m_bListenerCalled = false;
120 xPropSet->removeVetoableChangeListener(
121 aName, uno::Reference<beans::XVetoableChangeListener>(xListener));
123 CPPUNIT_ASSERT(!xListener->m_bListenerCalled);
124 }
125}
126
128{
129 uno::Reference<beans::XPropertySet> xPropSet(init(), UNO_QUERY_THROW);
130 uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropSet->getPropertySetInfo();
131 if (xPropInfo.is())
132 {
133 fillPropsToTest(xPropInfo);
134 }
135 else
136 {
137 // TODO: Add a means for the client code to populate the PropsToTest.
138 }
139}
140
142{
144
145 for (size_t i = 0, n = maPropsToTest.normal.size(); i < n; ++i)
146 {
148 CPPUNIT_ASSERT(bSuccess);
149 }
150}
151
153{
155 uno::Reference<beans::XPropertySet> xPropSet(init(), UNO_QUERY_THROW);
156
157 // Check read-only properties.
158 for (size_t i = 0, n = maPropsToTest.readonly.size(); i < n; ++i)
159 {
160 bool bSuccess = getSinglePropertyValue(xPropSet, maPropsToTest.readonly[i]);
161 CPPUNIT_ASSERT(bSuccess);
162 }
163
164 // Check writable properties.
165 for (size_t i = 0, n = maPropsToTest.normal.size(); i < n; ++i)
166 {
167 bool bSuccess = getSinglePropertyValue(xPropSet, maPropsToTest.normal[i]);
168 CPPUNIT_ASSERT(bSuccess);
169 }
170}
171
173{
174 bool bIgnore = isPropertyIgnored(rName);
175 if (bIgnore)
176 return false;
177
178 uno::Reference<beans::XPropertySet> xPropSet(init(), UNO_QUERY_THROW);
179 try
180 {
181 uno::Any any = xPropSet->getPropertyValue(rName);
182 const uno::Type& type = any.getValueType();
184 {
185 // boolean type
186 bool bOld = any.get<bool>();
187 xPropSet->setPropertyValue(rName, Any(!bOld));
188 }
190 {
191 // 8-bit integer
192 sal_Int8 nOld = any.get<sal_Int8>();
193 sal_Int8 nNew = nOld + 1;
194 xPropSet->setPropertyValue(rName, Any(nNew));
195 }
197 {
198 // 16-bit integer
199 sal_Int16 nOld = any.get<sal_Int16>();
200 sal_Int16 nNew = nOld + 1;
201 xPropSet->setPropertyValue(rName, Any(nNew));
202 }
204 {
205 // 32-bit integer
206 sal_Int32 nOld = any.get<sal_Int32>();
207 sal_Int32 nNew = nOld + 3;
208 xPropSet->setPropertyValue(rName, Any(nNew));
209 }
211 {
212 // 64-bit integer
213 sal_Int64 nOld = any.get<sal_Int64>();
214 sal_Int64 nNew = nOld + 4;
215 xPropSet->setPropertyValue(rName, Any(nNew));
216 }
217 else if (type == cppu::UnoType<float>::get())
218 {
219 // single precision
220 float fOld = any.get<float>();
221 float fNew = fOld + 1.2;
222 xPropSet->setPropertyValue(rName, Any(fNew));
223 }
224 else if (type == cppu::UnoType<double>::get())
225 {
226 // double precision
227 double fOld = any.get<double>();
228 double fNew = fOld + 1.3;
229 xPropSet->setPropertyValue(rName, Any(fNew));
230 }
232 {
233 // string type
234 OUString aOld = any.get<OUString>();
235 OUString aNew = aOld + "foo";
236 xPropSet->setPropertyValue(rName, Any(aNew));
237 }
239 {
240 // date time type
241 util::DateTime aDT = any.get<util::DateTime>();
242 aDT.Year += 1;
243 xPropSet->setPropertyValue(rName, Any(aDT));
244 }
245 else
246 {
247 std::cout << "Unknown type:\n"
248 "Type: "
249 << type.getTypeName()
250 << "\n"
251 "Name: "
252 << rName << "\n";
253 CPPUNIT_ASSERT_MESSAGE(
254 "XPropertySet::isPropertyValueChangeable: unknown type in Any tested.", false);
255 }
256
257 uno::Any anyTest = xPropSet->getPropertyValue(rName);
258 return any != anyTest;
259 }
260 catch (const uno::Exception&)
261 {
262 std::cout << "Exception thrown while retrieving with property: " << rName << "\n";
263 CPPUNIT_ASSERT_MESSAGE("XPropertySet::isPropertyValueChangeable: exception thrown while "
264 "retrieving the property value.",
265 false);
266 }
267
268 return false;
269}
270
271void XPropertySet::fillPropsToTest(const uno::Reference<beans::XPropertySetInfo>& xPropInfo)
272{
274 return;
275
276 const uno::Sequence<beans::Property> aProps = xPropInfo->getProperties();
277
278 // some properties should not be changed in a unspecific way.
279 // TODO: Maybe we should mark these properties read-only, instead of
280 // giving them a special treatment here?
281 std::set<OUString> aSkip;
282 aSkip.insert("PrinterName");
283 aSkip.insert("CharRelief");
284 aSkip.insert("IsLayerMode");
285
286 for (const beans::Property& aProp : aProps)
287 {
288 if (aSkip.count(aProp.Name) > 0)
289 continue;
290
291 if ((aProp.Attributes & beans::PropertyAttribute::READONLY) != 0)
292 {
293 maPropsToTest.readonly.push_back(aProp.Name);
294 continue;
295 }
296
297 if ((aProp.Attributes & beans::PropertyAttribute::MAYBEVOID) != 0)
298 continue;
299
300 bool bBound = (aProp.Attributes & beans::PropertyAttribute::BOUND) != 0;
301 bool bConstrained = (aProp.Attributes & beans::PropertyAttribute::CONSTRAINED) != 0;
302 bool bCanChange = isPropertyValueChangeable(aProp.Name);
303
304 if (bBound && bCanChange)
305 maPropsToTest.bound.push_back(aProp.Name);
306
307 if (bConstrained && bCanChange)
308 maPropsToTest.constrained.push_back(aProp.Name);
309
310 if (bCanChange)
311 maPropsToTest.normal.push_back(aProp.Name);
312 }
313
315}
316
317bool XPropertySet::getSinglePropertyValue(const uno::Reference<beans::XPropertySet>& xPropSet,
318 const OUString& rName)
319{
320 try
321 {
322 xPropSet->getPropertyValue(rName);
323 return true;
324 }
325 catch (const uno::Exception&)
326 {
327 }
328 return false;
329}
330
331bool XPropertySet::isPropertyIgnored(const OUString& rName)
332{
333 return m_IgnoreValue.count(rName) > 0;
334}
335
336} // namespace apitest
337
338/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const Any & any
void fillPropsToTest(const css::uno::Reference< css::beans::XPropertySetInfo > &xPropInfo)
PropsToTest maPropsToTest
bool isPropertyValueChangeable(const OUString &rName)
virtual css::uno::Reference< css::uno::XInterface > init()=0
static bool getSinglePropertyValue(const css::uno::Reference< css::beans::XPropertySet > &xPropSet, const OUString &rName)
std::set< OUString > m_IgnoreValue
virtual bool isPropertyIgnored(const OUString &rName)
OUString aName
sal_Int64 n
int i
std::vector< OUString > readonly
std::vector< OUString > normal
std::vector< OUString > bound
std::vector< OUString > constrained
signed char sal_Int8
ResultType type
bool m_bListenerCalled