diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sfx2/qa/cppunit | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sfx2/qa/cppunit')
-rw-r--r-- | sfx2/qa/cppunit/data/reload-page.odg | bin | 0 -> 8824 bytes | |||
-rw-r--r-- | sfx2/qa/cppunit/doc.cxx | 151 | ||||
-rw-r--r-- | sfx2/qa/cppunit/misc/hello.odt | bin | 0 -> 8159 bytes | |||
-rw-r--r-- | sfx2/qa/cppunit/test_classification.cxx | 112 | ||||
-rw-r--r-- | sfx2/qa/cppunit/test_controlleritem.cxx | 58 | ||||
-rw-r--r-- | sfx2/qa/cppunit/test_metadatable.cxx | 248 | ||||
-rw-r--r-- | sfx2/qa/cppunit/test_misc.cxx | 201 | ||||
-rw-r--r-- | sfx2/qa/cppunit/view.cxx | 64 |
8 files changed, 834 insertions, 0 deletions
diff --git a/sfx2/qa/cppunit/data/reload-page.odg b/sfx2/qa/cppunit/data/reload-page.odg Binary files differnew file mode 100644 index 0000000000..0e9cf08649 --- /dev/null +++ b/sfx2/qa/cppunit/data/reload-page.odg diff --git a/sfx2/qa/cppunit/doc.cxx b/sfx2/qa/cppunit/doc.cxx new file mode 100644 index 0000000000..9eea6d2939 --- /dev/null +++ b/sfx2/qa/cppunit/doc.cxx @@ -0,0 +1,151 @@ +/* -*- 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/unoapi_test.hxx> + +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> + +#include <comphelper/propertyvalue.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <osl/file.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/sequence.hxx> + +using namespace com::sun::star; + +namespace +{ +/// Covers sfx2/source/doc/ fixes. +class Test : public UnoApiTest +{ +public: + Test() + : UnoApiTest("/sfx2/qa/cppunit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testNoGrabBagShape) +{ + // Load a document and select the first shape. + css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue("ReadOnly", + true) }; + mxComponent = loadFromDesktop("private:factory/simpress", "", aArgs); + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(xModel, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xDrawPage( + xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + uno::Any aShape = xDrawPage->getByIndex(0); + uno::Reference<view::XSelectionSupplier> xController(xModel->getCurrentController(), + uno::UNO_QUERY); + xController->select(aShape); + + // See if it has a signing certificate associated. + auto pBaseModel = dynamic_cast<SfxBaseModel*>(xModel.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + + // Without the accompanying fix in place, this test would have failed with: + // An uncaught exception of type com.sun.star.beans.UnknownPropertyException + // which was not caught later, resulting in a crash. + pObjectShell->GetSignPDFCertificate(); +} + +CPPUNIT_TEST_FIXTURE(Test, testTempFilePath) +{ + // Create a test file in a directory that contains the URL-encoded "testÿ" string. + mxComponent = loadFromDesktop("private:factory/swriter"); + auto pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"CppunitTest/sfx2_doc.test.user/test%25C3%25Bf"); + osl::Directory::create(aTargetDir); + OUString aTargetFile = aTargetDir + "/test.odt"; + css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue( + "FilterName", OUString("writer8")) }; + pBaseModel->storeAsURL(aTargetFile, aArgs); + mxComponent->dispose(); + + // Load it and export to PDF. + mxComponent = loadFromDesktop(aTargetFile); + pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + OUString aPdfTarget = aTargetDir + "/test.pdf"; + css::uno::Sequence<css::beans::PropertyValue> aPdfArgs{ comphelper::makePropertyValue( + "FilterName", OUString("writer_pdf_Export")) }; + // Without the accompanying fix in place, this test would have failed on Windows with: + // An uncaught exception of type com.sun.star.io.IOException + // because we first tried to create a temp file next to test.odt in a directory named + // "test%25C3%25Bf" instead of a directory named "test%C3%Bf". + pBaseModel->storeToURL(aPdfTarget, aPdfArgs); +} + +CPPUNIT_TEST_FIXTURE(Test, testSetDocumentPropertiesUpdate) +{ + // Given a document with 3 custom props, 2 Zotero ones and one other: + mxComponent = loadFromDesktop("private:factory/swriter"); + auto pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + uno::Reference<document::XDocumentProperties> xDP = pBaseModel->getDocumentProperties(); + uno::Reference<beans::XPropertyContainer> xUDP = xDP->getUserDefinedProperties(); + xUDP->addProperty("ZOTERO_PREF_1", beans::PropertyAttribute::REMOVABLE, + uno::Any(OUString("foo"))); + xUDP->addProperty("ZOTERO_PREF_2", beans::PropertyAttribute::REMOVABLE, + uno::Any(OUString("bar"))); + xUDP->addProperty("OTHER", beans::PropertyAttribute::REMOVABLE, uno::Any(OUString("baz"))); + + // When updating the Zotero ones (1 update, 1 removal): + std::vector<beans::PropertyValue> aArgsVec = comphelper::JsonToPropertyValues(R"json( +{ + "UpdatedProperties": { + "type": "[]com.sun.star.beans.PropertyValue", + "value": { + "NamePrefix": { + "type": "string", + "value": "ZOTERO_PREF_" + }, + "UserDefinedProperties": { + "type": "[]com.sun.star.beans.PropertyValue", + "value": { + "ZOTERO_PREF_1": { + "type": "string", + "value": "test" + } + } + } + } + } +} +)json"_ostr); + uno::Sequence<beans::PropertyValue> aArgs = comphelper::containerToSequence(aArgsVec); + dispatchCommand(mxComponent, ".uno:SetDocumentProperties", aArgs); + + // Then make sure that OTHER is still there and that ZOTERO_PREF_1 + ZOTERO_PREF_2 gets updated + // to the new value of a single ZOTERO_PREF_1: + uno::Reference<beans::XPropertyAccess> xUDPAccess(xUDP, uno::UNO_QUERY); + comphelper::SequenceAsHashMap aMap(xUDPAccess->getPropertyValues()); + auto it = aMap.find("ZOTERO_PREF_1"); + CPPUNIT_ASSERT(it != aMap.end()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: test + // - Actual : foo + // i.e. ZOTERO_PREF_1 was not updated. + CPPUNIT_ASSERT_EQUAL(OUString("test"), it->second.get<OUString>()); + CPPUNIT_ASSERT(bool(aMap.find("ZOTERO_PREF_2") == aMap.end())); + CPPUNIT_ASSERT(aMap.find("OTHER") != aMap.end()); +} +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/qa/cppunit/misc/hello.odt b/sfx2/qa/cppunit/misc/hello.odt Binary files differnew file mode 100644 index 0000000000..23ce6a4db9 --- /dev/null +++ b/sfx2/qa/cppunit/misc/hello.odt diff --git a/sfx2/qa/cppunit/test_classification.cxx b/sfx2/qa/cppunit/test_classification.cxx new file mode 100644 index 0000000000..ffa90089fd --- /dev/null +++ b/sfx2/qa/cppunit/test_classification.cxx @@ -0,0 +1,112 @@ +/* -*- 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/unoapi_test.hxx> + +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/DispatchHelper.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysequence.hxx> + +using namespace ::com::sun::star; + +namespace +{ + +/// Tests the handling of the .uno:ClassificationApply command in various applications. +class ClassificationTest : public UnoApiTest +{ + void testClassification(); + +public: + ClassificationTest() + : UnoApiTest("/sfx2/qa/cppunit/data/") + { + } + + void testWriter(); + void testCalc(); + void testImpress(); + + CPPUNIT_TEST_SUITE(ClassificationTest); + CPPUNIT_TEST(testWriter); + CPPUNIT_TEST(testCalc); + CPPUNIT_TEST(testImpress); + CPPUNIT_TEST_SUITE_END(); +}; + +void ClassificationTest::testClassification() +{ + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"Name", uno::Any(OUString("Non-Business"))}, + {"Type", uno::Any(OUString("urn:bails:ExportControl:"))}, + })); + dispatchCommand(mxComponent, ".uno:ClassificationApply", aPropertyValues); + + uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDocumentPropertiesSupplier.is()); + uno::Reference<document::XDocumentProperties> xDocumentProperties = xDocumentPropertiesSupplier->getDocumentProperties(); + uno::Reference<beans::XPropertySet> xPropertySet(xDocumentProperties->getUserDefinedProperties(), uno::UNO_QUERY); + uno::Any aAny = xPropertySet->getPropertyValue("urn:bails:ExportControl:BusinessAuthorizationCategory:Identifier"); + CPPUNIT_ASSERT_EQUAL(OUString("urn:example:tscp:1:non-business"), aAny.get<OUString>()); + + aPropertyValues = comphelper::InitPropertySequence( + { + {"Name", uno::Any(OUString("Confidential"))}, + {"Type", uno::Any(OUString("urn:bails:NationalSecurity:"))}, + }); + dispatchCommand(mxComponent, ".uno:ClassificationApply", aPropertyValues); + aAny = xPropertySet->getPropertyValue("urn:bails:NationalSecurity:BusinessAuthorizationCategory:Identifier"); + CPPUNIT_ASSERT_EQUAL(OUString("urn:example:tscp:1:confidential"), aAny.get<OUString>()); + + aPropertyValues = comphelper::InitPropertySequence( + { + {"Name", uno::Any(OUString("Internal Only"))}, + {"Type", uno::Any(OUString("urn:bails:IntellectualProperty:"))}, + }); + dispatchCommand(mxComponent, ".uno:ClassificationApply", aPropertyValues); + aAny = xPropertySet->getPropertyValue("urn:bails:IntellectualProperty:BusinessAuthorizationCategory:Identifier"); + CPPUNIT_ASSERT_EQUAL(OUString("urn:example:tscp:1:internal-only"), aAny.get<OUString>()); +} + +void ClassificationTest::testWriter() +{ + // Test SID_CLASSIFICATION_APPLY handling in SwDocShell::Execute(). + mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"); + // This resulted in a beans::UnknownPropertyException when the request wasn't handled. + testClassification(); +} + +void ClassificationTest::testCalc() +{ + // Test SID_CLASSIFICATION_APPLY handling in ScFormatShell::ExecuteStyle(). + mxComponent = loadFromDesktop("private:factory/scalc", "com.sun.star.sheet.SpreadsheetDocument"); + // This resulted in a beans::UnknownPropertyException when the request wasn't handled. + testClassification(); +} + +void ClassificationTest::testImpress() +{ + // Test SID_CLASSIFICATION_APPLY handling in sd::DrawViewShell::FuTemporary(). + mxComponent = loadFromDesktop("private:factory/simpress", "com.sun.star.presentation.PresentationDocument"); + // This resulted in a beans::UnknownPropertyException when the request wasn't handled. + testClassification(); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ClassificationTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/qa/cppunit/test_controlleritem.cxx b/sfx2/qa/cppunit/test_controlleritem.cxx new file mode 100644 index 0000000000..75d2205367 --- /dev/null +++ b/sfx2/qa/cppunit/test_controlleritem.cxx @@ -0,0 +1,58 @@ +/* -*- 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 <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <sfx2/ctrlitem.hxx> + +namespace { + +class ControllerItemTest + : public ::CppUnit::TestFixture +{ +public: + void test(); + + CPPUNIT_TEST_SUITE(ControllerItemTest); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); + +private: +}; + +bool bDeleted = false; + +class FooController : public SfxControllerItem { +public: + FooController() : SfxControllerItem() {} + virtual ~FooController() override { bDeleted = true; } +}; + +void ControllerItemTest::test() +{ + FooController *pController(new FooController()); + + // TESTME: binding, un-binding, re-binding, IsBound, SetId etc. + + pController->dispose(); + delete pController; + CPPUNIT_ASSERT( bDeleted ); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ControllerItemTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/qa/cppunit/test_metadatable.cxx b/sfx2/qa/cppunit/test_metadatable.cxx new file mode 100644 index 0000000000..459f635d00 --- /dev/null +++ b/sfx2/qa/cppunit/test_metadatable.cxx @@ -0,0 +1,248 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <sfx2/Metadatable.hxx> +#include <sfx2/XmlIdRegistry.hxx> + +#include <memory> + + +using namespace ::com::sun::star; + + +namespace { + +class MetadatableTest + : public ::CppUnit::TestFixture +{ +public: + void test(); + + CPPUNIT_TEST_SUITE(MetadatableTest); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); + +private: +}; + +class MockMetadatable + : public ::sfx2::Metadatable +{ +private: + ::sfx2::IXmlIdRegistry & m_rRegistry; + +public: + MockMetadatable(::sfx2::IXmlIdRegistry & i_rReg, + bool const i_isInClip = false) + : m_rRegistry(i_rReg) + , m_bInClipboard(i_isInClip), m_bInUndo(false), m_bInContent(true) {} + bool m_bInClipboard; + bool m_bInUndo; + bool m_bInContent; + virtual bool IsInClipboard() const override { return m_bInClipboard; } + virtual bool IsInUndo() const override { return m_bInUndo; } + virtual bool IsInContent() const override { return m_bInContent; } + virtual ::sfx2::IXmlIdRegistry& GetRegistry() override { return m_rRegistry; } + virtual css::uno::Reference< css::rdf::XMetadatable > MakeUnoObject() override { return nullptr; } +}; + +void MetadatableTest::test() +{ + std::unique_ptr< ::sfx2::IXmlIdRegistry > const pReg( + ::sfx2::createXmlIdRegistry(false) ); + std::unique_ptr< ::sfx2::IXmlIdRegistry > const pRegClip( + ::sfx2::createXmlIdRegistry(true) ); + + MockMetadatable m1(*pReg); + MockMetadatable m2(*pReg); + MockMetadatable m3(*pReg); + MockMetadatable m4(*pReg); + MockMetadatable m5(*pReg); + OUString empty; + OUString content( "content.xml" ); + OUString sid3( "id3" ); + OUString sid4( "id4" ); + beans::StringPair id1(content, "id1"); + beans::StringPair id2(content, "id2"); + beans::StringPair id3(content, sid3); + beans::StringPair id4("styles.xml", sid4); + beans::StringPair id3e(empty, sid3); + beans::StringPair id4e(empty, sid4); + m1.SetMetadataReference(id1); + CPPUNIT_ASSERT_MESSAGE("set failed", bool(m1.GetMetadataReference() == id1)); + try { + m2.SetMetadataReference(id1); + CPPUNIT_ASSERT_MESSAGE("set duplicate succeeded", false); + } catch (const lang::IllegalArgumentException &) { } + m1.SetMetadataReference(id1); + CPPUNIT_ASSERT_MESSAGE("set failed (existing)", + bool(m1.GetMetadataReference() == id1)); + m1.EnsureMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("ensure failed (existing)", + bool(m1.GetMetadataReference() == id1)); + + m2.EnsureMetadataReference(); + beans::StringPair m2id(m2.GetMetadataReference()); + CPPUNIT_ASSERT_MESSAGE("ensure failed", !m2id.Second.isEmpty()); + m2.EnsureMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("ensure failed (idempotent)", + bool(m2.GetMetadataReference() == m2id)); + + m1.m_bInUndo = true; + CPPUNIT_ASSERT_MESSAGE("move to undo failed", + m1.GetMetadataReference().Second.isEmpty()); + + m1.m_bInUndo = false; + CPPUNIT_ASSERT_MESSAGE("move from undo failed", + bool(m1.GetMetadataReference() == id1)); + + m1.m_bInUndo = true; + try { + m2.SetMetadataReference(id1); // steal! + } catch (lang::IllegalArgumentException &) { + CPPUNIT_FAIL("set duplicate to undo failed"); + } + m1.m_bInUndo = false; + CPPUNIT_ASSERT_MESSAGE("move from undo: duplicate", + m1.GetMetadataReference().Second.isEmpty()); + + m3.RegisterAsCopyOf(m2); + CPPUNIT_ASSERT_MESSAGE("copy: source", bool(m2.GetMetadataReference() == id1)); + CPPUNIT_ASSERT_MESSAGE("copy: duplicate", + m3.GetMetadataReference().Second.isEmpty()); + m4.RegisterAsCopyOf(m3); + CPPUNIT_ASSERT_MESSAGE("copy: source", bool(m2.GetMetadataReference() == id1)); + CPPUNIT_ASSERT_MESSAGE("copy: duplicate", + m3.GetMetadataReference().Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("copy: duplicate", + m4.GetMetadataReference().Second.isEmpty()); + m2.m_bInUndo = true; + CPPUNIT_ASSERT_MESSAGE("duplicate to undo", + bool(m3.GetMetadataReference() == id1)); + CPPUNIT_ASSERT_MESSAGE("duplicate to undo", + m2.GetMetadataReference().Second.isEmpty()); + m2.m_bInUndo = false; + CPPUNIT_ASSERT_MESSAGE("duplicate from undo", + bool(m2.GetMetadataReference() == id1)); + CPPUNIT_ASSERT_MESSAGE("duplicate from undo", + m3.GetMetadataReference().Second.isEmpty()); + + m4.EnsureMetadataReference(); // new! + beans::StringPair m4id(m4.GetMetadataReference()); + CPPUNIT_ASSERT_MESSAGE("ensure on duplicate", + !m4id.Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("ensure on duplicate", + !(m4id == id1)); + + MockMetadatable mc1(*pRegClip, true); // in clipboard + MockMetadatable mc2(*pRegClip, true); + MockMetadatable mc3(*pRegClip, true); + MockMetadatable mc4(*pRegClip, true); + MockMetadatable m2p(*pReg); + MockMetadatable m3p(*pReg); + + mc1.SetMetadataReference(id2); + CPPUNIT_ASSERT_MESSAGE("set failed", bool(mc1.GetMetadataReference() == id2)); + try { + mc2.SetMetadataReference(id2); + CPPUNIT_FAIL("set duplicate succeeded"); + } catch (const lang::IllegalArgumentException &) { } + mc1.SetMetadataReference(id2); + CPPUNIT_ASSERT_MESSAGE("set failed (existing)", + bool(mc1.GetMetadataReference() == id2)); + mc1.EnsureMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("ensure failed (existing)", + bool(mc1.GetMetadataReference() == id2)); + mc2.EnsureMetadataReference(); + beans::StringPair mc2id(mc2.GetMetadataReference()); + CPPUNIT_ASSERT_MESSAGE("ensure failed", !mc2id.Second.isEmpty()); + mc2.EnsureMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("ensure failed (idempotent)", + bool(mc2.GetMetadataReference() == mc2id)); + mc2.RemoveMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("remove failed", + mc2.GetMetadataReference().Second.isEmpty()); + + // set up mc2 as copy of m2 and mc3 as copy of m3 + mc3.RegisterAsCopyOf(m3); + CPPUNIT_ASSERT_MESSAGE("copy to clipboard (latent)", + mc3.GetMetadataReference().Second.isEmpty() ); + mc2.RegisterAsCopyOf(m2); + CPPUNIT_ASSERT_MESSAGE("copy to clipboard (non-latent)", + bool(mc2.GetMetadataReference() == id1)); + // paste mc2 to m2p and mc3 to m3p + m2p.RegisterAsCopyOf(mc2); + CPPUNIT_ASSERT_MESSAGE("paste from clipboard (non-latent)", + m2p.GetMetadataReference().Second.isEmpty() ); + m3p.RegisterAsCopyOf(mc3); + CPPUNIT_ASSERT_MESSAGE("paste from clipboard (latent)", + m3p.GetMetadataReference().Second.isEmpty() ); + // delete m2, m2p, m3 + m2.RemoveMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("remove failed", + m2.GetMetadataReference().Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("paste-remove (non-latent)", + bool(m2p.GetMetadataReference() == id1)); + m2p.RemoveMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("remove failed", + m2p.GetMetadataReference().Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("paste-remove2 (non-latent)", + bool(m3.GetMetadataReference() == id1)); + m3.RemoveMetadataReference(); + CPPUNIT_ASSERT_MESSAGE("remove failed", + m3.GetMetadataReference().Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("paste-remove (latent)", + bool(m3p.GetMetadataReference() == id1)); + // delete mc2 + mc2.SetMetadataReference(beans::StringPair()); + CPPUNIT_ASSERT_MESSAGE("in clipboard becomes non-latent", + mc3.GetMetadataReference().Second.isEmpty() ); + // paste mc2 + m2p.RegisterAsCopyOf(mc2); + CPPUNIT_ASSERT_MESSAGE("remove-paste", + m2p.GetMetadataReference().Second.isEmpty()); + CPPUNIT_ASSERT_MESSAGE("remove-paste (stolen)", + bool(m3p.GetMetadataReference() == id1)); + + // auto-detect stream + m5.SetMetadataReference(id3e); + CPPUNIT_ASSERT_MESSAGE("auto-detect (content)", + bool(m5.GetMetadataReference() == id3)); + m5.m_bInContent = false; + m5.SetMetadataReference(id4e); + CPPUNIT_ASSERT_MESSAGE("auto-detect (styles)", + bool(m5.GetMetadataReference() == id4)); +} + + +CPPUNIT_TEST_SUITE_REGISTRATION(MetadatableTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/qa/cppunit/test_misc.cxx b/sfx2/qa/cppunit/test_misc.cxx new file mode 100644 index 0000000000..d80a037f6f --- /dev/null +++ b/sfx2/qa/cppunit/test_misc.cxx @@ -0,0 +1,201 @@ +/* -*- 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 <sal/types.h> + +#ifndef _WIN32 +#include <sys/stat.h> +#include <unistd.h> +#endif +#include <memory> + +#include <cppunit/TestAssert.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/document/DocumentProperties.hpp> +#include <com/sun/star/packages/zip/ZipFileAccess.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> + +#include <test/unoapixml_test.hxx> + +#include <unotools/ucbstreamhelper.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/app.hxx> +#include <osl/file.hxx> + + +using namespace ::com::sun::star; + + +namespace { + +class MiscTest + : public UnoApiXmlTest +{ +public: + MiscTest() + : UnoApiXmlTest("/sfx2/qa/cppunit/misc/") + { + } + + virtual void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override + { + // ODF + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("office"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:office:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("meta"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:meta:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dc"), BAD_CAST("http://purl.org/dc/elements/1.1/")); + // used in testCustomMetadata + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("foo"), BAD_CAST("http://foo.net")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("baz"), BAD_CAST("http://baz.net")); + } +}; + +CPPUNIT_TEST_FIXTURE(MiscTest, testODFCustomMetadata) +{ + uno::Reference<document::XDocumentProperties> const xProps( + ::com::sun::star::document::DocumentProperties::create(m_xContext)); + + OUString const url(m_directories.getURLFromSrc(u"/sfx2/qa/complex/sfx2/testdocuments/CUSTOM.odt")); + xProps->loadFromMedium(url, uno::Sequence<beans::PropertyValue>()); + CPPUNIT_ASSERT_EQUAL(OUString(""), xProps->getAuthor()); + uno::Sequence<beans::PropertyValue> mimeArgs({ + beans::PropertyValue("MediaType", -1, uno::Any(OUString("application/vnd.oasis.opendocument.text")), beans::PropertyState_DIRECT_VALUE) + }); + xProps->storeToMedium(maTempFile.GetURL(), mimeArgs); + + // check that custom metadata is preserved + xmlDocUniquePtr pXmlDoc = parseExport("meta.xml"); + assertXPathContent(pXmlDoc, "/office:document-meta/office:meta/bork"_ostr, "bork"); + assertXPath(pXmlDoc, "/office:document-meta/office:meta/foo:bar"_ostr, 1); + assertXPath(pXmlDoc, "/office:document-meta/office:meta/foo:bar/baz:foo"_ostr, 1); + assertXPath(pXmlDoc, "/office:document-meta/office:meta/foo:bar/baz:foo[@baz:bar='foo']"_ostr); + assertXPathContent(pXmlDoc, "/office:document-meta/office:meta/foo:bar/foo:baz"_ostr, "bar"); +} + +CPPUNIT_TEST_FIXTURE(MiscTest, testNoThumbnail) +{ + // Load a document. + loadFromFile(u"hello.odt"); + + // Save it with the NoThumbnail option and assert that it has no thumbnail. +#ifndef _WIN32 + mode_t nMask = umask(022); +#endif + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xStorable.is()); + uno::Sequence<beans::PropertyValue> aProperties( + comphelper::InitPropertySequence({ { "NoThumbnail", uno::Any(true) } })); + osl::File::remove(maTempFile.GetURL()); + xStorable->storeToURL(maTempFile.GetURL(), aProperties); + uno::Reference<packages::zip::XZipFileAccess2> xZipFile + = packages::zip::ZipFileAccess::createWithURL(m_xContext, maTempFile.GetURL()); + CPPUNIT_ASSERT(!xZipFile->hasByName("Thumbnails/thumbnail.png")); + +#ifndef _WIN32 + // Check permissions of the URL after store. + osl::DirectoryItem aItem; + CPPUNIT_ASSERT_EQUAL(osl::DirectoryItem::E_None, + osl::DirectoryItem::get(maTempFile.GetURL(), aItem)); + + osl::FileStatus aStatus(osl_FileStatus_Mask_Attributes); + CPPUNIT_ASSERT_EQUAL(osl::DirectoryItem::E_None, aItem.getFileStatus(aStatus)); + + // The following checks used to fail in the past, osl_File_Attribute_GrpRead was not set even if + // umask requested so: + CPPUNIT_ASSERT(aStatus.getAttributes() & osl_File_Attribute_GrpRead); + CPPUNIT_ASSERT(aStatus.getAttributes() & osl_File_Attribute_OthRead); + + // Now "save as" again to trigger the "overwrite" case. + xStorable->storeToURL(maTempFile.GetURL(), {}); + CPPUNIT_ASSERT_EQUAL(osl::DirectoryItem::E_None, aItem.getFileStatus(aStatus)); + // The following check used to fail in the past, result had temp file + // permissions. + CPPUNIT_ASSERT(aStatus.getAttributes() & osl_File_Attribute_GrpRead); + + umask(nMask); +#endif +} + +CPPUNIT_TEST_FIXTURE(MiscTest, testHardLinks) +{ +#ifndef _WIN32 + OUString aTargetDir = m_directories.getURLFromWorkdir(u"/CppunitTest/sfx2_misc.test.user/"); + const OUString aURL(aTargetDir + "hello.odt"); + osl::File::copy(createFileURL(u"hello.odt"), aURL); + OUString aTargetPath; + osl::FileBase::getSystemPathFromFileURL(aURL, aTargetPath); + OString aOld = aTargetPath.toUtf8(); + aTargetPath += ".2"; + OString aNew = aTargetPath.toUtf8(); + int nRet = link(aOld.getStr(), aNew.getStr()); + CPPUNIT_ASSERT_EQUAL(0, nRet); + + mxComponent = loadFromDesktop(aURL, "com.sun.star.text.TextDocument"); + + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + xStorable->store(); + + struct stat buf; + // coverity[fs_check_call] - this is legitimate in the context of this test + nRet = stat(aOld.getStr(), &buf); + CPPUNIT_ASSERT_EQUAL(0, nRet); + // This failed: hard link count was 1, the hard link broke on store. + CPPUNIT_ASSERT(buf.st_nlink > 1); + + // Test that symlinks are preserved as well. + nRet = remove(aNew.getStr()); + CPPUNIT_ASSERT_EQUAL(0, nRet); + nRet = symlink(aOld.getStr(), aNew.getStr()); + CPPUNIT_ASSERT_EQUAL(0, nRet); + xStorable->storeToURL(aURL + ".2", {}); + nRet = lstat(aNew.getStr(), &buf); + CPPUNIT_ASSERT_EQUAL(0, nRet); + // This failed, the hello.odt.2 symlink was replaced with a real file. + CPPUNIT_ASSERT(bool(S_ISLNK(buf.st_mode))); +#endif +} + +CPPUNIT_TEST_FIXTURE(MiscTest, testOverwrite) +{ + // tdf#60237 - try to overwrite an existing file using the different settings of the Overwrite option + mxComponent + = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument"); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xStorable.is()); + + // overwrite the file using the default case of the Overwrite option (true) + CPPUNIT_ASSERT_NO_THROW(xStorable->storeToURL(maTempFile.GetURL(), {})); + + // explicitly overwrite the file using the Overwrite option + CPPUNIT_ASSERT_NO_THROW(xStorable->storeToURL( + maTempFile.GetURL(), + comphelper::InitPropertySequence({ { "Overwrite", uno::Any(true) } }))); + + try + { + // overwrite an existing file with the Overwrite flag set to false + xStorable->storeToURL(maTempFile.GetURL(), comphelper::InitPropertySequence( + { { "Overwrite", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE("We expect an exception on overwriting an existing file", false); + } + catch (const css::uno::Exception&) + { + } +} + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/qa/cppunit/view.cxx b/sfx2/qa/cppunit/view.cxx new file mode 100644 index 0000000000..725cb5d02c --- /dev/null +++ b/sfx2/qa/cppunit/view.cxx @@ -0,0 +1,64 @@ +/* -*- 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/unoapi_test.hxx> + +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <sfx2/app.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/viewfrm.hxx> +#include <svl/itemset.hxx> +#include <svl/intitem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/bindings.hxx> + +using namespace com::sun::star; + +/// Covers sfx2/source/view/ fixes. +class Sfx2ViewTest : public UnoApiTest +{ +public: + Sfx2ViewTest() + : UnoApiTest("/sfx2/qa/cppunit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Sfx2ViewTest, testReloadPage) +{ + // Load a document, which has 2 pages. + loadFromFile(u"reload-page.odg"); + + // Reload, and request to start on page 2. + SfxViewFrame* pFrame = SfxViewFrame::Current(); + SfxAllItemSet aSet(SfxGetpApp()->GetPool()); + aSet.Put(SfxInt32Item(SID_PAGE_NUMBER, 1)); + SfxRequest aReq(SID_RELOAD, SfxCallMode::SLOT, aSet); + pFrame->ExecReload_Impl(aReq); + uno::Reference<frame::XModel> xModel = SfxObjectShell::Current()->GetBaseModel(); + mxComponent = xModel; + + // Check the current page after reload. + uno::Reference<drawing::XDrawView> xController(xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPage(xController->getCurrentPage(), uno::UNO_QUERY); + sal_Int32 nPage{}; + xPage->getPropertyValue("Number") >>= nPage; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. the document was opened on page 1, not page 2, SID_PAGE_NUMBER was ignored. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), nPage); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |