From 5aea0dd59cf15c0f93d432aa722c1e0e1df703e4 Mon Sep 17 00:00:00 2001 From: Xisco Fauli Date: Mon, 23 Sep 2024 16:32:16 +0200 Subject: [PATCH] sfx2: move DocumentProperties from Java to CppUnittest Change-Id: I007ff75fb63a20304726a22fa3d949eb3616069e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173820 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- sfx2/JunitTest_sfx2_complex.mk | 3 - sfx2/qa/complex/sfx2/DocumentProperties.java | 516 ------------------- sfx2/qa/complex/sfx2/tools/TestDocument.java | 34 -- sfx2/qa/cppunit/test_misc.cxx | 406 +++++++++++++++ 4 files changed, 406 insertions(+), 553 deletions(-) delete mode 100644 sfx2/qa/complex/sfx2/DocumentProperties.java delete mode 100644 sfx2/qa/complex/sfx2/tools/TestDocument.java diff --git a/sfx2/JunitTest_sfx2_complex.mk b/sfx2/JunitTest_sfx2_complex.mk index 504d37e75e6f..7e23021a3ac2 100644 --- a/sfx2/JunitTest_sfx2_complex.mk +++ b/sfx2/JunitTest_sfx2_complex.mk @@ -31,11 +31,9 @@ $(eval $(call gb_JunitTest_use_jars,sfx2_complex,\ )) $(eval $(call gb_JunitTest_add_sourcefiles,sfx2_complex,\ - sfx2/qa/complex/sfx2/DocumentProperties \ sfx2/qa/complex/sfx2/GlobalEventBroadcaster \ sfx2/qa/complex/sfx2/UndoManager \ sfx2/qa/complex/sfx2/DocumentEvents \ - sfx2/qa/complex/sfx2/tools/TestDocument \ sfx2/qa/complex/sfx2/tools/WriterHelper \ sfx2/qa/complex/sfx2/undo/CalcDocumentTest \ sfx2/qa/complex/sfx2/undo/ChartDocumentTest \ @@ -48,7 +46,6 @@ $(eval $(call gb_JunitTest_add_sourcefiles,sfx2_complex,\ )) $(eval $(call gb_JunitTest_add_classes,sfx2_complex,\ - complex.sfx2.DocumentProperties \ complex.sfx2.DocumentEvents \ complex.sfx2.UndoManager \ )) diff --git a/sfx2/qa/complex/sfx2/DocumentProperties.java b/sfx2/qa/complex/sfx2/DocumentProperties.java deleted file mode 100644 index fe830f118d6d..000000000000 --- a/sfx2/qa/complex/sfx2/DocumentProperties.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * 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 . - */ - -package complex.sfx2; - - -import complex.sfx2.tools.TestDocument; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; -import com.sun.star.lang.XInitialization; - -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.lang.Locale; -import com.sun.star.lang.EventObject; -import com.sun.star.util.Date; -import com.sun.star.util.DateTime; -import com.sun.star.util.Time; -import com.sun.star.util.Duration; -import com.sun.star.util.XModifyListener; -import com.sun.star.util.XModifyBroadcaster; -import com.sun.star.beans.XPropertyContainer; -import com.sun.star.beans.XPropertySet; -import com.sun.star.beans.PropertyValue; -import com.sun.star.beans.NamedValue; -import com.sun.star.beans.PropertyAttribute; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.beans.IllegalTypeException; - -import com.sun.star.document.XDocumentProperties; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openoffice.test.OfficeConnection; -import static org.junit.Assert.*; - -/** - * Test case for the service com.sun.star.document.DocumentProperties. - * Currently, this service is implemented in - * sfx2/source/doc/SfxDocumentMetaData.cxx. - * - */ -public class DocumentProperties -{ - @After public void cleanup() { - // nothing to do - } - - // for testing modifications - private class Listener implements XModifyListener { - private boolean m_Called; - - Listener() { - m_Called = false; - } - - private boolean reset() { - boolean oldCalled = m_Called; - m_Called = false; - return oldCalled; - } - - public void modified(EventObject e) { - m_Called = true; - } - - public void disposing(EventObject e) { - } - } - - @Test public void check() throws Exception - { - XMultiServiceFactory xMSF = getMSF(); - assertNotNull("could not create MultiServiceFactory.", xMSF); - XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xMSF); - Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext"); - XComponentContext xContext = UnoRuntime.queryInterface(XComponentContext.class, defaultCtx); - assertNotNull("could not get component context.", xContext); - - // TODO: Path to temp - String temp = util.utils.getOfficeTemp/*Dir*/(xMSF); - System.out.println("tempdir: " + temp); - - PropertyValue[] noArgs = { }; - PropertyValue mimetype = new PropertyValue(); - mimetype.Name = "MediaType"; - mimetype.Value = "application/vnd.oasis.opendocument.text"; - PropertyValue[] mimeArgs = { mimetype }; - PropertyValue cfile = new PropertyValue(); - cfile.Name = "URL"; - cfile.Value = temp + "EMPTY.odt"; - PropertyValue[] mimeEmptyArgs = { mimetype, cfile }; - - System.out.println("Creating service DocumentProperties..."); - - Object oDP = - xMSF.createInstance("com.sun.star.document.DocumentProperties"); - XDocumentProperties xDP = UnoRuntime.queryInterface(XDocumentProperties.class, oDP); - - System.out.println("...done"); - - - System.out.println("Checking initialize ..."); - - XDocumentProperties xDP2 = UnoRuntime.queryInterface(XDocumentProperties.class, xMSF.createInstance("com.sun.star.document.DocumentProperties")); - XInitialization xInit = UnoRuntime.queryInterface(XInitialization.class, xDP2); - xInit.initialize(new Object[] { }); - - System.out.println("...done"); - - System.out.println("Checking storing default-initialized meta data ..."); - - xDP2.storeToMedium("", mimeEmptyArgs); - - System.out.println("...done"); - - System.out.println("Checking loading default-initialized meta data ..."); - - xDP2.loadFromMedium("", mimeEmptyArgs); - assertEquals("Author", "", xDP2.getAuthor()); - - System.out.println("...done"); - - System.out.println("Checking loading from test document..."); - - String file = TestDocument.getUrl("TEST.odt"); - xDP.loadFromMedium(file, noArgs); -/* XInputStream xStream = - new StreamSimulator("./testdocuments/TEST.odt", true, param); - Object oSF = - xMSF.createInstance("com.sun.star.embed.StorageFactory"); - XSingleServiceFactory xSF = (XSingleServiceFactory) - UnoRuntime.queryInterface(XSingleServiceFactory.class, oSF); - Object oStor = xSF.createInstanceWithArguments( - new Object[] { xStream }); - XStorage xStor = (XStorage) UnoRuntime.queryInterface( - XStorage.class, oStor); - xDP.loadFromStorage(xStor);*/ - - System.out.println("...done"); - - System.out.println("Checking meta-data import..."); - - assertEquals("Author", "Karl-Heinz Mustermann", xDP.getAuthor()); - assertEquals( - "Generator", - "StarOffice/8$Solaris_x86 OpenOffice.org_project/680m232$Build-9227", - xDP.getGenerator()); - assertEquals("CreationDate", 2007, xDP.getCreationDate().Year); - assertEquals("Title", "Urgent Memo", xDP.getTitle()); - assertEquals("Subject", "Wichtige Mitteilung", xDP.getSubject()); - assertEquals( - "Description", - "Modern internal company memorandum in full-blocked style", - xDP.getDescription()); - assertEquals( - "ModifiedBy", "Karl-Heinz Mustermann", xDP.getModifiedBy()); - assertEquals( - "ModificationDate", 10, xDP.getModificationDate().Month); - assertEquals( - "PrintedBy", "Karl-Heinz Mustermann", xDP.getPrintedBy()); - assertEquals("PrintDate", 29, xDP.getPrintDate().Day); - assertEquals("TemplateName", "Modern Memo", xDP.getTemplateName()); - assertTrue("TemplateURL", - xDP.getTemplateURL().endsWith("memmodern.ott")); - assertEquals("TemplateDate", 17, xDP.getTemplateDate().Hours); - assertTrue( - "AutoloadURL", xDP.getAutoloadURL().endsWith("/TEST.odt")); - assertEquals("AutoloadSecs", 0, xDP.getAutoloadSecs()); - assertEquals("DefaultTarget", "_blank", xDP.getDefaultTarget()); - assertEquals("EditingCycles", 3, xDP.getEditingCycles()); - assertEquals("EditingDuration", 320, xDP.getEditingDuration()); - - String[] kws = xDP.getKeywords(); - assertTrue("Keywords", fromArray(kws).containsAll( - fromArray(new Object[] { "Asien", "Memo", "Reis" }))); - - NamedValue[] ds = xDP.getDocumentStatistics(); - assertTrue("DocumentStatistics:WordCount", containsNV(ds, - new NamedValue("WordCount", Integer.valueOf(23)))); - assertTrue("DocumentStatistics:PageCount", containsNV(ds, - new NamedValue("PageCount", Integer.valueOf(1)))); - - XPropertyContainer udpc = xDP.getUserDefinedProperties(); - XPropertySet udps = UnoRuntime.queryInterface( XPropertySet.class, udpc ); - assertEquals( - "UserDefined 1", "Dies ist ein wichtiger Hinweis", - udps.getPropertyValue("Hinweis")); - assertEquals( - "UserDefined 2", "Kann Spuren von N\u00FCssen enthalten", - udps.getPropertyValue("Warnung")); - - System.out.println("...done"); - - System.out.println("Checking meta-data updates..."); - - String str; - DateTime dt = new DateTime(); - Locale l = new Locale(); - int i; - - str = "me"; - xDP.setAuthor(str); - assertEquals("setAuthor", str, xDP.getAuthor()); - str = "the computa"; - xDP.setGenerator(str); - assertEquals("setGenerator", str, xDP.getGenerator()); - dt.Year = 2038; - dt.Month = 1; - dt.Day = 1; - xDP.setCreationDate(dt); - assertEquals( - "setCreationDate", dt.Year, xDP.getCreationDate().Year); - str = "El t'itulo"; - xDP.setTitle(str); - assertEquals("setTitle", str, xDP.getTitle()); - str = "Ein verkommenes Subjekt"; - xDP.setSubject(str); - assertEquals("setSubject", str, xDP.getSubject()); - str = "Este descripci'on no es importante"; - xDP.setDescription(str); - assertEquals("setDescription", str, xDP.getDescription()); - l.Language = "en"; - l.Country = "GB"; - xDP.setLanguage(l); - Locale l2 = xDP.getLanguage(); - assertEquals("setLanguage Lang", l.Language, l2.Language); - assertEquals("setLanguage Cty", l.Country, l2.Country); - str = "myself"; - xDP.setModifiedBy(str); - assertEquals("setModifiedBy", str, xDP.getModifiedBy()); - dt.Year = 2042; - xDP.setModificationDate(dt); - assertEquals( - "setModificationDate", dt.Year, xDP.getModificationDate().Year); - str = "i did not do it"; - xDP.setPrintedBy(str); - assertEquals("setPrintedBy", str, xDP.getPrintedBy()); - dt.Year = 2024; - xDP.setPrintDate(dt); - assertEquals("setPrintDate", dt.Year, xDP.getPrintDate().Year); - str = "blah"; - xDP.setTemplateName(str); - assertEquals("setTemplateName", str, xDP.getTemplateName()); - str = "gopher://some-hole-in-the-ground/"; - xDP.setTemplateURL(str); - assertEquals("setTemplateURL", str, xDP.getTemplateURL()); - dt.Year = 2043; - xDP.setTemplateDate(dt); - assertEquals( - "setTemplateDate", dt.Year, xDP.getTemplateDate().Year); - str = "http://nowhere/"; - xDP.setAutoloadURL(str); - assertEquals("setAutoloadURL", str, xDP.getAutoloadURL()); - i = 3661; // this might not work (due to conversion via double...) - xDP.setAutoloadSecs(i); - assertEquals("setAutoloadSecs", i, xDP.getAutoloadSecs()); - str = "_blank"; - xDP.setDefaultTarget(str); - assertEquals("setDefaultTarget", str, xDP.getDefaultTarget()); - i = 42; - xDP.setEditingCycles((short) i); - assertEquals("setEditingCycles", i, xDP.getEditingCycles()); - i = 84; - xDP.setEditingDuration(i); - assertEquals("setEditingDuration", i, xDP.getEditingDuration()); - str = ""; - - String[] kws2 = new String[] { - "keywordly", "keywordlike", "keywordalicious" }; - xDP.setKeywords(kws2); - kws = xDP.getKeywords(); - assertTrue("setKeywords", fromArray(kws).containsAll(fromArray(kws2))); - - NamedValue[] ds2 = new NamedValue[] { - new NamedValue("SyllableCount", Integer.valueOf(9)), - new NamedValue("FrameCount", Integer.valueOf(2)), - new NamedValue("SentenceCount", Integer.valueOf(7)) }; - xDP.setDocumentStatistics(ds2); - ds = xDP.getDocumentStatistics(); - assertTrue("setDocumentStatistics:SyllableCount", containsNV(ds, - new NamedValue("SyllableCount", Integer.valueOf(9)))); - assertTrue("setDocumentStatistics:FrameCount", containsNV(ds, - new NamedValue("FrameCount", Integer.valueOf(2)))); - assertTrue("setDocumentStatistics:SentenceCount", containsNV(ds, - new NamedValue("SentenceCount", Integer.valueOf(7)))); - - System.out.println("...done"); - - System.out.println("Checking user-defined meta-data updates..."); - - // actually, this tests the PropertyBag service - // but maybe the DocumentProperties service will be implemented - // differently some day... - boolean b = true; - double d = 3.1415; - // note that Time is only supported for backward compatibility! - Time t = new Time(); - t.Hours = 1; - t.Minutes = 16; - Date date = new Date(); - date.Year = 2071; - date.Month = 2; - date.Day = 3; - dt.Year = 2065; - Duration dur = new Duration(); - dur.Negative = true; - dur.Years = 1001; - dur.Months = 999; - dur.Days = 888; - dur.Hours = 777; - dur.Minutes = 666; - dur.Seconds = 555; - dur.NanoSeconds = 444444444; - - udpc.addProperty("Frobnicate", PropertyAttribute.REMOVABLE, b); - udpc.addProperty("FrobDuration", PropertyAttribute.REMOVABLE, dur); - udpc.addProperty("FrobDuration2", PropertyAttribute.REMOVABLE, t); - udpc.addProperty("FrobEndDate", PropertyAttribute.REMOVABLE, date); - udpc.addProperty("FrobStartTime", PropertyAttribute.REMOVABLE, dt); - udpc.addProperty("Pi", PropertyAttribute.REMOVABLE, Double.valueOf(d)); - udpc.addProperty("Foo", PropertyAttribute.REMOVABLE, "bar"); - udpc.addProperty("Removed", PropertyAttribute.REMOVABLE, "bar"); - // #i94175#: empty property name is valid ODF 1.1 - udpc.addProperty("", PropertyAttribute.REMOVABLE, "eeeeek"); - try { - udpc.removeProperty("Info 1"); - udpc.removeProperty("Removed"); - } catch (UnknownPropertyException e) { - fail("removeProperty failed"); - } - - try { - udpc.addProperty("Forbidden", PropertyAttribute.REMOVABLE, - new String[] { "foo", "bar" }); - fail("inserting value of non-supported type did not fail"); - } catch (IllegalTypeException e) { - // ignore - } - - assertEquals( - "UserDefined bool", b, udps.getPropertyValue("Frobnicate")); - assertTrue("UserDefined duration", eqDuration(dur, (Duration) - udps.getPropertyValue("FrobDuration"))); - assertTrue("UserDefined time", eqTime(t, (Time) - udps.getPropertyValue("FrobDuration2"))); - assertTrue("UserDefined date", eqDate(date, (Date) - udps.getPropertyValue("FrobEndDate"))); - assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime) - udps.getPropertyValue("FrobStartTime"))); - assertEquals("UserDefined float", d, udps.getPropertyValue("Pi")); - assertEquals( - "UserDefined string", "bar", udps.getPropertyValue("Foo")); - assertEquals( - "UserDefined empty name", "eeeeek", udps.getPropertyValue("")); - - try { - udps.getPropertyValue("Removed"); - fail("UserDefined remove didn't"); - } catch (UnknownPropertyException e) { - // ok - } - - System.out.println("...done"); - - System.out.println("Checking storing meta-data to file..."); - - xDP.storeToMedium(temp + "TEST.odt", mimeArgs); - - System.out.println("...done"); - - System.out.println("Checking loading meta-data from stored file..."); - - xDP.loadFromMedium(temp + "TEST.odt", noArgs); - - System.out.println("...done"); - - System.out.println("Checking user-defined meta-data from stored file..."); - - udpc = xDP.getUserDefinedProperties(); - udps = UnoRuntime.queryInterface( XPropertySet.class, udpc ); - - assertEquals( - "UserDefined bool", b, udps.getPropertyValue("Frobnicate")); - assertTrue("UserDefined duration", eqDuration(dur, (Duration) - udps.getPropertyValue("FrobDuration"))); - // this is now a Duration! - Duration t_dur = new Duration(false, (short)0, (short)0, (short)0, - t.Hours, t.Minutes, t.Seconds, - t.NanoSeconds); - assertTrue("UserDefined time", eqDuration(t_dur, (Duration) - udps.getPropertyValue("FrobDuration2"))); - assertTrue("UserDefined date", eqDate(date, (Date) - udps.getPropertyValue("FrobEndDate"))); - assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime) - udps.getPropertyValue("FrobStartTime"))); - assertEquals("UserDefined float", d, udps.getPropertyValue("Pi")); - assertEquals( - "UserDefined string", "bar", udps.getPropertyValue("Foo")); - - try { - udps.getPropertyValue("Removed"); - fail("UserDefined remove didn't"); - } catch (UnknownPropertyException e) { - // ok - } - - System.out.println("...done"); - - System.out.println("Checking notification listener interface..."); - - Listener listener = new Listener(); - XModifyBroadcaster xMB = UnoRuntime.queryInterface( XModifyBroadcaster.class, xDP ); - xMB.addModifyListener(listener); - xDP.setAuthor("not me"); - assertTrue("Listener Author", listener.reset()); - udpc.addProperty("Listener", PropertyAttribute.REMOVABLE, "foo"); - assertTrue("Listener UserDefined Add", listener.reset()); - udps.setPropertyValue("Listener", "bar"); - assertTrue("Listener UserDefined Set", listener.reset()); - udpc.removeProperty("Listener"); - assertTrue("Listener UserDefined Remove", listener.reset()); - xMB.removeModifyListener(listener); - udpc.addProperty("Listener2", PropertyAttribute.REMOVABLE, "foo"); - assertTrue("Removed Listener UserDefined Add", !listener.reset()); - - System.out.println("...done"); - } - - // grrr... - boolean eqDateTime(DateTime a, DateTime b) { - return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day - && a.Hours == b.Hours && a.Minutes == b.Minutes - && a.Seconds == b.Seconds - && a.NanoSeconds == b.NanoSeconds; - } - - boolean eqDate(Date a, Date b) { - return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day; - } - - boolean eqTime(Time a, Time b) { - return a.Hours == b.Hours && a.Minutes == b.Minutes - && a.Seconds == b.Seconds - && a.NanoSeconds == b.NanoSeconds; - } - - boolean eqDuration(Duration a, Duration b) { - return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days - && a.Hours == b.Hours && a.Minutes == b.Minutes - && a.Seconds == b.Seconds - && a.NanoSeconds == b.NanoSeconds - && a.Negative == b.Negative; - } - - java.util.Collection fromArray(Object[] os) { - java.util.Collection ret = new java.util.HashSet(); - for (int i = 0; i < os.length; ++i) { - ret.add(os[i]); - } - return ret; - } - - // bah, structs do not have proper equals(), and uno.Type is not comparable - public static boolean containsNV (NamedValue[] nvs, NamedValue nv) { - for (int i = 0; i < nvs.length; ++i) { - if (nvs[i].Name.equals(nv.Name) && nvs[i].Value.equals(nv.Value)) { - return true; - } - } - return false; - } - - private XMultiServiceFactory getMSF() - { - final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface( XMultiServiceFactory.class, connection.getComponentContext().getServiceManager() ); - return xMSF1; - } - - // setup and close connections - @BeforeClass public static void setUpConnection() throws Exception { - System.out.println( "------------------------------------------------------------" ); - System.out.println( "starting class: " + DocumentProperties.class.getName() ); - System.out.println( "------------------------------------------------------------" ); - connection.setUp(); - } - - @AfterClass public static void tearDownConnection() - throws InterruptedException, com.sun.star.uno.Exception - { - System.out.println( "------------------------------------------------------------" ); - System.out.println( "finishing class: " + DocumentProperties.class.getName() ); - System.out.println( "------------------------------------------------------------" ); - connection.tearDown(); - } - - private static final OfficeConnection connection = new OfficeConnection(); - -} - diff --git a/sfx2/qa/complex/sfx2/tools/TestDocument.java b/sfx2/qa/complex/sfx2/tools/TestDocument.java deleted file mode 100644 index 462c97fb99b7..000000000000 --- a/sfx2/qa/complex/sfx2/tools/TestDocument.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 . - */ - -package complex.sfx2.tools; - -import java.io.File; -import org.openoffice.test.OfficeFileUrl; -import org.openoffice.test.Argument; - -public final class TestDocument { - public static String getUrl(String name) { - return OfficeFileUrl.getAbsolute(new File(Argument.get("tdoc"), name)); - } - public static String getPath(String name) { - return new File(Argument.get("tdoc"), name).toString(); - } - - private TestDocument() {} -} diff --git a/sfx2/qa/cppunit/test_misc.cxx b/sfx2/qa/cppunit/test_misc.cxx index 4c842df2a4f7..c32fee011900 100644 --- a/sfx2/qa/cppunit/test_misc.cxx +++ b/sfx2/qa/cppunit/test_misc.cxx @@ -16,6 +16,9 @@ #include #include +#include +#include +#include #include #include #include @@ -24,6 +27,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include @@ -59,6 +69,28 @@ public: } }; +class Listener : public ::cppu::WeakImplHelper +{ +public: + Listener() + : bCalled(false) + { + } + + bool reset() + { + bool bOld = bCalled; + bCalled = false; + return bOld; + } + +private: + bool bCalled; + + virtual void SAL_CALL disposing(const lang::EventObject&) noexcept override {} + virtual void SAL_CALL modified(const lang::EventObject&) noexcept override { bCalled = true; } +}; + CPPUNIT_TEST_FIXTURE(MiscTest, testODFCustomMetadata) { uno::Reference const xProps( @@ -81,6 +113,380 @@ CPPUNIT_TEST_FIXTURE(MiscTest, testODFCustomMetadata) assertXPathContent(pXmlDoc, "/office:document-meta/office:meta/foo:bar/foo:baz"_ostr, u"bar"_ustr); } +/** + * Test case for the service com.sun.star.document.DocumentProperties. + * Currently, this service is implemented in + * sfx2/source/doc/SfxDocumentMetaData.cxx. + * + */ +CPPUNIT_TEST_FIXTURE(MiscTest, testDocumentProperties) +{ + uno::Reference const xProps( + ::com::sun::star::document::DocumentProperties::create(m_xContext)); + + OUString const url( + m_directories.getURLFromSrc(u"/sfx2/qa/complex/sfx2/testdocuments/TEST.odt")); + xProps->loadFromMedium(url, uno::Sequence()); + CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getAuthor()); + CPPUNIT_ASSERT_EQUAL(u"StarOffice/8$Solaris_x86 OpenOffice.org_project/680m232$Build-9227"_ustr, + xProps->getGenerator()); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2007), xProps->getCreationDate().Year); + CPPUNIT_ASSERT_EQUAL(u"Urgent Memo"_ustr, xProps->getTitle()); + CPPUNIT_ASSERT_EQUAL(u"Wichtige Mitteilung"_ustr, xProps->getSubject()); + CPPUNIT_ASSERT_EQUAL(u"Modern internal company memorandum in full-blocked style"_ustr, + xProps->getDescription()); + CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getModifiedBy()); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(10), xProps->getModificationDate().Month); + CPPUNIT_ASSERT_EQUAL(u"Karl-Heinz Mustermann"_ustr, xProps->getPrintedBy()); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(29), xProps->getPrintDate().Day); + CPPUNIT_ASSERT_EQUAL(u"Modern Memo"_ustr, xProps->getTemplateName()); + CPPUNIT_ASSERT(xProps->getTemplateURL().endsWith("memmodern.ott")); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(17), xProps->getTemplateDate().Hours); + CPPUNIT_ASSERT(xProps->getAutoloadURL().endsWith("/TEST.odt")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xProps->getAutoloadSecs()); + CPPUNIT_ASSERT_EQUAL(u"_blank"_ustr, xProps->getDefaultTarget()); + CPPUNIT_ASSERT_EQUAL(sal_Int16(3), xProps->getEditingCycles()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(320), xProps->getEditingDuration()); + + uno::Sequence aKeywords(xProps->getKeywords()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aKeywords.getLength()); + CPPUNIT_ASSERT_EQUAL(u"Memo"_ustr, aKeywords[0]); + CPPUNIT_ASSERT_EQUAL(u"Asien"_ustr, aKeywords[1]); + CPPUNIT_ASSERT_EQUAL(u"Reis"_ustr, aKeywords[2]); + + uno::Sequence aDocStats = xProps->getDocumentStatistics(); + auto it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats), + [](const css::beans::NamedValue& val) { + return val.Name == "WordCount" && val.Value.get() == 23; + }); + CPPUNIT_ASSERT(it != std::cend(aDocStats)); + + it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats), + [](const css::beans::NamedValue& val) { + return val.Name == "PageCount" && val.Value.get() == 1; + }); + CPPUNIT_ASSERT(it != std::cend(aDocStats)); + + uno::Reference xUDP = xProps->getUserDefinedProperties(); + uno::Reference xPropertySet(xUDP, uno::UNO_QUERY); + uno::Any aAny = xPropertySet->getPropertyValue(u"Hinweis"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Dies ist ein wichtiger Hinweis"_ustr, aAny.get()); + + aAny = xPropertySet->getPropertyValue(u"Warnung"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Kann Spuren von N\u00FCssen enthalten"_ustr, aAny.get()); + + xProps->setAuthor(u"me"_ustr); + CPPUNIT_ASSERT_EQUAL(u"me"_ustr, xProps->getAuthor()); + + xProps->setGenerator(u"the computa"_ustr); + CPPUNIT_ASSERT_EQUAL(u"the computa"_ustr, xProps->getGenerator()); + + css::util::DateTime aDateTime; + aDateTime.Day = 1; + aDateTime.Month = 1; + aDateTime.Year = 2038; + xProps->setCreationDate(aDateTime); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2038), xProps->getCreationDate().Year); + + xProps->setTitle(u"El t'itulo"_ustr); + CPPUNIT_ASSERT_EQUAL(u"El t'itulo"_ustr, xProps->getTitle()); + + xProps->setSubject(u"Ein verkommenes Subjekt"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Ein verkommenes Subjekt"_ustr, xProps->getSubject()); + + xProps->setDescription(u"Este descripci'on no es importante"_ustr); + CPPUNIT_ASSERT_EQUAL(u"Este descripci'on no es importante"_ustr, xProps->getDescription()); + + lang::Locale aLang; + aLang.Language = u"en"_ustr; + aLang.Country = u"GB"_ustr; + + xProps->setLanguage(aLang); + CPPUNIT_ASSERT_EQUAL(aLang.Language, xProps->getLanguage().Language); + CPPUNIT_ASSERT_EQUAL(aLang.Country, xProps->getLanguage().Country); + + xProps->setModifiedBy(u"myself"_ustr); + CPPUNIT_ASSERT_EQUAL(u"myself"_ustr, xProps->getModifiedBy()); + + aDateTime.Year = 2042; + xProps->setModificationDate(aDateTime); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2042), xProps->getModificationDate().Year); + + xProps->setPrintedBy(u"i did not do it"_ustr); + CPPUNIT_ASSERT_EQUAL(u"i did not do it"_ustr, xProps->getPrintedBy()); + + aDateTime.Year = 2024; + xProps->setPrintDate(aDateTime); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2024), xProps->getPrintDate().Year); + + xProps->setTemplateName(u"blah"_ustr); + CPPUNIT_ASSERT_EQUAL(u"blah"_ustr, xProps->getTemplateName()); + + xProps->setTemplateURL(u"gopher://some-hole-in-the-ground/"_ustr); + CPPUNIT_ASSERT_EQUAL(u"gopher://some-hole-in-the-ground/"_ustr, xProps->getTemplateURL()); + + aDateTime.Year = 2043; + xProps->setTemplateDate(aDateTime); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2043), xProps->getTemplateDate().Year); + + xProps->setAutoloadURL(u"http://nowhere/"_ustr); + CPPUNIT_ASSERT_EQUAL(u"http://nowhere/"_ustr, xProps->getAutoloadURL()); + + xProps->setAutoloadSecs(3661); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3661), xProps->getAutoloadSecs()); + + xProps->setDefaultTarget(u"_blank"_ustr); + CPPUNIT_ASSERT_EQUAL(u"_blank"_ustr, xProps->getDefaultTarget()); + + xProps->setEditingCycles(42); + CPPUNIT_ASSERT_EQUAL(sal_Int16(42), xProps->getEditingCycles()); + + xProps->setEditingDuration(84); + CPPUNIT_ASSERT_EQUAL(sal_Int32(84), xProps->getEditingDuration()); + + uno::Sequence aKeywords2{ u"keywordly"_ustr, u"keywordlike"_ustr, + u"keywordalicious"_ustr }; + xProps->setKeywords(aKeywords2); + aKeywords = xProps->getKeywords(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aKeywords.getLength()); + CPPUNIT_ASSERT_EQUAL(u"keywordly"_ustr, aKeywords[0]); + CPPUNIT_ASSERT_EQUAL(u"keywordlike"_ustr, aKeywords[1]); + CPPUNIT_ASSERT_EQUAL(u"keywordalicious"_ustr, aKeywords[2]); + + uno::Sequence aDocStats2{ { u"SyllableCount"_ustr, uno::Any(sal_Int16(9)) }, + { u"FrameCount"_ustr, uno::Any(sal_Int16(2)) }, + { u"SentenceCount"_ustr, + uno::Any(sal_Int16(7)) } }; + + xProps->setDocumentStatistics(aDocStats2); + aDocStats = xProps->getDocumentStatistics(); + + it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats), + [](const css::beans::NamedValue& val) { + return val.Name == "SyllableCount" && val.Value.get() == 9; + }); + CPPUNIT_ASSERT(it != std::cend(aDocStats)); + + it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats), + [](const css::beans::NamedValue& val) { + return val.Name == "FrameCount" && val.Value.get() == 2; + }); + CPPUNIT_ASSERT(it != std::cend(aDocStats)); + + it = std::find_if(std::cbegin(aDocStats), std::cend(aDocStats), + [](const css::beans::NamedValue& val) { + return val.Name == "SentenceCount" && val.Value.get() == 7; + }); + CPPUNIT_ASSERT(it != std::cend(aDocStats)); + + // actually, this tests the PropertyBag service + // but maybe the DocumentProperties service will be implemented + // differently some day... + + // note that Time is only supported for backward compatibility! + css::util::Time aTime; + aTime.Hours = 1; + aTime.Minutes = 16; + + css::util::Date aDate; + aDate.Year = 2071; + aDate.Month = 2; + aDate.Day = 3; + + aDateTime.Year = 2065; + + css::util::Duration aDur; + aDur.Negative = true; + aDur.Years = 1001; + aDur.Months = 999; + aDur.Days = 888; + aDur.Hours = 777; + aDur.Minutes = 666; + aDur.Seconds = 555; + aDur.NanoSeconds = 444444444; + + xUDP->addProperty("Frobnicate", beans::PropertyAttribute::REMOVABLE, uno::Any(true)); + xUDP->addProperty("FrobDuration", beans::PropertyAttribute::REMOVABLE, uno::Any(aDur)); + xUDP->addProperty("FrobDuration2", beans::PropertyAttribute::REMOVABLE, uno::Any(aTime)); + xUDP->addProperty("FrobEndDate", beans::PropertyAttribute::REMOVABLE, uno::Any(aDate)); + xUDP->addProperty("FrobStartTime", beans::PropertyAttribute::REMOVABLE, uno::Any(aDateTime)); + xUDP->addProperty("Pi", beans::PropertyAttribute::REMOVABLE, uno::Any(3.1415)); + xUDP->addProperty("Foo", beans::PropertyAttribute::REMOVABLE, uno::Any(u"bar"_ustr)); + xUDP->addProperty("Removed", beans::PropertyAttribute::REMOVABLE, uno::Any(u"bar"_ustr)); + // #i94175#: empty property name is valid ODF 1.1 + xUDP->addProperty("", beans::PropertyAttribute::REMOVABLE, uno::Any(u"eeeeek"_ustr)); + + try + { + xUDP->removeProperty(u"Info 1"_ustr); + xUDP->removeProperty(u"Removed"_ustr); + } + catch (beans::UnknownPropertyException&) + { + CPPUNIT_FAIL("removeProperty failed"); + } + + try + { + xUDP->addProperty("Forbidden", beans::PropertyAttribute::REMOVABLE, + uno::Any(uno::Sequence{ u"foo"_ustr, u"bar"_ustr })); + CPPUNIT_FAIL("inserting value of non-supported type did not fail"); + } + catch (beans::IllegalTypeException&) + { + } + + aAny = xPropertySet->getPropertyValue(u"Frobnicate"_ustr); + CPPUNIT_ASSERT_EQUAL(true, aAny.get()); + + aAny = xPropertySet->getPropertyValue(u"FrobDuration"_ustr); + css::util::Duration aDur2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDur.Negative, aDur2.Negative); + CPPUNIT_ASSERT_EQUAL(aDur.Years, aDur2.Years); + CPPUNIT_ASSERT_EQUAL(aDur.Months, aDur2.Months); + CPPUNIT_ASSERT_EQUAL(aDur.Days, aDur2.Days); + CPPUNIT_ASSERT_EQUAL(aDur.Hours, aDur2.Hours); + CPPUNIT_ASSERT_EQUAL(aDur.Minutes, aDur2.Minutes); + CPPUNIT_ASSERT_EQUAL(aDur.Seconds, aDur2.Seconds); + CPPUNIT_ASSERT_EQUAL(aDur.NanoSeconds, aDur2.NanoSeconds); + + aAny = xPropertySet->getPropertyValue(u"FrobDuration2"_ustr); + css::util::Time aTime2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aTime.Hours, aTime2.Hours); + CPPUNIT_ASSERT_EQUAL(aTime.Minutes, aTime2.Minutes); + CPPUNIT_ASSERT_EQUAL(aTime.Seconds, aTime2.Seconds); + CPPUNIT_ASSERT_EQUAL(aTime.NanoSeconds, aTime2.NanoSeconds); + + aAny = xPropertySet->getPropertyValue(u"FrobEndDate"_ustr); + css::util::Date aDate2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDate.Day, aDate2.Day); + CPPUNIT_ASSERT_EQUAL(aDate.Month, aDate2.Month); + CPPUNIT_ASSERT_EQUAL(aDate.Year, aDate2.Year); + + aAny = xPropertySet->getPropertyValue(u"FrobStartTime"_ustr); + css::util::DateTime aDateTime2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDateTime.Year, aDateTime2.Year); + CPPUNIT_ASSERT_EQUAL(aDateTime.Month, aDateTime2.Month); + CPPUNIT_ASSERT_EQUAL(aDateTime.Day, aDateTime2.Day); + CPPUNIT_ASSERT_EQUAL(aDateTime.Hours, aDateTime2.Hours); + CPPUNIT_ASSERT_EQUAL(aDateTime.Minutes, aDateTime2.Minutes); + CPPUNIT_ASSERT_EQUAL(aDateTime.Seconds, aDateTime2.Seconds); + CPPUNIT_ASSERT_EQUAL(aDateTime.NanoSeconds, aDateTime2.NanoSeconds); + + aAny = xPropertySet->getPropertyValue(u"Pi"_ustr); + double aPi = aAny.get(); + CPPUNIT_ASSERT_EQUAL(3.1415, aPi); + + aAny = xPropertySet->getPropertyValue(u"Foo"_ustr); + OUString aFoo = aAny.get(); + CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, aFoo); + + aAny = xPropertySet->getPropertyValue(u""_ustr); + OUString aEmpty = aAny.get(); + CPPUNIT_ASSERT_EQUAL(u"eeeeek"_ustr, aEmpty); + + try + { + xPropertySet->getPropertyValue(u"Removed"_ustr); + CPPUNIT_FAIL("UserDefined remove didn't"); + } + catch (beans::UnknownPropertyException&) + { + } + + uno::Sequence mimeArgs({ beans::PropertyValue( + u"MediaType"_ustr, -1, uno::Any(u"application/vnd.oasis.opendocument.text"_ustr), + beans::PropertyState_DIRECT_VALUE) }); + xProps->storeToMedium(maTempFile.GetURL(), mimeArgs); + + xProps->loadFromMedium(maTempFile.GetURL(), uno::Sequence()); + + xUDP = xProps->getUserDefinedProperties(); + xPropertySet.set(xUDP, uno::UNO_QUERY); + + aAny = xPropertySet->getPropertyValue(u"Frobnicate"_ustr); + CPPUNIT_ASSERT_EQUAL(true, aAny.get()); + + aAny = xPropertySet->getPropertyValue(u"FrobDuration"_ustr); + aDur2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDur.Negative, aDur2.Negative); + CPPUNIT_ASSERT_EQUAL(aDur.Years, aDur2.Years); + CPPUNIT_ASSERT_EQUAL(aDur.Months, aDur2.Months); + CPPUNIT_ASSERT_EQUAL(aDur.Days, aDur2.Days); + CPPUNIT_ASSERT_EQUAL(aDur.Hours, aDur2.Hours); + CPPUNIT_ASSERT_EQUAL(aDur.Minutes, aDur2.Minutes); + CPPUNIT_ASSERT_EQUAL(aDur.Seconds, aDur2.Seconds); + CPPUNIT_ASSERT_EQUAL(aDur.NanoSeconds, aDur2.NanoSeconds); + + css::util::Duration aDur3(false, 0, 0, 0, aTime.Hours, aTime.Minutes, aTime.Seconds, + aTime.NanoSeconds); + // this is now a Duration! + aAny = xPropertySet->getPropertyValue(u"FrobDuration2"_ustr); + aDur2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDur3.Negative, aDur2.Negative); + CPPUNIT_ASSERT_EQUAL(aDur3.Years, aDur2.Years); + CPPUNIT_ASSERT_EQUAL(aDur3.Months, aDur2.Months); + CPPUNIT_ASSERT_EQUAL(aDur3.Days, aDur2.Days); + CPPUNIT_ASSERT_EQUAL(aDur3.Hours, aDur2.Hours); + CPPUNIT_ASSERT_EQUAL(aDur3.Minutes, aDur2.Minutes); + CPPUNIT_ASSERT_EQUAL(aDur3.Seconds, aDur2.Seconds); + CPPUNIT_ASSERT_EQUAL(aDur3.NanoSeconds, aDur2.NanoSeconds); + + aAny = xPropertySet->getPropertyValue(u"FrobEndDate"_ustr); + aDate2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDate.Day, aDate2.Day); + CPPUNIT_ASSERT_EQUAL(aDate.Month, aDate2.Month); + CPPUNIT_ASSERT_EQUAL(aDate.Year, aDate2.Year); + + aAny = xPropertySet->getPropertyValue(u"FrobStartTime"_ustr); + aDateTime2 = aAny.get(); + CPPUNIT_ASSERT_EQUAL(aDateTime.Year, aDateTime2.Year); + CPPUNIT_ASSERT_EQUAL(aDateTime.Month, aDateTime2.Month); + CPPUNIT_ASSERT_EQUAL(aDateTime.Day, aDateTime2.Day); + CPPUNIT_ASSERT_EQUAL(aDateTime.Hours, aDateTime2.Hours); + CPPUNIT_ASSERT_EQUAL(aDateTime.Minutes, aDateTime2.Minutes); + CPPUNIT_ASSERT_EQUAL(aDateTime.Seconds, aDateTime2.Seconds); + CPPUNIT_ASSERT_EQUAL(aDateTime.NanoSeconds, aDateTime2.NanoSeconds); + + aAny = xPropertySet->getPropertyValue(u"Pi"_ustr); + aPi = aAny.get(); + CPPUNIT_ASSERT_EQUAL(3.1415, aPi); + + aAny = xPropertySet->getPropertyValue(u"Foo"_ustr); + aFoo = aAny.get(); + CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, aFoo); + + aAny = xPropertySet->getPropertyValue(u""_ustr); + aEmpty = aAny.get(); + CPPUNIT_ASSERT_EQUAL(u"eeeeek"_ustr, aEmpty); + + try + { + xPropertySet->getPropertyValue(u"Removed"_ustr); + CPPUNIT_FAIL("UserDefined remove didn't"); + } + catch (beans::UnknownPropertyException&) + { + } + + rtl::Reference xListener = new Listener(); + css::uno::Reference xBroadcaster(xProps, css::uno::UNO_QUERY); + xBroadcaster->addModifyListener(xListener); + xProps->setAuthor(u"not me"_ustr); + CPPUNIT_ASSERT(xListener->reset()); + xUDP->addProperty(u"Listener"_ustr, beans::PropertyAttribute::REMOVABLE, uno::Any(u"foo"_ustr)); + CPPUNIT_ASSERT(xListener->reset()); + xPropertySet->setPropertyValue(u"Listener"_ustr, uno::Any(u"bar"_ustr)); + CPPUNIT_ASSERT(xListener->reset()); + xUDP->removeProperty(u"Listener"_ustr); + CPPUNIT_ASSERT(xListener->reset()); + + xBroadcaster->removeModifyListener(xListener); + xUDP->addProperty(u"Listener2"_ustr, beans::PropertyAttribute::REMOVABLE, + uno::Any(u"foo"_ustr)); + CPPUNIT_ASSERT(!xListener->reset()); +} + CPPUNIT_TEST_FIXTURE(MiscTest, testNoThumbnail) { // Load a document.