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;
 }

Reply via email to