unotest/Library_unoexceptionprotector.mk | 1 unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx | 141 +++++++++- 2 files changed, 130 insertions(+), 12 deletions(-)
New commits: commit 7ccfc0277a44d0a9eee943fdbb952e16df36590c Author: Stephan Bergmann <stephan.bergm...@allotropia.de> AuthorDate: Mon Sep 23 14:52:40 2024 +0200 Commit: Stephan Bergmann <stephan.bergm...@allotropia.de> CommitDate: Mon Sep 23 21:17:44 2024 +0200 Best effort to print more details about caught UNO exception Change-Id: Ia8f098e4e441b6aba0d76d7184dc6cec2210f793 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173813 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de> diff --git a/unotest/Library_unoexceptionprotector.mk b/unotest/Library_unoexceptionprotector.mk index 52417c9883a9..ae751ac6e0a0 100644 --- a/unotest/Library_unoexceptionprotector.mk +++ b/unotest/Library_unoexceptionprotector.mk @@ -13,6 +13,7 @@ $(eval $(call gb_Library_Library,unoexceptionprotector)) $(eval $(call gb_Library_use_sdk_api,unoexceptionprotector)) $(eval $(call gb_Library_use_libraries,unoexceptionprotector,\ + comphelper \ cppu \ cppuhelper \ sal \ diff --git a/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx b/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx index 5a76cbdb11c1..19b84b8cbfb1 100644 --- a/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx +++ b/unotest/source/cpp/unoexceptionprotector/unoexceptionprotector.cxx @@ -17,16 +17,27 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <cstdint> #include <cstdlib> -#include <string> -#include <string_view> +#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 <osl/thread.h> -#include <rtl/string.hxx> +#include <o3tl/any.hxx> +#include <o3tl/unreachable.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> @@ -34,12 +45,106 @@ 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); +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: + out << std::uppercase << *o3tl::forceAccess<float>(value); + break; + case css::uno::TypeClass_DOUBLE: + out << std::uppercase << *o3tl::forceAccess<double>(value); + break; + case css::uno::TypeClass_CHAR: + out << "\u" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') + << std::uint_least16_t(*o3tl::forceAccess<char16_t>(value)) << std::dec; + 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: + { + 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)); + } + break; + } + case css::uno::TypeClass_INTERFACE: + out << '@' << value.getValue(); + break; + default: + O3TL_UNREACHABLE; + } } class Prot : public CppUnit::Protector @@ -62,11 +167,23 @@ bool Prot::protect( 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 exception of type " + convert(a.getValueTypeName()), - convert(e.Message))); + "An uncaught UNO exception", + s.str())); } return false; }