1
0
Fork 0
libreoffice/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

212 lines
7.1 KiB
C++

/* -*- 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 <cstdint>
#include <cstdlib>
#include <iomanip>
#include <ios>
#include <ostream>
#include <sstream>
#include <com/sun/star/reflection/XIdlReflection.hpp>
#include <com/sun/star/reflection/XIdlClass.hpp>
#include <com/sun/star/reflection/theCoreReflection.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Exception.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Type.hxx>
#include <com/sun/star/uno/TypeClass.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <comphelper/processfactory.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppunit/Message.h>
#include <o3tl/any.hxx>
#include <o3tl/unreachable.hxx>
#include <rtl/ustring.hxx>
#include <sal/types.h>
#include <cppunit/Protector.h>
namespace {
css::uno::Type translateType(css::uno::Reference<css::reflection::XIdlClass> const & type) {
return css::uno::Type(type->getTypeClass(), type->getName());
}
void printUnoValue(
std::ostream & out, css::uno::Reference<css::reflection::XIdlReflection> const & reflections,
css::uno::Type const & type, css::uno::Any const & value)
{
switch (type.getTypeClass()) {
case css::uno::TypeClass_VOID:
out << "void";
break;
case css::uno::TypeClass_BOOLEAN:
out << *o3tl::forceAccess<bool>(value);
break;
case css::uno::TypeClass_BYTE:
out << int(*o3tl::forceAccess<sal_Int8>(value));
break;
case css::uno::TypeClass_SHORT:
out << *o3tl::forceAccess<sal_Int16>(value);
break;
case css::uno::TypeClass_UNSIGNED_SHORT:
out << *o3tl::forceAccess<sal_uInt16>(value);
break;
case css::uno::TypeClass_LONG:
out << *o3tl::forceAccess<sal_Int32>(value);
break;
case css::uno::TypeClass_UNSIGNED_LONG:
out << *o3tl::forceAccess<sal_uInt32>(value);
break;
case css::uno::TypeClass_HYPER:
out << *o3tl::forceAccess<sal_Int64>(value);
break;
case css::uno::TypeClass_UNSIGNED_HYPER:
out << *o3tl::forceAccess<sal_uInt64>(value);
break;
case css::uno::TypeClass_FLOAT:
{
std::ios_base::fmtflags origfmt = out.flags();
out << std::uppercase << *o3tl::forceAccess<float>(value);
out.setf(origfmt);
break;
}
case css::uno::TypeClass_DOUBLE:
{
std::ios_base::fmtflags origfmt = out.flags();
out << std::uppercase << *o3tl::forceAccess<double>(value);
out.setf(origfmt);
break;
}
case css::uno::TypeClass_CHAR:
{
std::ios_base::fmtflags origfmt = out.flags();
out << "\\u" << std::hex << std::uppercase << std::setw(4) << std::setfill('0')
<< std::uint_least16_t(*o3tl::forceAccess<char16_t>(value));
out.setf(origfmt);
break;
}
case css::uno::TypeClass_STRING:
out << '"' << *o3tl::forceAccess<OUString>(value) << '"'; //TODO: encode content
break;
case css::uno::TypeClass_TYPE:
out << o3tl::forceAccess<css::uno::Type>(value)->getTypeName();
break;
case css::uno::TypeClass_ANY:
out << value.getValueTypeName() << ": ";
printUnoValue(out, reflections, value.getValueType(), value);
break;
case css::uno::TypeClass_SEQUENCE:
{
css::uno::Reference<css::reflection::XIdlClass> const refl(
reflections->forName(type.getTypeName()), css::uno::UNO_SET_THROW);
auto const t = translateType(refl->getComponentType());
auto const array = refl->getArray();
auto const n = array->getLen(value);
out << '[';
for (sal_Int32 i = 0; i != n; ++i) {
if (i != 0) {
out << ", ";
}
printUnoValue(out, reflections, t, array->get(value, i));
}
out << ']';
break;
}
case css::uno::TypeClass_ENUM:
out << value.getValueTypeName() << ' ' << *static_cast<sal_Int32 const *>(value.getValue());
break;
case css::uno::TypeClass_STRUCT:
case css::uno::TypeClass_EXCEPTION:
{
out << '{';
auto first = true;
for (auto const & f: css::uno::Reference<css::reflection::XIdlClass>(
reflections->forName(type.getTypeName()),
css::uno::UNO_SET_THROW)->getFields())
{
if (first) {
first = false;
} else {
out << ", ";
}
out << f->getName() << ": ";
printUnoValue(out, reflections, translateType(f->getType()), f->get(value));
}
out << '}';
break;
}
case css::uno::TypeClass_INTERFACE:
out << '@' << value.getValue();
break;
default:
O3TL_UNREACHABLE;
}
}
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());
std::ostringstream s;
try {
printUnoValue(
s,
css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext()),
cppu::UnoType<css::uno::Any>::get(), a);
} catch (css::uno::Exception &) {
// Best effort to print full details above; if that fails for whatever reason, print as
// much detailed information as possible, followed by at least the exception type and
// message:
s << "... " << a.getValueTypeName() << ": " << e.Message;
}
reportError(
context,
CppUnit::Message(
"An uncaught UNO exception",
s.str()));
}
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: */