Fix typo
[LibreOffice.git] / unotest / source / cpp / unoexceptionprotector / unoexceptionprotector.cxx
blob804b8e7d12ca7582bf9f2c508dbd9ab7fd494860
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cstdint>
21 #include <cstdlib>
22 #include <iomanip>
23 #include <ios>
24 #include <ostream>
25 #include <sstream>
27 #include <com/sun/star/reflection/XIdlReflection.hpp>
28 #include <com/sun/star/reflection/XIdlClass.hpp>
29 #include <com/sun/star/reflection/theCoreReflection.hpp>
30 #include <com/sun/star/uno/Any.hxx>
31 #include <com/sun/star/uno/Exception.hpp>
32 #include <com/sun/star/uno/Reference.hxx>
33 #include <com/sun/star/uno/Type.hxx>
34 #include <com/sun/star/uno/TypeClass.hpp>
35 #include <com/sun/star/uno/XComponentContext.hpp>
36 #include <comphelper/processfactory.hxx>
37 #include <cppuhelper/exc_hlp.hxx>
38 #include <cppunit/Message.h>
39 #include <o3tl/any.hxx>
40 #include <o3tl/unreachable.hxx>
41 #include <rtl/ustring.hxx>
42 #include <sal/types.h>
44 #include <cppunit/Protector.h>
46 namespace {
48 css::uno::Type translateType(css::uno::Reference<css::reflection::XIdlClass> const & type) {
49 return css::uno::Type(type->getTypeClass(), type->getName());
52 void printUnoValue(
53 std::ostream & out, css::uno::Reference<css::reflection::XIdlReflection> const & reflections,
54 css::uno::Type const & type, css::uno::Any const & value)
56 switch (type.getTypeClass()) {
57 case css::uno::TypeClass_VOID:
58 out << "void";
59 break;
60 case css::uno::TypeClass_BOOLEAN:
61 out << *o3tl::forceAccess<bool>(value);
62 break;
63 case css::uno::TypeClass_BYTE:
64 out << int(*o3tl::forceAccess<sal_Int8>(value));
65 break;
66 case css::uno::TypeClass_SHORT:
67 out << *o3tl::forceAccess<sal_Int16>(value);
68 break;
69 case css::uno::TypeClass_UNSIGNED_SHORT:
70 out << *o3tl::forceAccess<sal_uInt16>(value);
71 break;
72 case css::uno::TypeClass_LONG:
73 out << *o3tl::forceAccess<sal_Int32>(value);
74 break;
75 case css::uno::TypeClass_UNSIGNED_LONG:
76 out << *o3tl::forceAccess<sal_uInt32>(value);
77 break;
78 case css::uno::TypeClass_HYPER:
79 out << *o3tl::forceAccess<sal_Int64>(value);
80 break;
81 case css::uno::TypeClass_UNSIGNED_HYPER:
82 out << *o3tl::forceAccess<sal_uInt64>(value);
83 break;
84 case css::uno::TypeClass_FLOAT:
86 std::ios_base::fmtflags origfmt = out.flags();
87 out << std::uppercase << *o3tl::forceAccess<float>(value);
88 out.setf(origfmt);
89 break;
91 case css::uno::TypeClass_DOUBLE:
93 std::ios_base::fmtflags origfmt = out.flags();
94 out << std::uppercase << *o3tl::forceAccess<double>(value);
95 out.setf(origfmt);
96 break;
98 case css::uno::TypeClass_CHAR:
100 std::ios_base::fmtflags origfmt = out.flags();
101 out << "\\u" << std::hex << std::uppercase << std::setw(4) << std::setfill('0')
102 << std::uint_least16_t(*o3tl::forceAccess<char16_t>(value));
103 out.setf(origfmt);
104 break;
106 case css::uno::TypeClass_STRING:
107 out << '"' << *o3tl::forceAccess<OUString>(value) << '"'; //TODO: encode content
108 break;
109 case css::uno::TypeClass_TYPE:
110 out << o3tl::forceAccess<css::uno::Type>(value)->getTypeName();
111 break;
112 case css::uno::TypeClass_ANY:
113 out << value.getValueTypeName() << ": ";
114 printUnoValue(out, reflections, value.getValueType(), value);
115 break;
116 case css::uno::TypeClass_SEQUENCE:
118 css::uno::Reference<css::reflection::XIdlClass> const refl(
119 reflections->forName(type.getTypeName()), css::uno::UNO_SET_THROW);
120 auto const t = translateType(refl->getComponentType());
121 auto const array = refl->getArray();
122 auto const n = array->getLen(value);
123 out << '[';
124 for (sal_Int32 i = 0; i != n; ++i) {
125 if (i != 0) {
126 out << ", ";
128 printUnoValue(out, reflections, t, array->get(value, i));
130 out << ']';
131 break;
133 case css::uno::TypeClass_ENUM:
134 out << value.getValueTypeName() << ' ' << *static_cast<sal_Int32 const *>(value.getValue());
135 break;
136 case css::uno::TypeClass_STRUCT:
137 case css::uno::TypeClass_EXCEPTION:
139 out << '{';
140 auto first = true;
141 for (auto const & f: css::uno::Reference<css::reflection::XIdlClass>(
142 reflections->forName(type.getTypeName()),
143 css::uno::UNO_SET_THROW)->getFields())
145 if (first) {
146 first = false;
147 } else {
148 out << ", ";
150 out << f->getName() << ": ";
151 printUnoValue(out, reflections, translateType(f->getType()), f->get(value));
153 out << '}';
154 break;
156 case css::uno::TypeClass_INTERFACE:
157 out << '@' << value.getValue();
158 break;
159 default:
160 O3TL_UNREACHABLE;
164 class Prot : public CppUnit::Protector
166 public:
167 Prot() {}
169 Prot(const Prot&) = delete;
170 Prot& operator=(const Prot&) = delete;
172 virtual bool protect(
173 CppUnit::Functor const & functor,
174 CppUnit::ProtectorContext const & context) override;
177 bool Prot::protect(
178 CppUnit::Functor const & functor, CppUnit::ProtectorContext const & context)
180 try {
181 return functor();
182 } catch (const css::uno::Exception &e) {
183 css::uno::Any a(cppu::getCaughtException());
184 std::ostringstream s;
185 try {
186 printUnoValue(
188 css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext()),
189 cppu::UnoType<css::uno::Any>::get(), a);
190 } catch (css::uno::Exception &) {
191 // Best effort to print full details above; if that fails for whatever reason, print as
192 // much detailed information as possible, followed by at least the exception type and
193 // message:
194 s << "... " << a.getValueTypeName() << ": " << e.Message;
196 reportError(
197 context,
198 CppUnit::Message(
199 "An uncaught UNO exception",
200 s.str()));
202 return false;
207 extern "C" SAL_DLLPUBLIC_EXPORT CppUnit::Protector *
208 unoexceptionprotector() {
209 return std::getenv("CPPUNIT_PROPAGATE_EXCEPTIONS") == nullptr ? new Prot : nullptr;
212 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */