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 <cppu/unotype.hxx>
43 #include <cppuhelper/implbase.hxx>
45 #include <rtl/ref.hxx>
46 #include <rtl/ustring.hxx>
47 #include <sal/types.h>
48 #include <comphelper/processfactory.hxx>
49 #include <comphelper/configuration.hxx>
50 #include <comphelper/configurationlistener.hxx>
51 #include <cppunit/TestAssert.h>
52 #include <cppunit/TestFixture.h>
53 #include <cppunit/extensions/HelperMacros.h>
54 #include <cppunit/plugin/TestPlugIn.h>
55 #include <officecfg/Office/Math.hxx>
59 class Test
: public CppUnit::TestFixture
{
61 virtual void setUp() override
;
66 void testSetSetMemberName();
67 void testInsertSetMember();
68 void testLocalizedProperty();
69 void testReadCommands();
72 void testCrossThreads();
75 OUString
const & path
, OUString
const & relative
) const;
78 OUString
const & path
, OUString
const & name
,
79 css::uno::Any
const & value
) const;
81 bool resetKey(OUString
const & path
, OUString
const & name
) const;
83 css::uno::Reference
< css::uno::XInterface
> createViewAccess(
84 OUString
const & path
) const;
86 css::uno::Reference
< css::uno::XInterface
> createUpdateAccess(
87 OUString
const & path
) const;
89 CPPUNIT_TEST_SUITE(Test
);
90 CPPUNIT_TEST(testKeyFetch
);
91 CPPUNIT_TEST(testKeySet
);
92 CPPUNIT_TEST(testKeyReset
);
93 CPPUNIT_TEST(testSetSetMemberName
);
94 CPPUNIT_TEST(testInsertSetMember
);
95 CPPUNIT_TEST(testLocalizedProperty
);
96 CPPUNIT_TEST(testReadCommands
);
97 CPPUNIT_TEST(testListener
);
98 CPPUNIT_TEST(testRecursive
);
99 CPPUNIT_TEST(testCrossThreads
);
100 CPPUNIT_TEST_SUITE_END();
103 css::uno::Reference
< css::lang::XMultiServiceFactory
> provider_
;
107 public cppu::WeakImplHelper
< css::beans::XPropertyChangeListener
>
110 RecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
115 virtual ~RecursiveTest() override
;
117 virtual void step() const = 0;
122 virtual void SAL_CALL
disposing(css::lang::EventObject
const &) override
;
124 virtual void SAL_CALL
propertyChange(
125 css::beans::PropertyChangeEvent
const &) override
;
129 css::uno::Reference
< css::beans::XPropertySet
> properties_
;
132 RecursiveTest::RecursiveTest(
133 Test
const & theTest
, int count
, bool * destroyed
):
134 test_(theTest
), count_(count
), destroyed_(destroyed
)
137 void RecursiveTest::test()
140 test_
.createUpdateAccess(
141 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
142 ".uno:WebHtml"_ustr
),
143 css::uno::UNO_QUERY_THROW
);
144 properties_
->addPropertyChangeListener(u
"Label"_ustr
, this);
146 CPPUNIT_ASSERT_EQUAL(0, count_
);
147 css::uno::Reference
< css::lang::XComponent
>(
148 properties_
, css::uno::UNO_QUERY_THROW
)->dispose();
151 RecursiveTest::~RecursiveTest()
156 void RecursiveTest::disposing(css::lang::EventObject
const & Source
)
158 CPPUNIT_ASSERT(properties_
.is());
159 CPPUNIT_ASSERT_EQUAL(
160 css::uno::Reference
<css::uno::XInterface
>(
161 properties_
, css::uno::UNO_QUERY_THROW
),
166 void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent
const & evt
)
168 CPPUNIT_ASSERT_EQUAL(
169 css::uno::Reference
<css::uno::XInterface
>(
170 properties_
, css::uno::UNO_QUERY_THROW
),
172 CPPUNIT_ASSERT_EQUAL( u
"Label"_ustr
, evt
.PropertyName
);
179 class SimpleRecursiveTest
: public RecursiveTest
{
181 SimpleRecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
184 virtual void step() const override
;
187 SimpleRecursiveTest::SimpleRecursiveTest(
188 Test
const & theTest
, int count
, bool * destroyed
):
189 RecursiveTest(theTest
, count
, destroyed
)
192 void SimpleRecursiveTest::step() const
195 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
198 css::uno::Any(u
"step"_ustr
));
203 provider_
= css::configuration::theDefaultProvider::get(
204 comphelper::getProcessComponentContext() );
207 void Test::testKeyFetch()
213 u
"/org.openoffice.System"_ustr
,
214 u
"L10N/Locale"_ustr
) >>=
218 auto const v
= getKey(u
"/org.openoffice.System"_ustr
, u
"L10N/['Locale']"_ustr
);
219 CPPUNIT_ASSERT_EQUAL(cppu::UnoType
<OUString
>::get(), v
.getValueType());
223 void Test::testKeySet()
226 u
"/org.openoffice.System/L10N"_ustr
,
228 css::uno::Any(u
"com.sun.star.configuration.backend.LocaleBackend UILocale"_ustr
));
232 u
"/org.openoffice.System/L10N"_ustr
,
235 CPPUNIT_ASSERT_EQUAL( u
"com.sun.star.configuration.backend.LocaleBackend UILocale"_ustr
, s
);
238 void Test::testKeyReset()
241 u
"/org.openoffice.System/L10N"_ustr
,
247 u
"/org.openoffice.System/L10N"_ustr
,
250 CPPUNIT_ASSERT_EQUAL( u
"com.sun.star.configuration.backend.LocaleBackend Locale"_ustr
, s
);
254 void Test::testSetSetMemberName()
259 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
260 ".uno:FontworkShapeType"_ustr
,
263 CPPUNIT_ASSERT_EQUAL( u
"Fontwork Shape"_ustr
, s
);
265 css::uno::Reference
< css::container::XNameAccess
> access(
267 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/"
269 css::uno::UNO_QUERY_THROW
);
270 css::uno::Reference
< css::container::XNamed
> member
;
271 access
->getByName(u
".uno:FontworkGalleryFloater"_ustr
) >>= member
;
272 CPPUNIT_ASSERT(member
.is());
273 member
->setName(u
".uno:FontworkShapeType"_ustr
);
274 css::uno::Reference
< css::util::XChangesBatch
>(
275 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
276 css::uno::Reference
< css::lang::XComponent
>(
277 access
, css::uno::UNO_QUERY_THROW
)->dispose();
281 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands/"
282 ".uno:FontworkShapeType"_ustr
,
285 CPPUNIT_ASSERT_EQUAL( u
"Insert Fontwork"_ustr
, s
);
288 void Test::testInsertSetMember() {
289 css::uno::Reference
<css::container::XNameContainer
> access(
291 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/Commands"_ustr
),
292 css::uno::UNO_QUERY_THROW
);
293 css::uno::Reference
<css::uno::XInterface
> member
;
295 css::uno::Reference
<css::lang::XSingleServiceFactory
>(
296 access
, css::uno::UNO_QUERY_THROW
)->createInstance());
297 CPPUNIT_ASSERT(member
.is());
298 access
->insertByName(u
"A"_ustr
, css::uno::Any(member
));
300 css::uno::Reference
<css::lang::XSingleServiceFactory
>(
301 access
, css::uno::UNO_QUERY_THROW
)->createInstance());
302 CPPUNIT_ASSERT(member
.is());
304 access
->insertByName(u
""_ustr
, css::uno::Any(member
));
305 CPPUNIT_FAIL("expected IllegalArgumentException");
306 } catch (css::lang::IllegalArgumentException
&) {}
308 access
->insertByName(u
"\x01"_ustr
, css::uno::Any(member
));
309 CPPUNIT_FAIL("expected IllegalArgumentException");
310 } catch (css::lang::IllegalArgumentException
&) {}
312 access
->insertByName(u
"a/b"_ustr
, css::uno::Any(member
));
313 } catch (css::lang::IllegalArgumentException
&) {
314 CPPUNIT_FAIL("unexpected IllegalArgumentException");
316 css::uno::Reference
<css::util::XChangesBatch
>(
317 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
318 css::uno::Reference
<css::lang::XComponent
>(
319 access
, css::uno::UNO_QUERY_THROW
)->dispose();
322 void Test::testLocalizedProperty() {
323 auto const access
= css::configuration::ReadOnlyAccess::create(
324 comphelper::getProcessComponentContext(), u
"*"_ustr
);
326 // See <https://bugs.documentfoundation.org/show_bug.cgi?id=33638> "Pagination extension
327 // not localized in LibreOffice", which wants to retrieve the non-canonical xml:lang="pt-PT"
328 // value for the passed-in "pt" locale:
331 access
->getByHierarchicalName(u
"/org.libreoffice.unittest/localized/*pt"_ustr
) >>= v
);
332 CPPUNIT_ASSERT_EQUAL(u
"pt-PT"_ustr
, v
);
335 // See <https://gerrit.libreoffice.org/c/core/+/147089> "configmgr: fix no longer found
336 // es-419 -> es fallback", which wants to retrieve the xml:lang="es" value for the passed-in
340 access
->getByHierarchicalName(u
"/org.libreoffice.unittest/localized/*es-419"_ustr
) >>= v
);
341 CPPUNIT_ASSERT_EQUAL(u
"es"_ustr
, v
);
344 // See <https://git.libreoffice.org/core/+/dfc28be2487c13be36a90efd778b8d8f179c589d%5E%21>
345 // "configmgr: Use a proper LanguageTag-based locale fallback mechanism":
348 access
->getByHierarchicalName(u
"/org.libreoffice.unittest/localized/*zh-Hant-TW"_ustr
) >>= v
);
349 CPPUNIT_ASSERT_EQUAL(u
"zh-TW"_ustr
, v
);
352 // Make sure a degenerate passed-in "-" locale is handled gracefully:
355 access
->getByHierarchicalName(u
"/org.libreoffice.unittest/localized/*-"_ustr
) >>= v
);
356 CPPUNIT_ASSERT_EQUAL(u
"en-US"_ustr
, v
);
359 // Make sure a degenerate passed-in "-" locale is handled gracefully:
362 access
->getByHierarchicalName(u
"/org.libreoffice.unittest/noDefaultLang/*-"_ustr
) >>= v
);
363 CPPUNIT_ASSERT_EQUAL(u
"en-US"_ustr
, v
);
367 void Test::testReadCommands()
369 css::uno::Reference
< css::container::XNameAccess
> access(
371 u
"/org.openoffice.Office.UI.GenericCommands/UserInterface/"
373 css::uno::UNO_QUERY_THROW
);
374 const css::uno::Sequence
< OUString
> names(access
->getElementNames());
376 /*CPPUNIT_ASSERT_EQUAL(749, names.getLength());*/
377 // testSetSetMemberName() already removed ".uno:FontworkGalleryFloater"
378 sal_uInt32 n
= osl_getGlobalTimer();
379 for (int i
= 0; i
< 8; ++i
) {
380 for (OUString
const & childName
: names
) {
381 css::uno::Reference
< css::container::XNameAccess
> child
;
382 if (access
->getByName(childName
) >>= child
) {
383 CPPUNIT_ASSERT(child
.is());
384 child
->getByName(u
"Label"_ustr
);
385 child
->getByName(u
"ContextLabel"_ustr
);
386 child
->getByName(u
"Properties"_ustr
);
390 n
= osl_getGlobalTimer() - n
;
391 printf("Reading elements took %" SAL_PRIuUINT32
" ms\n", n
);
392 css::uno::Reference
< css::lang::XComponent
>(
393 access
, css::uno::UNO_QUERY_THROW
)->dispose();
396 void Test::testListener()
398 OUString aRandomPath
= u
"/org.openoffice.Office.Math/View"_ustr
;
400 // test with no props.
402 rtl::Reference
xListener(
403 new comphelper::ConfigurationListener(aRandomPath
));
404 xListener
->dispose();
409 rtl::Reference
xListener(
410 new comphelper::ConfigurationListener(aRandomPath
));
412 comphelper::ConfigurationListenerProperty
<bool> aSetting(xListener
, u
"AutoRedraw"_ustr
);
413 CPPUNIT_ASSERT_MESSAGE("check AutoRedraw defaults to true", aSetting
.get());
417 std::shared_ptr
< comphelper::ConfigurationChanges
> xChanges(
418 comphelper::ConfigurationChanges::create());
419 officecfg::Office::Math::View::AutoRedraw::set(false, xChanges
);
422 CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", !aSetting
.get());
426 std::shared_ptr
< comphelper::ConfigurationChanges
> xChanges(
427 comphelper::ConfigurationChanges::create());
428 officecfg::Office::Math::View::AutoRedraw::set(true, xChanges
);
431 CPPUNIT_ASSERT_MESSAGE("listener failed to trigger", aSetting
.get());
433 xListener
->dispose();
437 void Test::testRecursive()
439 bool destroyed
= false;
440 rtl::Reference
< RecursiveTest
>(
441 new SimpleRecursiveTest(*this, 100, &destroyed
))->test();
442 CPPUNIT_ASSERT(destroyed
);
445 void Test::testCrossThreads()
447 bool destroyed
= false;
448 rtl::Reference
< RecursiveTest
>(
449 new SimpleRecursiveTest(*this, 10, &destroyed
))->test();
450 CPPUNIT_ASSERT(destroyed
);
453 css::uno::Any
Test::getKey(
454 OUString
const & path
, OUString
const & relative
) const
456 css::uno::Reference
< css::container::XHierarchicalNameAccess
> access(
457 createViewAccess(path
), css::uno::UNO_QUERY_THROW
);
458 css::uno::Any
value(access
->getByHierarchicalName(relative
));
459 css::uno::Reference
< css::lang::XComponent
>(
460 access
, css::uno::UNO_QUERY_THROW
)->dispose();
465 OUString
const & path
, OUString
const & name
,
466 css::uno::Any
const & value
) const
468 css::uno::Reference
< css::container::XNameReplace
> access(
469 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
470 access
->replaceByName(name
, value
);
471 css::uno::Reference
< css::util::XChangesBatch
>(
472 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
473 css::uno::Reference
< css::lang::XComponent
>(
474 access
, css::uno::UNO_QUERY_THROW
)->dispose();
477 bool Test::resetKey(OUString
const & path
, OUString
const & name
)
480 //TODO: support setPropertyToDefault
481 css::uno::Reference
< css::util::XChangesBatch
> access(
482 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
483 css::uno::Reference
< css::beans::XPropertyState
> state(
484 access
, css::uno::UNO_QUERY
);
488 state
->setPropertyToDefault(name
);
489 access
->commitChanges();
490 css::uno::Reference
< css::lang::XComponent
>(
491 access
, css::uno::UNO_QUERY_THROW
)->dispose();
495 css::uno::Reference
< css::uno::XInterface
> Test::createViewAccess(
496 OUString
const & path
) const
499 css::beans::NamedValue(
501 css::uno::Any(path
)));
502 return provider_
->createInstanceWithArguments(
503 u
"com.sun.star.configuration.ConfigurationAccess"_ustr
,
504 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
507 css::uno::Reference
< css::uno::XInterface
> Test::createUpdateAccess(
508 OUString
const & path
) const
511 css::beans::NamedValue(
513 css::uno::Any(path
)));
514 return provider_
->createInstanceWithArguments(
515 u
"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr
,
516 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
519 CPPUNIT_TEST_SUITE_REGISTRATION(Test
);
523 CPPUNIT_PLUGIN_IMPLEMENT();
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */