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"
24 #include "com/sun/star/beans/NamedValue.hpp"
25 #include "com/sun/star/beans/PropertyChangeEvent.hpp"
26 #include "com/sun/star/beans/XPropertyChangeListener.hpp"
27 #include "com/sun/star/beans/XPropertySet.hpp"
28 #include "com/sun/star/beans/XPropertyState.hpp"
29 #include "com/sun/star/configuration/theDefaultProvider.hpp"
30 #include "com/sun/star/container/XHierarchicalNameAccess.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/uno/Any.hxx"
37 #include "com/sun/star/uno/Reference.hxx"
38 #include "com/sun/star/uno/RuntimeException.hpp"
39 #include "com/sun/star/uno/Sequence.hxx"
40 #include "com/sun/star/uno/XComponentContext.hpp"
41 #include "com/sun/star/uno/XInterface.hpp"
42 #include "com/sun/star/util/XChangesBatch.hpp"
43 #include "cppuhelper/implbase1.hxx"
44 #include "cppuhelper/servicefactory.hxx"
45 #include "osl/conditn.hxx"
46 #include "osl/thread.h"
47 #include "osl/thread.hxx"
49 #include "rtl/ref.hxx"
50 #include "rtl/string.h"
51 #include "rtl/textcvt.h"
52 #include "rtl/ustrbuf.hxx"
53 #include "rtl/ustring.h"
54 #include "rtl/ustring.hxx"
55 #include "sal/types.h"
56 #include "testshl/simpleheader.hxx"
61 OUString
const & path
, OUString
const & relative
,
62 OUString
* normalizedPath
, OUString
* name
)
64 sal_Int32 i
= relative
.lastIndexOf('/');
66 *normalizedPath
= path
;
69 OUStringBuffer
buf(path
);
70 buf
.append(sal_Unicode('/'));
71 buf
.append(relative
.copy(0, i
));
72 *normalizedPath
= buf
.makeStringAndClear();
73 *name
= relative
.copy(i
+ 1);
77 class Test
: public CppUnit::TestFixture
{
80 virtual void tearDown();
85 void testSetSetMemberName();
86 void testReadCommands();
89 void testCrossThreads();
92 OUString
const & path
, OUString
const & relative
) const;
95 OUString
const & path
, OUString
const & name
,
96 css::uno::Any
const & value
) const;
98 bool resetKey(OUString
const & path
, OUString
const & name
) const;
100 css::uno::Reference
< css::uno::XInterface
> createViewAccess(
101 OUString
const & path
) const;
103 css::uno::Reference
< css::uno::XInterface
> createUpdateAccess(
104 OUString
const & path
) const;
106 CPPUNIT_TEST_SUITE(Test
);
107 CPPUNIT_TEST(testKeyFetch
);
108 CPPUNIT_TEST(testKeySet
);
109 CPPUNIT_TEST(testKeyReset
);
110 CPPUNIT_TEST(testSetSetMemberName
);
111 CPPUNIT_TEST(testReadCommands
);
112 CPPUNIT_TEST(testThreads
);
113 CPPUNIT_TEST(testRecursive
);
114 CPPUNIT_TEST(testCrossThreads
);
115 CPPUNIT_TEST_SUITE_END();
118 css::uno::Reference
< css::uno::XComponentContext
> context_
;
119 css::uno::Reference
< css::lang::XMultiServiceFactory
> provider_
;
122 class TestThread
: public osl::Thread
{
124 TestThread(osl::Condition
& stop
);
126 bool getSuccess() const;
129 virtual bool iteration() = 0;
132 virtual void SAL_CALL
run();
134 osl::Condition
& stop_
;
138 TestThread::TestThread(
139 osl::Condition
& stop
):
140 stop_(stop
), success_(true)
143 bool TestThread::getSuccess() const {
147 void TestThread::run() {
149 while (!stop_
.check()) {
159 class ReaderThread
: public TestThread
{
162 osl::Condition
& stop
, Test
const & test
, OUString
const & path
,
163 OUString
const & relative
);
166 virtual bool iteration();
173 ReaderThread::ReaderThread(
174 osl::Condition
& stop
, Test
const & test
, OUString
const & path
,
175 OUString
const & relative
):
176 TestThread(stop
), test_(test
), path_(path
), relative_(relative
)
181 bool ReaderThread::iteration() {
182 return test_
.getKey(path_
, relative_
).hasValue();
185 class WriterThread
: public TestThread
{
188 osl::Condition
& stop
, Test
const & test
, OUString
const & path
,
189 OUString
const & relative
);
192 virtual bool iteration();
200 WriterThread::WriterThread(
201 osl::Condition
& stop
, Test
const & test
, OUString
const & path
,
202 OUString
const & relative
):
203 TestThread(stop
), test_(test
), index_(0)
205 normalize(path
, relative
, &path_
, &name_
);
209 bool WriterThread::iteration() {
210 OUString options
[] = {
214 OUString("bloaters") };
215 test_
.setKey(path_
, name_
, css::uno::makeAny(options
[index_
]));
216 index_
= (index_
+ 1) % (sizeof options
/ sizeof (OUString
));
221 public cppu::WeakImplHelper1
< css::beans::XPropertyChangeListener
>
224 RecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
229 virtual ~RecursiveTest();
231 virtual void step() const = 0;
236 virtual void SAL_CALL
disposing(css::lang::EventObject
const &)
237 throw (css::uno::RuntimeException
);
239 virtual void SAL_CALL
propertyChange(
240 css::beans::PropertyChangeEvent
const &)
241 throw (css::uno::RuntimeException
);
245 css::uno::Reference
< css::beans::XPropertySet
> properties_
;
248 RecursiveTest::RecursiveTest(
249 Test
const & theTest
, int count
, bool * destroyed
):
250 test_(theTest
), count_(count
), destroyed_(destroyed
)
253 void RecursiveTest::test() {
254 properties_
= css::uno::Reference
< css::beans::XPropertySet
>(
255 test_
.createUpdateAccess(
257 RTL_CONSTASCII_USTRINGPARAM(
258 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
260 css::uno::UNO_QUERY_THROW
);
261 properties_
->addPropertyChangeListener(
262 OUString("Label"), this);
264 CPPUNIT_ASSERT(count_
== 0);
265 css::uno::Reference
< css::lang::XComponent
>(
266 properties_
, css::uno::UNO_QUERY_THROW
)->dispose();
269 RecursiveTest::~RecursiveTest() {
273 void RecursiveTest::disposing(css::lang::EventObject
const & Source
)
274 throw (css::uno::RuntimeException
)
276 CPPUNIT_ASSERT(properties_
.is() && Source
.Source
== properties_
);
280 void RecursiveTest::propertyChange(css::beans::PropertyChangeEvent
const & evt
)
281 throw (css::uno::RuntimeException
)
283 CPPUNIT_ASSERT( evt
.Source
== properties_
&& evt
.PropertyName
== "Label" );
290 class SimpleRecursiveTest
: public RecursiveTest
{
292 SimpleRecursiveTest(Test
const & theTest
, int count
, bool * destroyed
);
295 virtual void step() const;
298 SimpleRecursiveTest::SimpleRecursiveTest(
299 Test
const & theTest
, int count
, bool * destroyed
):
300 RecursiveTest(theTest
, count
, destroyed
)
303 void SimpleRecursiveTest::step() const {
306 RTL_CONSTASCII_USTRINGPARAM(
307 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
310 css::uno::makeAny(OUString("step")));
313 class CrossThreadTest
: public RecursiveTest
{
315 CrossThreadTest(Test
const & theTest
, int count
, bool * destroyed
);
318 virtual void step() const;
321 CrossThreadTest::CrossThreadTest(
322 Test
const & theTest
, int count
, bool * destroyed
):
323 RecursiveTest(theTest
, count
, destroyed
)
326 void CrossThreadTest::step() const {
332 RTL_CONSTASCII_USTRINGPARAM(
333 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
335 OUString("Label")).join();
338 RTL_CONSTASCII_USTRINGPARAM(
339 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
345 char const * forward
= getForwardString();
346 rtl_uString
* registry
= 0;
348 rtl_convertStringToUString(
349 ®istry
, forward
, rtl_str_getLength(forward
),
350 osl_getThreadTextEncoding(),
351 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
|
352 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
|
353 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)));
354 context_
= css::uno::Reference
< css::uno::XComponentContext
>(
355 css::uno::Reference
< css::beans::XPropertySet
>(
356 cppu::createRegistryServiceFactory(
357 OUString(registry
, SAL_NO_ACQUIRE
)),
358 css::uno::UNO_QUERY_THROW
)->getPropertyValue(
359 OUString("DefaultContext")),
360 css::uno::UNO_QUERY_THROW
);
361 provider_
= css::configuration::theDefaultProvider::get(context_
);
364 void Test::tearDown() {
365 css::uno::Reference
< css::lang::XComponent
>(
366 context_
, css::uno::UNO_QUERY_THROW
)->dispose();
369 void Test::testKeyFetch() {
373 OUString("/org.openoffice.Setup"),
374 OUString("L10N/ooLocale")) >>=
378 OUString("/org.openoffice.Setup"),
379 OUString("Test/AString")) >>=
383 void Test::testKeySet() {
385 OUString("/org.openoffice.Setup/Test"),
387 css::uno::makeAny(OUString("baa")));
391 OUString("/org.openoffice.Setup/Test"),
392 OUString("AString")) >>=
394 CPPUNIT_ASSERT( s
== "baa" );
397 void Test::testKeyReset() {
399 OUString("/org.openoffice.Setup/Test"),
400 OUString("AString")))
405 OUString("/org.openoffice.Setup/Test"),
406 OUString("AString")) >>=
408 CPPUNIT_ASSERT( s
== "Foo" );
412 void Test::testSetSetMemberName() {
417 RTL_CONSTASCII_USTRINGPARAM(
418 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
419 ".uno:FontworkShapeType")),
420 OUString("Label")) >>=
422 CPPUNIT_ASSERT( s
== "Fontwork Shape" );
424 css::uno::Reference
< css::container::XNameAccess
> access(
427 RTL_CONSTASCII_USTRINGPARAM(
428 "/org.openoffice.UI.GenericCommands/UserInterface/"
430 css::uno::UNO_QUERY_THROW
);
431 css::uno::Reference
< css::container::XNamed
> member
;
433 OUString(".uno:FontworkGalleryFloater")) >>=
435 CPPUNIT_ASSERT(member
.is());
437 OUString(".uno:FontworkShapeType"));
438 css::uno::Reference
< css::util::XChangesBatch
>(
439 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
440 css::uno::Reference
< css::lang::XComponent
>(
441 access
, css::uno::UNO_QUERY_THROW
)->dispose();
446 RTL_CONSTASCII_USTRINGPARAM(
447 "/org.openoffice.UI.GenericCommands/UserInterface/Commands/"
448 ".uno:FontworkShapeType")),
449 OUString("Label")) >>=
451 CPPUNIT_ASSERT( s
== "Fontwork Gallery" );
454 void Test::testReadCommands() {
455 css::uno::Reference
< css::container::XNameAccess
> access(
458 RTL_CONSTASCII_USTRINGPARAM(
459 "/org.openoffice.UI.GenericCommands/UserInterface/"
461 css::uno::UNO_QUERY_THROW
);
462 css::uno::Sequence
< OUString
> names(access
->getElementNames());
463 CPPUNIT_ASSERT(names
.getLength() == 695);
464 // testSetSetMemberName() already removed ".uno:FontworkGalleryFloater"
465 sal_uInt32 n
= osl_getGlobalTimer();
466 for (int i
= 0; i
< 8; ++i
) {
467 for (sal_Int32 j
= 0; j
< names
.getLength(); ++j
) {
468 css::uno::Reference
< css::container::XNameAccess
> child
;
469 if (access
->getByName(names
[j
]) >>= child
) {
470 CPPUNIT_ASSERT(child
.is());
474 OUString("ContextLabel"));
476 OUString("Properties"));
480 n
= osl_getGlobalTimer() - n
;
481 t_print("Reading elements took %" SAL_PRIuUINT32
" ms\n", n
);
482 css::uno::Reference
< css::lang::XComponent
>(
483 access
, css::uno::UNO_QUERY_THROW
)->dispose();
486 void Test::testThreads() {
487 struct Entry
{ OUString path
; OUString relative
; };
489 { OUString("/org.openoffice.Setup"),
490 OUString("Test/AString") },
491 { OUString("/org.openoffice.Setup"),
492 OUString("Test/AString") },
494 "/org.openoffice.UI.GenericCommands"),
496 "UserInterface/Commands/dotuno:WebHtml/Label") },
498 "/org.openoffice.UI.GenericCommands"),
500 "UserInterface/Commands/dotuno:NewPresentation/Label") },
502 "/org.openoffice.UI.GenericCommands"),
504 "UserInterface/Commands/dotuno:RecentFileList/Label") },
505 { OUString("/org.openoffice.Setup"),
506 OUString("L10N/ooLocale") },
507 { OUString("/org.openoffice.Setup"),
508 OUString("Test/ABoolean") }
510 std::size_t const numReaders
= sizeof list
/ sizeof (Entry
);
511 std::size_t const numWriters
= numReaders
- 2;
512 ReaderThread
* readers
[numReaders
];
513 WriterThread
* writers
[numWriters
];
515 for (std::size_t i
= 0; i
< numReaders
; ++i
) {
516 CPPUNIT_ASSERT(getKey(list
[i
].path
, list
[i
].relative
).hasValue());
517 readers
[i
] = new ReaderThread(
518 stop
, *this, list
[i
].path
, list
[i
].relative
);
520 for (std::size_t i
= 0; i
< numWriters
; ++i
) {
521 writers
[i
] = new WriterThread(
522 stop
, *this, list
[i
].path
, list
[i
].relative
);
524 for (int i
= 0; i
< 5; ++i
) {
525 for (std::size_t j
= 0; j
< numReaders
; ++j
) {
528 normalize(list
[j
].path
, list
[j
].relative
, &path
, &name
);
529 resetKey(path
, name
);
530 osl::Thread::yield();
535 for (std::size_t i
= 0; i
< numReaders
; ++i
) {
537 success
= success
&& readers
[i
]->getSuccess();
540 for (std::size_t i
= 0; i
< numWriters
; ++i
) {
542 success
= success
&& writers
[i
]->getSuccess();
545 CPPUNIT_ASSERT(success
);
548 void Test::testRecursive() {
549 bool destroyed
= false;
550 rtl::Reference
< RecursiveTest
>(
551 new SimpleRecursiveTest(*this, 100, &destroyed
))->test();
552 CPPUNIT_ASSERT(destroyed
);
555 void Test::testCrossThreads() {
556 bool destroyed
= false;
557 rtl::Reference
< RecursiveTest
>(
558 new SimpleRecursiveTest(*this, 10, &destroyed
))->test();
559 CPPUNIT_ASSERT(destroyed
);
562 css::uno::Any
Test::getKey(
563 OUString
const & path
, OUString
const & relative
) const
565 css::uno::Reference
< css::container::XHierarchicalNameAccess
> access(
566 createViewAccess(path
), css::uno::UNO_QUERY_THROW
);
567 css::uno::Any
value(access
->getByHierarchicalName(relative
));
568 css::uno::Reference
< css::lang::XComponent
>(
569 access
, css::uno::UNO_QUERY_THROW
)->dispose();
574 OUString
const & path
, OUString
const & name
,
575 css::uno::Any
const & value
) const
577 css::uno::Reference
< css::container::XNameReplace
> access(
578 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
579 access
->replaceByName(name
, value
);
580 css::uno::Reference
< css::util::XChangesBatch
>(
581 access
, css::uno::UNO_QUERY_THROW
)->commitChanges();
582 css::uno::Reference
< css::lang::XComponent
>(
583 access
, css::uno::UNO_QUERY_THROW
)->dispose();
586 bool Test::resetKey(OUString
const & path
, OUString
const & name
)
589 //TODO: support setPropertyToDefault
590 css::uno::Reference
< css::util::XChangesBatch
> access(
591 createUpdateAccess(path
), css::uno::UNO_QUERY_THROW
);
592 css::uno::Reference
< css::beans::XPropertyState
> state(
593 access
, css::uno::UNO_QUERY
);
597 state
->setPropertyToDefault(name
);
598 access
->commitChanges();
599 css::uno::Reference
< css::lang::XComponent
>(
600 access
, css::uno::UNO_QUERY_THROW
)->dispose();
604 css::uno::Reference
< css::uno::XInterface
> Test::createViewAccess(
605 OUString
const & path
) const
609 css::beans::NamedValue(
610 OUString("nodepath"),
611 css::uno::makeAny(path
))));
612 return provider_
->createInstanceWithArguments(
614 "com.sun.star.configuration.ConfigurationAccess"),
615 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
618 css::uno::Reference
< css::uno::XInterface
> Test::createUpdateAccess(
619 OUString
const & path
) const
623 css::beans::NamedValue(
624 OUString("nodepath"),
625 css::uno::makeAny(path
))));
626 return provider_
->createInstanceWithArguments(
628 "com.sun.star.configuration.ConfigurationUpdateAccess"),
629 css::uno::Sequence
< css::uno::Any
>(&arg
, 1));
632 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Test
, "alltest");
638 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */