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 #include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include #include #include -#include -#include +#include +#include #include #include @@ -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 const & type) { + return css::uno::Type(type->getTypeClass(), type->getName()); +} + +void printUnoValue( + std::ostream & out, css::uno::Reference 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(value); + break; + case css::uno::TypeClass_BYTE: + out << int(*o3tl::forceAccess(value)); + break; + case css::uno::TypeClass_SHORT: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_UNSIGNED_SHORT: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_LONG: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_UNSIGNED_LONG: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_HYPER: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_UNSIGNED_HYPER: + out << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_FLOAT: + out << std::uppercase << *o3tl::forceAccess(value); + break; + case css::uno::TypeClass_DOUBLE: + out << std::uppercase << *o3tl::forceAccess(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(value)) << std::dec; + break; + case css::uno::TypeClass_STRING: + out << '"' << *o3tl::forceAccess(value) << '"'; //TODO: encode content + break; + case css::uno::TypeClass_TYPE: + out << o3tl::forceAccess(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 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(value.getValue()); + break; + case css::uno::TypeClass_STRUCT: + case css::uno::TypeClass_EXCEPTION: + { + auto first = true; + for (auto const & f: css::uno::Reference( + 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::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; }