diff options
Diffstat (limited to 'test')
42 files changed, 1507 insertions, 222 deletions
diff --git a/test/CppunitTest_test_a11y.mk b/test/CppunitTest_test_a11y.mk new file mode 100644 index 000000000000..3adcc2995718 --- /dev/null +++ b/test/CppunitTest_test_a11y.mk @@ -0,0 +1,36 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,test_a11y)) + +$(eval $(call gb_CppunitTest_add_exception_objects,test_a11y, \ + test/qa/cppunit/dialog \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,test_a11y, \ + acc \ + sal \ + cppu \ + subsequenttest \ + test \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,test_a11y)) +$(eval $(call gb_CppunitTest_use_rdb,test_a11y,services)) +$(eval $(call gb_CppunitTest_use_ure,test_a11y)) +$(eval $(call gb_CppunitTest_use_vcl,test_a11y)) + +$(eval $(call gb_CppunitTest_use_instdir_configuration,test_a11y)) +$(eval $(call gb_CppunitTest_use_common_configuration,test_a11y)) + +$(eval $(call gb_CppunitTest_use_packages,test_a11y, \ + postprocess_images \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/test/Library_subsequenttest.mk b/test/Library_subsequenttest.mk index 813b61ec538f..f306904b321e 100644 --- a/test/Library_subsequenttest.mk +++ b/test/Library_subsequenttest.mk @@ -27,23 +27,28 @@ $(eval $(call gb_Library_use_libraries,subsequenttest,\ cppuhelper \ i18nlangtag \ sal \ + sfx \ test \ + tk \ tl \ utl \ unotest \ vcl \ + docmodel \ )) $(eval $(call gb_Library_use_externals,subsequenttest,\ boost_headers \ cppunit \ + libxml2 \ )) $(eval $(call gb_Library_add_exception_objects,subsequenttest,\ test/source/unoapi_test \ - test/source/calc_unoapi_test \ + test/source/unoapixml_test \ test/source/a11y/AccessibilityTools \ test/source/a11y/accessibletestbase \ + test/source/a11y/eventposter \ test/source/a11y/swaccessibletestbase \ test/source/beans/xpropertyset \ test/source/chart/xchartdata \ @@ -183,12 +188,19 @@ $(eval $(call gb_Library_add_exception_objects,subsequenttest,\ test/source/table/xtablecolumns \ test/source/table/xtablerows \ test/source/text/baseindex \ + test/source/text/baseindexmark \ + test/source/text/documentindexmark \ + test/source/text/numberingrules \ + test/source/text/footnote \ test/source/text/textcontent \ + test/source/text/xautotextcontainer \ + test/source/text/xfootnote \ test/source/text/xsimpletext \ test/source/text/xtext \ test/source/text/xtextcontent \ test/source/text/xtextfield \ test/source/text/xtextrange \ + test/source/text/xtextrangecompare \ test/source/text/xdocumentindex \ test/source/text/textdocumentsettings \ test/source/text/textprintersettings \ diff --git a/test/Module_test.mk b/test/Module_test.mk index 080cc855b28c..99e722905151 100644 --- a/test/Module_test.mk +++ b/test/Module_test.mk @@ -20,6 +20,7 @@ $(eval $(call gb_Module_add_targets,test,\ )) $(eval $(call gb_Module_add_check_targets,test,\ + CppunitTest_test_a11y \ CppunitTest_test_xpath \ )) diff --git a/test/qa/cppunit/dialog.cxx b/test/qa/cppunit/dialog.cxx new file mode 100644 index 000000000000..f5f861371443 --- /dev/null +++ b/test/qa/cppunit/dialog.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/a11y/accessibletestbase.hxx> + +// FIXME: dialog API doesn't work on macos yet +// and this test crashes on some jenkins Windows boxes +#if !defined(MACOSX) && !defined(_WIN32) + +/* Checks an unexpected dialog opening (instead of the expected one) is properly caught, as it would + * otherwise block the test potentially indefinitely */ +CPPUNIT_TEST_FIXTURE(test::AccessibleTestBase, SelfTestIncorrectDialog) +{ + load(u"private:factory/swriter"_ustr); + + auto dialogWaiter = awaitDialog(u"This Dialog Does Not Exist", [](Dialog&) { + CPPUNIT_ASSERT_MESSAGE("This code should not be reached", false); + }); + + CPPUNIT_ASSERT(activateMenuItem(u"Insert", u"Section...")); + /* Make sure an incorrect dialog popping up is caught and raises. The exception is thrown in + * waitEndDialog() for consistency even though the error itself is likely to have been triggered + * by the activateMenuItem() call above */ + CPPUNIT_ASSERT_THROW(dialogWaiter->waitEndDialog(), css::uno::RuntimeException); +} + +/* Checks that an exception in the dialog callback code is properly handled and won't disturb + * subsequent tests if caught -- especially that DialogWaiter::waitEndDialog() won't timeout. */ +CPPUNIT_TEST_FIXTURE(test::AccessibleTestBase, SelfTestThrowInDialogCallback) +{ + load(u"private:factory/swriter"_ustr); + + class DummyException : public std::exception + { + }; + + auto dialogWaiter = awaitDialog(u"Hyperlink", [](Dialog&) { throw DummyException(); }); + + CPPUNIT_ASSERT(activateMenuItem(u"Insert", u"Hyperlink...")); + CPPUNIT_ASSERT_THROW(dialogWaiter->waitEndDialog(), DummyException); +} + +// Checks timeout if dialog does not show up as expected +CPPUNIT_TEST_FIXTURE(test::AccessibleTestBase, SelfTestNoDialog) +{ + load(u"private:factory/swriter"_ustr); + + auto dialogWaiter = awaitDialog(u"This Dialog Did Not Show Up", [](Dialog&) { + CPPUNIT_ASSERT_MESSAGE("This code should not be reached", false); + }); + + // as we don't actually call any dialog up, this should fail after a timeout + CPPUNIT_ASSERT(!dialogWaiter->waitEndDialog()); +} + +#endif //defined(MACOSX) + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/qa/cppunit/test_xpath.cxx b/test/qa/cppunit/test_xpath.cxx index c622e59617ec..8d105dd4eae6 100644 --- a/test/qa/cppunit/test_xpath.cxx +++ b/test/qa/cppunit/test_xpath.cxx @@ -25,22 +25,20 @@ CPPUNIT_TEST_FIXTURE(TestXPath, test_getXPath) xmlDocUniquePtr pTable(xmlParseDoc(s_xml)); CPPUNIT_ASSERT(pTable); // Must get existing element content without errors - CPPUNIT_ASSERT_ASSERTION_PASS(getXPath(pTable, "/xml/item", "")); + CPPUNIT_ASSERT_ASSERTION_PASS(assertXPath(pTable, "/xml/item"_ostr)); // Must error out when getting non-existing element - CPPUNIT_ASSERT_ASSERTION_FAIL(getXPath(pTable, "/xml/no_item", "")); + CPPUNIT_ASSERT_ASSERTION_FAIL(assertXPath(pTable, "/xml/no_item"_ostr)); // Must get existing attribute value correctly - CPPUNIT_ASSERT_ASSERTION_PASS(getXPath(pTable, "/xml/item", "attrib")); + CPPUNIT_ASSERT_ASSERTION_PASS(getXPath(pTable, "/xml/item"_ostr, "attrib"_ostr)); // Must fail when requested non-empty attribute doesn't exist - CPPUNIT_ASSERT_ASSERTION_FAIL(getXPath(pTable, "/xml/item", "no_attrib")); - // Must return empty string if not asking an attribute, regardless what is its content - CPPUNIT_ASSERT_EQUAL(OUString(), getXPath(pTable, "/xml/item", "")); + CPPUNIT_ASSERT_ASSERTION_FAIL(getXPath(pTable, "/xml/item"_ostr, "no_attrib"_ostr)); // Must properly return attribute content - CPPUNIT_ASSERT_EQUAL(OUString("val"), getXPath(pTable, "/xml/item", "attrib")); + CPPUNIT_ASSERT_EQUAL(OUString("val"), getXPath(pTable, "/xml/item"_ostr, "attrib"_ostr)); // Trying to get position of missing child of a node must fail assertion - CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pTable, "/xml/item", "absent")); + CPPUNIT_ASSERT_ASSERTION_FAIL(getXPathPosition(pTable, "/xml/item"_ostr, "absent")); // Asserting that an attribute is absent - CPPUNIT_ASSERT_ASSERTION_FAIL(assertXPathNoAttribute(pTable, "/xml/item", "attrib")); - CPPUNIT_ASSERT_ASSERTION_PASS(assertXPathNoAttribute(pTable, "/xml/item", "foo")); + CPPUNIT_ASSERT_ASSERTION_FAIL(assertXPathNoAttribute(pTable, "/xml/item"_ostr, "attrib"_ostr)); + CPPUNIT_ASSERT_ASSERTION_PASS(assertXPathNoAttribute(pTable, "/xml/item"_ostr, "foo"_ostr)); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/test/source/a11y/AccessibilityTools.cxx b/test/source/a11y/AccessibilityTools.cxx index 991089dcb3e0..f0a28d4cdad2 100644 --- a/test/source/a11y/AccessibilityTools.cxx +++ b/test/source/a11y/AccessibilityTools.cxx @@ -24,11 +24,17 @@ #include <com/sun/star/accessibility/AccessibleRole.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleAction.hpp> #include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <rtl/ustrbuf.hxx> #include <sal/log.hxx> +#include <toolkit/awt/vclxaccessiblecomponent.hxx> #include <vcl/scheduler.hxx> #include <vcl/timer.hxx> +#include <vcl/window.hxx> +#include <o3tl/string_view.hxx> using namespace css; @@ -43,9 +49,9 @@ AccessibilityTools::getAccessibleObjectForPredicate( } else { - int count = xCtx->getAccessibleChildCount(); + sal_Int64 count = xCtx->getAccessibleChildCount(); - for (int i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++) + for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++) { uno::Reference<accessibility::XAccessibleContext> xCtx2 = getAccessibleObjectForPredicate(xCtx->getAccessibleChild(i), cPredicate); @@ -82,6 +88,26 @@ AccessibilityTools::getAccessibleObjectForRole( return getAccessibleObjectForRole(xacc->getAccessibleContext(), role); } +/* this is basically the same as getAccessibleObjectForPredicate() but specialized for efficiency, + * and because the template version will not work with getAccessibleObjectForPredicate() anyway */ +css::uno::Reference<css::accessibility::XAccessibleContext> +AccessibilityTools::getAccessibleObjectForName( + const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx, const sal_Int16 role, + std::u16string_view name) +{ + if (xCtx->getAccessibleRole() == role && nameEquals(xCtx, name)) + return xCtx; + + auto nChildren = xCtx->getAccessibleChildCount(); + for (decltype(nChildren) i = 0; i < nChildren && i < AccessibilityTools::MAX_CHILDREN; i++) + { + if (auto xMatchChild = getAccessibleObjectForName(xCtx->getAccessibleChild(i), role, name)) + return xMatchChild; + } + + return nullptr; +} + bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessible>& xacc1, const uno::Reference<accessibility::XAccessible>& xacc2) { @@ -136,6 +162,51 @@ bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessibleC return equals(xctx1->getAccessibleParent(), xctx2->getAccessibleParent()); } +bool AccessibilityTools::nameEquals(const uno::Reference<accessibility::XAccessibleContext>& xCtx, + const std::u16string_view name) +{ + auto ctxName = xCtx->getAccessibleName(); + std::u16string_view rest; + + if (!o3tl::starts_with(ctxName, name, &rest)) + return false; + if (rest == u"") + return true; + +#if defined(_WIN32) + // see OAccessibleMenuItemComponent::GetAccessibleName(): + // on Win32, ignore a \tSHORTCUT suffix on a menu item + switch (xCtx->getAccessibleRole()) + { + case accessibility::AccessibleRole::MENU_ITEM: + case accessibility::AccessibleRole::RADIO_MENU_ITEM: + case accessibility::AccessibleRole::CHECK_MENU_ITEM: + return rest[0] == '\t'; + + default: + break; + } +#endif + +#if OSL_DEBUG_LEVEL > 0 + // see VCLXAccessibleComponent::getAccessibleName() + static const char* pEnvAppendType = getenv("LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME"); + if (pEnvAppendType && OUString::createFromAscii(pEnvAppendType) != u"0") + { + auto pVCLXAccessibleComponent = dynamic_cast<VCLXAccessibleComponent*>(xCtx.get()); + if (pVCLXAccessibleComponent) + { + auto windowType = pVCLXAccessibleComponent->GetWindow()->GetType(); + if (rest + == Concat2View(u" (Type = " + OUString::number(static_cast<sal_Int32>(windowType)) + + ")")) + return true; + } + } +#endif + return false; +} + static OUString unknownName(const sal_Int64 value) { return "unknown (" + OUString::number(value) + ")"; @@ -149,6 +220,8 @@ OUString AccessibilityTools::getRoleName(const sal_Int16 role) return "UNKNOWN"; case accessibility::AccessibleRole::ALERT: return "ALERT"; + case accessibility::AccessibleRole::BLOCK_QUOTE: + return "BLOCK_QUOTE"; case accessibility::AccessibleRole::BUTTON_DROPDOWN: return "BUTTON_DROPDOWN"; case accessibility::AccessibleRole::BUTTON_MENU: @@ -344,6 +417,9 @@ OUString AccessibilityTools::debugAccessibleStateSet(const sal_Int64 nCombinedSt case accessibility::AccessibleStateType::BUSY: name = "BUSY"; break; + case accessibility::AccessibleStateType::CHECKABLE: + name = "CHECKABLE"; + break; case accessibility::AccessibleStateType::CHECKED: name = "CHECKED"; break; @@ -586,6 +662,59 @@ OUString AccessibilityTools::debugName(accessibility::XAccessible* acc) return debugName(acc->getAccessibleContext().get()); } +OUString AccessibilityTools::debugName(accessibility::XAccessibleAction* xAct) +{ + OUStringBuffer r = "actions=["; + + const sal_Int32 nActions = xAct->getAccessibleActionCount(); + for (sal_Int32 i = 0; i < nActions; i++) + { + if (i > 0) + r.append(", "); + + r.append("description=\"" + xAct->getAccessibleActionDescription(i) + "\""); + + const auto& xKeyBinding = xAct->getAccessibleActionKeyBinding(i); + if (xKeyBinding) + { + r.append(" keybindings=["); + const sal_Int32 nKeyBindings = xKeyBinding->getAccessibleKeyBindingCount(); + for (sal_Int32 j = 0; j < nKeyBindings; j++) + { + if (j > 0) + r.append(", "); + + int k = 0; + for (const auto& keyStroke : xKeyBinding->getAccessibleKeyBinding(j)) + { + if (k++ > 0) + r.append(", "); + + r.append('"'); + if (keyStroke.Modifiers & awt::KeyModifier::MOD1) + r.append("<Mod1>"); + if (keyStroke.Modifiers & awt::KeyModifier::MOD2) + r.append("<Mod2>"); + if (keyStroke.Modifiers & awt::KeyModifier::MOD3) + r.append("<Mod3>"); + if (keyStroke.Modifiers & awt::KeyModifier::SHIFT) + r.append("<Shift>"); + r.append(OUStringChar(keyStroke.KeyChar) + "\""); + } + } + r.append("]"); + } + } + r.append("]"); + return r.makeStringAndClear(); +} + +OUString AccessibilityTools::debugName(accessibility::XAccessibleText* xTxt) +{ + uno::Reference<accessibility::XAccessibleContext> xCtx(xTxt, uno::UNO_QUERY); + return debugName(xCtx.get()); +} + OUString AccessibilityTools::debugName(const accessibility::AccessibleEventObject* evobj) { return "(AccessibleEventObject) { id=" + getEventIdName(evobj->EventId) diff --git a/test/source/a11y/accessibletestbase.cxx b/test/source/a11y/accessibletestbase.cxx index 3968c32fa08d..00aac5ea9900 100644 --- a/test/source/a11y/accessibletestbase.cxx +++ b/test/source/a11y/accessibletestbase.cxx @@ -16,16 +16,24 @@ #include <com/sun/star/accessibility/XAccessible.hpp> #include <com/sun/star/accessibility/XAccessibleAction.hpp> #include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/awt/XDialog2.hpp> +#include <com/sun/star/awt/XExtendedToolkit.hpp> #include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/XTopWindowListener.hpp> #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/FrameSearchFlag.hpp> #include <com/sun/star/frame/XFrame.hpp> #include <com/sun/star/frame/XFrame2.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> #include <com/sun/star/util/XCloseable.hpp> +#include <vcl/idle.hxx> #include <vcl/scheduler.hxx> +#include <vcl/svapp.hxx> + +#include <cppuhelper/implbase.hxx> #include <test/a11y/AccessibilityTools.hxx> @@ -113,10 +121,9 @@ test::AccessibleTestBase::getFirstRelationTargetOfType( const auto& rel = relset->getRelation(i); if (rel.RelationType == relationType) { - for (auto& target : rel.TargetSet) + for (const uno::Reference<accessibility::XAccessible>& targetAccessible : + rel.TargetSet) { - uno::Reference<accessibility::XAccessible> targetAccessible(target, - uno::UNO_QUERY); if (targetAccessible.is()) return targetAccessible->getAccessibleContext(); } @@ -134,7 +141,7 @@ test::AccessibleTestBase::getAllChildren( std::deque<uno::Reference<accessibility::XAccessibleContext>> children; auto childCount = xContext->getAccessibleChildCount(); - for (sal_Int32 i = 0; i < childCount && i < AccessibilityTools::MAX_CHILDREN; i++) + for (sal_Int64 i = 0; i < childCount && i < AccessibilityTools::MAX_CHILDREN; i++) { auto child = xContext->getAccessibleChild(i); children.push_back(child->getAccessibleContext()); @@ -169,12 +176,11 @@ void test::AccessibleTestBase::dumpA11YTree( << " (" << rel.RelationType << ")"; std::cout << " targets=["; int j = 0; - for (auto& target : rel.TargetSet) + for (const uno::Reference<accessibility::XAccessible>& xTarget : rel.TargetSet) { if (j++ > 0) std::cout << ", "; - uno::Reference<accessibility::XAccessible> ta(target, uno::UNO_QUERY_THROW); - std::cout << AccessibilityTools::debugString(ta); + std::cout << AccessibilityTools::debugString(xTarget); } std::cout << "])"; } @@ -193,32 +199,6 @@ void test::AccessibleTestBase::dumpA11YTree( } } -/* see OAccessibleMenuItemComponent::GetAccessibleName() */ -static bool accessibleNameMatches(const uno::Reference<accessibility::XAccessibleContext>& xContext, - std::u16string_view name) -{ - const OUString actualName = xContext->getAccessibleName(); - - if (actualName == name) - return true; - -#if defined(_WIN32) - /* on Win32, ignore a \tSHORTCUT suffix on a menu item */ - switch (xContext->getAccessibleRole()) - { - case accessibility::AccessibleRole::MENU_ITEM: - case accessibility::AccessibleRole::RADIO_MENU_ITEM: - case accessibility::AccessibleRole::CHECK_MENU_ITEM: - return actualName.startsWith(name) && actualName[name.length()] == '\t'; - - default: - break; - } -#endif - - return false; -} - /** Gets a child by name (usually in a menu) */ uno::Reference<accessibility::XAccessibleContext> test::AccessibleTestBase::getItemFromName( const uno::Reference<accessibility::XAccessibleContext>& xMenuCtx, std::u16string_view name) @@ -227,10 +207,10 @@ uno::Reference<accessibility::XAccessibleContext> test::AccessibleTestBase::getI std::cout << "looking up item " << OUString(name) << " in " << AccessibilityTools::debugString(xMenuCtx) << std::endl; - for (sal_Int32 i = 0; i < childCount && i < AccessibilityTools::MAX_CHILDREN; i++) + for (sal_Int64 i = 0; i < childCount && i < AccessibilityTools::MAX_CHILDREN; i++) { auto item = xMenuCtx->getAccessibleChild(i)->getAccessibleContext(); - if (accessibleNameMatches(item, name)) + if (AccessibilityTools::nameEquals(item, name)) { std::cout << "-> found " << AccessibilityTools::debugString(item) << std::endl; return item; @@ -257,4 +237,343 @@ bool test::AccessibleTestBase::activateMenuItem( return false; } +uno::Reference<accessibility::XAccessibleContext> test::AccessibleTestBase::getFocusedObject( + const uno::Reference<accessibility::XAccessibleContext>& xCtx) +{ + return AccessibilityTools::getAccessibleObjectForPredicate( + xCtx, [](const uno::Reference<accessibility::XAccessibleContext>& xCandidateCtx) { + const auto states = (accessibility::AccessibleStateType::FOCUSED + | accessibility::AccessibleStateType::SHOWING); + return (xCandidateCtx->getAccessibleStateSet() & states) == states; + }); +} + +uno::Reference<accessibility::XAccessibleContext> +test::AccessibleTestBase::tabTo(const uno::Reference<accessibility::XAccessible>& xRoot, + const sal_Int16 role, const std::u16string_view name, + const EventPosterHelperBase* pEventPosterHelper) +{ + AccessibleEventPosterHelper eventHelper; + if (!pEventPosterHelper) + { + eventHelper.setWindow(xRoot); + pEventPosterHelper = &eventHelper; + } + + auto xOriginalFocus = getFocusedObject(xRoot); + auto xFocus = xOriginalFocus; + int nSteps = 0; + + std::cout << "Tabbing to '" << OUString(name) << "'..." << std::endl; + while (xFocus && (nSteps == 0 || xFocus != xOriginalFocus)) + { + std::cout << " focused object is: " << AccessibilityTools::debugString(xFocus) + << std::endl; + if (xFocus->getAccessibleRole() == role && AccessibilityTools::nameEquals(xFocus, name)) + { + std::cout << " -> OK, focus matches" << std::endl; + return xFocus; + } + if (++nSteps > 100) + { + std::cerr << "Object not found after tabbing 100 times! bailing out" << std::endl; + break; + } + + std::cout << " -> no match, sending <TAB>" << std::endl; + pEventPosterHelper->postKeyEventAsync(0, awt::Key::TAB); + Scheduler::ProcessEventsToIdle(); + + const auto xPrevFocus = xFocus; + xFocus = getFocusedObject(xRoot); + if (!xFocus) + std::cerr << "Focus lost after sending <TAB>!" << std::endl; + else if (xPrevFocus == xFocus) + { + std::cerr << "Focus didn't move after sending <TAB>! bailing out" << std::endl; + std::cerr << "Focused object(s):" << std::endl; + int iFocusedCount = 0; + // count and print out objects with focused state + AccessibilityTools::getAccessibleObjectForPredicate( + xRoot, + [&iFocusedCount](const uno::Reference<accessibility::XAccessibleContext>& xCtx) { + const auto states = (accessibility::AccessibleStateType::FOCUSED + | accessibility::AccessibleStateType::SHOWING); + if ((xCtx->getAccessibleStateSet() & states) == states) + { + std::cerr << " * " << AccessibilityTools::debugString(xCtx) << std::endl; + iFocusedCount++; + } + return false; // keep going + }); + std::cerr << "Total focused element(s): " << iFocusedCount << std::endl; + if (iFocusedCount > 1) + std::cerr << "WARNING: there are more than one focused object! This usually means " + "there is a BUG in the focus handling of that accessibility tree." + << std::endl; + break; + } + } + + std::cerr << "NOT FOUND" << std::endl; + return nullptr; +} + +bool test::AccessibleTestBase::tabTo( + const uno::Reference<accessibility::XAccessible>& xRoot, + const uno::Reference<accessibility::XAccessibleContext>& xChild, + const EventPosterHelperBase* pEventPosterHelper) +{ + AccessibleEventPosterHelper eventHelper; + if (!pEventPosterHelper) + { + eventHelper.setWindow(xRoot); + pEventPosterHelper = &eventHelper; + } + + std::cout << "Tabbing to " << AccessibilityTools::debugString(xChild) << "..." << std::endl; + for (int i = 0; i < 100; i++) + { + if (xChild->getAccessibleStateSet() & accessibility::AccessibleStateType::FOCUSED) + return true; + + std::cout << " no match, sending <TAB>" << std::endl; + pEventPosterHelper->postKeyEventAsync(0, awt::Key::TAB); + Scheduler::ProcessEventsToIdle(); + } + + std::cerr << "NOT FOUND" << std::endl; + return false; +} + +#if !defined(MACOSX) +/* Dialog handling + * + * For now this doesn't actually work under macos, so the API is not available there not to create + * confusion. The problem there is we don't get notified of new dialogs, so we can't manage them + * or interact with them. + */ + +test::AccessibleTestBase::Dialog::Dialog(uno::Reference<awt::XDialog2>& xDialog2, bool bAutoClose) + : mbAutoClose(bAutoClose) + , mxDialog2(xDialog2) +{ + CPPUNIT_ASSERT(xDialog2.is()); + + mxAccessible.set(xDialog2, uno::UNO_QUERY); + if (mxAccessible) + setWindow(mxAccessible); + else + { + std::cerr << "WARNING: AccessibleTestBase::Dialog() constructed with awt::XDialog2 '" + << xDialog2->getTitle() + << "' not implementing accessibility::XAccessible. Event delivery will not work." + << std::endl; + } +} + +test::AccessibleTestBase::Dialog::~Dialog() +{ + if (mbAutoClose) + close(); +} + +void test::AccessibleTestBase::Dialog::close(sal_Int32 result) +{ + if (mxDialog2) + { + mxDialog2->endDialog(result); + mxDialog2.clear(); + } +} + +std::shared_ptr<test::AccessibleTestBase::DialogWaiter> +test::AccessibleTestBase::awaitDialog(const std::u16string_view name, + std::function<void(Dialog&)> callback, bool bAutoClose) +{ + /* Helper class to wait on a dialog to pop up and to close, running user code between the + * two. This has to work both for "other window"-style dialogues (non-modal), as well as + * for modal dialogues using Dialog::Execute() (which runs a nested main loop, hence + * blocking our test flow execution. + * The approach here is to wait on the WindowActivate event for the dialog, and run the + * test code in there. Then, close the dialog if not already done, resuming normal flow to + * the caller. */ + class ListenerHelper : public DialogWaiter + { + DialogCancelMode miPreviousDialogCancelMode; + uno::Reference<awt::XExtendedToolkit> mxToolkit; + bool mbWaitingForDialog; + std::exception_ptr mpException; + std::u16string_view msName; + std::function<void(Dialog&)> mCallback; + bool mbAutoClose; + Timer maTimeoutTimer; + Idle maIdleHandler; + uno::Reference<awt::XTopWindowListener> mxTopWindowListener; + std::unique_ptr<Dialog> mxDialog; + + public: + virtual ~ListenerHelper() + { + Application::SetDialogCancelMode(miPreviousDialogCancelMode); + mxToolkit->removeTopWindowListener(mxTopWindowListener); + maTimeoutTimer.Stop(); + maIdleHandler.Stop(); + } + + ListenerHelper(const std::u16string_view& name, std::function<void(Dialog&)> callback, + bool bAutoClose) + : mbWaitingForDialog(true) + , msName(name) + , mCallback(std::move(callback)) + , mbAutoClose(bAutoClose) + , maTimeoutTimer("workaround timer if we don't catch WindowActivate") + , maIdleHandler("runs user callback in idle time") + { + mxTopWindowListener.set(new MyTopWindowListener(this)); + mxToolkit.set(Application::GetVCLToolkit(), uno::UNO_QUERY_THROW); + mxToolkit->addTopWindowListener(mxTopWindowListener); + + maTimeoutTimer.SetInvokeHandler(LINK(this, ListenerHelper, timeoutTimerHandler)); + maTimeoutTimer.SetTimeout(60000); + maTimeoutTimer.Start(); + + maIdleHandler.SetInvokeHandler(LINK(this, ListenerHelper, idleHandler)); + maIdleHandler.SetPriority(TaskPriority::DEFAULT_IDLE); + + miPreviousDialogCancelMode = Application::GetDialogCancelMode(); + Application::SetDialogCancelMode(DialogCancelMode::Off); + } + + private: + // mimic IMPL_LINK inline + static void LinkStubtimeoutTimerHandler(void* instance, Timer* timer) + { + static_cast<ListenerHelper*>(instance)->timeoutTimerHandler(timer); + } + + void timeoutTimerHandler(Timer*) + { + std::cerr << "timeout waiting for dialog '" << OUString(msName) << "' to show up" + << std::endl; + + assert(mbWaitingForDialog); + + // This is not very nice, but it should help fail earlier if we never catch the dialog + // yet we're in a sub-loop and waitEndDialog() didn't have a chance to run yet. + throw new css::uno::RuntimeException("Timeout waiting for dialog"); + } + + class MyTopWindowListener : public ::cppu::WeakImplHelper<awt::XTopWindowListener> + { + private: + ListenerHelper* mpHelper; + + public: + MyTopWindowListener(ListenerHelper* pHelper) + : mpHelper(pHelper) + { + assert(mpHelper); + } + + // XTopWindowListener + virtual void SAL_CALL windowOpened(const lang::EventObject&) override {} + virtual void SAL_CALL windowClosing(const lang::EventObject&) override {} + virtual void SAL_CALL windowClosed(const lang::EventObject&) override {} + virtual void SAL_CALL windowMinimized(const lang::EventObject&) override {} + virtual void SAL_CALL windowNormalized(const lang::EventObject&) override {} + virtual void SAL_CALL windowDeactivated(const lang::EventObject&) override {} + virtual void SAL_CALL windowActivated(const lang::EventObject& xEvent) override + { + assert(mpHelper->mbWaitingForDialog); + + if (!xEvent.Source) + return; + + uno::Reference<awt::XDialog2> xDialog(xEvent.Source, uno::UNO_QUERY); + if (!xDialog) + return; + + // remove ourselves, we don't want to run again + mpHelper->mxToolkit->removeTopWindowListener(this); + + mpHelper->mxDialog = std::make_unique<Dialog>(xDialog, true); + + mpHelper->maIdleHandler.Start(); + } + + // XEventListener + virtual void SAL_CALL disposing(const lang::EventObject&) override {} + }; + + // mimic IMPL_LINK inline + static void LinkStubidleHandler(void* instance, Timer* idle) + { + static_cast<ListenerHelper*>(instance)->idleHandler(idle); + } + + void idleHandler(Timer*) + { + mbWaitingForDialog = false; + + maTimeoutTimer.ClearInvokeHandler(); + maTimeoutTimer.Stop(); + + /* The popping up dialog ought to be the right one, or something's fishy and + * we're bound to failure (e.g. waiting on a dialog that either will never come, or + * that will not run after the current one -- deadlock style) */ + if (msName != mxDialog->getWindow()->GetText()) + { + mpException = std::make_exception_ptr(css::uno::RuntimeException( + "Unexpected dialog '" + mxDialog->getWindow()->GetText() + + "' opened instead of the expected '" + msName + "'")); + } + else + { + std::cout << "found dialog, calling user callback" << std::endl; + + // set the real requested auto close now we're just calling the user callback + mxDialog->setAutoClose(mbAutoClose); + + try + { + mCallback(*mxDialog); + } + catch (...) + { + mpException = std::current_exception(); + } + } + + mxDialog.reset(); + } + + public: + virtual bool waitEndDialog(sal_uInt64 nTimeoutMs) override + { + /* Usually this loop will actually never run at all because a previous + * Scheduler::ProcessEventsToIdle() would have triggered the dialog already, but we + * can't be sure of that or of delays, so be safe and wait with a timeout. */ + if (mbWaitingForDialog) + { + Timer aTimer("wait for dialog"); + aTimer.SetTimeout(nTimeoutMs); + aTimer.Start(); + do + { + Application::Yield(); + } while (mbWaitingForDialog && aTimer.IsActive()); + } + + if (mpException) + std::rethrow_exception(mpException); + + return !mbWaitingForDialog; + } + }; + + return std::make_shared<ListenerHelper>(name, callback, bAutoClose); +} +#endif //defined(MACOSX) + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/a11y/eventposter.cxx b/test/source/a11y/eventposter.cxx new file mode 100644 index 000000000000..39e178e22756 --- /dev/null +++ b/test/source/a11y/eventposter.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/a11y/eventposter.hxx> + +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <sfx2/lokhelper.hxx> +#include <test/a11y/AccessibilityTools.hxx> +#include <toolkit/awt/vclxwindow.hxx> + +void test::EventPosterHelper::postKeyEventAsync(int nType, int nCharCode, int nKeyCode) const +{ + SfxLokHelper::postKeyEventAsync(mxWindow, nType, nCharCode, nKeyCode); +} + +void test::EventPosterHelper::postExtTextEventAsync(int nType, const OUString& rText) const +{ + SfxLokHelper::postExtTextEventAsync(mxWindow, nType, rText); +} + +void test::AccessibleEventPosterHelper::setWindow( + css::uno::Reference<css::accessibility::XAccessible> xAcc) +{ + while (auto xParent = xAcc->getAccessibleContext()->getAccessibleParent()) + xAcc = xParent; + auto vclXWindow = dynamic_cast<VCLXWindow*>(xAcc.get()); + if (!vclXWindow) + { + std::cerr << "WARNING: AccessibleEventPosterHelper::setWindow() called on " + "unsupported object " + << AccessibilityTools::debugString(xAcc) << ". Event delivery will not work." + << std::endl; + } + mxWindow = vclXWindow ? vclXWindow->GetWindow() : nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/beans/xpropertyset.cxx b/test/source/beans/xpropertyset.cxx index 00c3378106d9..038b1e5733b6 100644 --- a/test/source/beans/xpropertyset.cxx +++ b/test/source/beans/xpropertyset.cxx @@ -17,12 +17,14 @@ #include <com/sun/star/beans/XVetoableChangeListener.hpp> #include <com/sun/star/lang/EventObject.hpp> #include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/XComplexColor.hpp> #include <com/sun/star/uno/Any.hxx> #include <com/sun/star/uno/Reference.hxx> #include <com/sun/star/uno/Type.h> #include <cppuhelper/implbase.hxx> +#include <docmodel/uno/UnoComplexColor.hxx> #include <rtl/ref.hxx> #include <cppunit/TestAssert.h> @@ -242,6 +244,13 @@ bool XPropertySet::isPropertyValueChangeable(const OUString& rName) aDT.Year += 1; xPropSet->setPropertyValue(rName, Any(aDT)); } + else if (type == cppu::UnoType<uno::Reference<util::XComplexColor>>::get()) + { + auto xComplexColor = any.get<uno::Reference<util::XComplexColor>>(); + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + xPropSet->setPropertyValue(rName, + Any(model::color::createXComplexColor(aComplexColor))); + } else { std::cout << "Unknown type:\n" diff --git a/test/source/bootstrapfixture.cxx b/test/source/bootstrapfixture.cxx index d9048b39465d..f1db0bf66637 100644 --- a/test/source/bootstrapfixture.cxx +++ b/test/source/bootstrapfixture.cxx @@ -187,7 +187,7 @@ void test::BootstrapFixture::validate(const OUString& rPath, test::ValidationFor + m_directories.getPathFromSrc(u"/schema/mathml2/mathml2.xsd"); } - utl::TempFile aOutput; + utl::TempFileNamed aOutput; aOutput.EnableKillingFile(); OUString aOutputFile = aOutput.GetFileName(); OUString aCommand = aValidator + " " + rPath + " > " + aOutputFile + " 2>&1"; @@ -274,7 +274,7 @@ std::pair<double, double> test::BootstrapFixture::getDPIScaling() sal_uInt16 test::BootstrapFixture::getDefaultDeviceBitCount() { ScopedVclPtr<VirtualDevice> device - = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); + = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA); return device->GetBitCount(); } diff --git a/test/source/calc_unoapi_test.cxx b/test/source/calc_unoapi_test.cxx deleted file mode 100644 index 8d7e218d9cda..000000000000 --- a/test/source/calc_unoapi_test.cxx +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <test/calc_unoapi_test.hxx> - -using namespace css; -using namespace css::uno; - -CalcUnoApiTest::CalcUnoApiTest(const OUString& path) - : UnoApiTest(path) -{ -} - -void CalcUnoApiTest::setUp() -{ - UnoApiTest::setUp(); - - // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure, - // which is a private symbol to us, gets called - m_xCalcComponent = - getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument"); - CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is()); -} - -void CalcUnoApiTest::tearDown() -{ - uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose(); - UnoApiTest::tearDown(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/source/helper/transferable.cxx b/test/source/helper/transferable.cxx index 201b3c50e442..e264dba1abf6 100644 --- a/test/source/helper/transferable.cxx +++ b/test/source/helper/transferable.cxx @@ -28,13 +28,13 @@ OString OOO_DLLPUBLIC_TEST getTextSelection( { if (o3tl::getToken(mimeType, 0, ';', nIndex) == "charset=utf-8") { - mimeType = "text/plain;charset=utf-16"; + mimeType = "text/plain;charset=utf-16"_ostr; bConvert = true; } } datatransfer::DataFlavor aFlavor; - aFlavor.MimeType = OUString::fromUtf8(mimeType.getStr()); + aFlavor.MimeType = OUString::fromUtf8(mimeType); if (mimeType == "text/plain;charset=utf-16") aFlavor.DataType = cppu::UnoType<OUString>::get(); else diff --git a/test/source/htmltesttools.cxx b/test/source/htmltesttools.cxx index d61f07bd3d1b..dedda5f98225 100644 --- a/test/source/htmltesttools.cxx +++ b/test/source/htmltesttools.cxx @@ -12,7 +12,7 @@ #include <memory> -htmlDocUniquePtr HtmlTestTools::parseHtml(utl::TempFile const & aTempFile) +htmlDocUniquePtr HtmlTestTools::parseHtml(utl::TempFileNamed const & aTempFile) { SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ); htmlDocUniquePtr doc = parseHtmlStream(&aFileStream); diff --git a/test/source/lokcallback.cxx b/test/source/lokcallback.cxx index c938e1e699a8..0914ea4db73c 100644 --- a/test/source/lokcallback.cxx +++ b/test/source/lokcallback.cxx @@ -14,6 +14,10 @@ #include <tools/gen.hxx> #include <comphelper/lok.hxx> #include <sfx2/viewsh.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/sidebar/SidebarDockingWindow.hxx> TestLokCallbackWrapper::TestLokCallbackWrapper(LibreOfficeKitCallback callback, void* data) : Idle("TestLokCallbackWrapper flush timer") @@ -47,19 +51,20 @@ inline void TestLokCallbackWrapper::callCallback(int nType, const char* pPayload startTimer(); } -void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType, const char* pPayload) +void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType, const rtl::OString& pPayload) { - callCallback(nType, pPayload, NO_VIEWID); + callCallback(nType, pPayload.getStr(), NO_VIEWID); } -void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType, const char* pPayload, +void TestLokCallbackWrapper::libreOfficeKitViewCallbackWithViewId(int nType, + const rtl::OString& pPayload, int nViewId) { - callCallback(nType, pPayload, nViewId); + callCallback(nType, pPayload.getStr(), nViewId); } void TestLokCallbackWrapper::libreOfficeKitViewInvalidateTilesCallback( - const tools::Rectangle* pRect, int nPart) + const tools::Rectangle* pRect, int nPart, int nMode) { OStringBuffer buf(64); if (pRect) @@ -68,8 +73,8 @@ void TestLokCallbackWrapper::libreOfficeKitViewInvalidateTilesCallback( buf.append("EMPTY"); if (comphelper::LibreOfficeKit::isPartInInvalidation()) { - buf.append(", "); - buf.append(static_cast<sal_Int32>(nPart)); + buf.append(", " + OString::number(static_cast<sal_Int32>(nPart)) + ", " + + OString::number(static_cast<sal_Int32>(nMode))); } callCallback(LOK_CALLBACK_INVALIDATE_TILES, buf.makeStringAndClear().getStr(), NO_VIEWID); } @@ -106,6 +111,12 @@ void TestLokCallbackWrapper::libreOfficeKitViewUpdatedCallbackPerViewId(int nTyp startTimer(); } +void TestLokCallbackWrapper::libreOfficeKitViewAddPendingInvalidateTiles() +{ + // Invoke() will call flushPendingLOKInvalidateTiles(). + startTimer(); +} + void TestLokCallbackWrapper::discardUpdatedTypes(int nType, int nViewId) { // If a callback is called directly with an event, drop the updated flag for it, since @@ -139,8 +150,8 @@ void TestLokCallbackWrapper::flushLOKData() return; // Ask for payloads of all the pending types that need updating, and call the generic callback with that data. assert(m_viewId >= 0); - SfxViewShell* viewShell = SfxViewShell::GetFirst(false, [this](const SfxViewShell* shell) { - return shell->GetViewShellId().get() == m_viewId; + SfxViewShell* viewShell = SfxViewShell::GetFirst(false, [this](const SfxViewShell& shell) { + return shell.GetViewShellId().get() == m_viewId; }); assert(viewShell != nullptr); // First move data to local structures, so that callbacks don't possibly modify it. @@ -153,17 +164,17 @@ void TestLokCallbackWrapper::flushLOKData() { std::optional<OString> payload = viewShell->getLOKPayload(type, m_viewId); if (payload) - libreOfficeKitViewCallback(type, payload->getStr()); + libreOfficeKitViewCallback(type, *payload); } for (const PerViewIdData& data : updatedTypesPerViewId) { - viewShell = SfxViewShell::GetFirst(false, [data](const SfxViewShell* shell) { - return shell->GetViewShellId().get() == data.sourceViewId; + viewShell = SfxViewShell::GetFirst(false, [data](const SfxViewShell& shell) { + return shell.GetViewShellId().get() == data.sourceViewId; }); assert(viewShell != nullptr); std::optional<OString> payload = viewShell->getLOKPayload(data.type, data.viewId); if (payload) - libreOfficeKitViewCallbackWithViewId(data.type, payload->getStr(), data.viewId); + libreOfficeKitViewCallbackWithViewId(data.type, *payload, data.viewId); } } @@ -178,4 +189,23 @@ void TestLokCallbackWrapper::Invoke() flushLOKData(); } +SfxChildWindow* TestLokCallbackWrapper::InitializeSidebar() +{ + // in init.cxx we do setupSidebar which creates the controller, do it here + + SfxViewShell* pViewShell = SfxViewShell::Current(); + assert(pViewShell); + + SfxViewFrame& rViewFrame = pViewShell->GetViewFrame(); + SfxChildWindow* pSideBar = rViewFrame.GetChildWindow(SID_SIDEBAR); + assert(pSideBar); + + auto pDockingWin = dynamic_cast<sfx2::sidebar::SidebarDockingWindow*>(pSideBar->GetWindow()); + assert(pDockingWin); + + pDockingWin->GetOrCreateSidebarController(); // just to create the controller + + return pSideBar; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/source/screenshot_test.cxx b/test/source/screenshot_test.cxx index fdd172f29a68..9b85338303a0 100644 --- a/test/source/screenshot_test.cxx +++ b/test/source/screenshot_test.cxx @@ -24,15 +24,23 @@ namespace { - void splitHelpId( const OString& rHelpId, OUString& rDirname, OUString &rBasename ) + void splitHelpId( std::u16string_view rHelpId, std::u16string_view& rDirname, std::u16string_view& rBasename ) { - sal_Int32 nIndex = rHelpId.lastIndexOf( '/' ); + size_t nIndex = rHelpId.rfind( '/' ); - if( nIndex > 0 ) - rDirname = OStringToOUString( rHelpId.subView( 0, nIndex ), RTL_TEXTENCODING_UTF8 ); + if( nIndex != 0 && nIndex != std::u16string_view::npos) + rDirname = rHelpId.substr( 0, nIndex ); - if( rHelpId.getLength() > nIndex+1 ) - rBasename= OStringToOUString( rHelpId.subView( nIndex+1 ), RTL_TEXTENCODING_UTF8 ); + if (nIndex == std::u16string_view::npos) + { + if( rHelpId.size() > 0 ) + rBasename = rHelpId; + } + else + { + if( rHelpId.size() > nIndex+1 ) + rBasename = rHelpId.substr( nIndex+1 ); + } } } @@ -40,7 +48,7 @@ using namespace css; using namespace css::uno; /// the target directory for screenshots -constexpr OUStringLiteral g_aScreenshotDirectory(u"screenshots"); +constexpr OUString g_aScreenshotDirectory(u"screenshots"_ustr); ScreenshotTest::ScreenshotTest() : maParent(nullptr, "vcl/ui/screenshotparent.ui", "ScreenShot") @@ -71,11 +79,11 @@ void ScreenshotTest::setUp() } } -void ScreenshotTest::implSaveScreenshot(const BitmapEx& rScreenshot, const OString& rScreenshotId) +void ScreenshotTest::implSaveScreenshot(const BitmapEx& rScreenshot, std::u16string_view rScreenshotId) { - OUString aDirname, aBasename; - splitHelpId(rScreenshotId, aDirname, aBasename); - aDirname = g_aScreenshotDirectory + "/" + aDirname + + std::u16string_view aSplitDirname, aBasename; + splitHelpId(rScreenshotId, aSplitDirname, aBasename); + OUString aDirname = g_aScreenshotDirectory + "/" + aSplitDirname + ( (maCurrentLanguage == "en-US") ? OUString() : "/" + maCurrentLanguage ); auto const dirUrl = m_directories.getURLFromWorkdir(aDirname); @@ -102,7 +110,7 @@ void ScreenshotTest::saveScreenshot(VclAbstractDialog const & rDialog) if (!aScreenshot.IsEmpty()) { - const OString aScreenshotId = rDialog.GetScreenshotId(); + const OUString aScreenshotId = rDialog.GetScreenshotId(); if (!aScreenshotId.isEmpty()) { @@ -118,7 +126,7 @@ void ScreenshotTest::saveScreenshot(weld::Window& rDialog) if (!aScreenshot.IsEmpty()) { - const OString aScreenshotId = rDialog.get_help_id(); + const OUString aScreenshotId = rDialog.get_help_id(); assert(!aScreenshotId.isEmpty()); implSaveScreenshot(aScreenshot, aScreenshotId); } @@ -138,7 +146,7 @@ VclPtr<VclAbstractDialog> ScreenshotTest::createDialogByName(const OString& rNam void ScreenshotTest::dumpDialogToPath(VclAbstractDialog& rDialog) { - const std::vector<OString> aPageDescriptions(rDialog.getAllPageUIXMLDescriptions()); + const std::vector<OUString> aPageDescriptions(rDialog.getAllPageUIXMLDescriptions()); if (!aPageDescriptions.empty()) { @@ -171,14 +179,14 @@ void ScreenshotTest::dumpDialogToPath(weld::Builder& rBuilder) { for (int i = 0; i < nPages; ++i) { - OString sIdent(xTabCtrl->get_page_ident(i)); + OUString sIdent(xTabCtrl->get_page_ident(i)); xTabCtrl->set_current_page(sIdent); if (xTabCtrl->get_current_page_ident() == sIdent) { - OString sOrigHelpId(xDialog->get_help_id()); + OUString sOrigHelpId(xDialog->get_help_id()); // skip empty pages weld::Container* pPage = xTabCtrl->get_page(sIdent); - OString sBuildableName(pPage->get_buildable_name()); + OUString sBuildableName(pPage->get_buildable_name()); if (!sBuildableName.isEmpty() && !sBuildableName.startsWith("__")) xDialog->set_help_id(pPage->get_help_id()); saveScreenshot(*xDialog); @@ -247,7 +255,7 @@ void ScreenshotTest::processDialogBatchFile(std::u16string_view rFile) const OUString aURL(aDirectories.getURLFromSrc(rFile)); SvFileStream aStream(aURL, StreamMode::READ); OString aNextUIFile; - const OString aComment("#"); + static constexpr OStringLiteral aComment("#"); while (aStream.ReadLine(aNextUIFile)) { diff --git a/test/source/sheet/cellarealink.cxx b/test/source/sheet/cellarealink.cxx index bfaf4c3fe99b..93319542cb9b 100644 --- a/test/source/sheet/cellarealink.cxx +++ b/test/source/sheet/cellarealink.cxx @@ -22,7 +22,7 @@ void CellAreaLink::testUrl() { uno::Reference<beans::XPropertySet> xCellAreaLink(init(), uno::UNO_QUERY_THROW); - static const OUStringLiteral propName(u"Url"); + static constexpr OUString propName(u"Url"_ustr); OUString aUrl; CPPUNIT_ASSERT(xCellAreaLink->getPropertyValue(propName) >>= aUrl); @@ -39,7 +39,7 @@ void CellAreaLink::testFilter() { uno::Reference<beans::XPropertySet> xCellAreaLink(init(), uno::UNO_QUERY_THROW); - static const OUStringLiteral propName(u"Filter"); + static constexpr OUString propName(u"Filter"_ustr); OUString aFilter; CPPUNIT_ASSERT(xCellAreaLink->getPropertyValue(propName) >>= aFilter); @@ -56,7 +56,7 @@ void CellAreaLink::testFilterOptions() { uno::Reference<beans::XPropertySet> xCellAreaLink(init(), uno::UNO_QUERY_THROW); - static const OUStringLiteral propName(u"FilterOptions"); + static constexpr OUString propName(u"FilterOptions"_ustr); OUString aFilterOptions; CPPUNIT_ASSERT(xCellAreaLink->getPropertyValue(propName) >>= aFilterOptions); @@ -75,7 +75,7 @@ void CellAreaLink::testRefreshDelay() { uno::Reference<beans::XPropertySet> xCellAreaLink(init(), uno::UNO_QUERY_THROW); - static const OUStringLiteral propName(u"RefreshDelay"); + static constexpr OUString propName(u"RefreshDelay"_ustr); sal_Int32 aRefreshDelay = 0; CPPUNIT_ASSERT(xCellAreaLink->getPropertyValue(propName) >>= aRefreshDelay); @@ -94,7 +94,7 @@ void CellAreaLink::testRefreshPeriod() { uno::Reference<beans::XPropertySet> xCellAreaLink(init(), uno::UNO_QUERY_THROW); - static const OUStringLiteral propName(u"RefreshPeriod"); + static constexpr OUString propName(u"RefreshPeriod"_ustr); sal_Int32 aRefreshPeriod = 0; CPPUNIT_ASSERT(xCellAreaLink->getPropertyValue(propName) >>= aRefreshPeriod); diff --git a/test/source/sheet/databaserange.cxx b/test/source/sheet/databaserange.cxx index d87e3723ce3b..5bae62ce434e 100644 --- a/test/source/sheet/databaserange.cxx +++ b/test/source/sheet/databaserange.cxx @@ -26,7 +26,7 @@ void DatabaseRange::testMoveCells() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"MoveCells"); + static constexpr OUString propName(u"MoveCells"_ustr); bool bMoveCells = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bMoveCells); @@ -43,7 +43,7 @@ void DatabaseRange::testKeepFormats() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"KeepFormats"); + static constexpr OUString propName(u"KeepFormats"_ustr); bool bKeepFormats = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bKeepFormats); @@ -60,7 +60,7 @@ void DatabaseRange::testStripData() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"StripData"); + static constexpr OUString propName(u"StripData"_ustr); bool bStripData = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bStripData); @@ -77,7 +77,7 @@ void DatabaseRange::testAutoFilter() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"AutoFilter"); + static constexpr OUString propName(u"AutoFilter"_ustr); bool bAutoFilter = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bAutoFilter); @@ -94,7 +94,7 @@ void DatabaseRange::testUseFilterCriteriaSource() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"UseFilterCriteriaSource"); + static constexpr OUString propName(u"UseFilterCriteriaSource"_ustr); bool bUseFilterCriteriaSource = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bUseFilterCriteriaSource); @@ -113,7 +113,7 @@ void DatabaseRange::testFilterCriteriaSource() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"FilterCriteriaSource"); + static constexpr OUString propName(u"FilterCriteriaSource"_ustr); table::CellRangeAddress cellRangeAddress; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= cellRangeAddress); @@ -132,7 +132,7 @@ void DatabaseRange::testRefreshPeriod() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"RefreshPeriod"); + static constexpr OUString propName(u"RefreshPeriod"_ustr); sal_Int32 aRefreshPeriod = 1; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= aRefreshPeriod); @@ -151,7 +151,7 @@ void DatabaseRange::testFromSelection() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"FromSelection"); + static constexpr OUString propName(u"FromSelection"_ustr); bool bFromSelection = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bFromSelection); @@ -168,7 +168,7 @@ void DatabaseRange::testTokenIndex() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"TokenIndex"); + static constexpr OUString propName(u"TokenIndex"_ustr); sal_Int32 aTokenIndex = 0; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= aTokenIndex); @@ -185,7 +185,7 @@ void DatabaseRange::testTotalsRow() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"TotalsRow"); + static constexpr OUString propName(u"TotalsRow"_ustr); bool bTotalsRow = true; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bTotalsRow); @@ -202,7 +202,7 @@ void DatabaseRange::testContainsHeader() { uno::Reference<beans::XPropertySet> xDatabaseRange(init("DataArea"), UNO_QUERY_THROW); - static const OUStringLiteral propName(u"ContainsHeader"); + static constexpr OUString propName(u"ContainsHeader"_ustr); bool bContainsHeader = false; CPPUNIT_ASSERT(xDatabaseRange->getPropertyValue(propName) >>= bContainsHeader); diff --git a/test/source/sheet/datapilotitem.cxx b/test/source/sheet/datapilotitem.cxx index bfbe2110afec..7433097035d7 100644 --- a/test/source/sheet/datapilotitem.cxx +++ b/test/source/sheet/datapilotitem.cxx @@ -24,7 +24,7 @@ void DataPilotItem::testProperties() { uno::Reference<beans::XPropertySet> xItem(init(), UNO_QUERY_THROW); - static const OUStringLiteral propNameIS(u"IsHidden"); + static constexpr OUString propNameIS(u"IsHidden"_ustr); bool bIsHidden = true; CPPUNIT_ASSERT(xItem->getPropertyValue(propNameIS) >>= bIsHidden); @@ -36,7 +36,7 @@ void DataPilotItem::testProperties() CPPUNIT_ASSERT(xItem->getPropertyValue(propNameIS) >>= bIsHidden); CPPUNIT_ASSERT_MESSAGE("Value of IsHidden wasn't changed", !bIsHidden); - static const OUStringLiteral propNameSD(u"ShowDetail"); + static constexpr OUString propNameSD(u"ShowDetail"_ustr); bool bShowDetail = false; CPPUNIT_ASSERT(xItem->getPropertyValue(propNameSD) >>= bShowDetail); diff --git a/test/source/sheet/globalsheetsettings.cxx b/test/source/sheet/globalsheetsettings.cxx index 3e796fc58efe..40d01fe45d42 100644 --- a/test/source/sheet/globalsheetsettings.cxx +++ b/test/source/sheet/globalsheetsettings.cxx @@ -80,7 +80,6 @@ void GlobalSheetSettings::testGlobalSheetSettingsProperties() DoCheck("ExpandReferences", false, true, node, "ExpandReference"); DoCheck("MarkHeader", true, false, node, "HighlightSelection"); DoCheck("UseTabCol", false, true, node, "UseTabCol"); - DoCheck("UsePrinterMetrics", false, true, node, "UsePrinterMetrics"); DoCheck("ReplaceCellsWarning", true, false, node, "ReplaceCellsWarning"); node = "/org.openoffice.Office.Calc/Layout/Other/MeasureUnit"; diff --git a/test/source/sheet/xarrayformularange.cxx b/test/source/sheet/xarrayformularange.cxx index f7f30a1af73e..fb924a78bf2e 100644 --- a/test/source/sheet/xarrayformularange.cxx +++ b/test/source/sheet/xarrayformularange.cxx @@ -27,7 +27,7 @@ void XArrayFormulaRange::testGetSetArrayFormula() { uno::Reference<sheet::XArrayFormulaRange> xAFR(init(), UNO_QUERY_THROW); - static const OUStringLiteral sFormula(u"=1 + 2 * 5"); + static constexpr OUString sFormula(u"=1 + 2 * 5"_ustr); xAFR->setArrayFormula(sFormula); uno::Reference<sheet::XCellRangeAddressable> xCRA(xAFR, UNO_QUERY_THROW); diff --git a/test/source/sheet/xdatabaserange.cxx b/test/source/sheet/xdatabaserange.cxx index f1133ac00f5d..9f0828a30513 100644 --- a/test/source/sheet/xdatabaserange.cxx +++ b/test/source/sheet/xdatabaserange.cxx @@ -125,8 +125,7 @@ void XDatabaseRange::testGetFilterDescriptor() void XDatabaseRange::testGetImportDescriptor() { uno::Reference<sheet::XDatabaseRange> xDBRange(init("ImportDescriptor"), UNO_QUERY_THROW); - uno::Sequence<beans::PropertyValue> xImportDescr = xDBRange->getImportDescriptor(); - (void)xImportDescr; + (void)xDBRange->getImportDescriptor(); } void XDatabaseRange::testRefresh() diff --git a/test/source/sheet/xdatapilotdescriptor.cxx b/test/source/sheet/xdatapilotdescriptor.cxx index a9cbcf5b125c..20392ff8ae4b 100644 --- a/test/source/sheet/xdatapilotdescriptor.cxx +++ b/test/source/sheet/xdatapilotdescriptor.cxx @@ -16,7 +16,6 @@ #include <cppunit/TestAssert.h> -#include <o3tl/safeint.hxx> #include <rtl/ustring.hxx> using namespace css; @@ -175,10 +174,10 @@ void XDataPilotDescriptor::testGetHiddenFields() checkName( xIndex, 3 ); } -void XDataPilotDescriptor::checkName( uno::Reference< container::XIndexAccess > const & xIndex, sal_Int32 nIndex ) +void XDataPilotDescriptor::checkName( uno::Reference< container::XIndexAccess > const & xIndex, std::size_t nIndex ) { CPPUNIT_ASSERT(xIndex.is()); - CPPUNIT_ASSERT(maFieldNames.size() >= o3tl::make_unsigned(nIndex)); + CPPUNIT_ASSERT(maFieldNames.size() >= nIndex); for (sal_Int32 i = 0; i < xIndex->getCount(); ++i) { diff --git a/test/source/sheet/xfunctiondescriptions.cxx b/test/source/sheet/xfunctiondescriptions.cxx index 1b4ef645e2e7..4bed2b417712 100644 --- a/test/source/sheet/xfunctiondescriptions.cxx +++ b/test/source/sheet/xfunctiondescriptions.cxx @@ -41,7 +41,7 @@ void XFunctionDescriptions::testGetById() OUString aName1; uno::Sequence<beans::PropertyValue> aProps1; CPPUNIT_ASSERT(xFD->getByIndex(nNumber) >>= aProps1); - for (const auto& aProp : std::as_const(aProps1)) + for (const auto& aProp : aProps1) { if (aProp.Name == "Id") aId1 = aProp.Value.get<sal_Int32>(); diff --git a/test/source/sheet/xsheetannotationanchor.cxx b/test/source/sheet/xsheetannotationanchor.cxx index 9fbf4b00d2a0..8c8467d7885a 100644 --- a/test/source/sheet/xsheetannotationanchor.cxx +++ b/test/source/sheet/xsheetannotationanchor.cxx @@ -28,7 +28,7 @@ void XSheetAnnotationAnchor::testGetAnnotation() uno::Reference<sheet::XSheetAnnotation> xAnnotation(xAnchor->getAnnotation(), UNO_SET_THROW); CPPUNIT_ASSERT_MESSAGE("Unable to get XSheetAnnotation", xAnnotation.is()); - CPPUNIT_ASSERT_MESSAGE("Unable to check: getAuthor()", xAnnotation->getAuthor().isEmpty()); + CPPUNIT_ASSERT_MESSAGE("Unable to check: getAuthor()", !xAnnotation->getAuthor().isEmpty()); CPPUNIT_ASSERT_MESSAGE("Unable to check: getDate()", !xAnnotation->getDate().isEmpty()); CPPUNIT_ASSERT_MESSAGE("Unable to check: getIsVisible()", !xAnnotation->getIsVisible()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to check: getPosition()", table::CellAddress(0, 2, 3), diff --git a/test/source/sheet/xsheetoutline.cxx b/test/source/sheet/xsheetoutline.cxx index d60820021b29..ff3e519d301d 100644 --- a/test/source/sheet/xsheetoutline.cxx +++ b/test/source/sheet/xsheetoutline.cxx @@ -28,13 +28,13 @@ using namespace css::uno; namespace apitest { -constexpr OUStringLiteral colLevel1 = u"OutlineSheet.A1:Z1"; -constexpr OUStringLiteral colLevel2 = u"OutlineSheet.C1:W1"; -constexpr OUStringLiteral colLevel3 = u"OutlineSheet.E1:U1"; +constexpr OUString colLevel1 = u"OutlineSheet.A1:Z1"_ustr; +constexpr OUString colLevel2 = u"OutlineSheet.C1:W1"_ustr; +constexpr OUString colLevel3 = u"OutlineSheet.E1:U1"_ustr; constexpr OUStringLiteral colLevel4 = u"OutlineSheet.G1:S1"; -constexpr OUStringLiteral rowLevel1 = u"OutlineSheet.A1:A30"; -constexpr OUStringLiteral rowLevel2 = u"OutlineSheet.A3:A27"; +constexpr OUString rowLevel1 = u"OutlineSheet.A1:A30"_ustr; +constexpr OUString rowLevel2 = u"OutlineSheet.A3:A27"_ustr; static OUString getVisibleAddress( uno::Reference<sheet::XSpreadsheet> const& xSheet, @@ -102,14 +102,14 @@ void XSheetOutline::testShowDetail() aSheetOutline->showDetail(aLevelRangeAddress); CPPUNIT_ASSERT_EQUAL_MESSAGE("Row level 2 still hidden", - getVisibleAddress(aSheet, rowLevel2), OUString(rowLevel2)); + rowLevel2, getVisibleAddress(aSheet, rowLevel2)); // Column Level 2 aLevelRangeAddress = getAddressFromRangeString(aSheet, colLevel2); aSheetOutline->showDetail(aLevelRangeAddress); CPPUNIT_ASSERT_EQUAL_MESSAGE("Column level 2 still hidden", - getVisibleAddress(aSheet, colLevel2), OUString(colLevel2)); + colLevel2, getVisibleAddress(aSheet, colLevel2)); } @@ -254,8 +254,8 @@ void XSheetOutline::testClearOutline() aLevelRangeAddress = getAddressFromRangeString(aSheet, rowLevel1); aSheetOutline->hideDetail(aLevelRangeAddress); - CPPUNIT_ASSERT_EQUAL_MESSAGE("testClearOutline Columns are hidden after clear", getVisibleAddress(aSheet, colLevel1), OUString(colLevel1)); - CPPUNIT_ASSERT_EQUAL_MESSAGE("testClearOutline Rows are hidden after clear", getVisibleAddress(aSheet, rowLevel1), OUString(rowLevel1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("testClearOutline Columns are hidden after clear", colLevel1, getVisibleAddress(aSheet, colLevel1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("testClearOutline Rows are hidden after clear", rowLevel1, getVisibleAddress(aSheet, rowLevel1)); } diff --git a/test/source/sheet/xspreadsheets2.cxx b/test/source/sheet/xspreadsheets2.cxx index f88de2a43055..dd0fbbace5ac 100644 --- a/test/source/sheet/xspreadsheets2.cxx +++ b/test/source/sheet/xspreadsheets2.cxx @@ -26,15 +26,16 @@ #include <rtl/ustring.hxx> #include <cppunit/TestAssert.h> +#include <o3tl/string_view.hxx> using namespace css; using namespace css::uno; namespace apitest { -constexpr OUStringLiteral gaSrcSheetName(u"SheetToCopy"); +constexpr OUString gaSrcSheetName(u"SheetToCopy"_ustr); constexpr OUStringLiteral gaSrcFileName(u"rangenamessrc.ods"); -constexpr OUStringLiteral gaDestFileBase(u"ScNamedRangeObj.ods"); +constexpr OUString gaDestFileBase(u"ScNamedRangeObj.ods"_ustr); static sal_Int32 nInsertedSheets(0); @@ -242,7 +243,7 @@ void XSpreadsheets2::testImportCellStyle() //new style created in dest uno::Reference< beans::XPropertySet > xSrcCellPropSet (xSrcCell, UNO_QUERY_THROW); - static const OUStringLiteral aCellProperty(u"CellStyle"); + static constexpr OUString aCellProperty(u"CellStyle"_ustr); OUString aSrcStyleName; CPPUNIT_ASSERT(xSrcCellPropSet->getPropertyValue(aCellProperty) >>= aSrcStyleName); @@ -319,10 +320,7 @@ void XSpreadsheets2::testLastAfterInsertCopy() uno::Reference< sheet::XSpreadsheetDocument> XSpreadsheets2::getDoc(const OUString& aFileBase) { - OUString aFileURL; - createFileURL(aFileBase, aFileURL); - - uno::Reference< lang::XComponent > xComp = loadFromDesktop(aFileURL); + uno::Reference< lang::XComponent > xComp = loadFromDesktop(aFileBase); uno::Reference< sheet::XSpreadsheetDocument > xDoc(xComp, UNO_QUERY_THROW); return xDoc; } @@ -353,12 +351,14 @@ void XSpreadsheets2::importSheetToCopy() xDestSheet.set( xDestSheetIndexAccess->getByIndex(nDestPosEffective), UNO_QUERY_THROW); } -bool XSpreadsheets2::isExternalReference(const OUString& aDestContent, std::u16string_view aSrcContent ) +bool XSpreadsheets2::isExternalReference(std::u16string_view aDestContent, std::u16string_view aSrcContent ) { - CPPUNIT_ASSERT(aDestContent.startsWith("'file://")); + CPPUNIT_ASSERT(o3tl::starts_with(aDestContent, u"'file://")); - return (aDestContent.endsWithIgnoreAsciiCase(aSrcContent) // same cell address - && aDestContent.indexOf(gaSrcFileName)>0); // contains source file name + if (!o3tl::endsWithIgnoreAsciiCase(aDestContent, aSrcContent)) // same cell address + return false; + size_t nPos = aDestContent.find(gaSrcFileName); + return nPos != std::u16string_view::npos && nPos > 0; // contains source file name } } diff --git a/test/source/sheet/xsubtotalfield.cxx b/test/source/sheet/xsubtotalfield.cxx index dd022af10f14..45588d193c81 100644 --- a/test/source/sheet/xsubtotalfield.cxx +++ b/test/source/sheet/xsubtotalfield.cxx @@ -21,29 +21,18 @@ using namespace com::sun::star; using namespace com::sun::star::uno; -CPPUNIT_NS_BEGIN - -template<> struct assertion_traits<uno::Sequence< sheet::SubTotalColumn > > +template<> inline std::string +CPPUNIT_NS::assertion_traits<uno::Sequence< sheet::SubTotalColumn > >::toString( + const uno::Sequence< sheet::SubTotalColumn >& x) { - static bool equal(const uno::Sequence< sheet::SubTotalColumn >& x, - const uno::Sequence< sheet::SubTotalColumn >& y) - { - return x == y; - } - - static std::string toString(const uno::Sequence< sheet::SubTotalColumn >& x) - { - OStringStream ost; - ost << "Sequence: Length: " << x.getLength() << "\n"; - for (const auto& rElement : x) - ost << "Column: " << rElement.Column << " Function:\n"; - // FIXME: Find a way to print Function - //ost << "Column: " << element->Column << " Function: " << element->Function << "\n"; - return ost.str(); - } -}; - -CPPUNIT_NS_END + OStringStream ost; + ost << "Sequence: Length: " << x.getLength() << "\n"; + for (const auto& rElement : x) + ost << "Column: " << rElement.Column << " Function:\n"; + // FIXME: Find a way to print Function + //ost << "Column: " << element->Column << " Function: " << element->Function << "\n"; + return ost.str(); +} namespace apitest { diff --git a/test/source/table/xtablerows.cxx b/test/source/table/xtablerows.cxx index c241b2bb88f6..f44a6fcbce46 100644 --- a/test/source/table/xtablerows.cxx +++ b/test/source/table/xtablerows.cxx @@ -32,7 +32,7 @@ void XTableRows::testInsertByIndex() xTableRows->removeByIndex(0, 1); xTableRows->insertByIndex(0, 1); - CPPUNIT_ASSERT_DOUBLES_EQUAL(xCellRange->getCellByPosition(0, 1)->getValue(), 15.0, 0.1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(15.0, xCellRange->getCellByPosition(0, 1)->getValue(), 0.1); CPPUNIT_ASSERT_THROW(xTableRows->insertByIndex(-1, 1), uno::RuntimeException); } @@ -45,7 +45,7 @@ void XTableRows::testRemoveByIndex() uno::Reference<table::XTableRows> xTableRows(init(), uno::UNO_QUERY_THROW); xTableRows->removeByIndex(0, 1); - CPPUNIT_ASSERT_DOUBLES_EQUAL(xCellRange->getCellByPosition(0, 0)->getValue(), 15.0, 0.1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(15.0, xCellRange->getCellByPosition(0, 0)->getValue(), 0.1); CPPUNIT_ASSERT_THROW(xTableRows->removeByIndex(-1, 1), uno::RuntimeException); } diff --git a/test/source/text/baseindex.cxx b/test/source/text/baseindex.cxx index 56443dd1caab..172cabb57981 100644 --- a/test/source/text/baseindex.cxx +++ b/test/source/text/baseindex.cxx @@ -100,7 +100,7 @@ void BaseIndex::testBaseIndexProperties() // BackGraphicURL is "set-only" attribute CPPUNIT_ASSERT_MESSAGE("Expected RuntimeException wasn't thrown", bOK); - utl::TempFile aTempFile; + utl::TempFileNamed aTempFile; aTempFile.EnableKillingFile(); writerFileWithBitmap(aTempFile.GetURL()); diff --git a/test/source/text/baseindexmark.cxx b/test/source/text/baseindexmark.cxx new file mode 100644 index 000000000000..755b55856cf8 --- /dev/null +++ b/test/source/text/baseindexmark.cxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/cppunitasserthelper.hxx> +#include <test/text/baseindexmark.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace com::sun::star; +using namespace com::sun::star::uno; + +namespace apitest +{ +void BaseIndexMark::testBaseIndexMarkProperties() +{ + Reference<beans::XPropertySet> xBaseIndexMark(init(), UNO_QUERY_THROW); + OUString propName; + uno::Any aNewValue; + + propName = "AlternativeText"; + OUString aAlternativeTextGet = ""; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue AlternativeText", + xBaseIndexMark->getPropertyValue(propName) >>= aAlternativeTextGet); + + OUString aAlternativeTextSet = "testProperty"; + aNewValue <<= aAlternativeTextSet; + xBaseIndexMark->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xBaseIndexMark->getPropertyValue(propName) >>= aAlternativeTextGet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue AlternativeText", aAlternativeTextGet, + aAlternativeTextSet); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/text/documentindexmark.cxx b/test/source/text/documentindexmark.cxx new file mode 100644 index 000000000000..86c1cd9bc151 --- /dev/null +++ b/test/source/text/documentindexmark.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/cppunitasserthelper.hxx> +#include <test/text/documentindexmark.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace com::sun::star; +using namespace com::sun::star::uno; + +namespace apitest +{ +void DocumentIndexMark::testDocumentIndexMarkProperties() +{ + Reference<beans::XPropertySet> xDocumentIndexMark(init(), UNO_QUERY_THROW); + OUString propName; + uno::Any aNewValue; + + propName = "PrimaryKey"; + OUString aPrimaryKeyGet = ""; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue PrimaryKey", + xDocumentIndexMark->getPropertyValue(propName) >>= aPrimaryKeyGet); + + OUString aPrimaryKeySet = "testPropertyPK"; + aNewValue <<= aPrimaryKeySet; + xDocumentIndexMark->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xDocumentIndexMark->getPropertyValue(propName) >>= aPrimaryKeyGet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue PrimaryKey", aPrimaryKeyGet, + aPrimaryKeySet); + + propName = "SecondaryKey"; + OUString aSecondaryKeyGet = ""; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue SecondaryKey", + xDocumentIndexMark->getPropertyValue(propName) >>= aSecondaryKeyGet); + + OUString aSecondaryKeySet = "testPropertySK"; + aNewValue <<= aSecondaryKeySet; + xDocumentIndexMark->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xDocumentIndexMark->getPropertyValue(propName) >>= aSecondaryKeyGet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue SecondaryKey", aSecondaryKeyGet, + aSecondaryKeySet); + + propName = "IsMainEntry"; + bool bIsMainEntryGet = false; + bool bIsMainEntrySet = false; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue IsMainEntry", + xDocumentIndexMark->getPropertyValue(propName) >>= bIsMainEntryGet); + + aNewValue <<= !bIsMainEntryGet; + xDocumentIndexMark->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xDocumentIndexMark->getPropertyValue(propName) >>= bIsMainEntrySet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue IsMainEntry", !bIsMainEntryGet, + bIsMainEntrySet); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/text/footnote.cxx b/test/source/text/footnote.cxx new file mode 100644 index 000000000000..9f484cfd30cc --- /dev/null +++ b/test/source/text/footnote.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cppunit/TestAssert.h> + +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <test/unoapi_property_testers.hxx> +#include <test/text/footnote.hxx> + +namespace apitest +{ +Footnote::~Footnote() {} + +void Footnote::testFootnoteProperties() +{ + css::uno::Reference<css::beans::XPropertySet> xFootnote(init(), css::uno::UNO_QUERY_THROW); + + short aReferenceIdGet; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue ReferenceId", + xFootnote->getPropertyValue("ReferenceId") >>= aReferenceIdGet); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/source/text/numberingrules.cxx b/test/source/text/numberingrules.cxx new file mode 100644 index 000000000000..c54925650523 --- /dev/null +++ b/test/source/text/numberingrules.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/cppunitasserthelper.hxx> +#include <test/text/numberingrules.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/table/TableOrientation.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace com::sun::star; +using namespace com::sun::star::uno; + +namespace apitest +{ +void NumberingRules::testNumberingRulesProperties() +{ + Reference<beans::XPropertySet> xNumberingRules(init(), UNO_QUERY_THROW); + OUString propName; + uno::Any aNewValue; + + propName = "IsAbsoluteMargins"; + bool bIsAbsoluteMarginsGet = false; + bool bIsAbsoluteMarginsSet = false; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue IsAbsoluteMargins", + xNumberingRules->getPropertyValue(propName) >>= bIsAbsoluteMarginsGet); + + aNewValue <<= !bIsAbsoluteMarginsGet; + xNumberingRules->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xNumberingRules->getPropertyValue(propName) >>= bIsAbsoluteMarginsSet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue IsAbsoluteMargins", + !bIsAbsoluteMarginsGet, bIsAbsoluteMarginsSet); + + propName = "IsAutomatic"; + bool bIsAutomaticGet = false; + bool bIsAutomaticSet = false; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue IsAutomatic", + xNumberingRules->getPropertyValue(propName) >>= bIsAutomaticGet); + + bIsAutomaticGet = false; + aNewValue <<= !bIsAutomaticGet; + xNumberingRules->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xNumberingRules->getPropertyValue(propName) >>= bIsAutomaticSet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue IsAutomatic", !bIsAutomaticGet, + bIsAutomaticSet); + + propName = "IsContinuousNumbering"; + bool bIsContinuousNumberingGet = false; + bool bIsContinuousNumberingSet = false; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue IsContinuousNumbering", + xNumberingRules->getPropertyValue(propName) + >>= bIsContinuousNumberingGet); + + aNewValue <<= !bIsContinuousNumberingGet; + xNumberingRules->setPropertyValue(propName, aNewValue); + CPPUNIT_ASSERT(xNumberingRules->getPropertyValue(propName) >>= bIsContinuousNumberingSet); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unable to set PropertyValue IsContinuousNumbering", + !bIsContinuousNumberingGet, bIsContinuousNumberingSet); + + propName = "Name"; + OUString aNameGet = ""; + CPPUNIT_ASSERT_MESSAGE("Unable to get PropertyValue Name", + xNumberingRules->getPropertyValue(propName) >>= aNameGet); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/text/textprintersettings.cxx b/test/source/text/textprintersettings.cxx index b28c652413e5..da94c20203c1 100644 --- a/test/source/text/textprintersettings.cxx +++ b/test/source/text/textprintersettings.cxx @@ -21,13 +21,9 @@ void TextPrinterSettings::testPrinterSettingsProperties() css::uno::UNO_QUERY_THROW); testBooleanProperty(xPrinterSettings, "PrintGraphics"); - testBooleanProperty(xPrinterSettings, "PrintTables"); - testBooleanProperty(xPrinterSettings, "PrintDrawings"); testBooleanProperty(xPrinterSettings, "PrintLeftPages"); testBooleanProperty(xPrinterSettings, "PrintRightPages"); testBooleanProperty(xPrinterSettings, "PrintControls"); - testBooleanProperty(xPrinterSettings, "PrintReversed"); - testBooleanProperty(xPrinterSettings, "PrintControls"); testStringProperty(xPrinterSettings, "PrintFaxName", "FaxName"); testBooleanProperty(xPrinterSettings, "PrintProspect"); testBooleanProperty(xPrinterSettings, "PrintPageBackground"); diff --git a/test/source/text/textsettings.cxx b/test/source/text/textsettings.cxx index 112fc939dee9..039210390765 100644 --- a/test/source/text/textsettings.cxx +++ b/test/source/text/textsettings.cxx @@ -44,7 +44,7 @@ bool isPropertyReadOnly(css::uno::Reference<css::beans::XPropertySet> const& rxP // [property] string PrinterName; void testPrinterName(css::uno::Reference<css::beans::XPropertySet> const& rxSettings) { - static const OUStringLiteral rPropertyName(u"PrinterName"); + static constexpr OUString rPropertyName(u"PrinterName"_ustr); if (!extstsProperty(rxSettings, rPropertyName)) return; // Property is sometimes not set - bug? it is not defined as optional @@ -67,7 +67,7 @@ void testPrinterName(css::uno::Reference<css::beans::XPropertySet> const& rxSett // [optional, property] short PrinterIndependentLayout; void testPrinterIndependentLayout(css::uno::Reference<css::beans::XPropertySet> const& rxSettings) { - static const OUStringLiteral rPropertyName(u"PrinterIndependentLayout"); + static constexpr OUString rPropertyName(u"PrinterIndependentLayout"_ustr); if (!extstsProperty(rxSettings, rPropertyName)) return; // Property is optional @@ -91,7 +91,7 @@ void testPrinterIndependentLayout(css::uno::Reference<css::beans::XPropertySet> // [optional, property] com::sun::star::i18n::XForbiddenCharacters ForbiddenCharacters; void testForbiddenCharacters(css::uno::Reference<css::beans::XPropertySet> const& rxSettings) { - static const OUStringLiteral rPropertyName(u"ForbiddenCharacters"); + static constexpr OUString rPropertyName(u"ForbiddenCharacters"_ustr); if (!extstsProperty(rxSettings, rPropertyName)) return; // Property is optional diff --git a/test/source/text/xautotextcontainer.cxx b/test/source/text/xautotextcontainer.cxx new file mode 100644 index 000000000000..b1d001ba4dcd --- /dev/null +++ b/test/source/text/xautotextcontainer.cxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/text/xautotextcontainer.hxx> + +#include <com/sun/star/container/ElementExistException.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/text/XAutoTextContainer.hpp> +#include <com/sun/star/text/XAutoTextGroup.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace css; + +namespace apitest +{ +void XAutoTextContainer::testInsertNewByName() +{ + uno::Reference<text::XAutoTextContainer> xAutoTextContainer(init(), uno::UNO_QUERY_THROW); + + try + { + xAutoTextContainer->removeByName(m_aName + "Insert"); + } + catch (container::NoSuchElementException&) + { + } + uno::Reference<text::XAutoTextGroup> xGroup + = xAutoTextContainer->insertNewByName(m_aName + "Insert"); + + CPPUNIT_ASSERT(xGroup.is()); +} + +void XAutoTextContainer::testRemoveByName() +{ + uno::Reference<text::XAutoTextContainer> xAutoTextContainer(init(), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xAutoTextContainer->hasByName(m_aName)); + xAutoTextContainer->removeByName(m_aName); + CPPUNIT_ASSERT(!xAutoTextContainer->hasByName(m_aName)); +} + +} // namespace apitest + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/text/xfootnote.cxx b/test/source/text/xfootnote.cxx new file mode 100644 index 000000000000..d46506bf1fd4 --- /dev/null +++ b/test/source/text/xfootnote.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/text/xfootnote.hxx> + +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/text/XFootnote.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace css; +using namespace css::uno; + +namespace apitest +{ +void XFootnote::testGetSetLabel() +{ + Reference<text::XFootnote> xFootnote(init(), UNO_QUERY_THROW); + + rtl::OUString labelName = "New XFootnote Label"; + xFootnote->setLabel(labelName); + rtl::OUString newLabel = xFootnote->getLabel(); + CPPUNIT_ASSERT(!newLabel.isEmpty()); + CPPUNIT_ASSERT_EQUAL(labelName, newLabel); +} + +} // namespace apitest + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/text/xtextrangecompare.cxx b/test/source/text/xtextrangecompare.cxx new file mode 100644 index 000000000000..b31d6b864332 --- /dev/null +++ b/test/source/text/xtextrangecompare.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/text/xtextrangecompare.hxx> + +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/text/XTextRangeCompare.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppunit/TestAssert.h> + +using namespace css; +using namespace css::uno; + +namespace apitest +{ +void XTextRangeCompare::testCompareRegionStarts() +{ + Reference<text::XTextRangeCompare> xCompare(init(), UNO_QUERY_THROW); + Reference<text::XText> xText(xCompare, UNO_QUERY_THROW); + + try + { + Reference<text::XTextCursor> xCursor1 = xText->createTextCursor(); + xText->insertString(xCursor1, "XTextRangeCompare", false); + + xCursor1->gotoStart(false); + xCursor1->goRight(5, true); + Reference<text::XTextCursor> xCursor2 = xText->createTextCursor(); + xCursor2->gotoEnd(false); + xCursor2->goLeft(7, true); + + CPPUNIT_ASSERT(xCompare->compareRegionStarts(xCursor1, xCursor2)); + } + catch (lang::IllegalArgumentException&) + { + } +} + +void XTextRangeCompare::testCompareRegionEnds() +{ + Reference<text::XTextRangeCompare> xCompare(init(), UNO_QUERY_THROW); + Reference<text::XText> xText(xCompare, UNO_QUERY_THROW); + + try + { + Reference<text::XTextCursor> xCursor1 = xText->createTextCursor(); + xText->insertString(xCursor1, "XTextRangeCompare", false); + + xCursor1->gotoStart(false); + xCursor1->goRight(5, true); + Reference<text::XTextCursor> xCursor2 = xText->createTextCursor(); + xCursor2->gotoEnd(false); + xCursor2->goLeft(7, true); + + CPPUNIT_ASSERT(xCompare->compareRegionEnds(xCursor1, xCursor2)); + } + catch (lang::IllegalArgumentException&) + { + } +} + +} // namespace apitest + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/test/source/unoapi_test.cxx b/test/source/unoapi_test.cxx index e27d17507c76..ce88aac3158e 100644 --- a/test/source/unoapi_test.cxx +++ b/test/source/unoapi_test.cxx @@ -9,17 +9,26 @@ #include <test/unoapi_test.hxx> -#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> #include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <unotools/mediadescriptor.hxx> #include <utility> using namespace css; using namespace css::uno; UnoApiTest::UnoApiTest(OUString path) - : m_aBaseString(std::move(path)) + : mbSkipValidation(false) + , m_aBaseString(std::move(path)) { + maTempFile.EnableKillingFile(); } void UnoApiTest::setUp() @@ -29,17 +38,208 @@ void UnoApiTest::setUp() mxDesktop = css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())); CPPUNIT_ASSERT_MESSAGE("no desktop!", mxDesktop.is()); + SfxApplication::GetOrCreate(); +} + +void UnoApiTest::tearDown() +{ + if (mxComponent2.is()) + { + mxComponent2->dispose(); + mxComponent2.clear(); + } + + if (mxComponent.is()) + { + mxComponent->dispose(); + mxComponent.clear(); + } + + test::BootstrapFixture::tearDown(); +} + +OUString UnoApiTest::createFileURL(std::u16string_view aFileBase) +{ + return m_directories.getSrcRootURL() + m_aBaseString + "/" + aFileBase; +} + +OUString UnoApiTest::createFilePath(std::u16string_view aFileBase) +{ + return m_directories.getSrcRootPath() + "/" + m_aBaseString + "/" + aFileBase; +} + +void UnoApiTest::setTestInteractionHandler(const char* pPassword, + std::vector<beans::PropertyValue>& rFilterOptions) +{ + OUString sPassword = OUString::createFromAscii(pPassword); + auto& rPropertyValue = rFilterOptions.emplace_back(); + xInteractionHandler + = rtl::Reference<TestInteractionHandler>(new TestInteractionHandler(sPassword)); + css::uno::Reference<task::XInteractionHandler2> const xInteraction(xInteractionHandler); + rPropertyValue.Name = "InteractionHandler"; + rPropertyValue.Value <<= xInteraction; +} + +void UnoApiTest::load(OUString const& rURL, const char* pPassword) +{ + std::vector<beans::PropertyValue> aFilterOptions; + + if (pPassword) + { + setTestInteractionHandler(pPassword, aFilterOptions); + } + + if (!maImportFilterOptions.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterOptions"; + aValue.Value <<= maImportFilterOptions; + aFilterOptions.push_back(aValue); + } + + if (!maImportFilterName.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterName"; + aValue.Value <<= maImportFilterName; + aFilterOptions.push_back(aValue); + } + + loadWithParams(rURL, comphelper::containerToSequence(aFilterOptions)); + + if (pPassword) + { + CPPUNIT_ASSERT_MESSAGE("Password set but not requested", + xInteractionHandler->wasPasswordRequested()); + } +} + +void UnoApiTest::loadWithParams(OUString const& rURL, + const uno::Sequence<beans::PropertyValue>& rParams) +{ + if (mxComponent.is()) + { + mxComponent->dispose(); + mxComponent.clear(); + } + + mxComponent = loadFromDesktop(rURL, OUString(), rParams); +} + +OUString UnoApiTest::loadFromFile(std::u16string_view aFileBase, const char* pPassword) +{ + OUString aFileName = createFileURL(aFileBase); + load(aFileName, pPassword); + return aFileName; +} + +uno::Any UnoApiTest::executeMacro(const OUString& rScriptURL, + const uno::Sequence<uno::Any>& rParams) +{ + uno::Any aRet; + uno::Sequence<sal_Int16> aOutParamIndex; + uno::Sequence<uno::Any> aOutParam; + + ErrCode result = SfxObjectShell::CallXScript(mxComponent, rScriptURL, rParams, aRet, + aOutParamIndex, aOutParam); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, result); + + return aRet; +} + +void UnoApiTest::save(const OUString& rFilter, const char* pPassword) +{ + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= rFilter; + if (!maFilterOptions.isEmpty()) + aMediaDescriptor["FilterOptions"] <<= maFilterOptions; + + if (pPassword) + { + if (rFilter != "Office Open XML Text" && rFilter != "Calc Office Open XML" + && rFilter != "Impress Office Open XML") + { + aMediaDescriptor["Password"] <<= OUString::createFromAscii(pPassword); + } + else + { + OUString sPassword = OUString::createFromAscii(pPassword); + uno::Sequence<beans::NamedValue> aEncryptionData{ + { "CryptoType", uno::Any(OUString("Standard")) }, + { "OOXPassword", uno::Any(sPassword) } + }; + aMediaDescriptor[utl::MediaDescriptor::PROP_ENCRYPTIONDATA] <<= aEncryptionData; + + // validation fails with "zip END header not found" + skipValidation(); + } + } + + saveWithParams(aMediaDescriptor.getAsConstPropertyValueList()); + + if (!mbSkipValidation) + { + if (rFilter == "Calc Office Open XML") + validate(maTempFile.GetFileName(), test::OOXML); + /* + // too many validation errors right now + else if (rFilter == "Office Open XML Text") + validate(maTempFile.GetFileName(), test::OOXML); + */ + else if (rFilter == "Impress Office Open XML") + validate(maTempFile.GetFileName(), test::OOXML); + else if (rFilter == "writer8") + validate(maTempFile.GetFileName(), test::ODF); + else if (rFilter == "calc8") + validate(maTempFile.GetFileName(), test::ODF); + else if (rFilter == "impress8") + validate(maTempFile.GetFileName(), test::ODF); + else if (rFilter == "draw8") + validate(maTempFile.GetFileName(), test::ODF); + else if (rFilter == "OpenDocument Text Flat XML") + validate(maTempFile.GetFileName(), test::ODF); + else if (rFilter == "MS Word 97") + validate(maTempFile.GetFileName(), test::MSBINARY); + else if (rFilter == "MS Excel 97") + validate(maTempFile.GetFileName(), test::MSBINARY); + else if (rFilter == "MS PowerPoint 97") + validate(maTempFile.GetFileName(), test::MSBINARY); + } +} + +void UnoApiTest::saveWithParams(const uno::Sequence<beans::PropertyValue>& rParams) +{ + css::uno::Reference<frame::XStorable> xStorable(mxComponent, css::uno::UNO_QUERY_THROW); + xStorable->storeToURL(maTempFile.GetURL(), rParams); +} + +void UnoApiTest::saveAndReload(const OUString& rFilter, const char* pPassword) +{ + save(rFilter, pPassword); + + load(maTempFile.GetURL(), pPassword); } -void UnoApiTest::createFileURL(std::u16string_view aFileBase, OUString& rFilePath) +std::unique_ptr<vcl::pdf::PDFiumDocument> UnoApiTest::parsePDFExport(const OString& rPassword) { - rFilePath = m_directories.getSrcRootURL() + m_aBaseString + "/" + aFileBase; + SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ); + maMemory.WriteStream(aFile); + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return nullptr; + } + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPDFium->openDocument(maMemory.GetData(), maMemory.GetSize(), rPassword); + CPPUNIT_ASSERT(pPdfDocument); + return pPdfDocument; } -void UnoApiTest::closeDocument(uno::Reference<lang::XComponent> const& xDocument) +void UnoApiTest::createTempCopy(std::u16string_view fileName) { - uno::Reference<util::XCloseable> xCloseable(xDocument, UNO_QUERY_THROW); - xCloseable->close(false); + OUString url = createFileURL(fileName); + auto const e = osl::File::copy(url, maTempFile.GetURL()); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/source/unoapixml_test.cxx b/test/source/unoapixml_test.cxx new file mode 100644 index 000000000000..d07c97351066 --- /dev/null +++ b/test/source/unoapixml_test.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <test/unoapixml_test.hxx> + +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <utility> + +using namespace css; + +UnoApiXmlTest::UnoApiXmlTest(OUString path) + : UnoApiTest(std::move(path)) +{ +} + +xmlDocUniquePtr UnoApiXmlTest::parseExport(OUString const& rStreamName) +{ + std::unique_ptr<SvStream> const pStream(parseExportStream(maTempFile.GetURL(), rStreamName)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + return pXmlDoc; +} + +xmlDocUniquePtr UnoApiXmlTest::parseExportedFile() +{ + auto stream(SvFileStream(maTempFile.GetURL(), StreamMode::READ | StreamMode::TEMPORARY)); + return parseXmlStream(&stream); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/source/xmltesttools.cxx b/test/source/xmltesttools.cxx index ab9e5dcff8b8..b0e4cf48e989 100644 --- a/test/source/xmltesttools.cxx +++ b/test/source/xmltesttools.cxx @@ -42,7 +42,7 @@ XmlTestTools::XmlTestTools() XmlTestTools::~XmlTestTools() {} -xmlDocUniquePtr XmlTestTools::parseXml(utl::TempFile const & aTempFile) +xmlDocUniquePtr XmlTestTools::parseXml(utl::TempFileNamed const & aTempFile) { SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ); return parseXmlStream(&aFileStream); @@ -76,8 +76,14 @@ xmlXPathObjectPtr XmlTestTools::getXPathNode(const xmlDocUniquePtr& pXmlDoc, con return pXmlXpathObj; } -void XmlTestTools::registerNamespaces(xmlXPathContextPtr& /*pXmlXpathCtx*/) +void XmlTestTools::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) { + // ooxml + XmlTestTools::registerOOXMLNamespaces(pXmlXpathCtx); + // odf + XmlTestTools::registerODFNamespaces(pXmlXpathCtx); + // reqif-xhtml + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("reqif-xhtml"), BAD_CAST("http://www.w3.org/1999/xhtml")); } OUString XmlTestTools::getXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, const OString& rAttribute) @@ -88,11 +94,7 @@ OUString XmlTestTools::getXPath(const xmlDocUniquePtr& pXmlDoc, const OString& r xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OString::Concat("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(), 1, xmlXPathNodeSetGetLength(pXmlNodes)); - if (rAttribute.isEmpty()) - { - xmlXPathFreeObject(pXmlObj); - return OUString(); - } + CPPUNIT_ASSERT(!rAttribute.isEmpty()); xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; xmlChar * prop = xmlGetProp(pXmlNode, BAD_CAST(rAttribute.getStr())); OString sAttAbsent = OString::Concat("In <") + pXmlDoc->name + ">, XPath '" + rXPath @@ -148,9 +150,11 @@ OUString XmlTestTools::getXPathContent(const xmlDocUniquePtr& pXmlDoc, const OSt xmlXPathFreeObject(pXmlObj); return convertedVal; } +#if LIBXML_VERSION < 21000 || defined(LIBXML_XPTR_LOCS_ENABLED) case XPATH_POINT: case XPATH_RANGE: case XPATH_LOCATIONSET: +#endif case XPATH_USERS: case XPATH_XSLT_TREE: xmlXPathFreeObject(pXmlObj); @@ -160,11 +164,6 @@ OUString XmlTestTools::getXPathContent(const xmlDocUniquePtr& pXmlDoc, const OSt CPPUNIT_FAIL("Invalid XPath type"); } -void XmlTestTools::assertXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath) -{ - getXPath(pXmlDoc, rXPath, ""); // it asserts that rXPath exists, and returns exactly one node -} - void XmlTestTools::assertXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, const OString& rAttribute, const OUString& rExpectedValue) { OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute); @@ -172,6 +171,14 @@ void XmlTestTools::assertXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rX rExpectedValue, aValue); } +void XmlTestTools::assertXPathDoubleValue(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, const OString& rAttribute, double expectedValue, double delta) +{ + OUString aValue = getXPath(pXmlDoc, rXPath, rAttribute); + double pathValue = aValue.toDouble(); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(std::string("In <") + std::string(pXmlDoc->name ? pXmlDoc->name : "") + ">, attribute '" + std::string(rAttribute) + "' of '" + std::string(rXPath) + "' incorrect value.", + expectedValue, pathValue, delta); +} + void XmlTestTools::assertXPathAttrs(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, const std::vector<std::pair<OString, OUString>>& aPairVector) { @@ -181,13 +188,19 @@ void XmlTestTools::assertXPathAttrs(const xmlDocUniquePtr& pXmlDoc, const OStrin } } -void XmlTestTools::assertXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, int nNumberOfNodes) +int XmlTestTools::countXPathNodes(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath) { xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath); xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; - CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OString::Concat("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(), - nNumberOfNodes, xmlXPathNodeSetGetLength(pXmlNodes)); + const int n = xmlXPathNodeSetGetLength(pXmlNodes); xmlXPathFreeObject(pXmlObj); + return n; +} + +void XmlTestTools::assertXPath(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, int nNumberOfNodes) +{ + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OString::Concat("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(), + nNumberOfNodes, countXPathNodes(pXmlDoc, rXPath)); } void XmlTestTools::assertXPathContent(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, const OUString& rContent) @@ -279,8 +292,24 @@ int XmlTestTools::getXPathPosition(const xmlDocUniquePtr& pXmlDoc, const OString return nRet; } +void XmlTestTools::assertXPathNodeName(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, + const OString& rExpectedName) +{ + xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, rXPath); + xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OString::Concat("In <") + pXmlDoc->name + ">, XPath '" + rXPath + "' number of nodes is incorrect").getStr(), + 1, + xmlXPathNodeSetGetLength(pXmlNodes)); + xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString(OString::Concat("In XPath '" + rXPath + "' name of node is incorrect")).getStr(), + rExpectedName, oconvert(pXmlNode->name)); + xmlXPathFreeObject(pXmlObj); +} + void XmlTestTools::registerODFNamespaces(xmlXPathContextPtr& pXmlXpathCtx) { + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("manifest"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("style"), @@ -442,6 +471,8 @@ void XmlTestTools::registerOOXMLNamespaces(xmlXPathContextPtr& pXmlXpathCtx) BAD_CAST("http://schemas.microsoft.com/office/drawing/2012/chart")); xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xr2"), BAD_CAST("http://schemas.microsoft.com/office/spreadsheetml/2015/revision2")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("asvg"), + BAD_CAST("http://schemas.microsoft.com/office/drawing/2016/SVG/main")); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/test/user-template/registry-common/modifications.xcd b/test/user-template/registry-common/modifications.xcd index b5e3ad6f9fd1..a212242785ea 100644 --- a/test/user-template/registry-common/modifications.xcd +++ b/test/user-template/registry-common/modifications.xcd @@ -8,6 +8,27 @@ * --> <oor:data xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:oor="http://openoffice.org/2001/registry"> + <oor:component-schema oor:package="org.libreoffice" oor:name="unittest"> + <component> + <prop oor:name="localized" oor:localized="true" oor:type="xs:string"> + </prop> + <prop oor:name="noDefaultLang" oor:localized="true" oor:type="xs:string"> + </prop> + </component> + </oor:component-schema> + <oor:component-data oor:package="org.libreoffice" oor:name="unittest"> + <prop oor:name="localized"> + <value>default</value> + <value xml:lang="en-US">en-US</value> + <value xml:lang="es">es</value> + <value xml:lang="pt-PT">pt-PT</value> + <value xml:lang="zh-CN">zh-CN</value> + <value xml:lang="zh-TW">zh-TW</value> + </prop> + <prop oor:name="noDefaultLang"> + <value xml:lang="en-US">en-US</value> + </prop> + </oor:component-data> <oor:component-data xmlns:install="http://openoffice.org/2004/installation" oor:name="VCL" oor:package="org.openoffice"> <node oor:name="DefaultFonts"> <node oor:name="ar"> |