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 /unotest/source/cpp | |
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 'unotest/source/cpp')
-rw-r--r-- | unotest/source/cpp/bootstrapfixturebase.cxx | 43 | ||||
-rw-r--r-- | unotest/source/cpp/directories.cxx | 66 | ||||
-rw-r--r-- | unotest/source/cpp/filters-test.cxx | 170 | ||||
-rw-r--r-- | unotest/source/cpp/getargument.cxx | 36 | ||||
-rw-r--r-- | unotest/source/cpp/gettestargument.cxx | 34 | ||||
-rw-r--r-- | unotest/source/cpp/macros_test.cxx | 232 | ||||
-rw-r--r-- | unotest/source/cpp/officeconnection.cxx | 151 | ||||
-rw-r--r-- | unotest/source/cpp/toabsolutefileurl.cxx | 61 | ||||
-rw-r--r-- | unotest/source/cpp/unobootstrapprotector/unobootstrapprotector.cxx | 93 | ||||
-rw-r--r-- | unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx | 81 |
10 files changed, 967 insertions, 0 deletions
diff --git a/unotest/source/cpp/bootstrapfixturebase.cxx b/unotest/source/cpp/bootstrapfixturebase.cxx new file mode 100644 index 0000000000..dd92d3822f --- /dev/null +++ b/unotest/source/cpp/bootstrapfixturebase.cxx @@ -0,0 +1,43 @@ +/* -*- 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/config.h> +#include <config_features.h> + +#include <unotest/bootstrapfixturebase.hxx> +#include <comphelper/processfactory.hxx> +#if HAVE_FEATURE_SCRIPTING +#include <basic/sbstar.hxx> +#endif + +using namespace ::com::sun::star; + +// NB. this constructor is called before any tests are run, once for each +// test function in a rather non-intuitive way. This is why all the 'real' +// heavy lifting is deferred until setUp. setUp and tearDown are interleaved +// between the tests as you might expect. +test::BootstrapFixtureBase::BootstrapFixtureBase() {} + +test::BootstrapFixtureBase::~BootstrapFixtureBase() {} + +void test::BootstrapFixtureBase::setUp() +{ + m_xContext = comphelper::getProcessComponentContext(); + m_xFactory = m_xContext->getServiceManager(); + m_xSFactory.set(m_xFactory, uno::UNO_QUERY_THROW); +} + +void test::BootstrapFixtureBase::tearDown() +{ +#if HAVE_FEATURE_SCRIPTING + StarBASIC::DetachAllDocBasicItems(); +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/directories.cxx b/unotest/source/cpp/directories.cxx new file mode 100644 index 0000000000..93bcd4daed --- /dev/null +++ b/unotest/source/cpp/directories.cxx @@ -0,0 +1,66 @@ +/* -*- 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/config.h> + +#include <cppunit/TestAssert.h> +#include <osl/file.hxx> +#include <unotest/directories.hxx> + +namespace +{ +OUString getFileURLFromSystemPath(OUString const& path) +{ + OUString url; + osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath(path, url); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); + if (!url.endsWith("/")) + { + url += "/"; + } + return url; +} +} + +test::Directories::Directories() +{ + const char* pSrcRoot = getenv("SRC_ROOT"); + CPPUNIT_ASSERT_MESSAGE("SRC_ROOT env variable not set", pSrcRoot != nullptr); + CPPUNIT_ASSERT_MESSAGE("SRC_ROOT env variable not set", pSrcRoot[0] != 0); + const char* pWorkdirRoot = getenv("WORKDIR_FOR_BUILD"); + CPPUNIT_ASSERT_MESSAGE("$WORKDIR_FOR_BUILD env variable not set", pWorkdirRoot != nullptr); + CPPUNIT_ASSERT_MESSAGE("$WORKDIR_FOR_BUILD env variable not set", pWorkdirRoot[0] != 0); + m_aSrcRootPath = OUString::createFromAscii(pSrcRoot); + m_aSrcRootURL = getFileURLFromSystemPath(m_aSrcRootPath); + + m_aWorkdirRootPath = OUString::createFromAscii(pWorkdirRoot); + m_aWorkdirRootURL = getFileURLFromSystemPath(m_aWorkdirRootPath); +} + +OUString test::Directories::getURLFromSrc(std::u16string_view rPath) const +{ + return m_aSrcRootURL + rPath; +} + +OUString test::Directories::getPathFromSrc(std::u16string_view rPath) const +{ + return m_aSrcRootPath + rPath; +} + +OUString test::Directories::getURLFromWorkdir(std::u16string_view rPath) const +{ + return m_aWorkdirRootURL + rPath; +} + +OUString test::Directories::getPathFromWorkdir(std::u16string_view rPath) const +{ + return m_aWorkdirRootPath + rPath; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/filters-test.cxx b/unotest/source/cpp/filters-test.cxx new file mode 100644 index 0000000000..1eaaa62197 --- /dev/null +++ b/unotest/source/cpp/filters-test.cxx @@ -0,0 +1,170 @@ +/* -*- 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/config.h> + +#include <set> +#include <string_view> + +#include <unotest/filters-test.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <rtl/cipher.h> + +#include <cppunit/TestAssert.h> + +namespace test { + +static void decode(const OUString& rIn, const OUString &rOut) +{ + rtlCipher cipher = rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream); + CPPUNIT_ASSERT_MESSAGE("cipher creation failed", cipher != nullptr); + + //mcrypt --bare -a arcfour -o hex -k 435645 -s 3 + const sal_uInt8 aKey[3] = {'C', 'V', 'E'}; + + rtlCipherError result = rtl_cipher_init(cipher, rtl_Cipher_DirectionDecode, aKey, std::size(aKey), nullptr, 0); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("cipher init failed", rtl_Cipher_E_None, result); + + osl::File aIn(rIn); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aIn.open(osl_File_OpenFlag_Read)); + + osl::File aOut(rOut); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aOut.open(osl_File_OpenFlag_Write)); + + sal_uInt8 in[8192]; + sal_uInt8 out[8192]; + sal_uInt64 nBytesRead, nBytesWritten; + while(true) + { + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aIn.read(in, sizeof(in), nBytesRead)); + if (!nBytesRead) + break; + CPPUNIT_ASSERT_EQUAL(rtl_Cipher_E_None, rtl_cipher_decode(cipher, in, nBytesRead, out, sizeof(out))); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aOut.write(out, nBytesRead, nBytesWritten)); + CPPUNIT_ASSERT_EQUAL(nBytesRead, nBytesWritten); + } + + rtl_cipher_destroy(cipher); +} + +void FiltersTest::recursiveScan(filterStatus nExpected, + const OUString &rFilter, const OUString &rURL, + const OUString &rUserData, SfxFilterFlags nFilterFlags, + SotClipboardFormatId nClipboardID, unsigned int nFilterVersion, bool bExport) +{ + osl::Directory aDir(rURL); + + CPPUNIT_ASSERT_EQUAL_MESSAGE(OUString("Failed to open directory " + rURL).toUtf8().getStr(), osl::FileBase::E_None, aDir.open()); + osl::DirectoryItem aItem; + osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type); + std::set<OUString> dirs; + std::set<OUString> files; + while (aDir.getNextItem(aItem) == osl::FileBase::E_None) + { + aItem.getFileStatus(aFileStatus); + OUString sURL = aFileStatus.getFileURL(); + if (aFileStatus.getFileType() == osl::FileStatus::Directory) + { + dirs.insert(sURL); + } + else + { + files.insert(sURL); + } + } + for (auto const & sURL: dirs) { + recursiveScan(nExpected, rFilter, sURL, rUserData, + nFilterFlags, nClipboardID, nFilterVersion, bExport); + } + for (auto const & sURL: files) { + OUString sTmpFile; + bool bEncrypted = false; + + sal_Int32 nLastSlash = sURL.lastIndexOf('/'); + + if ((nLastSlash != -1) && (nLastSlash+1 < sURL.getLength())) + { + //ignore .files + if (sURL[nLastSlash+1] == '.') + continue; + + if ( + (sURL.match("BID", nLastSlash+1)) || + (sURL.match("CVE", nLastSlash+1)) || + (sURL.match("EDB", nLastSlash+1)) || + (sURL.match("RC4", nLastSlash+1)) // just means "encrypted" + ) + { + bEncrypted = true; + } + } + + OString aRes( + OString::Concat(bExport ? std::string_view("save") : std::string_view("load")) + " " + + OUStringToOString(sURL, osl_getThreadTextEncoding())); + + OUString realUrl; + if (bEncrypted) + { + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, osl::FileBase::createTempFile(nullptr, nullptr, &sTmpFile)); + decode(sURL, sTmpFile); + realUrl = sTmpFile; + } + else + { + realUrl = sURL; + } + + //output name early, so in the case of a hang, the name of + //the hanging input file is visible + fprintf(stderr, "Testing %s:\n", aRes.getStr()); + sal_uInt32 nStartTime = osl_getGlobalTimer(); + bool bRes; + if (!bExport) + bRes = load(rFilter, realUrl, rUserData, nFilterFlags, + nClipboardID, nFilterVersion); + else + bRes = save(rFilter, realUrl, rUserData, nFilterFlags, + nClipboardID, nFilterVersion); + sal_uInt32 nEndTime = osl_getGlobalTimer(); + + if (bEncrypted) + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, osl::File::remove(sTmpFile)); + + fprintf(stderr, "Tested %s: %s (%" SAL_PRIuUINT32 "ms)\n", + aRes.getStr(), bRes?"Pass":"Fail", nEndTime-nStartTime); + if (nExpected == test::indeterminate) + continue; + filterStatus nResult = bRes ? test::pass : test::fail; + CPPUNIT_ASSERT_EQUAL_MESSAGE(aRes.getStr(), nExpected, nResult); + } + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, aDir.close()); +} + +void FiltersTest::testDir(const OUString &rFilter, + std::u16string_view rURL, const OUString &rUserData, + SfxFilterFlags nFilterFlags, SotClipboardFormatId nClipboardID, + unsigned int nFilterVersion, bool bExport) +{ + recursiveScan(test::pass, rFilter, + OUString::Concat(rURL) + "pass", + rUserData, nFilterFlags, nClipboardID, nFilterVersion, bExport); + recursiveScan(test::fail, rFilter, + OUString::Concat(rURL) + "fail", + rUserData, nFilterFlags, nClipboardID, nFilterVersion, bExport); + recursiveScan(test::indeterminate, rFilter, + OUString::Concat(rURL) + "indeterminate", + rUserData, nFilterFlags, nClipboardID, nFilterVersion, bExport); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/getargument.cxx b/unotest/source/cpp/getargument.cxx new file mode 100644 index 0000000000..22cd39fc59 --- /dev/null +++ b/unotest/source/cpp/getargument.cxx @@ -0,0 +1,36 @@ +/* -*- 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/config.h> + +#include <osl/diagnose.h> +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <unotest/getargument.hxx> + +namespace test +{ +bool getArgument(std::u16string_view name, OUString* value) +{ + OSL_ASSERT(value != nullptr); + return rtl::Bootstrap::get(OUString::Concat("arg-") + name, *value); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/gettestargument.cxx b/unotest/source/cpp/gettestargument.cxx new file mode 100644 index 0000000000..8d10b07cca --- /dev/null +++ b/unotest/source/cpp/gettestargument.cxx @@ -0,0 +1,34 @@ +/* -*- 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/config.h> + +#include <rtl/ustring.hxx> +#include <unotest/getargument.hxx> +#include <unotest/gettestargument.hxx> + +namespace test +{ +bool getTestArgument(std::u16string_view name, OUString* value) +{ + return getArgument(Concat2View(OUString::Concat("testarg.") + name), value); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/macros_test.cxx b/unotest/source/cpp/macros_test.cxx new file mode 100644 index 0000000000..3bb2a22a5d --- /dev/null +++ b/unotest/source/cpp/macros_test.cxx @@ -0,0 +1,232 @@ +/* -*- 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 <unotest/macros_test.hxx> + +#include <vector> + +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/frame/DispatchHelper.hpp> +#include <com/sun/star/packages/zip/ZipFileAccess.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> + +#include <basic/basrdll.hxx> +#include <cppunit/TestAssert.h> +#include <comphelper/sequence.hxx> +#include <comphelper/processfactory.hxx> +#include <unotest/directories.hxx> +#include <osl/file.hxx> +#include <osl/process.h> +#include <osl/thread.h> +#include <tools/datetime.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/scheduler.hxx> + +using namespace css; + +namespace unotest +{ +MacrosTest::MacrosTest() + : mpDll(std::make_unique<BasicDLL>()) +{ +} + +MacrosTest::~MacrosTest() = default; + +uno::Reference<css::lang::XComponent> +MacrosTest::loadFromDesktop(const OUString& rURL, const OUString& rDocService, + const uno::Sequence<beans::PropertyValue>& rExtraArgs) +{ + CPPUNIT_ASSERT_MESSAGE("no desktop", mxDesktop.is()); + std::vector<beans::PropertyValue> args; + beans::PropertyValue aMacroValue; + aMacroValue.Name = "MacroExecutionMode"; + aMacroValue.Handle = -1; + aMacroValue.Value <<= document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN; + aMacroValue.State = beans::PropertyState_DIRECT_VALUE; + args.push_back(aMacroValue); + + if (!rDocService.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "DocumentService"; + aValue.Handle = -1; + aValue.Value <<= rDocService; + aValue.State = beans::PropertyState_DIRECT_VALUE; + args.push_back(aValue); + } + + args.insert(args.end(), rExtraArgs.begin(), rExtraArgs.end()); + + uno::Reference<lang::XComponent> xComponent = mxDesktop->loadComponentFromURL( + rURL, "_default", 0, comphelper::containerToSequence(args)); + OUString sMessage = "loading failed: " + rURL; + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sMessage, RTL_TEXTENCODING_UTF8).getStr(), + xComponent.is()); + return xComponent; +} + +css::uno::Any +MacrosTest::dispatchCommand(const uno::Reference<lang::XComponent>& xComponent, + const OUString& rCommand, + const uno::Sequence<beans::PropertyValue>& rPropertyValues) +{ + uno::Reference<frame::XController> xController + = uno::Reference<frame::XModel>(xComponent, uno::UNO_QUERY_THROW)->getCurrentController(); + CPPUNIT_ASSERT(xController.is()); + uno::Reference<frame::XDispatchProvider> xFrame(xController->getFrame(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xFrame.is()); + + uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext(); + uno::Reference<frame::XDispatchHelper> xDispatchHelper(frame::DispatchHelper::create(xContext)); + CPPUNIT_ASSERT(xDispatchHelper.is()); + + auto ret = xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, rPropertyValues); + Scheduler::ProcessEventsToIdle(); + + return ret; +} + +std::unique_ptr<SvStream> MacrosTest::parseExportStream(const OUString& url, + const OUString& rStreamName) +{ + uno::Reference<uno::XComponentContext> xComponentContext + = comphelper::getProcessComponentContext(); + uno::Reference<packages::zip::XZipFileAccess2> const xZipNames( + packages::zip::ZipFileAccess::createWithURL(xComponentContext, url)); + uno::Reference<io::XInputStream> const xInputStream(xZipNames->getByName(rStreamName), + uno::UNO_QUERY); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + return pStream; +} + +void MacrosTest::setUpNssGpg(const test::Directories& rDirectories, const OUString& rTestName) +{ + OUString aSourceDir = rDirectories.getURLFromSrc(u"/test/signing-keys/"); + OUString aTargetDir + = rDirectories.getURLFromWorkdir(Concat2View("CppunitTest/" + rTestName + ".test.user")); + + // Set up NSS database in workdir/CppunitTest/ + osl::File::copy(aSourceDir + "cert9.db", aTargetDir + "/cert9.db"); + osl::File::copy(aSourceDir + "key4.db", aTargetDir + "/key4.db"); + osl::File::copy(aSourceDir + "pkcs11.txt", aTargetDir + "/pkcs11.txt"); + + // Make gpg use our own defined setup & keys + osl::File::copy(aSourceDir + "pubring.gpg", aTargetDir + "/pubring.gpg"); + osl::File::copy(aSourceDir + "random_seed", aTargetDir + "/random_seed"); + osl::File::copy(aSourceDir + "secring.gpg", aTargetDir + "/secring.gpg"); + osl::File::copy(aSourceDir + "trustdb.gpg", aTargetDir + "/trustdb.gpg"); + + OUString aTargetPath; + osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath); + +#ifdef _WIN32 + // CryptoAPI test certificates + osl::File::copy(aSourceDir + "test.p7b", aTargetDir + "/test.p7b"); + OUString caVar("LIBO_TEST_CRYPTOAPI_PKCS7"); + osl_setEnvironment(caVar.pData, aTargetPath.pData); +#else + OUString mozCertVar("MOZILLA_CERTIFICATE_FOLDER"); + // explicit prefix with "sql:" needed for CentOS7 system NSS 3.67 + osl_setEnvironment(mozCertVar.pData, OUString("sql:" + aTargetPath).pData); +#endif + OUString gpgHomeVar("GNUPGHOME"); + osl_setEnvironment(gpgHomeVar.pData, aTargetPath.pData); + +#if HAVE_GPGCONF_SOCKETDIR + auto const ldPath = std::getenv("LIBO_LD_PATH"); + m_gpgconfCommandPrefix + = ldPath == nullptr ? OString() : OString::Concat("LD_LIBRARY_PATH=") + ldPath + " "; + OString path; + bool ok = aTargetPath.convertToString(&path, osl_getThreadTextEncoding(), + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR); + // if conversion fails, at least provide a best-effort conversion in the message here, for + // context + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(aTargetPath, RTL_TEXTENCODING_UTF8).getStr(), ok); + m_gpgconfCommandPrefix += "GNUPGHOME=" + path + " " GPGME_GPGCONF; + // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system + // behavior will conform to POSIX (and the relevant env var to set is named LD_LIBRARY_PATH), and + // (b) gpgconf --create-socketdir should return zero: + OString cmd = m_gpgconfCommandPrefix + " --create-socketdir"; + int res = std::system(cmd.getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res); +#else + (void)this; +#endif +} + +void MacrosTest::tearDownNssGpg() +{ +#if HAVE_GPGCONF_SOCKETDIR + // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system + // behavior will conform to POSIX, and (b) gpgconf --remove-socketdir should return zero: + OString cmd = m_gpgconfCommandPrefix + " --remove-socketdir"; + int res = std::system(cmd.getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res); +#else + (void)this; +#endif +} + +namespace +{ +struct Valid +{ + DateTime now; + OUString subjectName; + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env; + Valid(const css::uno::Sequence<css::beans::PropertyValue>& rFilterData, + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rEnv) + : now(DateTime::SYSTEM) + , env(rEnv) + { + for (const auto& propVal : rFilterData) + { + if (propVal.Name == "SignCertificateSubjectName") + propVal.Value >>= subjectName; + } + } + bool operator()(const css::uno::Reference<css::security::XCertificate>& cert) const + { + if (!now.IsBetween(cert->getNotValidBefore(), cert->getNotValidAfter())) + return false; + if (!subjectName.isEmpty() && subjectName != cert->getSubjectName()) + return false; + if (env->verifyCertificate(cert, {}) != css::security::CertificateValidity::VALID) + return false; + return true; + } +}; +} + +bool MacrosTest::IsValid(const css::uno::Reference<css::security::XCertificate>& cert, + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env) +{ + const Valid test({}, env); + return test(cert); +} + +css::uno::Reference<css::security::XCertificate> MacrosTest::GetValidCertificate( + const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs, + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env, + const css::uno::Sequence<css::beans::PropertyValue>& rFilterData) +{ + if (auto it = std::find_if(certs.begin(), certs.end(), Valid(rFilterData, env)); + it != certs.end()) + return *it; + return {}; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/officeconnection.cxx b/unotest/source/cpp/officeconnection.cxx new file mode 100644 index 0000000000..850b19440d --- /dev/null +++ b/unotest/source/cpp/officeconnection.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/. + * + * 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 <com/sun/star/bridge/UnoUrlResolver.hpp> +#include <com/sun/star/bridge/XUnoUrlResolver.hpp> +#include <com/sun/star/connection/NoConnectException.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/bootstrap.hxx> +#include <cppunit/TestAssert.h> +#include <osl/process.h> +#include <osl/test/uniquepipename.hxx> +#include <osl/time.h> +#include <unotest/getargument.hxx> +#include <unotest/officeconnection.hxx> +#include <unotest/toabsolutefileurl.hxx> + +namespace test { + +OfficeConnection::OfficeConnection(): process_(nullptr) {} + +OfficeConnection::~OfficeConnection() {} + +void OfficeConnection::setUp() { + css::uno::Reference< css::bridge::XUnoUrlResolver > resolver( + css::bridge::UnoUrlResolver::create( + cppu::defaultBootstrap_InitialComponentContext())); + OUString desc; + OUString argSoffice; + CPPUNIT_ASSERT( + getArgument( + u"soffice", + &argSoffice)); + if (argSoffice.match("path:")) { + desc = "pipe,name=" + osl::test::uniquePipeName("oootest"); + OUString noquickArg("--quickstart=no"); + OUString norestoreArg("--norestore"); + OUString nologoArg("--nologo"); + // disable use of the unix standalone splash screen app for the + // tests (probably not needed in combination with --headless?) + OUString headlessArg("--headless"); + OUString acceptArg("--accept=" + desc + ";urp"); + OUString argUser; + CPPUNIT_ASSERT( + getArgument(u"user", &argUser)); + OUString userArg("-env:UserInstallation=" + toAbsoluteFileUrl(argUser)); + OUString jreArg( + "-env:UNO_JAVA_JFW_ENV_JREHOME=true"); + rtl_uString * args[] = { + noquickArg.pData, norestoreArg.pData, + nologoArg.pData, headlessArg.pData, acceptArg.pData, userArg.pData, + jreArg.pData }; + rtl_uString ** envs = nullptr; + OUString argEnv; + if (getArgument(u"env", &argEnv)) + { + envs = &argEnv.pData; + } + // coverity[callee_ptr_arith] - arith is fine + CPPUNIT_ASSERT_EQUAL( + osl_Process_E_None, + osl_executeProcess( + toAbsoluteFileUrl( + argSoffice.copy(RTL_CONSTASCII_LENGTH("path:"))).pData, + args, std::size(args), 0, nullptr, nullptr, envs, envs == nullptr ? 0 : 1, + &process_)); + } else if (argSoffice.match("connect:")) { + desc = argSoffice.copy(RTL_CONSTASCII_LENGTH("connect:")); + } else { + CPPUNIT_FAIL( + "\"soffice\" argument starts with neither \"path:\" nor" + " \"connect:\""); + } + for (;;) { + try { + context_ = + css::uno::Reference< css::uno::XComponentContext >( + resolver->resolve( + "uno:" + desc + ";urp;StarOffice.ComponentContext"), + css::uno::UNO_QUERY_THROW); + break; + } catch (css::connection::NoConnectException &) {} + if (process_ != nullptr) { + TimeValue delay = { 1, 0 }; // 1 sec + CPPUNIT_ASSERT_EQUAL( + osl_Process_E_TimedOut, + osl_joinProcessWithTimeout(process_, &delay)); + } + } +} + +void OfficeConnection::tearDown() { + if (process_ == nullptr) + return; + + if (context_.is()) { + css::uno::Reference< css::frame::XDesktop2 > desktop = css::frame::Desktop::create( context_ ); + context_.clear(); + try { + CPPUNIT_ASSERT(desktop->terminate()); + desktop.clear(); + } catch (css::lang::DisposedException &) {} + // it appears that DisposedExceptions can already happen while + // receiving the response of the terminate call + } + CPPUNIT_ASSERT_EQUAL(osl_Process_E_None, osl_joinProcess(process_)); + oslProcessInfo info; + info.Size = sizeof info; + CPPUNIT_ASSERT_EQUAL( + osl_Process_E_None, + osl_getProcessInfo(process_, osl_Process_EXITCODE, &info)); + CPPUNIT_ASSERT_EQUAL(oslProcessExitCode(0), info.Code); + osl_freeProcessHandle(process_); + process_ = nullptr; // guard against subsequent calls to isStillAlive +} + + +bool OfficeConnection::isStillAlive() const { + if (process_ == nullptr) { + // In case "soffice" argument starts with "connect:" we have no direct + // control over the liveness of the soffice.bin process (would need to + // directly monitor the bridge) so can only assume the best here: + return true; + } + TimeValue delay = { 0, 0 }; // 0 sec + oslProcessError e = osl_joinProcessWithTimeout(process_, &delay); + CPPUNIT_ASSERT(e == osl_Process_E_None || e == osl_Process_E_TimedOut); + return e == osl_Process_E_TimedOut; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/toabsolutefileurl.cxx b/unotest/source/cpp/toabsolutefileurl.cxx new file mode 100644 index 0000000000..ea8b6f66c2 --- /dev/null +++ b/unotest/source/cpp/toabsolutefileurl.cxx @@ -0,0 +1,61 @@ +/* -*- 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/config.h> + +#include <com/sun/star/uno/RuntimeException.hpp> +#include <osl/file.hxx> +#include <osl/process.h> +#include <rtl/ustring.hxx> +#include <unotest/toabsolutefileurl.hxx> + +namespace test { + +OUString toAbsoluteFileUrl(OUString const & relativePathname) { + OUString cwd; + oslProcessError e1 = osl_getProcessWorkingDir(&cwd.pData); + if (e1 != osl_Process_E_None) { + throw css::uno::RuntimeException( + "osl_getProcessWorkingDir failed with " + OUString::number(e1)); + } + OUString url; + osl::FileBase::RC e2 = osl::FileBase::getFileURLFromSystemPath( + relativePathname, url); + if (e2 != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "osl::FileBase::getFileURLFromSystemPath(" + + relativePathname + + ") failed with " + + OUString::number(e2)); + } + OUString absUrl; + e2 = osl::FileBase::getAbsoluteFileURL(cwd, url, absUrl); + if (e2 != osl::FileBase::E_None) { + throw css::uno::RuntimeException( + "osl::FileBase::getAbsoluteFileURL(" + + cwd + ", " + url + + ") failed with " + + OUString::number(e2)); + } + return absUrl; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/unobootstrapprotector/unobootstrapprotector.cxx b/unotest/source/cpp/unobootstrapprotector/unobootstrapprotector.cxx new file mode 100644 index 0000000000..5ad175b9d0 --- /dev/null +++ b/unotest/source/cpp/unobootstrapprotector/unobootstrapprotector.cxx @@ -0,0 +1,93 @@ +/* -*- 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 <com/sun/star/uno/Exception.hpp> + +#include <cppuhelper/bootstrap.hxx> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <sal/types.h> + +#include <cppunit/Protector.h> + +namespace { + +using namespace com::sun::star; + +//cppunit calls instantiates a new TextFixture for each test and calls setUp +//and tearDown on that for every test in a fixture + +//We basically need to call dispose on our root component context to +//shut down cleanly in the right order. + +//But we can't setup and tear down the root component context for +//every test because all the uno singletons will be invalid after +//the first dispose. So lets setup the default context once before +//all tests are run, and tear it down once after all have finished + +class Prot : public CppUnit::Protector +{ +public: + Prot(); + + virtual ~Prot() override; + + Prot(const Prot&) = delete; + Prot& operator=(const Prot&) = delete; + + virtual bool protect( + CppUnit::Functor const & functor, + CppUnit::ProtectorContext const & context) override; +private: + uno::Reference<uno::XComponentContext> m_xContext; +}; + + +Prot::Prot() + : m_xContext(cppu::defaultBootstrap_InitialComponentContext()) +{ + uno::Reference<lang::XMultiComponentFactory> xFactory = m_xContext->getServiceManager(); + uno::Reference<lang::XMultiServiceFactory> xSFactory(xFactory, uno::UNO_QUERY_THROW); + + comphelper::setProcessServiceFactory(xSFactory); +} + +bool Prot::protect( + CppUnit::Functor const & functor, CppUnit::ProtectorContext const &) +{ + return functor(); +} + +Prot::~Prot() +{ + uno::Reference< lang::XComponent >(m_xContext, uno::UNO_QUERY_THROW)->dispose(); +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT CppUnit::Protector * unobootstrapprotector() +{ + return new Prot; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx b/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx new file mode 100644 index 0000000000..5a76cbdb11 --- /dev/null +++ b/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx @@ -0,0 +1,81 @@ +/* -*- 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 <cstdlib> +#include <string> +#include <string_view> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <cppuhelper/exc_hlp.hxx> +#include <cppunit/Message.h> +#include <osl/thread.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +#include <cppunit/Protector.h> + +namespace { + +// Best effort conversion: +std::string convert(std::u16string_view s16) { + OString s8(OUStringToOString(s16, osl_getThreadTextEncoding())); + static_assert(sizeof (sal_Int32) <= sizeof (std::string::size_type), "got to be at least equal"); + // ensure following cast is legitimate + return std::string(s8); +} + +class Prot : public CppUnit::Protector +{ +public: + Prot() {} + + Prot(const Prot&) = delete; + Prot& operator=(const Prot&) = delete; + + virtual bool protect( + CppUnit::Functor const & functor, + CppUnit::ProtectorContext const & context) override; +}; + +bool Prot::protect( + CppUnit::Functor const & functor, CppUnit::ProtectorContext const & context) +{ + try { + return functor(); + } catch (const css::uno::Exception &e) { + css::uno::Any a(cppu::getCaughtException()); + reportError( + context, + CppUnit::Message( + "An uncaught exception of type " + convert(a.getValueTypeName()), + convert(e.Message))); + } + return false; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT CppUnit::Protector * +unoexceptionprotector() { + return std::getenv("CPPUNIT_PROPAGATE_EXCEPTIONS") == nullptr ? new Prot : nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |