1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <test/beans/xpropertyset.hxx>
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>
21 #include <com/sun/star/uno/Any.hxx>
22 #include <com/sun/star/uno/Reference.hxx>
23 #include <com/sun/star/uno/Type.h>
25 #include <cppuhelper/implbase.hxx>
26 #include <rtl/ref.hxx>
28 #include <cppunit/TestAssert.h>
31 using namespace css::uno
;
35 XPropertySet::PropsToTest::PropsToTest()
42 class MockedPropertyChangeListener
: public ::cppu::WeakImplHelper
<beans::XPropertyChangeListener
>
45 MockedPropertyChangeListener()
46 : m_bListenerCalled(false)
50 bool m_bListenerCalled
;
52 virtual void SAL_CALL
propertyChange(const beans::PropertyChangeEvent
& /* xEvent */) override
54 m_bListenerCalled
= true;
57 virtual void SAL_CALL
disposing(const lang::EventObject
& /* xEventObj */) override
{}
60 class MockedVetoableChangeListener
: public ::cppu::WeakImplHelper
<beans::XVetoableChangeListener
>
63 MockedVetoableChangeListener()
64 : m_bListenerCalled(false)
68 bool m_bListenerCalled
;
70 virtual void SAL_CALL
vetoableChange(const beans::PropertyChangeEvent
& /* xEvent */) override
72 m_bListenerCalled
= true;
75 virtual void SAL_CALL
disposing(const lang::EventObject
& /* xEventObj */) override
{}
79 void XPropertySet::testPropertyChangeListener()
81 uno::Reference
<beans::XPropertySet
> xPropSet(init(), uno::UNO_QUERY_THROW
);
82 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
83 fillPropsToTest(xPropInfo
);
85 for (const auto& aName
: maPropsToTest
.bound
)
87 rtl::Reference
<MockedPropertyChangeListener
> xListener
= new MockedPropertyChangeListener();
88 xPropSet
->addPropertyChangeListener(
89 aName
, uno::Reference
<beans::XPropertyChangeListener
>(xListener
.get()));
90 if (!isPropertyValueChangeable(aName
))
93 CPPUNIT_ASSERT(xListener
->m_bListenerCalled
);
95 xListener
->m_bListenerCalled
= false;
96 xPropSet
->removePropertyChangeListener(
97 aName
, uno::Reference
<beans::XPropertyChangeListener
>(xListener
.get()));
98 isPropertyValueChangeable(aName
);
99 CPPUNIT_ASSERT(!xListener
->m_bListenerCalled
);
103 void XPropertySet::testVetoableChangeListener()
105 uno::Reference
<beans::XPropertySet
> xPropSet(init(), uno::UNO_QUERY_THROW
);
106 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
107 fillPropsToTest(xPropInfo
);
109 for (const auto& aName
: maPropsToTest
.bound
)
111 rtl::Reference
<MockedVetoableChangeListener
> xListener
= new MockedVetoableChangeListener();
112 xPropSet
->addVetoableChangeListener(
113 aName
, uno::Reference
<beans::XVetoableChangeListener
>(xListener
.get()));
114 if (!isPropertyValueChangeable(aName
))
117 CPPUNIT_ASSERT(xListener
->m_bListenerCalled
);
119 xListener
->m_bListenerCalled
= false;
120 xPropSet
->removeVetoableChangeListener(
121 aName
, uno::Reference
<beans::XVetoableChangeListener
>(xListener
.get()));
122 isPropertyValueChangeable(aName
);
123 CPPUNIT_ASSERT(!xListener
->m_bListenerCalled
);
127 void XPropertySet::testGetPropertySetInfo()
129 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
130 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
133 fillPropsToTest(xPropInfo
);
137 // TODO: Add a means for the client code to populate the PropsToTest.
141 void XPropertySet::testSetPropertyValue()
143 testGetPropertySetInfo();
145 for (size_t i
= 0, n
= maPropsToTest
.normal
.size(); i
< n
; ++i
)
147 bool bSuccess
= isPropertyValueChangeable(maPropsToTest
.normal
[i
]);
148 CPPUNIT_ASSERT(bSuccess
);
152 void XPropertySet::testGetPropertyValue()
154 testGetPropertySetInfo();
155 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
157 // Check read-only properties.
158 for (size_t i
= 0, n
= maPropsToTest
.readonly
.size(); i
< n
; ++i
)
160 bool bSuccess
= getSinglePropertyValue(xPropSet
, maPropsToTest
.readonly
[i
]);
161 CPPUNIT_ASSERT(bSuccess
);
164 // Check writable properties.
165 for (size_t i
= 0, n
= maPropsToTest
.normal
.size(); i
< n
; ++i
)
167 bool bSuccess
= getSinglePropertyValue(xPropSet
, maPropsToTest
.normal
[i
]);
168 CPPUNIT_ASSERT(bSuccess
);
172 bool XPropertySet::isPropertyValueChangeable(const OUString
& rName
)
174 bool bIgnore
= isPropertyIgnored(rName
);
178 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
181 uno::Any any
= xPropSet
->getPropertyValue(rName
);
182 const uno::Type
& type
= any
.getValueType();
183 if (type
== cppu::UnoType
<bool>::get())
186 bool bOld
= any
.get
<bool>();
187 xPropSet
->setPropertyValue(rName
, makeAny(!bOld
));
189 else if (type
== cppu::UnoType
<sal_Int8
>::get())
192 sal_Int8 nOld
= any
.get
<sal_Int8
>();
193 sal_Int8 nNew
= nOld
+ 1;
194 xPropSet
->setPropertyValue(rName
, makeAny(nNew
));
196 else if (type
== cppu::UnoType
<sal_Int16
>::get())
199 sal_Int16 nOld
= any
.get
<sal_Int16
>();
200 sal_Int16 nNew
= nOld
+ 1;
201 xPropSet
->setPropertyValue(rName
, makeAny(nNew
));
203 else if (type
== cppu::UnoType
<sal_Int32
>::get())
206 sal_Int32 nOld
= any
.get
<sal_Int32
>();
207 sal_Int32 nNew
= nOld
+ 3;
208 xPropSet
->setPropertyValue(rName
, makeAny(nNew
));
210 else if (type
== cppu::UnoType
<sal_Int64
>::get())
213 sal_Int64 nOld
= any
.get
<sal_Int64
>();
214 sal_Int64 nNew
= nOld
+ 4;
215 xPropSet
->setPropertyValue(rName
, makeAny(nNew
));
217 else if (type
== cppu::UnoType
<float>::get())
220 float fOld
= any
.get
<float>();
221 float fNew
= fOld
+ 1.2;
222 xPropSet
->setPropertyValue(rName
, makeAny(fNew
));
224 else if (type
== cppu::UnoType
<double>::get())
227 double fOld
= any
.get
<double>();
228 double fNew
= fOld
+ 1.3;
229 xPropSet
->setPropertyValue(rName
, makeAny(fNew
));
231 else if (type
== cppu::UnoType
<OUString
>::get())
234 OUString aOld
= any
.get
<OUString
>();
235 OUString aNew
= aOld
+ "foo";
236 xPropSet
->setPropertyValue(rName
, makeAny(aNew
));
238 else if (type
== cppu::UnoType
<util::DateTime
>::get())
241 util::DateTime aDT
= any
.get
<util::DateTime
>();
243 xPropSet
->setPropertyValue(rName
, makeAny(aDT
));
247 std::cout
<< "Unknown type:\n"
249 << type
.getTypeName()
253 CPPUNIT_ASSERT_MESSAGE(
254 "XPropertySet::isPropertyValueChangeable: unknown type in Any tested.", false);
257 uno::Any anyTest
= xPropSet
->getPropertyValue(rName
);
258 return any
!= anyTest
;
260 catch (const uno::Exception
&)
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.",
271 void XPropertySet::fillPropsToTest(const uno::Reference
<beans::XPropertySetInfo
>& xPropInfo
)
273 if (maPropsToTest
.initialized
)
276 const uno::Sequence
<beans::Property
> aProps
= xPropInfo
->getProperties();
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");
286 for (const beans::Property
& aProp
: aProps
)
288 if (aSkip
.count(aProp
.Name
) > 0)
291 if ((aProp
.Attributes
& beans::PropertyAttribute::READONLY
) != 0)
293 maPropsToTest
.readonly
.push_back(aProp
.Name
);
297 if ((aProp
.Attributes
& beans::PropertyAttribute::MAYBEVOID
) != 0)
300 bool bBound
= (aProp
.Attributes
& beans::PropertyAttribute::BOUND
) != 0;
301 bool bConstrained
= (aProp
.Attributes
& beans::PropertyAttribute::CONSTRAINED
) != 0;
302 bool bCanChange
= isPropertyValueChangeable(aProp
.Name
);
304 if (bBound
&& bCanChange
)
305 maPropsToTest
.bound
.push_back(aProp
.Name
);
307 if (bConstrained
&& bCanChange
)
308 maPropsToTest
.constrained
.push_back(aProp
.Name
);
311 maPropsToTest
.normal
.push_back(aProp
.Name
);
314 maPropsToTest
.initialized
= true;
317 bool XPropertySet::getSinglePropertyValue(const uno::Reference
<beans::XPropertySet
>& xPropSet
,
318 const OUString
& rName
)
322 xPropSet
->getPropertyValue(rName
);
325 catch (const uno::Exception
&)
331 bool XPropertySet::isPropertyIgnored(const OUString
& rName
)
333 return m_IgnoreValue
.count(rName
) > 0;
336 } // namespace apitest
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */