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>
20 #include <com/sun/star/util/XComplexColor.hpp>
22 #include <com/sun/star/uno/Any.hxx>
23 #include <com/sun/star/uno/Reference.hxx>
24 #include <com/sun/star/uno/Type.h>
26 #include <cppuhelper/implbase.hxx>
27 #include <docmodel/uno/UnoComplexColor.hxx>
28 #include <rtl/ref.hxx>
30 #include <cppunit/TestAssert.h>
33 using namespace css::uno
;
37 XPropertySet::PropsToTest::PropsToTest()
44 class MockedPropertyChangeListener
: public ::cppu::WeakImplHelper
<beans::XPropertyChangeListener
>
47 MockedPropertyChangeListener()
48 : m_bListenerCalled(false)
52 bool m_bListenerCalled
;
54 virtual void SAL_CALL
propertyChange(const beans::PropertyChangeEvent
& /* xEvent */) override
56 m_bListenerCalled
= true;
59 virtual void SAL_CALL
disposing(const lang::EventObject
& /* xEventObj */) override
{}
62 class MockedVetoableChangeListener
: public ::cppu::WeakImplHelper
<beans::XVetoableChangeListener
>
65 MockedVetoableChangeListener()
66 : m_bListenerCalled(false)
70 bool m_bListenerCalled
;
72 virtual void SAL_CALL
vetoableChange(const beans::PropertyChangeEvent
& /* xEvent */) override
74 m_bListenerCalled
= true;
77 virtual void SAL_CALL
disposing(const lang::EventObject
& /* xEventObj */) override
{}
81 void XPropertySet::testPropertyChangeListener()
83 uno::Reference
<beans::XPropertySet
> xPropSet(init(), uno::UNO_QUERY_THROW
);
84 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
85 fillPropsToTest(xPropInfo
);
87 for (const auto& aName
: maPropsToTest
.bound
)
89 rtl::Reference
<MockedPropertyChangeListener
> xListener
= new MockedPropertyChangeListener();
90 xPropSet
->addPropertyChangeListener(
91 aName
, uno::Reference
<beans::XPropertyChangeListener
>(xListener
));
92 if (!isPropertyValueChangeable(aName
))
95 CPPUNIT_ASSERT(xListener
->m_bListenerCalled
);
97 xListener
->m_bListenerCalled
= false;
98 xPropSet
->removePropertyChangeListener(
99 aName
, uno::Reference
<beans::XPropertyChangeListener
>(xListener
));
100 isPropertyValueChangeable(aName
);
101 CPPUNIT_ASSERT(!xListener
->m_bListenerCalled
);
105 void XPropertySet::testVetoableChangeListener()
107 uno::Reference
<beans::XPropertySet
> xPropSet(init(), uno::UNO_QUERY_THROW
);
108 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
109 fillPropsToTest(xPropInfo
);
111 for (const auto& aName
: maPropsToTest
.bound
)
113 rtl::Reference
<MockedVetoableChangeListener
> xListener
= new MockedVetoableChangeListener();
114 xPropSet
->addVetoableChangeListener(
115 aName
, uno::Reference
<beans::XVetoableChangeListener
>(xListener
));
116 if (!isPropertyValueChangeable(aName
))
119 CPPUNIT_ASSERT(xListener
->m_bListenerCalled
);
121 xListener
->m_bListenerCalled
= false;
122 xPropSet
->removeVetoableChangeListener(
123 aName
, uno::Reference
<beans::XVetoableChangeListener
>(xListener
));
124 isPropertyValueChangeable(aName
);
125 CPPUNIT_ASSERT(!xListener
->m_bListenerCalled
);
129 void XPropertySet::testGetPropertySetInfo()
131 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
132 uno::Reference
<beans::XPropertySetInfo
> xPropInfo
= xPropSet
->getPropertySetInfo();
135 fillPropsToTest(xPropInfo
);
139 // TODO: Add a means for the client code to populate the PropsToTest.
143 void XPropertySet::testSetPropertyValue()
145 testGetPropertySetInfo();
147 for (size_t i
= 0, n
= maPropsToTest
.normal
.size(); i
< n
; ++i
)
149 bool bSuccess
= isPropertyValueChangeable(maPropsToTest
.normal
[i
]);
150 CPPUNIT_ASSERT(bSuccess
);
154 void XPropertySet::testGetPropertyValue()
156 testGetPropertySetInfo();
157 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
159 // Check read-only properties.
160 for (size_t i
= 0, n
= maPropsToTest
.readonly
.size(); i
< n
; ++i
)
162 bool bSuccess
= getSinglePropertyValue(xPropSet
, maPropsToTest
.readonly
[i
]);
163 CPPUNIT_ASSERT(bSuccess
);
166 // Check writable properties.
167 for (size_t i
= 0, n
= maPropsToTest
.normal
.size(); i
< n
; ++i
)
169 bool bSuccess
= getSinglePropertyValue(xPropSet
, maPropsToTest
.normal
[i
]);
170 CPPUNIT_ASSERT(bSuccess
);
174 bool XPropertySet::isPropertyValueChangeable(const OUString
& rName
)
176 bool bIgnore
= isPropertyIgnored(rName
);
180 uno::Reference
<beans::XPropertySet
> xPropSet(init(), UNO_QUERY_THROW
);
183 uno::Any any
= xPropSet
->getPropertyValue(rName
);
184 const uno::Type
& type
= any
.getValueType();
185 if (type
== cppu::UnoType
<bool>::get())
188 bool bOld
= any
.get
<bool>();
189 xPropSet
->setPropertyValue(rName
, Any(!bOld
));
191 else if (type
== cppu::UnoType
<sal_Int8
>::get())
194 sal_Int8 nOld
= any
.get
<sal_Int8
>();
195 sal_Int8 nNew
= nOld
+ 1;
196 xPropSet
->setPropertyValue(rName
, Any(nNew
));
198 else if (type
== cppu::UnoType
<sal_Int16
>::get())
201 sal_Int16 nOld
= any
.get
<sal_Int16
>();
202 sal_Int16 nNew
= nOld
+ 1;
203 xPropSet
->setPropertyValue(rName
, Any(nNew
));
205 else if (type
== cppu::UnoType
<sal_Int32
>::get())
208 sal_Int32 nOld
= any
.get
<sal_Int32
>();
209 sal_Int32 nNew
= nOld
+ 3;
210 xPropSet
->setPropertyValue(rName
, Any(nNew
));
212 else if (type
== cppu::UnoType
<sal_Int64
>::get())
215 sal_Int64 nOld
= any
.get
<sal_Int64
>();
216 sal_Int64 nNew
= nOld
+ 4;
217 xPropSet
->setPropertyValue(rName
, Any(nNew
));
219 else if (type
== cppu::UnoType
<float>::get())
222 float fOld
= any
.get
<float>();
223 float fNew
= fOld
+ 1.2;
224 xPropSet
->setPropertyValue(rName
, Any(fNew
));
226 else if (type
== cppu::UnoType
<double>::get())
229 double fOld
= any
.get
<double>();
230 double fNew
= fOld
+ 1.3;
231 xPropSet
->setPropertyValue(rName
, Any(fNew
));
233 else if (type
== cppu::UnoType
<OUString
>::get())
236 OUString aOld
= any
.get
<OUString
>();
237 OUString aNew
= aOld
+ "foo";
238 xPropSet
->setPropertyValue(rName
, Any(aNew
));
240 else if (type
== cppu::UnoType
<util::DateTime
>::get())
243 util::DateTime aDT
= any
.get
<util::DateTime
>();
245 xPropSet
->setPropertyValue(rName
, Any(aDT
));
247 else if (type
== cppu::UnoType
<uno::Reference
<util::XComplexColor
>>::get())
249 auto xComplexColor
= any
.get
<uno::Reference
<util::XComplexColor
>>();
250 auto aComplexColor
= model::color::getFromXComplexColor(xComplexColor
);
251 xPropSet
->setPropertyValue(rName
,
252 Any(model::color::createXComplexColor(aComplexColor
)));
256 std::cout
<< "Unknown type:\n"
258 << type
.getTypeName()
262 CPPUNIT_ASSERT_MESSAGE(
263 "XPropertySet::isPropertyValueChangeable: unknown type in Any tested.", false);
266 uno::Any anyTest
= xPropSet
->getPropertyValue(rName
);
267 return any
!= anyTest
;
269 catch (const uno::Exception
&)
271 std::cout
<< "Exception thrown while retrieving with property: " << rName
<< "\n";
272 CPPUNIT_ASSERT_MESSAGE("XPropertySet::isPropertyValueChangeable: exception thrown while "
273 "retrieving the property value.",
280 void XPropertySet::fillPropsToTest(const uno::Reference
<beans::XPropertySetInfo
>& xPropInfo
)
282 if (maPropsToTest
.initialized
)
285 const uno::Sequence
<beans::Property
> aProps
= xPropInfo
->getProperties();
287 // some properties should not be changed in a unspecific way.
288 // TODO: Maybe we should mark these properties read-only, instead of
289 // giving them a special treatment here?
290 std::set
<OUString
> aSkip
;
291 aSkip
.insert("PrinterName");
292 aSkip
.insert("CharRelief");
293 aSkip
.insert("IsLayerMode");
295 for (const beans::Property
& aProp
: aProps
)
297 if (aSkip
.count(aProp
.Name
) > 0)
300 if ((aProp
.Attributes
& beans::PropertyAttribute::READONLY
) != 0)
302 maPropsToTest
.readonly
.push_back(aProp
.Name
);
306 if ((aProp
.Attributes
& beans::PropertyAttribute::MAYBEVOID
) != 0)
309 bool bBound
= (aProp
.Attributes
& beans::PropertyAttribute::BOUND
) != 0;
310 bool bConstrained
= (aProp
.Attributes
& beans::PropertyAttribute::CONSTRAINED
) != 0;
311 bool bCanChange
= isPropertyValueChangeable(aProp
.Name
);
313 if (bBound
&& bCanChange
)
314 maPropsToTest
.bound
.push_back(aProp
.Name
);
316 if (bConstrained
&& bCanChange
)
317 maPropsToTest
.constrained
.push_back(aProp
.Name
);
320 maPropsToTest
.normal
.push_back(aProp
.Name
);
323 maPropsToTest
.initialized
= true;
326 bool XPropertySet::getSinglePropertyValue(const uno::Reference
<beans::XPropertySet
>& xPropSet
,
327 const OUString
& rName
)
331 xPropSet
->getPropertyValue(rName
);
334 catch (const uno::Exception
&)
340 bool XPropertySet::isPropertyIgnored(const OUString
& rName
)
342 return m_IgnoreValue
.count(rName
) > 0;
345 } // namespace apitest
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */