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/.
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 <sal/config.h>
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
24 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/beans/XPropertyState.hpp>
27 #include <com/sun/star/configuration/ReadOnlyAccess.hpp>
28 #include <com/sun/star/configuration/theDefaultProvider.hpp>
29 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/container/XNameReplace.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/lang/EventObject.hpp>
34 #include <com/sun/star/lang/XComponent.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <com/sun/star/uno/Reference.hxx>
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <com/sun/star/uno/XInterface.hpp>
41 #include <com/sun/star/util/XChangesBatch.hpp>
42 #include <cppuhelper/implbase.hxx>
44 #include <rtl/ref.hxx>
45 #include <rtl/ustring.hxx>
46 #include <sal/types.h>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/configuration.hxx>
49 #include <comphelper/configurationlistener.hxx>
50 #include <cppunit/TestAssert.h>
51 #include <cppunit/TestFixture.h>
52 #include <cppunit/extensions/HelperMacros.h>
53 #include <cppunit/plugin/TestPlugIn.h>
54 #include <officecfg/Office/Math.hxx>
58 class Test
: public CppUnit::TestFixture
{
60 virtual void setUp() override
;
65 void testSetSetMemberName();
66 void testInsertSetMember();
67 void testLocalizedProperty();
68 void testReadCommands();
71 void testCrossThreads();
74 OUString
const & path
, OUString
const & relative
) const;
77 OUString
const & path
, OUString
const & name
,
78 css::uno::Any
const & value
) const;
80 bool resetKey(OUString
const & path
, OUString
const & name
) const;
82 css::uno::Reference
< css::uno::XInterface
> createViewAccess(
83 OUString
const & path
) const;
85 css::uno::Reference
< css::uno::XInterface
> createUpdateAccess(
86 OUString
const & path
) const;
88 CPPUNIT_TEST_SUITE(Test
);
89 CPPUNIT_TEST(testKeyFetch
);
90 CPPUNIT_TEST(testKeySet
);
91 CPPUNIT_TEST(testKeyReset
);
92 CPPUNIT_TEST(testSetSetMemberName
);
93 CPPUNIT_TEST(testInsertSetMember
);
94 CPPUNIT_TEST(testLocalizedProperty
);
95 CPPUNIT_TEST(testReadCommands
);
96 CPPUNIT_TEST(testListener
);
97 CPPUNIT_TEST(testRecursive
);
98 CPPUNIT_TEST(testCrossThreads
);
99 CPPUNIT_TEST_SUITE_END();
102 css::uno::Reference
< css::lang::XMultiServiceFactory
> provider_
;
106 public cppu::WeakImplHelper
< css::beans::XPropertyChangeListener
>
109 RecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
114 virtual ~RecursiveTest() override
;
116 virtual void step() const = 0;
121 virtual void SAL_CALL
disposing(css::lang::EventObject
const &) override
;
123 virtual void SAL_CALL
propertyChange(
124 css::beans::PropertyChangeEvent
const &) override
;
128 css::uno::Reference
< css::beans::XPropertySet
> properties_
;
131 RecursiveTest::RecursiveTest(
132 Test
const & theTest
, int count
, bool * destroyed
):
133 test_(theTest
), count_(count
), destroyed_(destroyed
)
136 void RecursiveTest::test()
139 test_
.createUpdateAccess(
140 "/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
142 css::uno::UNO_QUERY_THROW
);
143 properties_
->addPropertyChangeListener("Label", this);
145 CPPUNIT_ASSERT_EQUAL(0, count_
);
146 css::uno::Reference
< css::lang::XComponent
>(
147 properties_
, css::uno::UNO_QUERY_THROW
)->dispose();
150 RecursiveTest::~RecursiveTest()
155 void RecursiveTest::disposing(css::lang::EventObject
const & Source
)
157 CPPUNIT_ASSERT(properties_
.is());
158 CPPUNIT_ASSERT_EQUAL(
159 css::uno::Reference
<css::uno::XInterface
>(
160 properties_
, css::uno::UNO_QUERY_THROW
),
165 void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent
const & evt
)
167 CPPUNIT_ASSERT_EQUAL(
168 css::uno::Reference
<css::uno::XInterface
>(
169 properties_
, css::uno::UNO_QUERY_THROW
),
171 CPPUNIT_ASSERT_EQUAL( OUString("Label"), evt
.PropertyName
);
178 class SimpleRecursiveTest
: public RecursiveTest
{
180 SimpleRecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
183 virtual void step() const override
;
186 SimpleRecursiveTest::SimpleRecursiveTest(
187 Test
const & theTest
, int count
, bool * destroyed
):
188 RecursiveTest(theTest
, count
, destroyed
)
191 void SimpleRecursiveTest::step() const
194 "/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
197 css::uno::Any(OUString("step")));
202 provider_
= css::configuration::theDefaultProvider::get(
203 comphelper::getProcessComponentContext() );
206 void Test::testKeyFetch()
211 "/org.openoffice.System",
216 void Test::testKeySet()
219 "/org.openoffice.System/L10N",
221 css::uno::Any(OUString("com.sun.star.configuration.backend.LocaleBackend UILocale")));
225 "/org.openoffice.System/L10N",
228 CPPUNIT_ASSERT_EQUAL( OUString("com.sun.star.configuration.backend.LocaleBackend UILocale"), s
);
231 void Test::testKeyReset()
234 "/org.openoffice.System/L10N",
240 "/org.openoffice.System/L10N",
243 CPPUNIT_ASSERT_EQUAL( OUString("com.sun.star.configuration.backend.LocaleBackend Locale"), s
);
247 void Test::testSetSetMemberName()
252 "/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
253 ".uno:FontworkShapeType",
256 CPPUNIT_ASSERT_EQUAL( OUString("Fontwork Shape"), s
);
258 css::uno::Reference
< css::container::XNameAccess
> access(
260 "/org.openoffice.Office.UI.GenericCommands/UserInterface/"
262 css::uno::UNO_QUERY_THROW
);
263 css::uno::Reference
< css::container::XNamed
> member
;
264 access
->getByName(".uno:FontworkGalleryFloater") >>= member
;
265 CPPUNIT_ASSERT(member
.is());
266 member
->setName(".uno:FontworkShapeType");
267 css::uno::Reference
< css::util::XChangesBatch
>(
268 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
269 css::uno::Reference
< css::lang::XComponent
>(
270 access
, css::uno::UNO_QUERY_THROW
)->dispose();
274 "/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
275 ".uno:FontworkShapeType",
278 CPPUNIT_ASSERT_EQUAL( OUString("Insert Fontwork"), s
);
281 void Test::testInsertSetMember() {
282 css::uno::Reference
<css::container::XNameContainer
> access(
284 "/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands"),
285 css::uno::UNO_QUERY_THROW
);
286 css::uno::Reference
<css::uno::XInterface
> member
;
288 css::uno::Reference
<css::lang::XSingleServiceFactory
>(
289 access
, css::uno::UNO_QUERY_THROW
)->createInstance());
290 CPPUNIT_ASSERT(member
.is());
291 access
->insertByName("A", css::uno::Any(member
));
293 css::uno::Reference
<css::lang::XSingleServiceFactory
>(
294 access
, css::uno::UNO_QUERY_THROW
)->createInstance());
295 CPPUNIT_ASSERT(member
.is());
297 access
->insertByName("", css::uno::Any(member
));
298 CPPUNIT_FAIL("expected IllegalArgumentException");
299 } catch (css::lang::IllegalArgumentException
&) {}
301 access
->insertByName("\x01", css::uno::Any(member
));
302 CPPUNIT_FAIL("expected IllegalArgumentException");
303 } catch (css::lang::IllegalArgumentException
&) {}
305 access
->insertByName("a/b", css::uno::Any(member
));
306 } catch (css::lang::IllegalArgumentException
&) {
307 CPPUNIT_FAIL("unexpected IllegalArgumentException");
309 css::uno::Reference
<css::util::XChangesBatch
>(
310 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
311 css::uno::Reference
<css::lang::XComponent
>(
312 access
, css::uno::UNO_QUERY_THROW
)->dispose();
315 void Test::testLocalizedProperty() {
316 auto const access
= css::configuration::ReadOnlyAccess::create(
317 comphelper::getProcessComponentContext(), "*");
319 // See <https://bugs.documentfoundation.org/show_bug.cgi?id=33638> "Pagination extension
320 // not localized in LibreOffice", which wants to retrieve the non-canonical xml:lang="pt-PT"
321 // value for the passed-in "pt" locale:
324 access
->getByHierarchicalName("/org.libreoffice.unittest/localized/*pt") >>= v
);
325 CPPUNIT_ASSERT_EQUAL(OUString("pt-PT"), v
);
328 // Make sure a degenerate passed-in "-" locale is handled gracefully:
331 access
->getByHierarchicalName("/org.libreoffice.unittest/localized/*-") >>= v
);
332 CPPUNIT_ASSERT_EQUAL(OUString("default"), v
);
336 void Test::testReadCommands()
338 css::uno::Reference
< css::container::XNameAccess
> access(
340 "/org.openoffice.Office.UI.GenericCommands/UserInterface/"
342 css::uno::UNO_QUERY_THROW
);
343 const css::uno::Sequence
< OUString
> names(access
->getElementNames());
345 /*CPPUNIT_ASSERT_EQUAL(749, names.getLength());*/
346 // testSetSetMemberName() already removed ".uno:FontworkGalleryFloater"
347 sal_uInt32 n
= osl_getGlobalTimer();
348 for (int i
= 0; i
< 8; ++i
) {
349 for (OUString
const & childName
: names
) {
350 css::uno::Reference
< css::container::XNameAccess
> child
;
351 if (access
->getByName(childName
) >>= child
) {
352 CPPUNIT_ASSERT(child
.is());
353 child
->getByName("Label");
354 child
->getByName("ContextLabel");
355 child
->getByName("Properties");
359 n
= osl_getGlobalTimer() - n
;
360 printf("Reading elements took %" SAL_PRIuUINT32
" ms\n", n
);
361 css::uno::Reference
< css::lang::XComponent
>(
362 access
, css::uno::UNO_QUERY_THROW
)->dispose();
365 void Test::testListener()
367 OUString aRandomPath
= "/org.openoffice.Office.Math/View";
369 // test with no props.
371 rtl::Reference
xListener(
372 new comphelper::ConfigurationListener(aRandomPath
));
373 xListener
->dispose();
378 rtl::Reference
xListener(
379 new comphelper::ConfigurationListener(aRandomPath
));
381 comphelper::ConfigurationListenerProperty
<bool> aSetting(xListener
, "AutoRedraw");
382 CPPUNIT_ASSERT_MESSAGE("check AutoRedraw defaults to true", aSetting
.get());
386 std::shared_ptr
< comphelper::ConfigurationChanges
> xChanges(
387 comphelper::ConfigurationChanges::create());
388 officecfg::Office::Math::View::AutoRedraw::set(false, xChanges
);
391 CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", !aSetting
.get());
395 std::shared_ptr
< comphelper::ConfigurationChanges
> xChanges(
396 comphelper::ConfigurationChanges::create());
397 officecfg::Office::Math::View::AutoRedraw::set(true, xChanges
);
400 CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", aSetting
.get());
402 xListener
->dispose();
406 void Test::testRecursive()
408 bool destroyed
= false;
409 rtl::Reference
< RecursiveTest
>(
410 new SimpleRecursiveTest(*this, 100, &destroyed
))->test();
411 CPPUNIT_ASSERT(destroyed
);
414 void Test::testCrossThreads()
416 bool destroyed
= false;
417 rtl::Reference
< RecursiveTest
>(
418 new SimpleRecursiveTest(*this, 10, &destroyed
))->test();
419 CPPUNIT_ASSERT(destroyed
);
422 css::uno::Any
Test::getKey(
423 OUString
const & path
, OUString
const & relative
) const
425 css::uno::Reference
< css::container::XHierarchicalNameAccess
> access(
426 createViewAccess(path
), css::uno::UNO_QUERY_THROW
);
427 css::uno::Any
value(access
->getByHierarchicalName(relative
));
428 css::uno::Reference
< css::lang::XComponent
>(
429 access
, css::uno::UNO_QUERY_THROW
)->dispose();
434 OUString
const & path
, OUString
const & name
,
435 css::uno::Any
const & value
) const
437 css::uno::Reference
< css::container::XNameReplace
> access(
438 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
439 access
->replaceByName(name
, value
);
440 css::uno::Reference
< css::util::XChangesBatch
>(
441 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
442 css::uno::Reference
< css::lang::XComponent
>(
443 access
, css::uno::UNO_QUERY_THROW
)->dispose();
446 bool Test::resetKey(OUString
const & path
, OUString
const & name
)
449 //TODO: support setPropertyToDefault
450 css::uno::Reference
< css::util::XChangesBatch
> access(
451 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
452 css::uno::Reference
< css::beans::XPropertyState
> state(
453 access
, css::uno::UNO_QUERY
);
457 state
->setPropertyToDefault(name
);
458 access
->commitChanges();
459 css::uno::Reference
< css::lang::XComponent
>(
460 access
, css::uno::UNO_QUERY_THROW
)->dispose();
464 css::uno::Reference
< css::uno::XInterface
> Test::createViewAccess(
465 OUString
const & path
) const
468 css::beans::NamedValue(
470 css::uno::Any(path
)));
471 return provider_
->createInstanceWithArguments(
472 "com.sun.star.configuration.ConfigurationAccess",
473 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
476 css::uno::Reference
< css::uno::XInterface
> Test::createUpdateAccess(
477 OUString
const & path
) const
480 css::beans::NamedValue(
482 css::uno::Any(path
)));
483 return provider_
->createInstanceWithArguments(
484 "com.sun.star.configuration.ConfigurationUpdateAccess",
485 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
488 CPPUNIT_TEST_SUITE_REGISTRATION(Test
);
492 CPPUNIT_PLUGIN_IMPLEMENT();
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */